diff options
Diffstat (limited to 'test/tpm_test/ecc_test.py')
-rw-r--r-- | test/tpm_test/ecc_test.py | 188 |
1 files changed, 156 insertions, 32 deletions
diff --git a/test/tpm_test/ecc_test.py b/test/tpm_test/ecc_test.py index 65b0b5fdb7..b1594db84d 100644 --- a/test/tpm_test/ecc_test.py +++ b/test/tpm_test/ecc_test.py @@ -4,7 +4,7 @@ # found in the LICENSE file. """Module for testing ecc functions using extended commands.""" -import binascii +from binascii import a2b_hex as a2b import hashlib import os import struct @@ -17,6 +17,9 @@ _ECC_OPCODES = { 'VERIFY': 0x01, 'KEYGEN': 0x02, 'KEYDERIVE': 0x03, + 'TEST_POINT': 0x04, + 'VERIFY_ANY': 0x05, + 'SIGN_ANY': 0x06, } _ECC_CURVES = { @@ -42,54 +45,134 @@ _HASH_FUNC = { 'NIST-P256': hashlib.sha256 } -# Command format. +NIST_P256_QX = ('12c3d6a2679ca8ee3c4d927f204ed5bc' + 'b4577a04b0ac02b2a36ab3e9e10781de') +NIST_P256_QY = ('5c85ad7413971172fca5738fee9d0e7b' + 'c59ffd8a626d689bc6cca4b58665521d') + +PKEY = ('fc441e07744e48f109b7e66b29482f7b' + '7e3ec91fa27fd4870991b289fea0d20a') + +## +# Field size: +# FIELD LENGTH +# OP 1 +# CURVE_ID 1 +# SIGN_MODE 1 +# HASHING 1 +# MSG_LEN 2 (big endian) +# MSG MSG_LEN +# R_LEN 2 (big endian) +# R R_LEN +# S_LEN 2 (big endian) +# S S_LEN +# DIGEST_LEN 2 (big endian) +# DIGEST DIGEST_LEN +# D_LEN 2 (big endian) +# D D_LEN +# QX_LEN 2 (big endian) +# QX QX_LEN +# QY_LEN 2 (big endian) +# QY QX_LEN # -# 0x00 OP -# 0x00 CURVE_ID -# 0x00 SIGN_MODE -# 0x00 HASHING -# 0x00 MSB IN LEN -# 0x00 LSB IN LEN -# .... IN -# 0x00 MSB DIGEST LEN -# 0x00 LSB DIGEST LEN -# .... DIGEST +# Command formats: # -_ECC_CMD_FORMAT = '{o:c}{c:c}{s:c}{h:c}{ml:s}{msg}{dl:s}{dig}' +# 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}' + +# +# 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}' + +# 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}' + +# 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}' + +# +# 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): op = _ECC_OPCODES['SIGN'] digest = hash_func(msg).digest() digest_len = len(digest) - return _ECC_CMD_FORMAT.format(o=op, c=curve_id, s=sign_mode, h=_HASH['NONE'], - ml=struct.pack('>H', 0), msg='', - dl=struct.pack('>H', digest_len), dig=digest) + return _TEST_SIGN.format(o=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): + op = _ECC_OPCODES['SIGN_ANY'] + digest = hash_func(msg).digest() + digest_len = len(digest) + return _TEST_SIGN_ANY.format(o=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): op = _ECC_OPCODES['VERIFY'] - sig_len = len(sig) digest = hash_func(msg).digest() digest_len = len(digest) - return _ECC_CMD_FORMAT.format(o=op, c=curve_id, s=sign_mode, h=_HASH['NONE'], - ml=struct.pack('>H', sig_len), msg=sig, - dl=struct.pack('>H', digest_len), dig=digest) + return _TEST_VERIFY.format(o=op, c=curve_id, sm=sign_mode, h=_HASH['SHA256'], + rs=sig, + dl=struct.pack('>H', digest_len), + dig=digest) + +def _verify_any_cmd(curve_id, hash_func, sign_mode, msg, sig, qx, qy): + op = _ECC_OPCODES['VERIFY_ANY'] + digest = hash_func(msg).digest() + digest_len = len(digest) + return _TEST_VERIFY_ANY.format(o=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(qx)), qx=qx, + qyl=struct.pack('>H', len(qy)), qy=qy) + +def _test_point_cmd(curve_id, qx, qy): + op = _ECC_OPCODES['TEST_POINT'] + return _TEST_POINT.format(o=op, c=curve_id, + qxl=struct.pack('>H', len(qx)), qx=qx, + qyl=struct.pack('>H', len(qy)), qy=qy) def _keygen_cmd(curve_id): op = _ECC_OPCODES['KEYGEN'] - return _ECC_CMD_FORMAT.format(o=op, c=curve_id, s=_SIGN_MODE['NONE'], - h=_HASH['NONE'], ml=struct.pack('>H', 0), msg='', - dl=struct.pack('>H', 0), dig='') + return _TEST_KEYGEN.format(o=op, c=curve_id) def _keyderive_cmd(curve_id, seed): op = _ECC_OPCODES['KEYDERIVE'] seed_len = len(seed) - return _ECC_CMD_FORMAT.format(o=op, c=curve_id, s=_SIGN_MODE['NONE'], - h=_HASH['NONE'], ml=struct.pack('>H', seed_len), - msg=seed, dl=struct.pack('>H', 0), dig='') + return _TEST_KEYDERIVE.format(o=op, c=curve_id, + ml=struct.pack('>H', seed_len), msg=seed) _SIGN_INPUTS = ( @@ -117,18 +200,57 @@ 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' signature = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) - + if signature[:1] != expected: + raise subcmd.TpmTestError('%s error:%s:%s' % ( + test_name, utils.hex_dump(signature[:1]), utils.hex_dump(expected))) cmd = _verify_cmd(_ECC_CURVES[curve_id], _HASH_FUNC[curve_id], - _SIGN_MODE[sign_mode], msg, signature) + _SIGN_MODE[sign_mode], msg, signature[1:]) wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) verified = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) + + if verified[:1] != expected: + raise subcmd.TpmTestError('%s error:%s:%s' % ( + test_name, utils.hex_dump(verified[:1]), utils.hex_dump(expected))) + print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) + +def _sign_test_any(tpm): + msg = 'Hello CR50' + + for data in _SIGN_INPUTS: + curve_id, sign_mode = data + test_name = 'ECC-SIGN, Q:%s:%s' % data + 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' - if verified != expected: + signature = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) + if signature[:1] != expected: + raise subcmd.TpmTestError('%s error:%s:%s' % ( + test_name, utils.hex_dump(signature[:1]), utils.hex_dump(expected))) + # make sure properly supplied Q.x, Q.y works + cmd = _verify_any_cmd(_ECC_CURVES[curve_id], _HASH_FUNC[curve_id], + _SIGN_MODE[sign_mode], msg, signature[1:], + 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) + if verified[:1] != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( - test_name, utils.hex_dump(verified), utils.hex_dump(expected))) + test_name, utils.hex_dump(verified[:1]), utils.hex_dump(expected))) print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) +def _point_test(tpm): + test_name = 'POINT-TEST: NIST-P256' + cmd = _test_point_cmd(_ECC_CURVES['NIST-P256'], + 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' + if verified != expected: + raise subcmd.TpmTestError('%s error:%s:%s' % ( + test_name, utils.hex_dump(verified), utils.hex_dump(expected))) + print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) def _keygen_test(tpm): for data in _KEYGEN_INPUTS: @@ -138,9 +260,9 @@ def _keygen_test(tpm): wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.ECC, cmd)) valid = tpm.unwrap_ext_response(subcmd.ECC, wrapped_response) expected = '\x01' - if valid != expected: + if valid[:1] != expected: raise subcmd.TpmTestError('%s error:%s:%s' % ( - test_name, utils.hex_dump(valid), utils.hex_dump(expected))) + test_name, utils.hex_dump(valid[:1]), utils.hex_dump(expected))) print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) @@ -161,5 +283,7 @@ def _keyderive_test(tpm): def ecc_test(tpm): _sign_test(tpm) + _sign_test_any(tpm) + _point_test(tpm) _keygen_test(tpm) _keyderive_test(tpm) |