summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-09-01 14:37:25 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-14 23:36:32 +0000
commitd83a3c89d3733b8ca49f95b93a8c2e4c7db5689e (patch)
tree91138fdd132fa7ab3a29f3d8f1437b005b9b345a
parent404fbff010c86aa27ec1d6ed3d030e71c1536ba7 (diff)
downloadchrome-ec-d83a3c89d3733b8ca49f95b93a8c2e4c7db5689e.tar.gz
cr50: make p256_int aligned - improve code size & performance
p256_int was defined as packed struct to allow in place processing of TPM2 commands. However, it is not practical to pad and reverse bytes in place, support for misaligned access results in bloated code, lower performance and side-channel leaks. With this change introduce p256_from_be_bin_size() function which handles all cases with conversion big-endian number into p256_int internal representation (little-endian for cr50) with skipping leading zeros if present in big-endian, checking of size and zero padding. Bonuses: - code size reduction 336 bytes - a bit higher performance for p256 - support for zero padded big-endian in TPM2 ECC, as well as more reliable checks for input parameters. BUG=none TEST=make BOARD=cr50 CRYPTO_TEST=1; test/tpm_test/tpmtest.py in console p256_test as unit test for padding function. ------------------------------ Test Result Summary ----------------------------- Test executed on: Tue Sep 14 15:13:11 2021 Performed Tests: 248 Passed Tests: 248 Failed Tests: 0 Errors: 0 Warnings: 0 ========================================================= Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: Idd04d4e8d30225398814650332fe9be7182a8966 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3138754 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Auto-Submit: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Bendebury <vbendeb@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-rw-r--r--board/cr50/build.mk6
-rw-r--r--board/cr50/dcrypto/internal.h10
-rw-r--r--board/cr50/dcrypto/p256.c95
-rw-r--r--board/cr50/dcrypto/u2f.c7
-rw-r--r--board/cr50/dcrypto/u2f_impl.h2
-rw-r--r--board/cr50/tpm2/ecc.c208
-rw-r--r--common/u2f.c17
7 files changed, 186 insertions, 159 deletions
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index 4576e30c0e..b221c4f050 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -19,7 +19,7 @@ ifeq ($(BOARD_MK_INCLUDED_ONCE),)
# List of variables which can be defined in the environment or set in the make
# command line.
ENV_VARS := CR50_DEV CRYPTO_TEST H1_RED_BOARD U2F_TEST RND_TEST DRBG_TEST\
- ECDSA_TEST DCRYPTO_TEST
+ ECDSA_TEST DCRYPTO_TEST P256_BIN_TEST
ifneq ($(CRYPTO_TEST),)
CPPFLAGS += -DCRYPTO_TEST_SETUP
@@ -44,6 +44,10 @@ ifneq ($(DCRYPTO_TEST),)
CPPFLAGS += -DCRYPTO_TEST_CMD_DCRYPTO_TEST=1
endif
+ifneq ($(P256_BIN_TEST),)
+CPPFLAGS += -DP256_BIN_TEST=1
+endif
+
endif
diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h
index 6df2df3ef9..b88d0a1d25 100644
--- a/board/cr50/dcrypto/internal.h
+++ b/board/cr50/dcrypto/internal.h
@@ -180,7 +180,7 @@ typedef struct p256_int {
p256_digit a[P256_NDIGITS];
uint8_t b8[P256_NBYTES];
};
-} __packed p256_int;
+} p256_int;
extern const p256_int SECP256r1_nMin2;
@@ -211,6 +211,14 @@ void p256_to_bin(const p256_int *src, uint8_t dst[P256_NBYTES]);
*/
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int *dst);
+/**
+ * Reads from big-endian binary form of given size, add padding with
+ * zeros if short. Check that leading digits beyond P256_NBYTES are zeroes.
+ *
+ * @return true if provided big-endian fits into p256.
+ */
+bool p256_from_be_bin_size(const uint8_t *src, size_t len, p256_int *dst);
+
int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key,
const p256_int *message, p256_int *r, p256_int *s)
__attribute__((warn_unused_result));
diff --git a/board/cr50/dcrypto/p256.c b/board/cr50/dcrypto/p256.c
index 6c923b4699..49c2fe4b2b 100644
--- a/board/cr50/dcrypto/p256.c
+++ b/board/cr50/dcrypto/p256.c
@@ -4,6 +4,7 @@
*/
#include "dcrypto.h"
+#include "endian.h"
const p256_int SECP256r1_nMin2 = /* P-256 curve order - 2 */
{ .a = { 0xfc632551 - 2, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0,
@@ -135,6 +136,34 @@ void p256_to_bin(const p256_int *src, uint8_t dst[P256_NBYTES])
#endif
}
+bool p256_from_be_bin_size(const uint8_t *src, size_t len, p256_int *dst)
+{
+ size_t i;
+
+ /**
+ * Skip zero padding if input length is larger than P-256 size.
+ * This may happen with TPM2 commands receiving big-endian number
+ * with leading zeroes from external sources.
+ */
+ while (len > P256_NBYTES) {
+ if (*src != 0)
+ return false;
+ len--;
+ src++;
+ }
+
+ i = len;
+ /* Now add zero padding little-endian p256 if length is smaller. */
+ while (i < P256_NBYTES) {
+ dst->b8[i] = 0;
+ i++;
+ }
+ reverse_bytes(dst->b8, src, len);
+
+ /* Note: this code is correct only for little-endian platform. */
+ return true;
+}
+
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int *dst)
{
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
@@ -193,3 +222,69 @@ enum hmac_result p256_hmac_drbg_generate(struct drbg_ctx *ctx, p256_int *rnd)
return result;
}
+
+#ifndef P256_BIN_TEST
+#define P256_BIN_TEST 0
+#endif
+
+#ifdef CRYPTO_TEST_SETUP
+
+#if P256_BIN_TEST
+#include "console.h"
+
+static int cmd_p256_bin_test(int argc, char *argv[])
+{
+ static const uint8_t i1[] = {
+ 0, 0, 0x10, 0x11, 0x12, 0x13, 0x20, 0x21, 0x22,
+ 0x23, 0x30, 0x31, 0x32, 0x33, 0x40, 0x41, 0x42, 0x43,
+ 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63, 0x70,
+ 0x71, 0x72, 0x73, 0x80, 0x81, 0x82, 0x83, 0x84
+ };
+ p256_int e = { .a = { 0x80818283, 0x70717273, 0x60616263, 0x50515253,
+ 0x40414243, 0x30313233, 0x20212223,
+ 0x10111213 } };
+
+ p256_int r;
+ bool passed = true;
+ bool result;
+
+ /* zero padded */
+ result = p256_from_be_bin_size(i1, 34, &r);
+ passed = result && (p256_cmp(&r, &e) == 0);
+ ccprintf("in=%ph\nout=%ph\n", HEX_BUF(i1, 34), HEX_BUF(&r, sizeof(r)));
+
+ /* right sized. */
+ memset(&r, 0, sizeof(r));
+ result = p256_from_be_bin_size(i1 + 2, 32, &r);
+ passed = passed && (p256_cmp(&r, &e) == 0);
+ ccprintf("in=%ph\nout=%ph\n", HEX_BUF(i1 + 2, 32),
+ HEX_BUF(&r, sizeof(r)));
+
+ /**
+ * Smaller big num, where padding high byte(s) with zeroes is needed.
+ * we do this by loading 31 byte starting 1 byte higher.
+ * This will result in same value as in 'e' except that the
+ * highest byte will be 0 (e.a[7] == 0x00111213).
+ */
+ memset(&r, 0, sizeof(r));
+ result = p256_from_be_bin_size(i1 + 3, 31, &r);
+
+ /* Update expected result by clearing high byte */
+ e.b8[31] = 0x00;
+ passed = passed && (p256_cmp(&r, &e) == 0);
+ ccprintf("in=%ph\nout=%ph\n", HEX_BUF(i1 + 3, 31),
+ HEX_BUF(&r, sizeof(r)));
+
+ /* larger big num. */
+ result = p256_from_be_bin_size(i1 + 2, 33, &r);
+ passed = passed && !result;
+
+ ccprintf("p256_from_be_bin_size() test %s\n",
+ (passed) ? "PASSED" : "NOT PASSED");
+
+ return EC_SUCCESS;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(p256_test, cmd_p256_bin_test, NULL, NULL);
+#endif /* P256_BIN_TEST */
+
+#endif /* CRYPTO_TEST_SETUP */
diff --git a/board/cr50/dcrypto/u2f.c b/board/cr50/dcrypto/u2f.c
index 9f987fbd64..91c80577b6 100644
--- a/board/cr50/dcrypto/u2f.c
+++ b/board/cr50/dcrypto/u2f.c
@@ -433,7 +433,7 @@ static bool g2f_individual_key_pair(const struct u2f_state *state, p256_int *d,
#define G2F_CERT_NAME "CrO2"
size_t g2f_attestation_cert_serial(const struct u2f_state *state,
- const uint8_t *serial, uint8_t *buf)
+ const p256_int *serial, uint8_t *buf)
{
p256_int d, pk_x, pk_y;
@@ -441,9 +441,8 @@ size_t g2f_attestation_cert_serial(const struct u2f_state *state,
return 0;
/* Note that max length is not currently respected here. */
- return DCRYPTO_x509_gen_u2f_cert_name(&d, &pk_x, &pk_y,
- (p256_int *)serial, G2F_CERT_NAME,
- buf,
+ return DCRYPTO_x509_gen_u2f_cert_name(&d, &pk_x, &pk_y, serial,
+ G2F_CERT_NAME, buf,
G2F_ATTESTATION_CERT_MAX_LEN);
}
diff --git a/board/cr50/dcrypto/u2f_impl.h b/board/cr50/dcrypto/u2f_impl.h
index 7f0f10ef36..be3fbd6b76 100644
--- a/board/cr50/dcrypto/u2f_impl.h
+++ b/board/cr50/dcrypto/u2f_impl.h
@@ -145,7 +145,7 @@ enum ec_error_list u2f_authorize_keyhandle(const struct u2f_state *state,
* @return size of certificate written to buf, 0 on error.
*/
size_t g2f_attestation_cert_serial(const struct u2f_state *state,
- const uint8_t *serial, uint8_t *buf);
+ const p256_int *serial, uint8_t *buf);
/**
* Verify that provided key handle and public key match.
diff --git a/board/cr50/tpm2/ecc.c b/board/cr50/tpm2/ecc.c
index 90a6dac08b..8f9392af28 100644
--- a/board/cr50/tpm2/ecc.c
+++ b/board/cr50/tpm2/ecc.c
@@ -14,66 +14,22 @@
#include "util.h"
#include "dcrypto.h"
-static void reverse_tpm2b(TPM2B *b)
-{
- reverse(b->buffer, b->size);
-}
-
TPM2B_BYTE_VALUE(4);
TPM2B_BYTE_VALUE(32);
-static int check_p256_param(const TPM2B_ECC_PARAMETER *a)
-{
- return a->b.size == sizeof(p256_int);
-}
-
-static int check_p256_param_in_range(const TPM2B_ECC_PARAMETER *a)
-{
- return a->b.size <= sizeof(p256_int);
-}
-
-static int check_p256_point_in_range(const TPMS_ECC_POINT *a)
-{
- return check_p256_param_in_range(&a->x) &&
- check_p256_param_in_range(&a->y);
-}
-
-static void append_zeros_to_p256_param(TPM2B_ECC_PARAMETER *a)
-{
- while (a->b.size < sizeof(p256_int)) {
- a->b.buffer[a->b.size] = 0;
- a->b.size++;
- }
-}
-
-static void append_zeros_to_p256_point(TPMS_ECC_POINT *a)
-{
- append_zeros_to_p256_param(&a->x);
- append_zeros_to_p256_param(&a->y);
-}
-
BOOL _cpri__EccIsPointOnCurve(TPM_ECC_CURVE curve_id, TPMS_ECC_POINT *q)
{
int result;
- int x_size = q->x.b.size;
- int y_size = q->y.b.size;
+ p256_int x, y;
switch (curve_id) {
case TPM_ECC_NIST_P256:
- if (!check_p256_point_in_range(q))
- return FALSE;
-
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
- append_zeros_to_p256_point(q);
- result = dcrypto_p256_is_valid_point((p256_int *) q->x.b.buffer,
- (p256_int *) q->y.b.buffer);
+ if (!p256_from_be_bin_size(q->x.b.buffer, q->x.b.size, &x) ||
+ !p256_from_be_bin_size(q->y.b.buffer, q->y.b.size, &y))
+ return FALSE;
- q->x.b.size = x_size;
- q->y.b.size = y_size;
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
+ result = dcrypto_p256_is_valid_point(&x, &y);
if (result)
return TRUE;
@@ -90,61 +46,44 @@ CRYPT_RESULT _cpri__EccPointMultiply(
TPM2B_ECC_PARAMETER *n1, TPMS_ECC_POINT *in, TPM2B_ECC_PARAMETER *n2)
{
int result;
+ p256_int n, in_x, in_y, out_x, out_y;
switch (curve_id) {
case TPM_ECC_NIST_P256:
- if ((n1 != NULL && n2 != NULL) ||
- (n1 == NULL && n2 == NULL))
+ if ((n1 != NULL && n2 != NULL) || (n1 == NULL && n2 == NULL))
/* Only one of n1 or n2 must be specified. */
return CRYPT_PARAMETER;
- if ((n2 != NULL && in == NULL) ||
- (n2 == NULL && in != NULL))
+ if ((n2 != NULL && in == NULL) || (n2 == NULL && in != NULL))
return CRYPT_PARAMETER;
- if (n1 != NULL && !check_p256_param(n1))
+ if (n1 != NULL &&
+ !p256_from_be_bin_size(n1->b.buffer, n1->b.size, &n))
return CRYPT_PARAMETER;
if (in != NULL && !_cpri__EccIsPointOnCurve(curve_id, in))
return CRYPT_POINT;
- if (n2 != NULL && !check_p256_param(n2))
+ if (n2 != NULL &&
+ !p256_from_be_bin_size(n2->b.buffer, n2->b.size, &n))
return CRYPT_PARAMETER;
if (n1 != NULL) {
- reverse_tpm2b(&n1->b);
-
- result = DCRYPTO_p256_base_point_mul(
- (p256_int *) out->x.b.buffer,
- (p256_int *) out->y.b.buffer,
- (p256_int *) n1->b.buffer);
-
- reverse_tpm2b(&n1->b);
+ result =
+ DCRYPTO_p256_base_point_mul(&out_x, &out_y, &n);
} else {
- const int x_size = in->x.b.size;
- const int y_size = in->y.b.size;
-
- reverse_tpm2b(&n2->b);
- reverse_tpm2b(&in->x.b);
- reverse_tpm2b(&in->y.b);
- append_zeros_to_p256_point(in);
-
- result = DCRYPTO_p256_point_mul(
- (p256_int *) out->x.b.buffer,
- (p256_int *) out->y.b.buffer,
- (p256_int *) n2->b.buffer,
- (p256_int *) in->x.b.buffer,
- (p256_int *) in->y.b.buffer);
-
- reverse_tpm2b(&n2->b);
- in->x.b.size = x_size;
- in->y.b.size = y_size;
- reverse_tpm2b(&in->x.b);
- reverse_tpm2b(&in->y.b);
+ if (!p256_from_be_bin_size(in->x.b.buffer, in->x.b.size,
+ &in_x) ||
+ !p256_from_be_bin_size(in->y.b.buffer, in->y.b.size,
+ &in_y))
+ return CRYPT_PARAMETER;
+
+ result = DCRYPTO_p256_point_mul(&out_x, &out_y, &n,
+ &in_x, &in_y);
}
+ p256_clear(&n);
if (result) {
out->x.b.size = sizeof(p256_int);
out->y.b.size = sizeof(p256_int);
- reverse_tpm2b(&out->x.b);
- reverse_tpm2b(&out->y.b);
-
+ p256_to_bin(&out_x, out->x.b.buffer);
+ p256_to_bin(&out_y, out->y.b.buffer);
return CRYPT_SUCCESS;
} else {
return CRYPT_NO_RESULT;
@@ -225,22 +164,22 @@ CRYPT_RESULT _cpri__GenerateKeyEcc(
}
for (; count != 0; count++) {
+ p256_int x, y, key;
+
memcpy(marshaled_counter.t.buffer, &count, sizeof(count));
_cpri__KDFa(hash_alg, &local_seed.b, label, local_extra,
&marshaled_counter.b, sizeof(key_bytes) * 8, key_bytes,
NULL, FALSE);
- if (DCRYPTO_p256_key_from_bytes(
- (p256_int *) q->x.b.buffer,
- (p256_int *) q->y.b.buffer,
- (p256_int *) d->b.buffer, key_bytes)) {
+ if (DCRYPTO_p256_key_from_bytes(&x, &y, &key, key_bytes)) {
q->x.b.size = sizeof(p256_int);
+ p256_to_bin(&x, q->x.b.buffer);
+
q->y.b.size = sizeof(p256_int);
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
+ p256_to_bin(&y, q->y.b.buffer);
d->b.size = sizeof(p256_int);
- reverse_tpm2b(&d->b);
-
+ p256_to_bin(&key, d->b.buffer);
+ p256_clear(&key);
break;
}
}
@@ -263,7 +202,7 @@ CRYPT_RESULT _cpri__SignEcc(
{
uint8_t digest_local[sizeof(p256_int)];
const size_t digest_len = MIN(digest->size, sizeof(digest_local));
- p256_int p256_digest;
+ p256_int p256_digest, key, p256_r, p256_s;
int result;
if (curve_id != TPM_ECC_NIST_P256)
@@ -271,31 +210,23 @@ CRYPT_RESULT _cpri__SignEcc(
switch (scheme) {
case TPM_ALG_ECDSA: {
- const UINT16 d_size = d->b.size;
-
- if (!check_p256_param_in_range(d))
+ if (!p256_from_be_bin_size(d->b.buffer, d->b.size, &key))
return CRYPT_PARAMETER;
+
/* Truncate / zero-pad the digest as appropriate. */
memset(digest_local, 0, sizeof(digest_local));
memcpy(digest_local + sizeof(digest_local) - digest_len,
- digest->buffer, digest_len);
+ digest->buffer, digest_len);
p256_from_bin(digest_local, &p256_digest);
- reverse_tpm2b(&d->b);
- append_zeros_to_p256_param(d);
-
- result = fips_p256_ecdsa_sign(
- (p256_int *) d->b.buffer,
- &p256_digest,
- (p256_int *) r->b.buffer,
- (p256_int *) s->b.buffer);
- d->b.size = d_size;
- reverse_tpm2b(&d->b);
+ result = fips_p256_ecdsa_sign(&key, &p256_digest, &p256_r,
+ &p256_s);
+ p256_clear(&key);
r->b.size = sizeof(p256_int);
s->b.size = sizeof(p256_int);
- reverse_tpm2b(&r->b);
- reverse_tpm2b(&s->b);
+ p256_to_bin(&p256_r, r->b.buffer);
+ p256_to_bin(&p256_s, s->b.buffer);
if (result)
return CRYPT_SUCCESS;
@@ -314,7 +245,7 @@ CRYPT_RESULT _cpri__ValidateSignatureEcc(
{
uint8_t digest_local[sizeof(p256_int)];
const size_t digest_len = MIN(digest->size, sizeof(digest_local));
- p256_int p256_digest;
+ p256_int p256_digest, q_x, q_y, p256_r, p256_s;
int result;
if (curve_id != TPM_ECC_NIST_P256)
@@ -322,43 +253,20 @@ CRYPT_RESULT _cpri__ValidateSignatureEcc(
switch (scheme) {
case TPM_ALG_ECDSA: {
- const UINT16 qx_size = q->x.b.size;
- const UINT16 qy_size = q->y.b.size;
- const UINT16 r_size = r->b.size;
- const UINT16 s_size = s->b.size;
+ if (!p256_from_be_bin_size(q->x.b.buffer, q->x.b.size, &q_x) ||
+ !p256_from_be_bin_size(q->y.b.buffer, q->y.b.size, &q_y) ||
+ !p256_from_be_bin_size(r->b.buffer, r->b.size, &p256_r) ||
+ !p256_from_be_bin_size(s->b.buffer, s->b.size, &p256_s))
+ return CRYPT_PARAMETER;
/* Truncate / zero-pad the digest as appropriate. */
memset(digest_local, 0, sizeof(digest_local));
memcpy(digest_local + sizeof(digest_local) - digest_len,
- digest->buffer, digest_len);
+ digest->buffer, digest_len);
p256_from_bin(digest_local, &p256_digest);
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
- append_zeros_to_p256_point(q);
-
- reverse_tpm2b(&r->b);
- append_zeros_to_p256_param(r);
-
- reverse_tpm2b(&s->b);
- append_zeros_to_p256_param(s);
-
- result = dcrypto_p256_ecdsa_verify(
- (p256_int *) q->x.b.buffer,
- (p256_int *) q->y.b.buffer,
- &p256_digest,
- (p256_int *) r->b.buffer,
- (p256_int *) s->b.buffer);
-
- /* restore original size */
- q->x.b.size = qx_size;
- q->y.b.size = qy_size;
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
- r->b.size = r_size;
- reverse_tpm2b(&r->b);
- s->b.size = s_size;
- reverse_tpm2b(&s->b);
+ result = dcrypto_p256_ecdsa_verify(&q_x, &q_y, &p256_digest,
+ &p256_r, &p256_s);
if (result)
return CRYPT_SUCCESS;
@@ -375,26 +283,26 @@ CRYPT_RESULT _cpri__GetEphemeralEcc(TPMS_ECC_POINT *q, TPM2B_ECC_PARAMETER *d,
{
int result;
uint8_t key_bytes[P256_NBYTES] __aligned(4);
+ p256_int x, y, key;
if (curve_id != TPM_ECC_NIST_P256)
return CRYPT_PARAMETER;
rand_bytes(key_bytes, sizeof(key_bytes));
- result = DCRYPTO_p256_key_from_bytes((p256_int *) q->x.b.buffer,
- (p256_int *) q->y.b.buffer,
- (p256_int *) d->b.buffer,
- key_bytes);
+ result = DCRYPTO_p256_key_from_bytes(&x, &y, &key, key_bytes);
+
always_memset(key_bytes, 0, sizeof(key_bytes));
if (result) {
q->x.b.size = sizeof(p256_int);
q->y.b.size = sizeof(p256_int);
- reverse_tpm2b(&q->x.b);
- reverse_tpm2b(&q->y.b);
+ p256_to_bin(&x, q->x.b.buffer);
+ p256_to_bin(&y, q->y.b.buffer);
d->b.size = sizeof(p256_int);
- reverse_tpm2b(&d->b);
+ p256_to_bin(&key, d->b.buffer);
+ p256_clear(&key);
return CRYPT_SUCCESS;
} else {
diff --git a/common/u2f.c b/common/u2f.c
index e5fe20371e..0795d88359 100644
--- a/common/u2f.c
+++ b/common/u2f.c
@@ -21,7 +21,6 @@
#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ##args)
-
size_t g2f_attestation_cert(uint8_t *buf)
{
uint8_t *serial;
@@ -34,7 +33,21 @@ size_t g2f_attestation_cert(uint8_t *buf)
if (system_get_chip_unique_id(&serial) != P256_NBYTES)
return 0;
- return g2f_attestation_cert_serial(state, serial, buf);
+#ifdef CHIP_G
+ /**
+ * chip/g implementation of system_get_chip_unique_id() always
+ * returns 32-bit aligned pointer, but host mock-ups do no guarantee
+ * that, so copy data to aligned location.
+ */
+ return g2f_attestation_cert_serial(state, (p256_int *)serial, buf);
+#else
+ {
+ p256_int p256_serial;
+
+ memcpy(&p256_serial, serial, sizeof(p256_serial));
+ return g2f_attestation_cert_serial(state, &p256_serial, buf);
+ }
+#endif
}
/* U2F GENERATE command */