v3.28.2: the outfile ADM encoding fix
The ADM column carries the key's hex value (the length varies, 4-16 hex
digits) - the form the preset store and /api/verify-adm use (pySim pads
it with 'f' to the 8 CHV bytes). The parser treated it as an ASCII
string hex-encoded and either mangled it (3632333239463337 -> 62329F37,
a wrong ADM that would fail VERIFY and consume an attempt) or dropped it
(CFA3DD9C6B7F0F8C - the live report with AM0027_alfa_dsa.out).
- The ADM is stored as-is: non-hex stripped, uppercased, [0-9A-F]{4,16};
a non-hex or too-short value is dropped with "ADM is not 4-16 hex
digits".
- _ascii_from_hex() is gone (its only user was the ADM column).
- Docs: help EN/RU, api.md and the repo AGENTS now say "the key's hex
value, 4-16 hex digits (the length varies)".
Note: presets imported from a BAP-style file before this fix hold the
mangled ADM - re-import or correct them.
Tests: the BAP fixture (the hex as-is), the AM0027 shape, a
short/lowercase value and the drop cases. Both real samples verified
(BAP 3632333239463337, AM0027 CFA3DD9C6B7F0F8C; the ALFA sample has no
ADM column and is unchanged). 915 frontend + 925 Python; sw cache
simple-v440.
This commit is contained in:
+27
-3
@@ -139,7 +139,7 @@ class BapShapeTests(unittest.TestCase):
|
||||
self.assertEqual(p['pin2'], '4321')
|
||||
self.assertEqual(p['puk1'], '12345678')
|
||||
self.assertEqual(p['puk2'], '87654321')
|
||||
self.assertEqual(p['adm'], '62329F37') # the ASCII-hex decode
|
||||
self.assertEqual(p['adm'], '3632333239463337') # the key's hex value as-is
|
||||
# EKI, KIK and the IMSI columns are ignored - one keyset only
|
||||
self.assertEqual(len(p['keysets']), 1)
|
||||
self.assertEqual(p['keysets'][0]['kicKey'], K16A)
|
||||
@@ -233,11 +233,35 @@ class OptionTests(unittest.TestCase):
|
||||
self.assertEqual(len(res['presets']), 1)
|
||||
self.assertEqual(res['presets'][0]['pin1'], '1234')
|
||||
self.assertNotIn('adm', res['presets'][0])
|
||||
# a present ADM is decoded from its ASCII-hex form
|
||||
# the ADM column is the key's hex value, stored as-is (v3.28.2): the
|
||||
# length varies, and the value is never ASCII-decoded
|
||||
text = ('ICCID KIC1 KID1 ADM\n' + DIGITS_F + ' ' + K16A + ' ' + K16B +
|
||||
' 3632333239463337\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
self.assertEqual(res['presets'][0]['adm'], '62329F37')
|
||||
self.assertEqual(res['presets'][0]['adm'], '3632333239463337')
|
||||
# ...an 8-byte binary-looking value (the AM0027 sample's shape)
|
||||
text = ('ICCID KIC1 KID1 ADM\n' + DIGITS_F + ' ' + K16A + ' ' + K16B +
|
||||
' CFA3DD9C6B7F0F8C\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
self.assertEqual(res['presets'][0]['adm'], 'CFA3DD9C6B7F0F8C')
|
||||
# ...a shorter key (4 hex digits) and the lowercase form
|
||||
text = ('ICCID KIC1 KID1 ADM\n' + DIGITS_F + ' ' + K16A + ' ' + K16B +
|
||||
' 1a2b3c4d\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
self.assertEqual(res['presets'][0]['adm'], '1A2B3C4D')
|
||||
# a non-hex or too-short ADM is dropped with its reason
|
||||
text = ('ICCID KIC1 KID1 ADM\n' + DIGITS_F + ' ' + K16A + ' ' + K16B +
|
||||
' ZZZZ\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
self.assertNotIn('adm', res['presets'][0])
|
||||
self.assertTrue(any('ADM is not 4-16 hex digits' in s
|
||||
for s in res['report']['skipped']))
|
||||
text = ('ICCID KIC1 KID1 ADM\n' + DIGITS_F + ' ' + K16A + ' ' + K16B +
|
||||
' 123\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
self.assertNotIn('adm', res['presets'][0])
|
||||
self.assertTrue(any('ADM is not 4-16 hex digits' in s
|
||||
for s in res['report']['skipped']))
|
||||
# a present but invalid PIN is dropped, the card kept
|
||||
text = ('ICCID KIC1 KID1 PIN1\n' + DIGITS_F + ' ' + K16A + ' ' + K16B + ' 12\n')
|
||||
res = outfile.parse_outfile(text)
|
||||
|
||||
Reference in New Issue
Block a user