Files
OpenCellular/test/tpm_test/ecc_test.py
Vadim Bendebury a0ee706819 cr50: test: consolidate test exceptions
There is no point in defining tpm test exception classes per test
type, one common class is enough, especially if the source module of
the exception is reported.

BRANCH=none
BUG=none
TEST=tried running the test without the USB FTDI cable plugged in, got
     the following error message:

     $ ./test/tpm_test/tpmtest.py
     Starting MPSSE at 800 kHz

     Error in tpmtest.py:54:  Failed to connect
     $

Change-Id: I5642aa70c8a581099887b58e3a436d7f8d7608a1
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/327300
Reviewed-by: Nagendra Modadugu <ngm@google.com>
2016-02-11 20:16:13 -08:00

166 lines
4.5 KiB
Python

#!/usr/bin/python
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module for testing ecc functions using extended commands."""
import binascii
import hashlib
import os
import struct
import subcmd
import utils
_EC_OPCODES = {
'SIGN': 0x00,
'VERIFY': 0x01,
'KEYGEN': 0x02,
'KEYDERIVE': 0x03,
}
_EC_CURVES = {
'NIST-P256': 0x03,
}
# TPM2 signature codes.
_SIGN_MODE = {
'NONE': 0x00,
'ECDSA': 0x18,
# TODO(ngm): add support for SCHNORR.
# 'SCHNORR': 0x1c
}
# TPM2 ALG codes.
_HASH = {
'NONE': 0x00,
'SHA1': 0x04,
'SHA256': 0x0B
}
_HASH_FUNC = {
'NIST-P256': hashlib.sha256
}
# Command format.
#
# 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
#
_EC_CMD_FORMAT = '{o:c}{c:c}{s:c}{h:c}{ml:s}{msg}{dl:s}{dig}'
def _sign_cmd(curve_id, hash_func, sign_mode, msg):
op = _EC_OPCODES['SIGN']
digest = hash_func(msg).digest()
digest_len = len(digest)
return _EC_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)
def _verify_cmd(curve_id, hash_func, sign_mode, msg, sig):
op = _EC_OPCODES['VERIFY']
sig_len = len(sig)
digest = hash_func(msg).digest()
digest_len = len(digest)
return _EC_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)
def _keygen_cmd(curve_id):
op = _EC_OPCODES['KEYGEN']
return _EC_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='')
def _keyderive_cmd(curve_id, seed):
op = _EC_OPCODES['KEYDERIVE']
seed_len = len(seed)
return _EC_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='')
_SIGN_INPUTS = (
('NIST-P256', 'ECDSA'),
)
_KEYGEN_INPUTS = (
('NIST-P256',),
)
_KEYDERIVE_INPUTS = (
# Curve-id, random seed size.
('NIST-P256', 32),
)
def _sign_test(tpm):
msg = 'Hello CR50'
for data in _SIGN_INPUTS:
curve_id, sign_mode = data
test_name = 'EC-SIGN:%s:%s' % data
cmd = _sign_cmd(_EC_CURVES[curve_id], _HASH_FUNC[curve_id],
_SIGN_MODE[sign_mode], msg)
wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.EC, cmd))
signature = tpm.unwrap_ext_response(subcmd.EC, wrapped_response)
cmd = _verify_cmd(_EC_CURVES[curve_id], _HASH_FUNC[curve_id],
_SIGN_MODE[sign_mode], msg, signature)
wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.EC, cmd))
verified = tpm.unwrap_ext_response(subcmd.EC, 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:
curve_id, = data
test_name = 'EC-KEYGEN:%s' % data
cmd = _keygen_cmd(_EC_CURVES[curve_id])
wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.EC, cmd))
valid = tpm.unwrap_ext_response(subcmd.EC, wrapped_response)
expected = '\x01'
if valid != expected:
raise subcmd.TpmTestError('%s error:%s:%s' % (
test_name, utils.hex_dump(valid), utils.hex_dump(expected)))
print('%sSUCCESS: %s' % (utils.cursor_back(), test_name))
def _keyderive_test(tpm):
for data in _KEYDERIVE_INPUTS:
curve_id, seed_bytes = data
seed = os.urandom(seed_bytes)
test_name = 'EC-KEYDERIVE:%s' % data[0]
cmd = _keyderive_cmd(_EC_CURVES[curve_id], seed)
wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.EC, cmd))
valid = tpm.unwrap_ext_response(subcmd.EC, wrapped_response)
expected = '\x01'
if valid != expected:
raise subcmd.TpmTestError('%s error:%s:%s' % (
test_name, utils.hex_dump(valid), utils.hex_dump(expected)))
print('%sSUCCESS: %s' % (utils.cursor_back(), test_name))
def ecc_test(tpm):
_sign_test(tpm)
_keygen_test(tpm)
_keyderive_test(tpm)