summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYicheng Li <yichengli@chromium.org>2021-02-17 14:41:04 -0800
committerCommit Bot <commit-bot@chromium.org>2021-02-18 18:02:18 +0000
commit7e2f4d3004026f0633c18c17287192f4df124e79 (patch)
tree444f39395fed932a9c8feb38f6e6e20f8e3e8e70
parent19f4c3e2df6b36a225babecb0eabf19abe38c0a2 (diff)
downloadchrome-ec-7e2f4d3004026f0633c18c17287192f4df124e79.tar.gz
u2f: Move some u2f logic to common/ for testing
Since this is cr50's branch, there's no semantic difference whether we put logic in board/cr50/u2f.c or common/u2f.c. EC's build system doesn't quite allow unit-testing board-specific logic, so to unit-test some of the crypto logic in board/cr50/u2f.c, things need to move to common/u2f.c. There's no change in functionality. There should also be no problem for merging/cherry-picking ToT changes to cr50_stab, because any new u2f changes are made on cr50_stab only and not on ToT. BUG=b:172971998 TEST=make run-u2f TEST=make CR50_DEV=1 BOARD=cr50 Change-Id: I3cb8d78fd6427620a6fe20cef12708899d2896b5 Signed-off-by: Yicheng Li <yichengli@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2702496 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r--board/cr50/u2f.c79
-rw-r--r--common/u2f.c73
-rw-r--r--include/u2f_impl.h20
-rw-r--r--test/u2f.c40
4 files changed, 110 insertions, 102 deletions
diff --git a/board/cr50/u2f.c b/board/cr50/u2f.c
index 12af471ff9..750708012b 100644
--- a/board/cr50/u2f.c
+++ b/board/cr50/u2f.c
@@ -54,14 +54,6 @@ enum touch_state pop_check_presence(int consume)
return recent ? POP_TOUCH_YES : POP_TOUCH_NO;
}
-/* ---- non-volatile U2F state ---- */
-
-struct u2f_state {
- uint32_t salt[8];
- uint32_t salt_kek[8];
- uint32_t salt_kh[8];
-};
-
static const uint8_t k_salt = NVMEM_VAR_G2F_SALT;
static const uint8_t k_salt_deprecated = NVMEM_VAR_U2F_SALT;
@@ -138,7 +130,7 @@ static int load_state(struct u2f_state *state)
return 1;
}
-static struct u2f_state *get_state(void)
+struct u2f_state *get_state(void)
{
static int state_loaded;
static struct u2f_state state;
@@ -166,54 +158,6 @@ static int _derive_key(enum dcrypto_appid appid, const uint32_t input[8],
return result;
}
-int u2f_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
- const uint8_t *origin_seed,
- struct u2f_key_handle *key_handle)
-{
- LITE_HMAC_CTX ctx;
- struct u2f_state *state = get_state();
-
- if (!state)
- return EC_ERROR_UNKNOWN;
-
- memcpy(key_handle->origin_seed, origin_seed, P256_NBYTES);
-
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, origin, P256_NBYTES);
- HASH_update(&ctx.hash, user, P256_NBYTES);
- HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
-
- memcpy(key_handle->hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
-
- return EC_SUCCESS;
-}
-
-int u2f_origin_user_versioned_keyhandle(
- const uint8_t *origin, const uint8_t *user, const uint8_t *origin_seed,
- uint8_t version,
- struct u2f_versioned_key_handle_header *key_handle_header)
-{
- LITE_HMAC_CTX ctx;
- struct u2f_state *state = get_state();
-
- if (!state)
- return EC_ERROR_UNKNOWN;
-
- key_handle_header->version = version;
- memcpy(key_handle_header->origin_seed, origin_seed, P256_NBYTES);
-
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, origin, P256_NBYTES);
- HASH_update(&ctx.hash, user, P256_NBYTES);
- HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
- HASH_update(&ctx.hash, &version, sizeof(key_handle_header->version));
-
- memcpy(key_handle_header->kh_hmac, DCRYPTO_HMAC_final(&ctx),
- SHA256_DIGEST_SIZE);
-
- return EC_SUCCESS;
-}
-
int u2f_origin_user_keypair(const uint8_t *key_handle, size_t key_handle_size,
p256_int *d, p256_int *pk_x, p256_int *pk_y)
{
@@ -241,27 +185,6 @@ int u2f_origin_user_keypair(const uint8_t *key_handle, size_t key_handle_size,
return EC_SUCCESS;
}
-int u2f_authorization_hmac(const uint8_t *authorization_salt,
- const struct u2f_versioned_key_handle_header *header,
- const uint8_t *auth_time_secret_hash, uint8_t *hmac)
-{
- LITE_HMAC_CTX ctx;
- struct u2f_state *state = get_state();
-
- if (!state)
- return EC_ERROR_UNKNOWN;
-
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, authorization_salt, U2F_AUTHORIZATION_SALT_SIZE);
- HASH_update(&ctx.hash, (uint8_t *)header,
- sizeof(struct u2f_versioned_key_handle_header));
- HASH_update(&ctx.hash, auth_time_secret_hash, SHA256_DIGEST_SIZE);
-
- memcpy(hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
-
- return EC_SUCCESS;
-}
-
int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len)
{
uint32_t buf[P256_NDIGITS];
diff --git a/common/u2f.c b/common/u2f.c
index 936dd7f035..7a5b3e5945 100644
--- a/common/u2f.c
+++ b/common/u2f.c
@@ -264,8 +264,8 @@ static int verify_versioned_kh_owned(
BUILD_ASSERT(sizeof(struct u2f_sign_resp) <= sizeof(struct u2f_sign_req));
/* U2F SIGN command */
-static enum vendor_cmd_rc u2f_sign(enum vendor_cmd_cc code, void *buf,
- size_t input_size, size_t *response_size)
+enum vendor_cmd_rc u2f_sign(enum vendor_cmd_cc code, void *buf,
+ size_t input_size, size_t *response_size)
{
const struct u2f_sign_req *req = buf;
const struct u2f_sign_versioned_req *req_versioned = buf;
@@ -504,3 +504,72 @@ static enum vendor_cmd_rc u2f_attest(enum vendor_cmd_cc code, void *buf,
return VENDOR_RC_SUCCESS;
}
DECLARE_VENDOR_COMMAND(VENDOR_CC_U2F_ATTEST, u2f_attest);
+
+int u2f_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
+ const uint8_t *origin_seed,
+ struct u2f_key_handle *key_handle)
+{
+ LITE_HMAC_CTX ctx;
+ struct u2f_state *state = get_state();
+
+ if (!state)
+ return EC_ERROR_UNKNOWN;
+
+ memcpy(key_handle->origin_seed, origin_seed, P256_NBYTES);
+
+ DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HASH_update(&ctx.hash, origin, P256_NBYTES);
+ HASH_update(&ctx.hash, user, P256_NBYTES);
+ HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
+
+ memcpy(key_handle->hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+
+ return EC_SUCCESS;
+}
+
+int u2f_origin_user_versioned_keyhandle(
+ const uint8_t *origin, const uint8_t *user, const uint8_t *origin_seed,
+ uint8_t version,
+ struct u2f_versioned_key_handle_header *key_handle_header)
+{
+ LITE_HMAC_CTX ctx;
+ struct u2f_state *state = get_state();
+
+ if (!state)
+ return EC_ERROR_UNKNOWN;
+
+ key_handle_header->version = version;
+ memcpy(key_handle_header->origin_seed, origin_seed, P256_NBYTES);
+
+ DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HASH_update(&ctx.hash, origin, P256_NBYTES);
+ HASH_update(&ctx.hash, user, P256_NBYTES);
+ HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
+ HASH_update(&ctx.hash, &version, sizeof(key_handle_header->version));
+
+ memcpy(key_handle_header->kh_hmac, DCRYPTO_HMAC_final(&ctx),
+ SHA256_DIGEST_SIZE);
+
+ return EC_SUCCESS;
+}
+
+int u2f_authorization_hmac(const uint8_t *authorization_salt,
+ const struct u2f_versioned_key_handle_header *header,
+ const uint8_t *auth_time_secret_hash, uint8_t *hmac)
+{
+ LITE_HMAC_CTX ctx;
+ struct u2f_state *state = get_state();
+
+ if (!state)
+ return EC_ERROR_UNKNOWN;
+
+ DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HASH_update(&ctx.hash, authorization_salt, U2F_AUTHORIZATION_SALT_SIZE);
+ HASH_update(&ctx.hash, (uint8_t *)header,
+ sizeof(struct u2f_versioned_key_handle_header));
+ HASH_update(&ctx.hash, auth_time_secret_hash, SHA256_DIGEST_SIZE);
+
+ memcpy(hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+
+ return EC_SUCCESS;
+}
diff --git a/include/u2f_impl.h b/include/u2f_impl.h
index a2f2cfaa97..d3f4800387 100644
--- a/include/u2f_impl.h
+++ b/include/u2f_impl.h
@@ -33,6 +33,19 @@ enum touch_state {
*/
enum touch_state pop_check_presence(int consume);
+/* ---- non-volatile U2F state ---- */
+
+struct u2f_state {
+ uint32_t salt[8];
+ uint32_t salt_kek[8];
+ uint32_t salt_kh[8];
+};
+
+/**
+ * Get the current u2f state from the board.
+ */
+struct u2f_state *get_state(void);
+
/* ---- platform cryptography hooks ---- */
/**
@@ -145,4 +158,11 @@ int g2f_attestation_cert(uint8_t *buf);
enum vendor_cmd_rc u2f_generate(enum vendor_cmd_cc code, void *buf,
size_t input_size, size_t *response_size);
+/**
+ * U2F_SIGN command handler. Verifies a key handle is owned and signs data with
+ * it.
+ */
+enum vendor_cmd_rc u2f_sign(enum vendor_cmd_cc code, void *buf,
+ size_t input_size, size_t *response_size);
+
#endif /* __CROS_EC_U2F_IMPL_H */
diff --git a/test/u2f.c b/test/u2f.c
index 3d36ff1830..56ae0cf65e 100644
--- a/test/u2f.c
+++ b/test/u2f.c
@@ -65,11 +65,29 @@ void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
SHA256_init(ctx);
}
+void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
+ unsigned int len)
+{
+ SHA256_init(&ctx->hash);
+}
+
+const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
+{
+ return SHA256_final(&ctx->hash);
+}
+
/******************************************************************************/
/* Mock implementations of U2F functionality.
*/
static int presence;
+static struct u2f_state state;
+
+struct u2f_state *get_state(void)
+{
+ return &state;
+}
+
enum touch_state pop_check_presence(int consume)
{
enum touch_state ret = presence ?
@@ -80,21 +98,6 @@ enum touch_state pop_check_presence(int consume)
return ret;
}
-int u2f_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
- const uint8_t *seed,
- struct u2f_key_handle *key_handle)
-{
- return EC_SUCCESS;
-}
-
-int u2f_origin_user_versioned_keyhandle(
- const uint8_t *origin, const uint8_t *user, const uint8_t *seed,
- uint8_t version,
- struct u2f_versioned_key_handle_header *key_handle_header)
-{
- return EC_SUCCESS;
-}
-
int u2f_origin_user_keypair(const uint8_t *key_handle, size_t key_handle_size,
p256_int *d, p256_int *pk_x, p256_int *pk_y)
{
@@ -106,13 +109,6 @@ int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y)
return EC_SUCCESS;
}
-int u2f_authorization_hmac(const uint8_t *authorization_salt,
- const struct u2f_versioned_key_handle_header *header,
- const uint8_t *auth_time_secret_hash, uint8_t *hmac)
-{
- return EC_SUCCESS;
-}
-
/******************************************************************************/
/* Tests begin here.
*/