diff options
-rw-r--r-- | test/tpm_test/crypto_test.py | 57 | ||||
-rw-r--r-- | test/tpm_test/drbg_test.py | 51 | ||||
-rw-r--r-- | test/tpm_test/ecc_test.py | 127 | ||||
-rw-r--r-- | test/tpm_test/ecies_test.py | 86 | ||||
-rwxr-xr-x | test/tpm_test/genvectors.py | 29 | ||||
-rw-r--r-- | test/tpm_test/hash_test.py | 21 | ||||
-rw-r--r-- | test/tpm_test/hkdf_test.py | 16 | ||||
-rw-r--r-- | test/tpm_test/rsa_test.py | 110 | ||||
-rwxr-xr-x | test/tpm_test/tpmtest.py | 13 | ||||
-rw-r--r-- | test/tpm_test/trng_test.py | 2 | ||||
-rw-r--r-- | test/tpm_test/upgrade_test.py | 4 | ||||
-rw-r--r-- | test/tpm_test/utils.py | 2 |
12 files changed, 228 insertions, 290 deletions
diff --git a/test/tpm_test/crypto_test.py b/test/tpm_test/crypto_test.py index c11528c8f2..b10b04df1c 100644 --- a/test/tpm_test/crypto_test.py +++ b/test/tpm_test/crypto_test.py @@ -64,8 +64,8 @@ def get_attribute(tdesc, attr_name, required=True): text = text.replace(' ', '') # Convert hex-text to little-endian binary (in 4-byte word chunks) - value = '' - for block in range(len(text)/8): + value = b'' + for block in range(len(text)//8): try: value += struct.pack('<I', int('0x%s' % text[8*block:8*(block+1)], 16)) @@ -76,7 +76,8 @@ def get_attribute(tdesc, attr_name, required=True): # Unpack remaining hex text, without introducing a zero pad. for block in range(-1, -(len(text) % 8), -1): - value += chr(int(text[2*block:len(text) + (2*block)+2], 16)) + value += int(text[2*block:len(text) +\ + (2*block)+2], 16).to_bytes(1, 'big') return value @@ -134,19 +135,27 @@ def crypto_run(node_name, op_type, key, init_vec, aad, in_text, out_text, tpm): except KeyError: raise subcmd.TpmTestError('unrecognizable mode in node "%s"' % node_name) + # Command structure, shared out of band with the test driver running + # on the host: + # + # field | size | note + # ================================================================ + # mode | 1 | 0 - decrypt, 1 - encrypt + # cipher_mode | 1 | as per aes_test_cipher_mode + # key_len | 1 | key size in bytes (16, 24 or 32) + # key | key len | key to use + # iv_len | 1 | either 0 or 16 + # iv | 0 or 16 | as defined by iv_len + # aad_len | <= 127 | additional authentication data length + # aad | aad_len | additional authentication data + # text_len | 2 | size of the text to process, big endian + # text | text_len | text to encrypt/decrypt + cmd = op_type.to_bytes(1, 'big') + submode.to_bytes(1, 'big') +\ + len(key).to_bytes(1, 'big') + key +\ + len(init_vec).to_bytes(1, 'big') + init_vec +\ + len(aad).to_bytes(1, 'big') + aad +\ + len(in_text).to_bytes(2, 'big') + in_text - cmd = '%c' % op_type # Encrypt or decrypt - cmd += '%c' % submode # A particular type of a generic algorithm. - cmd += '%c' % len(key) - cmd += key - cmd += '%c' % len(init_vec) - if init_vec: - cmd += init_vec - cmd += '%c' % len(aad) - if aad: - cmd += aad - cmd += struct.pack('>H', len(in_text)) - cmd += in_text if tpm.debug_enabled(): print('%d:%d cmd size' % (op_type, mode_cmd), len(cmd), utils.hex_dump(cmd)) @@ -191,11 +200,15 @@ def crypto_test(tdesc, tpm): node_name, ''.join('%2.2x' % ord(x) for x in key))) init_vec = get_attribute(tdesc, 'iv', required=False) + if isinstance(init_vec, str): + init_vec = bytes(init_vec, 'ascii') if init_vec and not node_name.startswith('AES:GCM') and len(init_vec) != 16: raise subcmd.TpmTestError('wrong iv size "%s:%s"' % ( node_name, ''.join('%2.2x' % ord(x) for x in init_vec))) clear_text = get_attribute(tdesc, 'clear_text', required=False) + if isinstance(clear_text, str): + clear_text = bytes(clear_text, 'ascii') if clear_text: clear_text_len = get_attribute(tdesc, 'clear_text_len', required=False) if clear_text_len: @@ -205,17 +218,25 @@ def crypto_test(tdesc, tpm): if tpm.debug_enabled(): print('clear text size', len(clear_text)) cipher_text = get_attribute(tdesc, 'cipher_text', required=False) + if isinstance(cipher_text, str): + cipher_text = bytes(cipher_text, 'ascii') if clear_text_len: cipher_text = cipher_text[:int(clear_text_len)] tag = get_attribute(tdesc, 'tag', required=False) - aad = get_attribute(tdesc, 'aad', required=False) + if isinstance(tag, str): + tag = bytes(tag, 'ascii') + + aad = get_attribute(tdesc, 'aad', required=False) or b'' + if isinstance(aad, str): + aad = bytes(aad, 'ascii') if aad: aad_len = get_attribute(tdesc, 'aad_len', required=False) if aad_len: aad = aad[:int(aad_len)] real_cipher_text = crypto_run(node_name, ENCRYPT, key, init_vec, - aad or '', clear_text, cipher_text + tag, tpm) - crypto_run(node_name, DECRYPT, key, init_vec, aad or '', + aad, clear_text, + cipher_text + tag, tpm) + crypto_run(node_name, DECRYPT, key, init_vec, aad, real_cipher_text[:len(real_cipher_text) - len(tag)], clear_text + tag, tpm) print(utils.cursor_back() + 'SUCCESS: %s' % node_name) diff --git a/test/tpm_test/drbg_test.py b/test/tpm_test/drbg_test.py index e85e841d7c..dba30a2473 100644 --- a/test/tpm_test/drbg_test.py +++ b/test/tpm_test/drbg_test.py @@ -8,17 +8,16 @@ from __future__ import print_function from binascii import a2b_hex as a2b -from struct import pack import subcmd import utils # A standard empty response to DRBG extended commands. -EMPTY_DRBG_RESPONSE = ''.join('%c' % x for x in (0x80, 0x01, - 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x00, - 0x00, subcmd.DRBG_TEST)) +EMPTY_DRBG_RESPONSE = bytes([0x80, 0x01, + 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, + 0x00, subcmd.DRBG_TEST]) DRBG_INIT = 0 DRBG_RESEED = 1 @@ -48,25 +47,41 @@ TEST_INPUTS = ( (DRBG_GENERATE, ('85D011A3B36AC6B25A792F213A1C22C80BFD1C5B47BCA04CD0D9834BB466447B', 'B03863C42C9396B4936D83A551871A424C5A8EDBDC9D1E0E8E89710D58B5CA1E')), - ) -_DRBG_INIT_FORMAT = '{op:c}{p0l:s}{p0}{p1l:s}{p1}{p2l:s}{p2}' -def _drbg_init_cmd(operation, entropy, nonce, perso): - return _DRBG_INIT_FORMAT.format(op=operation, - p0l=pack('>H', len(entropy)), p0=entropy, - p1l=pack('>H', len(nonce)), p1=nonce, - p2l=pack('>H', len(perso)), p2=perso) - -_DRBG_GEN_FORMAT = '{op:c}{p0l:s}{p0}{p1l:s}' - +# DRBG_TEST command structure: +# +# field | size | note +# ========================================================================== +# mode | 1 | 0 - DRBG_INIT, 1 - DRBG_RESEED, 2 - DRBG_GENERATE +# p0_len | 2 | size of first input in bytes +# p0 | p0_len | entropy for INIT & SEED, input for GENERATE +# p1_len | 2 | size of second input in bytes (for INIT & RESEED) +# | | or size of expected output for GENERATE +# p1 | p1_len | nonce for INIT & SEED +# p2_len | 2 | size of third input in bytes for DRBG_INIT +# p2 | p2_len | personalization for INIT & SEED +# +# DRBG_INIT (entropy, nonce, perso) +# DRBG_RESEED (entropy, additional input 1, additional input 2) +# DRBG_INIT and DRBG_RESEED returns empty response +# (up to a maximum of 128 bytes) +# DRBG_INIT and DRBG_RESEED commands follow same format +def _drbg_init_cmd(drbg_op, entropy, nonce, perso): + return drbg_op.to_bytes(1, 'big') +\ + len(entropy).to_bytes(2, 'big') + entropy +\ + len(nonce).to_bytes(2, 'big') + nonce +\ + len(perso).to_bytes(2, 'big') + perso + +# DRBG_GENERATE (p0_len, p0 - additional input 1, p1_len - size of output) +# DRBG_GENERATE returns p1_len bytes of generated data def _drbg_gen_cmd(inp, out): outlen = len(out) if outlen == 0: outlen = 32 # if we don't care about output value, still need to have it - return _DRBG_GEN_FORMAT.format(op=DRBG_GENERATE, - p0l=pack('>H', len(inp)), p0=inp, - p1l=pack('>H', outlen)) + return DRBG_GENERATE.to_bytes(1, 'big') +\ + len(inp).to_bytes(2, 'big') + inp +\ + outlen.to_bytes(2, 'big') def drbg_test(tpm): diff --git a/test/tpm_test/ecc_test.py b/test/tpm_test/ecc_test.py index a20c6e0e4b..e0d5fb361a 100644 --- a/test/tpm_test/ecc_test.py +++ b/test/tpm_test/ecc_test.py @@ -74,106 +74,69 @@ PKEY = ('fc441e07744e48f109b7e66b29482f7b' # QY QX_LEN # # Command formats: -# + # TEST_SIGN: # OP | CURVE_ID | SIGN_MODE | HASHING | DIGEST_LEN | DIGEST # @returns 0/1 | R_LEN | R | S_LEN | S -_TEST_SIGN = '{o:c}{c:c}{s:c}{h:c}{dl:s}{dig}' - -# TEST_SIGN_ANY: -# OP | CURVE_ID | SIGN_MODE | HASHING | DIGEST_LEN | DIGEST | D_LEN | D -# @returns 0/1 | R_LEN | R | S_LEN | S -_TEST_SIGN_ANY = '{o:c}{c:c}{s:c}{h:c}{dl:s}{dig}{pl:s}{pk}' +def _sign_cmd(curve_id, hash_func, sign_mode, msg): + digest = hash_func(msg).digest() + return struct.pack('>BBBBH', _ECC_OPCODES['SIGN'], curve_id, sign_mode, + _HASH['NONE'], len(digest)) + digest -# # TEST_VERIFY: # OP | CURVE_ID | SIGN_MODE | HASHING | R_LEN | R | S_LEN | S # DIGEST_LEN | DIGEST # @returns 1 if successful -_TEST_VERIFY = '{o:c}{c:c}{sm:c}{h:c}{rs}{dl:s}{dig}' +# below we assume sig = [R_LEN | R | S_LEN | S] as it came from SIGN +def _verify_cmd(curve_id, hash_func, sign_mode, msg, sig): + digest = hash_func(msg).digest() + return struct.pack('>BBBB', _ECC_OPCODES['VERIFY'], curve_id, sign_mode, + _HASH['NONE']) + sig +\ + len(digest).to_bytes(2, 'big') + digest + +# TEST_SIGN_ANY: +# OP | CURVE_ID | SIGN_MODE | HASHING | DIGEST_LEN | DIGEST | D_LEN | D +# @returns 0/1 | R_LEN | R | S_LEN | S +def _sign_any_cmd(curve_id, hash_func, sign_mode, msg, pkey): + digest = hash_func(msg).digest() + return struct.pack('>BBBBH', _ECC_OPCODES['SIGN_ANY'], curve_id, sign_mode, + _HASH['NONE'], len(digest)) + digest +\ + len(pkey).to_bytes(2, 'big') + pkey # TEST_VERIFY_ANY: # OP | CURVE_ID | SIGN_MODE | HASHING | R_LEN | R | S_LEN | S | # DIGEST_LEN | DIGEST | QX_LEN | QX | QY_LEN | QY # @returns 1 if successful -_TEST_VERIFY_ANY = _TEST_VERIFY + '{qxl:s}{qx}{qyl:s}{qy}' - -# TEST_KEYDERIVE: -# OP | CURVE_ID | SEED_LEN | SEED -# @returns 1 if successful -# -_TEST_KEYDERIVE = '{o:c}{c:c}{ml:s}{msg}' +# pylint: disable=too-many-arguments +def _verify_any_cmd(curve_id, hash_func, sign_mode, msg, sig, q_x, q_y): + digest = hash_func(msg).digest() + return struct.pack('>BBBB', _ECC_OPCODES['VERIFY_ANY'], curve_id, sign_mode, + _HASH['NONE']) + sig +\ + len(digest).to_bytes(2, 'big') + digest +\ + len(q_x).to_bytes(2, 'big') + q_x+ \ + len(q_y).to_bytes(2, 'big') + q_y # TEST_POINT: # OP | CURVE_ID | QX_LEN | QX | QY_LEN | QY # @returns 1 if point is on curve - -_TEST_POINT = '{o:c}{c:c}{qxl:s}{qx}{qyl:s}{qy}' +def _test_point_cmd(curve_id, q_x, q_y): + return struct.pack('>BB', _ECC_OPCODES['TEST_POINT'], curve_id) +\ + len(q_x).to_bytes(2, 'big') + q_x+ \ + len(q_y).to_bytes(2, 'big') + q_y # # TEST_KEYGEN: # OP | CURVE_ID # @returns 0/1 | D_LEN | D | QX_LEN | QX | QY_LEN | QY -# -_TEST_KEYGEN = '{o:c}{c:c}' - -def _sign_cmd(curve_id, hash_func, sign_mode, msg): - ecc_op = _ECC_OPCODES['SIGN'] - digest = hash_func(msg).digest() - digest_len = len(digest) - return _TEST_SIGN.format(o=ecc_op, c=curve_id, s=sign_mode, - h=_HASH['SHA256'], - dl=struct.pack('>H', digest_len), dig=digest) - -def _sign_any_cmd(curve_id, hash_func, sign_mode, msg, pkey): - ecc_op = _ECC_OPCODES['SIGN_ANY'] - digest = hash_func(msg).digest() - digest_len = len(digest) - return _TEST_SIGN_ANY.format(o=ecc_op, c=curve_id, s=sign_mode, - h=_HASH['SHA256'], - dl=struct.pack('>H', digest_len), dig=digest, - pl=struct.pack('>H', len(pkey)), pk=pkey) - - -def _verify_cmd(curve_id, hash_func, sign_mode, msg, sig): - ecc_op = _ECC_OPCODES['VERIFY'] - digest = hash_func(msg).digest() - digest_len = len(digest) - return _TEST_VERIFY.format(o=ecc_op, c=curve_id, sm=sign_mode, - h=_HASH['SHA256'], - rs=sig, - dl=struct.pack('>H', digest_len), - dig=digest) - -# pylint: disable=too-many-arguments -def _verify_any_cmd(curve_id, hash_func, sign_mode, msg, sig, q_x, q_y): - ecc_op = _ECC_OPCODES['VERIFY_ANY'] - digest = hash_func(msg).digest() - digest_len = len(digest) - return _TEST_VERIFY_ANY.format(o=ecc_op, c=curve_id, sm=sign_mode, - h=_HASH['SHA256'], - rs=sig, - dl=struct.pack('>H', digest_len), dig=digest, - qxl=struct.pack('>H', len(q_x)), qx=q_x, - qyl=struct.pack('>H', len(q_y)), qy=q_y) - -def _test_point_cmd(curve_id, q_x, q_y): - ecc_op = _ECC_OPCODES['TEST_POINT'] - return _TEST_POINT.format(o=ecc_op, c=curve_id, - qxl=struct.pack('>H', len(q_x)), qx=q_x, - qyl=struct.pack('>H', len(q_y)), qy=q_y) - def _keygen_cmd(curve_id): - ecc_op = _ECC_OPCODES['KEYGEN'] - return _TEST_KEYGEN.format(o=ecc_op, c=curve_id) - + return struct.pack('>BB', _ECC_OPCODES['KEYGEN'], curve_id) +# TEST_KEYDERIVE: +# OP | CURVE_ID | SEED_LEN | SEED +# @returns 1 if successful def _keyderive_cmd(curve_id, seed): - ecc_op = _ECC_OPCODES['KEYDERIVE'] - seed_len = len(seed) - return _TEST_KEYDERIVE.format(o=ecc_op, c=curve_id, - ml=struct.pack('>H', seed_len), msg=seed) - + return struct.pack('>BBH', _ECC_OPCODES['KEYDERIVE'], curve_id, + len(seed)) + seed _SIGN_INPUTS = ( ('NIST-P256', 'ECDSA'), @@ -192,7 +155,7 @@ _KEYDERIVE_INPUTS = ( def _sign_test(tpm): - msg = 'Hello CR50' + msg = b'Hello CR50' for data in _SIGN_INPUTS: curve_id, sign_mode = data @@ -200,7 +163,7 @@ def _sign_test(tpm): cmd = _sign_cmd(_ECC_CURVES[curve_id], _HASH_FUNC[curve_id], _SIGN_MODE[sign_mode], msg) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) - expected = '\x01' + expected = b'\x01' signature = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) if signature[:1] != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( @@ -218,7 +181,7 @@ def _sign_test(tpm): print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) def _sign_test_any(tpm): - msg = 'Hello CR50' + msg = b'Hello CR50' for data in _SIGN_INPUTS: curve_id, sign_mode = data @@ -226,7 +189,7 @@ def _sign_test_any(tpm): cmd = _sign_any_cmd(_ECC_CURVES[curve_id], _HASH_FUNC[curve_id], _SIGN_MODE[sign_mode], msg, a2b(PKEY)) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) - expected = '\x01' + expected = b'\x01' signature = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) if signature[:1] != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( @@ -250,7 +213,7 @@ def _point_test(tpm): a2b(NIST_P256_QX), a2b(NIST_P256_QY)) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) verified = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) - expected = '\x01' + expected = b'\x01' if verified != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( test_name, utils.hex_dump(verified), utils.hex_dump(expected))) @@ -263,7 +226,7 @@ def _keygen_test(tpm): cmd = _keygen_cmd(_ECC_CURVES[curve_id]) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) valid = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) - expected = '\x01' + expected = b'\x01' if valid[:1] != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( test_name, utils.hex_dump(valid[:1]), utils.hex_dump(expected))) @@ -278,7 +241,7 @@ def _keyderive_test(tpm): cmd = _keyderive_cmd(_ECC_CURVES[curve_id], seed) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) valid = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) - expected = '\x01' + expected = b'\x01' if valid != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( test_name, utils.hex_dump(valid), utils.hex_dump(expected))) diff --git a/test/tpm_test/ecies_test.py b/test/tpm_test/ecies_test.py index 04d5963310..c19be8d123 100644 --- a/test/tpm_test/ecies_test.py +++ b/test/tpm_test/ecies_test.py @@ -5,7 +5,6 @@ """Module for testing ECIES using extended commands.""" from binascii import a2b_hex as a2b -from struct import pack import subcmd import utils @@ -39,18 +38,16 @@ _ECIES_OPCODES = { # 1 LSB INFO LEN # INFO_LEN INFO # -_ECIES_CMD_FORMAT = ('{o:c}{inl:s}{input}{al:s}{iv}' - '{xl:s}{x}{yl:s}{y}{sl:s}{s}{il:s}{i}') -_DEFAULT_SALT = 'Salt!' -_DEFAULT_INFO = 'Info!' -_STATIC_IV = ''.join([chr(x) for x in range(16)]) +_DEFAULT_SALT = b'Salt!' +_DEFAULT_INFO = b'Info!' +_STATIC_IV = bytes([x for x in range(16)]) _ECIES_INPUTS = ( ( - '', - 'Test message!!', + b'', + b'Test message!!', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -60,8 +57,8 @@ _ECIES_INPUTS = ( 'SIMPLE' ), ( - '', - 'Multi block test message!!!!', + b'', + b'Multi block test message!!!!', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -71,8 +68,8 @@ _ECIES_INPUTS = ( 'MULTI-BLOCK' ), ( - 'Auth data', - 'Test message!!!!', + b'Auth data', + b'Test message!!!!', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -82,8 +79,8 @@ _ECIES_INPUTS = ( 'AUTH-DATA' ), ( - 'Auth data' * 10, - 'Test message!!!!', + b'Auth data' * 10, + b'Test message!!!!', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -93,8 +90,8 @@ _ECIES_INPUTS = ( 'LARGE-AUTH-DATA' ), ( - 'Auth data', - 'Test message!!!!' * 5, + b'Auth data', + b'Test message!!!!' * 5, _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -104,19 +101,19 @@ _ECIES_INPUTS = ( 'LARGE-PLAINTEXT-DATA' ), ( - '', - 'Test message!!', + b'', + b'Test message!!', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), a2b('8750c295cd33be5846868e2869bf2c8cfeefbc4a574874c7388bf40f74e8e0e6'), - '', - '', + b'', + b'', 'NO-SALT-INFO' ), ( - 'Auth data', - '', + b'Auth data', + b'', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -126,8 +123,8 @@ _ECIES_INPUTS = ( 'AUTH-NULL-PLAINTEXT' ), ( - '', - '', + b'', + b'', _STATIC_IV, a2b('6fdaf5e2e11dd61c116222c748d99b45f69031c9d4d3d5787a9a0fdd3b9c471a'), a2b('98e76f53febd6bedc8fa19ce1543cb3f8f5cbc72c74602f1bfdee88c19d3d9d0'), @@ -141,7 +138,7 @@ _ECIES_INPUTS = ( _ECIES_COMPAT_INPUTS = ( ( a2b('d61262f22e8c70414777cbc060d1e387'), - 'The quick brown fox jumps over the lazy dog.', + b'The quick brown fox jumps over the lazy dog.', a2b('d61262f22e8c70414777cbc060d1e387'), a2b('040c23b1abb7f7e3d2da6ffd70ce9e6f5bf90467c0e1f2e708483d2e61220f0a' '0257110d695bec78ac1e15333219d7ba3f8f2f155b76acd56d99680031d83853' @@ -155,7 +152,7 @@ _ECIES_COMPAT_INPUTS = ( ), ( a2b('b3a89ed5a7fb6685a67db54c62e663e7'), - 'Test message!!', + b'Test message!!', a2b('b3a89ed5a7fb6685a67db54c62e663e7'), a2b('04b9d46d1f333baf6896ce7b64d344092671795438b1dc35a21b0d13b004f28a1c' 'edd4f1f7ff63106772270050cb62152b07e9c02bbee79db7a3fb4155c464e0d5b3' @@ -170,26 +167,23 @@ _ECIES_COMPAT_INPUTS = ( # pylint: disable=too-many-arguments def _encrypt_cmd(auth, in_data, init_vec, pubx, puby, salt, info): - ecies_op = _ECIES_OPCODES['ENCRYPT'] - return _ECIES_CMD_FORMAT.format(o=ecies_op, - inl=pack('>H', len(auth+in_data)), - input=auth+in_data, - al=pack('>H', len(auth)), iv=init_vec, - xl=pack('>H', len(pubx)), x=pubx, - yl=pack('>H', len(puby)), y=puby, - sl=pack('>H', len(salt)), s=salt, - il=pack('>H', len(info)), i=info) - -# pylint: disable=too-many-arguments -def _decrypt_cmd(auth, in_data, init_vec, tag, salt, info): - ecies_op = _ECIES_OPCODES['DECRYPT'] - return _ECIES_CMD_FORMAT.format(o=ecies_op, inl=pack('>H', len(in_data)), - input=in_data, - al=pack('>H', len(auth)), iv=init_vec, - xl=pack('>H', len(tag)), x=tag, - yl=pack('>H', 0), y='', - sl=pack('>H', len(salt)), s=salt, - il=pack('>H', len(info)), i=info) + return _ECIES_OPCODES['ENCRYPT'].to_bytes(1, 'big') +\ + len(auth+in_data).to_bytes(2, 'big') + auth + in_data +\ + len(auth).to_bytes(2, 'big') + init_vec +\ + len(pubx).to_bytes(2, 'big') + pubx +\ + len(puby).to_bytes(2, 'big') + puby +\ + len(salt).to_bytes(2, 'big') + salt +\ + len(info).to_bytes(2, 'big') + info + + +def _decrypt_cmd(auth, in_data, init_vec, d, salt, info): + return _ECIES_OPCODES['DECRYPT'].to_bytes(1, 'big') +\ + len(in_data).to_bytes(2, 'big') + in_data +\ + len(auth).to_bytes(2, 'big') + init_vec +\ + len(d).to_bytes(2, 'big') + d +\ + bytes([0, 0]) +\ + len(salt).to_bytes(2, 'big') + salt +\ + len(info).to_bytes(2, 'big') + info # pylint: disable=too-many-locals def _ecies_test(tpm): diff --git a/test/tpm_test/genvectors.py b/test/tpm_test/genvectors.py index 85c9b8a200..baf276bd88 100755 --- a/test/tpm_test/genvectors.py +++ b/test/tpm_test/genvectors.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2016 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be @@ -6,8 +6,6 @@ """Module for generating AES test vectors.""" -from binascii import b2a_hex as b2a -from itertools import izip_longest import os from Crypto.Cipher import AES @@ -41,12 +39,15 @@ def h2be(v): Convert input big-endian byte-string to 4-byte segmented little-endian words. Pad-bytes (if necessary) are the empty string. """ - word = [iter(v)] * 4 - return ''.join([ - ''.join(b[::-1]) for b in izip_longest(*word, fillvalue='') - ]) + out = b'' + while v: + out += int.from_bytes(v[:4].ljust(4, bytes([0])), 'big')\ + .to_bytes(4, 'little')[4-len(v[:4]):] + v = v[4:] + return out +print('<crypto_tests>') for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]: for key_bytes in [16, 24, 32]: test_num = 0 @@ -58,7 +59,7 @@ for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]: actual_pt_len = pt_len if pt_len % 16: - pt_len = 16 * ((pt_len / 16) + 1) + pt_len = 16 * ((pt_len // 16) + 1) key = os.urandom(key_bytes) iv = os.urandom(16) @@ -69,11 +70,11 @@ for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]: obj = AES.new(key, mode=mode, IV=iv, segment_size=128) assert obj.decrypt(ct)[:pt_len] == pt - - print template.format(mode=modes[mode], + print(template.format(mode=modes[mode], key_bits=str(key_bytes * 8), test_num=str(test_num), - pt=b2a(h2be(pt[:actual_pt_len])), - key=b2a(h2be(key)), - ct=b2a(h2be(ct[:actual_pt_len])), - iv=b2a(h2be(iv))), + pt=h2be(pt[:actual_pt_len]).hex(), + key=h2be(key).hex(), + ct=h2be(ct[:actual_pt_len]).hex(), + iv=h2be(iv).hex())) +print('</crypto_tests>') diff --git a/test/tpm_test/hash_test.py b/test/tpm_test/hash_test.py index a518be043c..9a5184e261 100644 --- a/test/tpm_test/hash_test.py +++ b/test/tpm_test/hash_test.py @@ -10,7 +10,6 @@ from __future__ import print_function import hashlib import hmac import struct - import subcmd import utils @@ -30,8 +29,8 @@ ALG_SHA384 = 2 ALG_SHA512 = 3 # A standard empty response to HASH extended commands. -EMPTY_RESPONSE = ''.join('%c' % x for x in (0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01)) +EMPTY_RESPONSE = bytes([0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]) TEST_INPUTS = ( # Hash cmd alg handle hmac_key text (CMD_HMAC_SW, ALG_SHA256, 0, 'hmac_key1', 'some text, this time for sw hmac'), @@ -118,21 +117,19 @@ def hash_test(tpm): for test in TEST_INPUTS: hash_cmd, hash_alg, handle, hmac_key, text = test + text = bytes(text, 'ascii') + hmac_key = bytes(hmac_key, 'ascii') mode_name = cmd_map[hash_cmd] alg_name, hash_func = alg_map[hash_alg] test_name = '%s:%s:%d' % (mode_name, alg_name, handle) - cmd = '%c' % hash_cmd - cmd += '%c' % hash_alg - cmd += '%c' % handle # Ignored for single shots - - cmd += struct.pack('>H', len(text)) - cmd += text + cmd = struct.pack('>BBBH', hash_cmd, hash_alg, handle, + len(text)) + text # for HMAC add key if hash_cmd in (CMD_HMAC_SW, CMD_HMAC_HW): - cmd += struct.pack('>H', len(hmac_key)) - cmd += hmac_key + cmd += len(hmac_key).to_bytes(2, 'big') + hmac_key + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.HASH, cmd)) if hash_cmd in (CMD_HASH_START, CMD_HASH_CONT): if hash_cmd == CMD_HASH_START: @@ -149,7 +146,7 @@ def hash_test(tpm): elif hash_cmd == CMD_HASH: hash_context = hash_func() elif hash_cmd in (CMD_HMAC_SW, CMD_HMAC_HW): - hash_context = hmac.new(bytes(hmac_key), digestmod=hash_func) + hash_context = hmac.new(hmac_key, digestmod=hash_func) else: raise subcmd.TpmTestError('Unknown command %d' % hash_cmd) hash_context.update(text) diff --git a/test/tpm_test/hkdf_test.py b/test/tpm_test/hkdf_test.py index 8fe8fe8b56..ab1c87301a 100644 --- a/test/tpm_test/hkdf_test.py +++ b/test/tpm_test/hkdf_test.py @@ -6,7 +6,6 @@ """Module for testing HKDF using extended commands.""" from binascii import a2b_hex as a2b -from struct import pack import subcmd import utils @@ -32,18 +31,11 @@ _HKDF_OPCODES = { # INFO_LEN INFO # 1 MSB OKM LEN # 1 LSB OKM LEN -# -_HKDF_CMD_FORMAT = '{op:c}{sl:s}{salt}{ikml:s}{ikm}{infol:s}{info}{okml:s}' - - def _rfc_test_cmd(salt, ikm, info, okml): - hkdf_op = _HKDF_OPCODES['TEST_RFC'] - return _HKDF_CMD_FORMAT.format(op=hkdf_op, - sl=pack('>H', len(salt)), salt=salt, - ikml=pack('>H', len(ikm)), ikm=ikm, - infol=pack('>H', len(info)), info=info, - okml=pack('>H', okml)) - + return _HKDF_OPCODES['TEST_RFC'].to_bytes(1, 'big') + \ + len(salt).to_bytes(2, 'big') + salt + \ + len(ikm).to_bytes(2, 'big') + ikm + \ + len(info).to_bytes(2, 'big') + info + okml.to_bytes(2, 'big') # # Test vectors for HKDF-SHA256 from RFC 5869. diff --git a/test/tpm_test/rsa_test.py b/test/tpm_test/rsa_test.py index 1d377b3ae2..52754b38d8 100644 --- a/test/tpm_test/rsa_test.py +++ b/test/tpm_test/rsa_test.py @@ -8,7 +8,6 @@ import binascii import os import struct - import Crypto import Crypto.Hash.SHA import Crypto.Hash.SHA256 @@ -89,83 +88,38 @@ _KEYS = { # 0x00 LSB DIGEST LEN # .... DIGEST # -_RSA_CMD_FORMAT = '{o:c}{p:c}{h:c}{kl:s}{ml:s}{msg}{dl:s}{dig}' - - def _decrypt_cmd(padding, hashing, key_len, msg): - rsa_op = _RSA_OPCODES['DECRYPT'] - msg_len = len(msg) - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', msg_len), msg=msg, - dl='', dig='') - + return struct.pack('>BBBHH', _RSA_OPCODES['DECRYPT'], padding, hashing, + key_len, len(msg)) + msg + bytes([0, 0]) def _encrypt_cmd(padding, hashing, key_len, msg): - rsa_op = _RSA_OPCODES['ENCRYPT'] - msg_len = len(msg) - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', msg_len), msg=msg, - dl='', dig='') - + return struct.pack('>BBBHH', _RSA_OPCODES['ENCRYPT'], padding, hashing, + key_len, len(msg)) + msg + bytes([0, 0]) def _sign_cmd(padding, hashing, key_len, digest): - rsa_op = _RSA_OPCODES['SIGN'] - digest_len = len(digest) - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', digest_len), msg=digest, - dl='', dig='') - + return struct.pack('>BBBHH', _RSA_OPCODES['SIGN'], padding, hashing, + key_len, len(digest)) + digest + bytes([0, 0]) def _verify_cmd(padding, hashing, key_len, sig, digest): - rsa_op = _RSA_OPCODES['VERIFY'] - sig_len = len(sig) - digest_len = len(digest) - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', sig_len), msg=sig, - dl=struct.pack('>H', digest_len), dig=digest) - + return struct.pack('>BBBHH', _RSA_OPCODES['VERIFY'], padding, hashing, + key_len, len(sig)) + sig +\ + len(digest).to_bytes(2, 'big') + digest def _keytest_cmd(key_len): - rsa_op = _RSA_OPCODES['KEYTEST'] - return _RSA_CMD_FORMAT.format(o=rsa_op, p=0, h=_HASH['NONE'], - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', 0), msg='', - dl='', dig='') - + return struct.pack('>BBBHHH', _RSA_OPCODES['KEYTEST'], 0, 0, key_len, 0, 0) def _keygen_cmd(key_len, exponent, label): assert exponent == 65537 - rsa_op = _RSA_OPCODES['KEYGEN'] - padding = _RSA_PADDING['NONE'] - hashing = _HASH['NONE'] - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', len(label)), msg=label, - dl=struct.pack('>H', 0), dig='') - + return struct.pack('>BBBHH', _RSA_OPCODES['KEYGEN'], 0, 0, key_len, + len(label)) + label + bytes([0, 0]) def _primegen_cmd(seed): - rsa_op = _RSA_OPCODES['PRIMEGEN'] - padding = _RSA_PADDING['NONE'] - hashing = _HASH['NONE'] - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', len(seed) * 8 * 2), - ml=struct.pack('>H', len(seed)), msg=seed, - dl=struct.pack('>H', 0), dig='') + return struct.pack('>BBBHH', _RSA_OPCODES['PRIMEGEN'], 0, 0, len(seed) * 16, + len(seed)) + seed + bytes([0, 0]) def _x509_verify_cmd(key_len): - rsa_op = _RSA_OPCODES['X509_VERIFY'] - padding = _RSA_PADDING['NONE'] - hashing = _HASH['NONE'] - return _RSA_CMD_FORMAT.format(o=rsa_op, p=padding, h=hashing, - kl=struct.pack('>H', key_len), - ml=struct.pack('>H', 0), msg='', - dl=struct.pack('>H', 0), dig='') - + return struct.pack('>BBBHHH', _RSA_OPCODES['X509_VERIFY'], 0, 0, + key_len, 0, 0) _PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, @@ -579,13 +533,13 @@ def _prime_from_seed(seed): return window # Set LSB, and top two bits. - candidate = chr(ord(seed[0]) | 192) + seed[1:-1] + chr(ord(seed[-1]) | 1) + candidate = bytes([(seed[0] | 192)]) + seed[1:-1] + bytes([seed[-1] | 1]) candidate = int(binascii.b2a_hex(candidate), 16) assert len(bin(candidate)[2:]) == len(seed) * 8 window = _window(candidate, _PRIMES[:4096]) for i, bit in enumerate(window): if not bit: - if rsa.prime.randomized_primality_testing(candidate + i, rounds): + if rsa.prime.miller_rabin_primality_testing(candidate + i, rounds): return candidate + i return None @@ -633,11 +587,11 @@ _KEYTEST_INPUTS = ( ) _KEYGEN_INPUTS = ( - (768, 65537, '', None), - (1024, 65537, 'rsa_test', None), + (768, 65537, b'', None), + (1024, 65537, b'rsa_test', None), # pylint: disable=line-too-long - (2048, 65537, 'RSA key by vendor', 20811475686431332186511278472307159547870512766846593830860105577496044159545322178313772755518365593670114793803805067608811418757734989708137784444223785391864604211835387393923163468734914392307047296990698533218399115126417934050463597455237478939601236799120239663591264311485133747167378663829046579164891864068853210530642835833947569643788911200934265596274935082689832626616967124524353322373059893974744194447740045242468136414689225322177212281193879756355471091445748150740871146034049776312457888356154834233819876846764944450478069436248506560967902863015152471662817623176815923756421011384149834497587), - (2048, 65537, '', None), + (2048, 65537, b'RSA key by vendor', 20811475686431332186511278472307159547870512766846593830860105577496044159545322178313772755518365593670114793803805067608811418757734989708137784444223785391864604211835387393923163468734914392307047296990698533218399115126417934050463597455237478939601236799120239663591264311485133747167378663829046579164891864068853210530642835833947569643788911200934265596274935082689832626616967124524353322373059893974744194447740045242468136414689225322177212281193879756355471091445748150740871146034049776312457888356154834233819876846764944450478069436248506560967902863015152471662817623176815923756421011384149834497587), + (2048, 65537, b'', None), ) # 2048-bit will be done in hardware (i.e. fast), rest are in software. @@ -653,7 +607,7 @@ _PRIMEGEN_INPUTS = ( ) def _encrypt_tests(tpm): - msg = 'Hello CR50!' + msg = b'Hello CR50!' for data in _ENCRYPT_INPUTS: padding, hashing, key_len = data @@ -710,7 +664,7 @@ def _verify_tests(tpm): key_len, signature, msg_hash.digest()) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) verified = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) - expected = '\x01' + expected = b'\x01' if verified != expected: raise subcmd.TpmTestError('%s error:%s%s' % ( test_name, utils.hex_dump(verified), utils.hex_dump(expected))) @@ -724,7 +678,7 @@ def _keytest_tests(tpm): cmd = _keytest_cmd(key_len) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) valid = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) - expected = '\x01' + expected = b'\x01' if valid != expected: raise subcmd.TpmTestError('%s error:%s%s' % ( test_name, utils.hex_dump(valid), utils.hex_dump(expected))) @@ -746,12 +700,12 @@ def _keygen_tests(tpm): raise subcmd.TpmTestError('%s error:%s' % ( test_name, utils.hex_dump(result))) - N = int(binascii.b2a_hex(result[0:result_len * 2 / 3]), 16) + N = int(binascii.b2a_hex(result[0:result_len * 2 // 3]), 16) if expected_N and N != expected_N: raise subcmd.TpmTestError('%s error:%s' % (test_name, utils.hex_dump(result))) - p = int(binascii.b2a_hex(result[result_len * 2 / 3:]), 16) - q = N / p + p = int(binascii.b2a_hex(result[result_len * 2 // 3:]), 16) + q = N // p if not rsa.prime.is_prime(p): raise subcmd.TpmTestError('%s error:%s' % (test_name, utils.hex_dump(result))) @@ -768,15 +722,15 @@ def _primegen_tests(tpm): for data in _PRIMEGEN_INPUTS: key_len = data test_name = 'RSA-PRIMEGEN:%d' % data - seed = rsa.randnum.read_random_bits(key_len / 2) - assert len(seed) == key_len / 16 + seed = rsa.randnum.read_random_bits(key_len // 2) + assert len(seed) == key_len // 16 # dcrypto interface is little-endian. cmd = _primegen_cmd(seed[::-1]) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) result = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) result_len = len(result) - if result_len != key_len / 16: + if result_len != key_len // 16: raise subcmd.TpmTestError('%s error:%s' % ( test_name, utils.hex_dump(result))) @@ -796,7 +750,7 @@ def _x509_verify_tests(tpm): cmd = _x509_verify_cmd(2048) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) valid = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) - expected = '\x01' + expected = b'\x01' if valid != expected: raise subcmd.TpmTestError('%s error:%s%s' % ( test_name, utils.hex_dump(valid), utils.hex_dump(expected))) diff --git a/test/tpm_test/tpmtest.py b/test/tpm_test/tpmtest.py index 96f2587396..0ec33ce8f1 100755 --- a/test/tpm_test/tpmtest.py +++ b/test/tpm_test/tpmtest.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be @@ -35,7 +35,7 @@ import upgrade_test EXT_CMD = 0xbaccd00a -class TPM(object): +class TPM: """TPM accessor class. Object of this class allows to send valid and extended TPM commands (using @@ -67,7 +67,7 @@ class TPM(object): """ (tag, size, cmd_code, _) = struct.unpack_from( - self.HEADER_FMT, data_blob + ' ') + self.HEADER_FMT, data_blob + b' ') prefix = 'Misformatted blob: ' if tag not in (0x8001, 0x8002): raise subcmd.TpmTestError(prefix + 'bad tag value 0x%4.4x' % tag) @@ -186,9 +186,10 @@ def main(): rsa_test.rsa_test(tpm_object) upgrade_test.upgrade(tpm_object) except subcmd.TpmTestError as tpm_exc: - exc_file, exc_line = traceback.extract_tb(sys.exc_traceback)[-1][:2] - print('\nError in %s:%s: ' % (os.path.basename(exc_file), exc_line), - tpm_exc) + _, _, exc_traceback = sys.exc_info() + exc_file, exc_line = traceback.extract_tb(exc_traceback)[-1][:2] + print('\nError in %s:%s: ' % (os.path.basename(exc_file), + exc_line), tpm_exc) if debug_needed: traceback.print_exc() sys.exit(1) diff --git a/test/tpm_test/trng_test.py b/test/tpm_test/trng_test.py index ddfc659339..c4d9395e80 100644 --- a/test/tpm_test/trng_test.py +++ b/test/tpm_test/trng_test.py @@ -49,5 +49,5 @@ def trng_test(tpm): raise subcmd.TpmTestError("Unexpected response to \'%s\': %s" % ('trng', utils.hex_dump(response))) out_file.write(response[12:]) - print('%s %d%%\r' % (utils.cursor_back(), (block/10)), end='') + print('%s %d%%\r' % (utils.cursor_back(), (block//10)), end='') print('%sSUCCESS: %s' % (utils.cursor_back(), 'trng')) diff --git a/test/tpm_test/upgrade_test.py b/test/tpm_test/upgrade_test.py index 2cf03cc8ea..1cdd15a728 100644 --- a/test/tpm_test/upgrade_test.py +++ b/test/tpm_test/upgrade_test.py @@ -45,7 +45,7 @@ def upgrade(tpm): else: raise subcmd.TpmTestError('Unknown base address 0x%x' % base) fname = os.path.join(os.path.dirname(__file__), '../..', fname) - data = open(fname, 'r').read()[:2000] + data = open(fname, 'rb').read()[:2000] transferred = 0 block_size = 1024 @@ -60,7 +60,7 @@ def upgrade(tpm): resp = tpm.unwrap_ext_response(subcmd.FW_UPGRADE, tpm.command(tpm.wrap_ext_command( subcmd.FW_UPGRADE, cmd))) - code = ord(resp[0]) + code = resp[0] if code: raise subcmd.TpmTestError('%x - resp %d' % (base, code)) base += tx_size diff --git a/test/tpm_test/utils.py b/test/tpm_test/utils.py index 7b42bcd508..5a58dc3b38 100644 --- a/test/tpm_test/utils.py +++ b/test/tpm_test/utils.py @@ -30,7 +30,7 @@ def hex_dump(binstr): i = 0 while i < len(binstr): strsize = min(16, len(binstr) - i) - hexstr = ' '.join('%2.2x' % ord(x) for x in binstr[i:i+strsize]) + hexstr = ' '.join('%2.2x' % x for x in binstr[i:i+strsize]) dump_lines.append(hexstr) i += strsize dump_lines.append('') |