summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/host/dcrypto.h25
-rw-r--r--common/u2f.c10
-rw-r--r--include/u2f_impl.h13
-rw-r--r--test/build.mk2
-rw-r--r--test/test_config.h6
-rw-r--r--test/u2f.c173
-rw-r--r--test/u2f.tasklist9
7 files changed, 234 insertions, 4 deletions
diff --git a/board/host/dcrypto.h b/board/host/dcrypto.h
index 31f04e51aa..ce924e64fa 100644
--- a/board/host/dcrypto.h
+++ b/board/host/dcrypto.h
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-/* Provides the minimal declarations needed by pinweaver to build on
+/* Provides the minimal declarations needed by pinweaver and u2f to build on
* CHIP_HOST. While it might be preferable to simply use the original dcrypto.h,
* That would require incorporating additional headers / dependencies such as
* cryptoc.
@@ -73,6 +73,29 @@ void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx);
int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
uint32_t output[8]);
+#include "cryptoc/p256.h"
+
+int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x,
+ const p256_int *pk_y, const p256_int *serial,
+ const char *name, uint8_t *cert,
+ const int n);
+
+int DCRYPTO_ladder_random(void *output);
+
+#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))
+
+struct drbg_ctx {
+ uint32_t k[SHA256_DIGEST_WORDS];
+ uint32_t v[SHA256_DIGEST_WORDS];
+ uint32_t reseed_counter;
+};
+
+int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key,
+ const p256_int *message, p256_int *r, p256_int *s);
+
+void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key,
+ const p256_int *message);
+
#endif /* CONFIG_DCRYPTO_MOCK */
#endif /* __CROS_EC_HOST_DCRYPTO_H */
diff --git a/common/u2f.c b/common/u2f.c
index 5205809379..936dd7f035 100644
--- a/common/u2f.c
+++ b/common/u2f.c
@@ -7,7 +7,11 @@
#include "console.h"
#include "cryptoc/p256.h"
+
+#ifndef TEST_BUILD
#include "cryptoc/sha256.h"
+#endif
+
#include "dcrypto.h"
#include "extension.h"
#include "system.h"
@@ -79,8 +83,8 @@ static void copy_versioned_kh_pubkey_out(p256_int *opk_x, p256_int *opk_y,
}
/* U2F GENERATE command */
-static enum vendor_cmd_rc u2f_generate(enum vendor_cmd_cc code, void *buf,
- size_t input_size, size_t *response_size)
+enum vendor_cmd_rc u2f_generate(enum vendor_cmd_cc code, void *buf,
+ size_t input_size, size_t *response_size)
{
struct u2f_generate_req *req = buf;
uint8_t kh_version =
@@ -440,7 +444,7 @@ static enum vendor_cmd_rc u2f_attest(enum vendor_cmd_cc code, void *buf,
int verify_ret;
- HASH_CTX h_ctx;
+ struct HASH_CTX h_ctx;
struct drbg_ctx dr_ctx;
/* Data hash, and corresponding signature. */
diff --git a/include/u2f_impl.h b/include/u2f_impl.h
index fd2cc05ba1..a2f2cfaa97 100644
--- a/include/u2f_impl.h
+++ b/include/u2f_impl.h
@@ -9,7 +9,13 @@
#define __CROS_EC_U2F_IMPL_H
#include "common.h"
+
+#ifdef TEST_BUILD
+#include "board/host/dcrypto.h"
+#endif
+
#include "cryptoc/p256.h"
+#include "tpm_vendor_cmds.h"
#include "u2f.h"
/* ---- Physical presence ---- */
@@ -132,4 +138,11 @@ int u2f_gen_kek_seed(int commit);
*/
int g2f_attestation_cert(uint8_t *buf);
+/**
+ * U2F_GENERATE command handler. Generates a key handle according to input
+ * parameters.
+ */
+enum vendor_cmd_rc u2f_generate(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/build.mk b/test/build.mk
index ec40d00b95..ec51ab4bf9 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -48,6 +48,7 @@ test-list-host += static_if_error
test-list-host += system
test-list-host += thermal
test-list-host += timer_dos
+test-list-host += u2f
test-list-host += uptime
test-list-host += utils
test-list-host += utils_str
@@ -91,6 +92,7 @@ system-y=system.o
thermal-y=thermal.o
timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
+u2f-y=u2f.o
uptime-y=uptime.o
utils-y=utils.o
utils_str-y=utils_str.o
diff --git a/test/test_config.h b/test/test_config.h
index 75ca65a6c3..0a66429ef1 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -180,6 +180,12 @@ enum nvmem_users { NVMEM_TPM = 0, NVMEM_CR50, NVMEM_NUM_USERS };
#define CONFIG_HOSTCMD_RTC
#endif
+#ifdef TEST_U2F
+#define CONFIG_DCRYPTO_MOCK
+#define CONFIG_U2F
+#define CC_EXTENSION CC_COMMAND
+#endif
+
#ifdef TEST_VBOOT
#define CONFIG_RWSIG
#define CONFIG_SHA256
diff --git a/test/u2f.c b/test/u2f.c
new file mode 100644
index 0000000000..3d36ff1830
--- /dev/null
+++ b/test/u2f.c
@@ -0,0 +1,173 @@
+/* Copyright 2021 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.
+ */
+
+#include "test_util.h"
+#include "u2f_impl.h"
+
+/******************************************************************************/
+/* Mock implementations of cr50 board.
+ */
+int system_get_chip_unique_id(uint8_t **id)
+{
+ return P256_NBYTES;
+}
+
+/******************************************************************************/
+/* Mock implementations of Dcrypto functionality.
+ */
+int DCRYPTO_ladder_random(void *output)
+{
+ memset(output, 0, P256_NBYTES);
+ /* Return 1 for success, 0 for error. */
+ return 1;
+}
+
+int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x,
+ const p256_int *pk_y, const p256_int *serial,
+ const char *name, uint8_t *cert,
+ const int n)
+{
+ /* Return the size of certificate, 0 means error. */
+ return 0;
+}
+
+int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key,
+ const p256_int *message, p256_int *r, p256_int *s)
+{
+ memset(r, 0, sizeof(p256_int));
+ memset(s, 0, sizeof(p256_int));
+ /* Return 1 for success, 0 for error. */
+ return 1;
+}
+
+void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx,
+ const p256_int *key,
+ const p256_int *message)
+{
+ memset(ctx, 0, sizeof(struct drbg_ctx));
+}
+
+void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len)
+{
+ if (ctx)
+ SHA256_update(ctx, data, len);
+}
+
+uint8_t *HASH_final(struct HASH_CTX *ctx)
+{
+ return SHA256_final(ctx);
+}
+
+void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
+{
+ SHA256_init(ctx);
+}
+
+/******************************************************************************/
+/* Mock implementations of U2F functionality.
+ */
+static int presence;
+
+enum touch_state pop_check_presence(int consume)
+{
+ enum touch_state ret = presence ?
+ POP_TOUCH_YES : POP_TOUCH_NO;
+
+ if (consume)
+ presence = 0;
+ 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)
+{
+ return EC_SUCCESS;
+}
+
+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.
+ */
+static uint8_t buffer[512];
+
+test_static int test_u2f_generate_no_require_presence(void)
+{
+ struct u2f_generate_req *req = (struct u2f_generate_req *)buffer;
+ size_t response_size = sizeof(struct u2f_generate_resp);
+ int ret;
+
+ memset(buffer, 0, sizeof(buffer));
+ req->flags = 0;
+ presence = 0;
+ ret = u2f_generate(
+ VENDOR_CC_U2F_GENERATE, &buffer,
+ sizeof(struct u2f_generate_req),
+ &response_size);
+
+ TEST_ASSERT(ret == VENDOR_RC_SUCCESS);
+ return EC_SUCCESS;
+}
+
+test_static int test_u2f_generate_require_presence(void)
+{
+ struct u2f_generate_req *req = (struct u2f_generate_req *)buffer;
+ size_t response_size = sizeof(struct u2f_generate_resp);
+ int ret;
+
+ memset(buffer, 0, sizeof(buffer));
+ req->flags = U2F_AUTH_FLAG_TUP;
+ presence = 0;
+ ret = u2f_generate(
+ VENDOR_CC_U2F_GENERATE, &buffer,
+ sizeof(struct u2f_generate_req),
+ &response_size);
+ TEST_ASSERT(ret == VENDOR_RC_NOT_ALLOWED);
+
+ memset(buffer, 0, sizeof(buffer));
+ req->flags = U2F_AUTH_FLAG_TUP;
+ response_size = sizeof(struct u2f_generate_resp);
+ presence = 1;
+ ret = u2f_generate(
+ VENDOR_CC_U2F_GENERATE, &buffer,
+ sizeof(struct u2f_generate_req),
+ &response_size);
+ TEST_ASSERT(ret == VENDOR_RC_SUCCESS);
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ RUN_TEST(test_u2f_generate_no_require_presence);
+ RUN_TEST(test_u2f_generate_require_presence);
+
+ test_print_result();
+}
diff --git a/test/u2f.tasklist b/test/u2f.tasklist
new file mode 100644
index 0000000000..299cf25390
--- /dev/null
+++ b/test/u2f.tasklist
@@ -0,0 +1,9 @@
+/* Copyright 2021 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.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST