summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2019-11-11 16:39:14 -0800
committerCommit Bot <commit-bot@chromium.org>2020-06-05 07:25:19 +0000
commit65e147217ad968743b5f6e3d94db6b5dcefb11ad (patch)
treee52229ecfe021c36fa4f4cc52fbb52643084673c
parentf9cca4269a124019f56980471d152b68177837f0 (diff)
downloadchrome-ec-stabilize-lazor-13278.B-cr50_stab.tar.gz
cr50: add functionality for ACVP tests of elliptic curve implementationstabilize-lazor-13278.B-cr50_stab
NIST ACVP test expects access to test point is on curve and verification of signature with arbitrary public key. Current implementation supported only fixed public key. ACVP tests to be submitted separately. Added two new test commands to support ACVP: - TEST_POINT - test that given point is on selected curve - TEST_VERIFY_ANY - same as TEST_VERIFY, but use provided Q - TEST_SIGN_ANY - same as TEST_SIGN, but use provided d (private key) BUG=b:138578319 TEST=make CRYPTO_TEST=1 BOARD=cr50 -j && test/tpm_test/tpmtest.py Change-Id: Ibeabede935f5bbac918b3043072e05f8a6417aa4 Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2227077 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org> Auto-Submit: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-rw-r--r--board/cr50/tpm2/ecc.c324
-rw-r--r--test/tpm_test/ecc_test.py188
2 files changed, 368 insertions, 144 deletions
diff --git a/board/cr50/tpm2/ecc.c b/board/cr50/tpm2/ecc.c
index 3aea411487..95afd01ce9 100644
--- a/board/cr50/tpm2/ecc.c
+++ b/board/cr50/tpm2/ecc.c
@@ -361,13 +361,17 @@ CRYPT_RESULT _cpri__GetEphemeralEcc(TPMS_ECC_POINT *q, TPM2B_ECC_PARAMETER *d,
#ifdef CRYPTO_TEST_SETUP
+#include "console.h"
#include "extension.h"
enum {
TEST_SIGN = 0,
TEST_VERIFY = 1,
TEST_KEYGEN = 2,
- TEST_KEYDERIVE = 3
+ TEST_KEYDERIVE = 3,
+ TEST_POINT = 4,
+ TEST_VERIFY_ANY = 5,
+ TEST_SIGN_ANY = 6,
};
struct TPM2B_ECC_PARAMETER_aligned {
@@ -434,182 +438,278 @@ static int point_equals(const TPMS_ECC_POINT *a, const TPMS_ECC_POINT *b)
return !diff;
}
+/**
+ * Parse TPM_2B data, copy data to destination, update position
+ * @param ptr - pointer to current position, updated if parsed successfully
+ * @param cmd_size - remaining number of bytes, [in/out]
+ * @param len [out] - length of parsed data
+ * @param out [out] - destination buffer to copy data
+ * @param out_len - size of destination buffer
+ */
+static int parse_2b(uint8_t **ptr, size_t *cmd_size, uint16_t *len,
+ uint8_t *out, size_t out_len)
+{
+ uint16_t length;
+ uint8_t *local_ptr = *ptr;
+
+ *len = 0;
+ /* if there is no space for 2 bytes of length, exit */
+ if (*cmd_size < sizeof(length))
+ return 0;
+ length = local_ptr[0];
+ length = (length << 8) | local_ptr[1];
+ *cmd_size -= sizeof(length);
+ local_ptr += 2;
+ if (*cmd_size < length || length > out_len) {
+ ccprintf("%s: length = %d (0x%4x),"
+ " data available = %d, out_len = %d\n",
+ __func__, length, length, *cmd_size, out_len);
+ *cmd_size = 0;
+ return 0;
+ }
+ *len = length;
+ memcpy(out, local_ptr, length);
+ *ptr = local_ptr + length;
+ *cmd_size -= length;
+ return 1;
+}
+
+static void store_2b(uint8_t **ptr, size_t *rsp_size, TPM2B_ECC_PARAMETER *p)
+{
+ uint8_t *out = *ptr;
+
+ *out++ = p->t.size >> 8;
+ *out++ = p->t.size & 0xff;
+ memcpy(out, p->t.buffer, p->t.size);
+ *ptr = out + p->t.size;
+ *rsp_size += 2 + p->t.size;
+}
+
static void ecc_command_handler(void *cmd_body, size_t cmd_size,
size_t *response_size_out)
{
uint8_t *cmd;
uint8_t op;
uint8_t curve_id;
- uint8_t sign_mode;
- uint8_t hashing;
- uint16_t in_len;
- uint8_t in[MAX_MSG_BYTES];
- uint16_t digest_len;
+ uint8_t sign_mode = 0;
+ uint8_t hashing = 0;
+ TPM2B_SEED seed;
+
struct TPM2B_MAX_BUFFER_aligned digest;
uint8_t *out = (uint8_t *) cmd_body;
- uint32_t *response_size = (uint32_t *) response_size_out;
+ size_t *response_size = response_size_out;
TPMS_ECC_POINT q;
TPM2B_ECC_PARAMETER d;
struct TPM2B_ECC_PARAMETER_aligned r;
struct TPM2B_ECC_PARAMETER_aligned s;
-
- /* Command format.
+ /**
+ * Command formats:
+ *
+ * TEST_SIGN:
+ * OP | CURVE_ID | SIGN_MODE | HASHING | DIGEST_LEN | DIGEST
+ * @returns 0/1 | R_LEN | R | S_LEN | S
+ *
+ * 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_VERIFY:
+ * OP | CURVE_ID | SIGN_MODE | HASHING | R_LEN | R | S_LEN | S
+ * DIGEST_LEN | DIGEST
+ * @returns 0/1 | if successful
+ *
+ * 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_KEYDERIVE :
+ * OP | CURVE_ID | SEED_LEN | SEED
+ * @returns 1 if successful
+ *
+ * TEST_POINT:
+ * OP | CURVE_ID | QX_LEN | QX | QY_LEN | QY
+ * @returns 1 if point is on curve
*
- * OFFSET FIELD
- * 0 OP
- * 1 CURVE_ID
- * 2 SIGN_MODE
- * 3 HASHING
- * 4 MSB IN LEN
- * 5 LSB IN LEN
- * 6 IN
- * 6 + IN_LEN MSB DIGEST LEN
- * 7 + IN_LEN LSB DIGEST LEN
- * 8 + IN_LEN DIGEST
+ * TEST_KEYGEN:
+ * OP | CURVE_ID
+ * @returns 0/1 | D_LEN | D | QX_LEN | QX | QY_LEN | QY
+ *
+ * Field size:
+ * FIELD LENGTH
+ * OP 1
+ * CURVE_ID 1
+ * SIGN_MODE 1
+ * HASHING 1
+ * MSG_LEN 2 (big endian)
+ * MSG MSG_LEN
+ * SEED_LEN 2 (big endian)
+ * SEED SEED_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
*/
+ *response_size = 0;
+ if (cmd_size < 2)
+ return;
- cmd = (uint8_t *) cmd_body;
+ cmd = (uint8_t *)cmd_body;
op = *cmd++;
curve_id = *cmd++;
- sign_mode = *cmd++;
- hashing = *cmd++;
- in_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
- cmd += 2;
- if (in_len > sizeof(in)) {
- *response_size = 0;
- return;
+ cmd_size -= 2;
+
+ if (op == TEST_SIGN || op == TEST_VERIFY || op == TEST_VERIFY_ANY ||
+ op == TEST_SIGN_ANY) {
+ if (cmd_size >= 2) {
+ sign_mode = *cmd++;
+ hashing = *cmd++;
+ cmd_size -= 2;
+ } else
+ return;
+ }
+
+ if (op == TEST_SIGN || op == TEST_SIGN_ANY) {
+ if (!parse_2b(&cmd, &cmd_size, &digest.d.t.size,
+ digest.d.t.buffer, sizeof(digest.d.t.buffer)))
+ return;
+ if (op == TEST_SIGN_ANY &&
+ !parse_2b(&cmd, &cmd_size, &d.t.size, d.t.buffer,
+ sizeof(d.t.buffer)))
+ return;
+ if (op == TEST_SIGN) {
+ if (curve_id == TPM_ECC_NIST_P256)
+ d = NIST_P256_d.d;
+ else
+ return;
+ }
}
- memcpy(in, cmd, in_len);
- cmd += in_len;
- digest_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
- cmd += 2;
- if (digest_len > sizeof(digest.d.t.buffer)) {
- *response_size = 0;
+ if (op == TEST_KEYDERIVE &&
+ !parse_2b(&cmd, &cmd_size, &seed.t.size, seed.t.buffer,
+ sizeof(seed.t.buffer)))
return;
+
+ if (op == TEST_VERIFY || op == TEST_VERIFY_ANY) {
+ if (!parse_2b(&cmd, &cmd_size, &r.d.t.size, r.d.t.buffer,
+ sizeof(r.d.t.buffer)))
+ return;
+ if (!parse_2b(&cmd, &cmd_size, &s.d.t.size, s.d.t.buffer,
+ sizeof(s.d.t.buffer)))
+ return;
+ if (!parse_2b(&cmd, &cmd_size, &digest.d.t.size,
+ digest.d.t.buffer, sizeof(digest.d.t.buffer)))
+ return;
}
- digest.d.t.size = digest_len;
- memcpy(digest.d.t.buffer, cmd, digest_len);
- cmd += digest_len;
- /* Make copies of d, and q, as const data is immutable. */
- switch (curve_id) {
- case TPM_ECC_NIST_P256:
- d = NIST_P256_d.d;
+ if (op == TEST_VERIFY_ANY || op == TEST_POINT) {
+ if (!parse_2b(&cmd, &cmd_size, &q.x.t.size, q.x.t.buffer,
+ sizeof(q.x.t.buffer)))
+ return;
+ if (!parse_2b(&cmd, &cmd_size, &q.y.t.size, q.y.t.buffer,
+ sizeof(q.y.t.buffer)))
+ return;
+ } else {
+ /* use fixed signature */
q.x = NIST_P256_qx.d;
q.y = NIST_P256_qy.d;
- break;
- default:
- *response_size = 0;
- return;
}
+ /* there should be no other data as command is parsed */
+ if (cmd_size != 0)
+ return;
+
+ *out = 0;
+ *response_size = 1;
switch (op) {
case TEST_SIGN:
- if (_cpri__SignEcc(&r.d, &s.d, sign_mode, hashing,
- curve_id, &d, &digest.d.b, NULL)
- != CRYPT_SUCCESS) {
- *response_size = 0;
+ case TEST_SIGN_ANY:
+ if (hashing != TPM_ALG_SHA256 && hashing != TPM_ALG_NULL)
+ return;
+ if (_cpri__SignEcc(&r.d, &s.d, sign_mode, hashing, curve_id, &d,
+ &digest.d.b, NULL) != CRYPT_SUCCESS) {
+ ccprintf("test_sign: error signing\n");
return;
}
- memcpy(out, r.d.b.buffer, r.d.b.size);
- out += r.d.b.size;
- memcpy(out, s.d.b.buffer, s.d.b.size);
- *response_size = r.d.b.size + s.d.b.size;
+ *out++ = 1;
+ store_2b(&out, response_size, &r.d);
+ store_2b(&out, response_size, &s.d);
break;
case TEST_VERIFY:
- r.d.b.size = in_len / 2;
- memcpy(r.d.b.buffer, in, r.d.b.size);
- s.d.b.size = in_len / 2;
- memcpy(s.d.b.buffer, in + r.d.b.size, s.d.b.size);
- if (_cpri__ValidateSignatureEcc(
- &r.d, &s.d, sign_mode, hashing, curve_id,
- &q, &digest.d.b) != CRYPT_SUCCESS) {
- *response_size = 0;
- } else {
+ case TEST_VERIFY_ANY:
+ if (_cpri__ValidateSignatureEcc(&r.d, &s.d, sign_mode, hashing,
+ curve_id, &q,
+ &digest.d.b) != CRYPT_SUCCESS) {
+ ccprintf("test_verify: verification failed\n");
+ } else
*out = 1;
- *response_size = 1;
- }
return;
- case TEST_KEYGEN:
- {
+ case TEST_KEYGEN: {
struct TPM2B_ECC_PARAMETER_aligned d_local;
TPMS_ECC_POINT q_local;
if (_cpri__GetEphemeralEcc(&q, &d_local.d, curve_id)
- != CRYPT_SUCCESS) {
- *response_size = 0;
+ != CRYPT_SUCCESS)
return;
- }
- if (_cpri__EccIsPointOnCurve(curve_id, &q) != TRUE) {
- *response_size = 0;
+
+ if (_cpri__EccIsPointOnCurve(curve_id, &q) != TRUE)
return;
- }
/* Verify correspondence of secret with the public point. */
if (_cpri__EccPointMultiply(
&q_local, curve_id, &d_local.d,
- NULL, NULL) != CRYPT_SUCCESS) {
- *response_size = 0;
+ NULL, NULL) != CRYPT_SUCCESS)
return;
- }
- if (!point_equals(&q, &q_local)) {
- *response_size = 0;
+ if (!point_equals(&q, &q_local))
return;
- }
- *out = 1;
- *response_size = 1;
+
+ *out++ = 1;
+ store_2b(&out, response_size, &d_local.d);
+ store_2b(&out, response_size, &q.x);
+ store_2b(&out, response_size, &q.y);
return;
}
- case TEST_KEYDERIVE:
- {
- /* Random seed. */
- TPM2B_SEED seed;
+ case TEST_KEYDERIVE: {
struct TPM2B_ECC_PARAMETER_aligned d_local;
TPMS_ECC_POINT q_local;
const char *label = "ecc_test";
-
- if (in_len > PRIMARY_SEED_SIZE) {
- *response_size = 0;
+ if (_cpri__GenerateKeyEcc(&q, &d_local.d, curve_id, hashing,
+ &seed.b, label, NULL,
+ NULL) != CRYPT_SUCCESS)
return;
- }
- seed.t.size = in_len;
- memcpy(seed.t.buffer, in, in_len);
-
- if (_cpri__GenerateKeyEcc(
- &q, &d_local.d, curve_id, hashing,
- &seed.b, label, NULL, NULL) != CRYPT_SUCCESS) {
- *response_size = 0;
- return;
- }
- if (_cpri__EccIsPointOnCurve(curve_id, &q) != TRUE) {
- *response_size = 0;
+ if (_cpri__EccIsPointOnCurve(curve_id, &q) != TRUE)
return;
- }
/* Verify correspondence of secret with the public point. */
- if (_cpri__EccPointMultiply(
- &q_local, curve_id, &d_local.d,
- NULL, NULL) != CRYPT_SUCCESS) {
- *response_size = 0;
+ if (_cpri__EccPointMultiply(&q_local, curve_id, &d_local.d,
+ NULL, NULL) != CRYPT_SUCCESS)
return;
- }
- if (!point_equals(&q, &q_local)) {
- *response_size = 0;
+
+ if (!point_equals(&q, &q_local))
return;
- }
*out = 1;
- *response_size = 1;
- return;
+ break;
}
+ case TEST_POINT:
+ *out = _cpri__EccIsPointOnCurve(curve_id, &q);
+ break;
+
default:
- *response_size = 0;
- return;
+ break;
}
}
diff --git a/test/tpm_test/ecc_test.py b/test/tpm_test/ecc_test.py
index 155a497b98..9ec34c2f21 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)