summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2016-01-22 11:37:48 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-02-08 15:24:29 -0800
commit7ac69e594b9a092dfeb76a4969396f7ddde4fbee (patch)
treec8c9eb1d45a74fbc9b9892e28a0c75b46818cb2a /test
parent89424bfbedba6c06f4a4ef9e444a2c4d0575883a (diff)
downloadchrome-ec-7ac69e594b9a092dfeb76a4969396f7ddde4fbee.tar.gz
CR50: Add initial elliptic curve crypto implementation.
This change adds support for NIST-P256 curve operations. BRANCH=none BUG=chrome-os-partner:43025,chrome-os-partner:47524 TEST=new tests under test/tpm2/ pass. Change-Id: I03a35ff3ab8af3c52282d882937880bfa2bdcd32 Signed-off-by: nagendra modadugu <ngm@google.com> Reviewed-on: https://chromium-review.googlesource.com/324540 Commit-Ready: Nagendra Modadugu <ngm@google.com> Tested-by: Nagendra Modadugu <ngm@google.com> Reviewed-by: Marius Schilder <mschilder@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/tpm_test/ecc_test.py169
-rw-r--r--test/tpm_test/subcmd.py1
-rwxr-xr-xtest/tpm_test/tpmtest.py2
3 files changed, 172 insertions, 0 deletions
diff --git a/test/tpm_test/ecc_test.py b/test/tpm_test/ecc_test.py
new file mode 100644
index 0000000000..cd4bb0a261
--- /dev/null
+++ b/test/tpm_test/ecc_test.py
@@ -0,0 +1,169 @@
+#!/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),
+)
+
+
+class ECError(Exception):
+ pass
+
+
+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 ECError('%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 ECError('%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 ECError('%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)
diff --git a/test/tpm_test/subcmd.py b/test/tpm_test/subcmd.py
index f7bd8090a0..d14c2e9b9c 100644
--- a/test/tpm_test/subcmd.py
+++ b/test/tpm_test/subcmd.py
@@ -9,3 +9,4 @@
AES = 0
HASH = 1
RSA = 2
+EC = 3
diff --git a/test/tpm_test/tpmtest.py b/test/tpm_test/tpmtest.py
index 52d7205022..173f0ec693 100755
--- a/test/tpm_test/tpmtest.py
+++ b/test/tpm_test/tpmtest.py
@@ -19,6 +19,7 @@ root_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.append(os.path.join(root_dir, '..', '..', 'build', 'tpm_test'))
import crypto_test
+import ecc_test
import ftdi_spi_tpm
import hash_test
import rsa_test
@@ -135,6 +136,7 @@ if __name__ == '__main__':
t = TPM(debug_mode=debug_needed)
crypto_test.crypto_tests(t, os.path.join(root_dir, 'crypto_test.xml'))
+ ecc_test.ecc_test(t)
hash_test.hash_test(t)
rsa_test.rsa_test(t)
except (TpmError, crypto_test.CryptoError, hash_test.HashError,