diff options
Diffstat (limited to 'board/cr50/u2f.c')
-rw-r--r-- | board/cr50/u2f.c | 708 |
1 files changed, 161 insertions, 547 deletions
diff --git a/board/cr50/u2f.c b/board/cr50/u2f.c index 78bc25c01f..43082d5008 100644 --- a/board/cr50/u2f.c +++ b/board/cr50/u2f.c @@ -3,179 +3,181 @@ * found in the LICENSE file. */ -#if defined(CRYPTO_TEST_SETUP) || defined(CR50_DEV) -#include "console.h" -#endif +/* Helpers to emulate a U2F HID dongle over the TPM transport */ +#include "console.h" #include "dcrypto.h" -#include "fips_rand.h" - -#include "u2f_cmds.h" +#include "extension.h" +#include "nvmem_vars.h" +#include "rbox.h" +#include "registers.h" +#include "signed_header.h" +#include "system.h" +#include "tpm_nvmem_ops.h" +#include "tpm_vendor_cmds.h" +#include "u2f.h" #include "u2f_impl.h" #include "util.h" -enum ec_error_list u2f_generate_hmac_key(struct u2f_state *state) -{ - /* HMAC key for key handle. */ - if (!fips_rand_bytes(state->hmac_key, sizeof(state->hmac_key))) - return EC_ERROR_HW_INTERNAL; - return EC_SUCCESS; -} +#define CPRINTS(format, args...) cprints(CC_EXTENSION, format, ## args) -enum ec_error_list u2f_generate_drbg_entropy(struct u2f_state *state) -{ - state->drbg_entropy_size = 0; - /* Get U2F entropy from health-checked TRNG. */ - if (!fips_trng_bytes(state->drbg_entropy, sizeof(state->drbg_entropy))) - return EC_ERROR_HW_INTERNAL; - state->drbg_entropy_size = sizeof(state->drbg_entropy); - return EC_SUCCESS; -} +/* ---- physical presence (using the laptop power button) ---- */ -enum ec_error_list u2f_generate_g2f_secret(struct u2f_state *state) +static timestamp_t last_press; + +/* how long do we keep the last button press as valid presence */ +#define PRESENCE_TIMEOUT (10 * SECOND) + +void power_button_record(void) { - /* G2F specific path. */ - if (!fips_rand_bytes(state->salt, sizeof(state->salt))) - return EC_ERROR_HW_INTERNAL; - return EC_SUCCESS; + if (ap_is_on() && rbox_powerbtn_is_pressed()) { + last_press = get_time(); +#ifdef CR50_DEV + CPRINTS("record pp"); +#endif + } } -/* Compute Key handle's HMAC. */ -static void u2f_origin_user_mac(const struct u2f_state *state, - const uint8_t *user, const uint8_t *origin, - const uint8_t *origin_seed, uint8_t kh_version, - uint8_t *kh_hmac) +enum touch_state pop_check_presence(int consume) { - struct hmac_sha256_ctx ctx; - - /* HMAC(u2f_hmac_key, origin || user || origin seed || version) */ - - HMAC_SHA256_hw_init(&ctx, state->hmac_key, SHA256_DIGEST_SIZE); - HMAC_SHA256_update(&ctx, origin, U2F_APPID_SIZE); - HMAC_SHA256_update(&ctx, user, U2F_USER_SECRET_SIZE); - HMAC_SHA256_update(&ctx, origin_seed, U2F_ORIGIN_SEED_SIZE); - if (kh_version != 0) - HMAC_SHA256_update(&ctx, &kh_version, sizeof(kh_version)); -#ifdef CR50_DEV_U2F_VERBOSE - ccprintf("origin %ph\n", HEX_BUF(origin, U2F_APPID_SIZE)); - ccprintf("user %ph\n", HEX_BUF(user, U2F_USER_SECRET_SIZE)); - ccprintf("origin_seed %ph\n", - HEX_BUF(origin_seed, U2F_ORIGIN_SEED_SIZE)); - cflush(); +#ifdef CRYPTO_TEST_SETUP + return POP_TOUCH_YES; +#else + int recent = ((last_press.val > 0) && + ((get_time().val - last_press.val) < PRESENCE_TIMEOUT)); + +#ifdef CR50_DEV + if (recent) + CPRINTS("User presence: consumed %d", consume); #endif - memcpy(kh_hmac, HMAC_SHA256_final(&ctx), SHA256_DIGEST_SIZE); -#ifdef CR50_DEV_U2F_VERBOSE - ccprintf("kh_hmac %ph\n", HEX_BUF(kh_hmac, SHA256_DIGEST_SIZE)); - cflush(); + if (consume) + last_press.val = 0; + + /* user physical presence on the power button */ + return recent ? POP_TOUCH_YES : POP_TOUCH_NO; #endif } -static void u2f_authorization_mac(const struct u2f_state *state, - const union u2f_key_handle_variant *kh, - uint8_t kh_version, - const uint8_t *auth_time_secret_hash, - uint8_t *kh_auth_mac) +static const uint8_t k_salt = NVMEM_VAR_G2F_SALT; +static const uint8_t k_salt_deprecated = NVMEM_VAR_U2F_SALT; + +static int load_state(struct u2f_state *state) { - struct hmac_sha256_ctx ctx; - const uint8_t *auth_salt = NULL; - const void *kh_header = NULL; - size_t kh_header_size = 0; - - if (kh_version == 0) { - memset(kh_auth_mac, 0xff, SHA256_DIGEST_SIZE); - return; + const struct tuple *t_salt = getvar(&k_salt, sizeof(k_salt)); + + if (!t_salt) { + /* Delete the old salt if present, no-op if not. */ + if (setvar(&k_salt_deprecated, sizeof(k_salt_deprecated), + NULL, 0)) + return 0; + + /* create random salt */ + if (!DCRYPTO_ladder_random(state->salt)) + return 0; + if (setvar(&k_salt, sizeof(k_salt), + (const uint8_t *)state->salt, sizeof(state->salt))) + return 0; + } else { + memcpy(state->salt, tuple_val(t_salt), sizeof(state->salt)); + freevar(t_salt); + } + + if (read_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, sizeof(state->salt_kek), + state->salt_kek) == TPM_READ_NOT_FOUND) { + /* + * Not found means that we have not used u2f before, + * or not used it with updated fw that resets kek seed + * on TPM clear. + */ + if (t_salt) { /* Note that memory has been freed already!. */ + /* + * We have previously used u2f, and may have + * existing registrations; we don't want to + * invalidate these, so preserve the existing + * seed as a one-off. It will be changed on + * next TPM clear. + */ + memcpy(state->salt_kek, state->salt, + sizeof(state->salt_kek)); + } else { + /* + * We have never used u2f before - generate + * new seed. + */ + if (!DCRYPTO_ladder_random(state->salt_kek)) + return 0; + } + if (write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, + sizeof(state->salt_kek), + state->salt_kek, + 1 /* commit */) != TPM_WRITE_CREATED) + return 0; } - /* At some point we may have v2 key handle, so prepare for it. */ - if (kh_version == 1) { - auth_salt = kh->v1.authorization_salt; - kh_header = &kh->v1; - kh_header_size = U2F_V1_KH_HEADER_SIZE; + + if (read_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KH_SALT, + sizeof(state->salt_kh), + state->salt_kh) == TPM_READ_NOT_FOUND) { + /* + * We have never used u2f before - generate + * new seed. + */ + if (!DCRYPTO_ladder_random(state->salt_kh)) + return 0; + + if (write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KH_SALT, + sizeof(state->salt_kh), + state->salt_kh, + 1 /* commit */) != TPM_WRITE_CREATED) + return 0; } - /** - * HMAC(u2f_hmac_key, auth_salt || key_handle_header - * || authTimeSecret) - */ - HMAC_SHA256_hw_init(&ctx, state->hmac_key, SHA256_DIGEST_SIZE); - HMAC_SHA256_update(&ctx, auth_salt, U2F_AUTHORIZATION_SALT_SIZE); - HMAC_SHA256_update(&ctx, kh_header, kh_header_size); + return 1; +} + +struct u2f_state *get_state(void) +{ + static int state_loaded; + static struct u2f_state state; - HMAC_SHA256_update(&ctx, auth_time_secret_hash, - U2F_AUTH_TIME_SECRET_SIZE); + if (!state_loaded) + state_loaded = load_state(&state); - memcpy(kh_auth_mac, HMAC_SHA256_final(&ctx), SHA256_DIGEST_SIZE); + return state_loaded ? &state : NULL; } -static int app_hw_device_id(enum dcrypto_appid appid, const uint32_t input[8], - uint32_t output[8]) +/* ---- chip-specific U2F crypto ---- */ + +static int _derive_key(enum dcrypto_appid appid, const uint32_t input[8], + uint32_t output[8]) { struct APPKEY_CTX ctx; int result; - /** - * Setup USR-based application key. This loads (if not already done) - * application-specific DeviceID. - * Internally it computes: - * HMAC(hw_device_id, SHA256(name[appid])), but we don't care about - * process. - * Important property: - * For same appid it will load same value. - */ + /* Setup USR-based application key. */ if (!DCRYPTO_appkey_init(appid, &ctx)) return 0; - - /** - * Compute HMAC(HMAC(hw_device_id, SHA256(name[appid])), input) - * It is not used as a key though, and treated as personalization - * string for DRBG. - */ result = DCRYPTO_appkey_derive(appid, input, output); DCRYPTO_appkey_finish(&ctx); return result; } -/** - * Generate an origin and user-specific ECDSA key pair from the specified - * key handle. - * - * If pk_x and pk_y are NULL, public key generation will be skipped. - * - * @param state U2F state parameters - * @param kh key handle - * @param kh_version key handle version (0 - legacy, 1 - versioned) - * @param d pointer to ECDSA private key - * @param pk_x pointer to public key point - * @param pk_y pointer to public key point - * - * @return EC_SUCCESS if a valid key pair was created. - */ -static enum ec_error_list u2f_origin_user_key_pair( - const struct u2f_state *state, const union u2f_key_handle_variant *kh, - uint8_t kh_version, p256_int *d, p256_int *pk_x, p256_int *pk_y) +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) { uint32_t dev_salt[P256_NDIGITS]; uint8_t key_seed[P256_NBYTES]; struct drbg_ctx drbg; - size_t key_handle_size = 0; - uint8_t *key_handle = NULL; - - if (kh_version == 0) { - key_handle_size = sizeof(struct u2f_key_handle_v0); - key_handle = (uint8_t *)&kh->v0; - } else if ((kh_version == 1) && (kh->v1.version == kh_version)) { - key_handle_size = U2F_V1_KH_HEADER_SIZE; - key_handle = (uint8_t *)&kh->v1; - } else { - return EC_ERROR_INVAL; - } + struct u2f_state *state = get_state(); - /* TODO(sukhomlinov): implement new FIPS path. */ - if (!app_hw_device_id(U2F_ORIGIN, state->hmac_key, dev_salt)) + if (!state) return EC_ERROR_UNKNOWN; - hmac_drbg_init(&drbg, state->drbg_entropy, P256_NBYTES, dev_salt, + if (!_derive_key(U2F_ORIGIN, state->salt_kek, dev_salt)) + return EC_ERROR_UNKNOWN; + + hmac_drbg_init(&drbg, state->salt_kh, P256_NBYTES, dev_salt, P256_NBYTES, NULL, 0); hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed), key_handle, @@ -184,243 +186,41 @@ static enum ec_error_list u2f_origin_user_key_pair( if (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, key_seed)) return EC_ERROR_TRY_AGAIN; -#ifdef CR50_DEV_U2F_VERBOSE - ccprintf("user private key %ph\n", HEX_BUF(d, sizeof(*d))); - cflush(); - if (pk_x) - ccprintf("user public x %ph\n", HEX_BUF(pk_x, sizeof(*pk_x))); - if (pk_y) - ccprintf("user public y %ph\n", HEX_BUF(pk_y, sizeof(*pk_y))); - cflush(); -#endif - return EC_SUCCESS; } -enum ec_error_list u2f_generate(const struct u2f_state *state, - const uint8_t *user, const uint8_t *origin, - const uint8_t *authTimeSecretHash, - union u2f_key_handle_variant *kh, - uint8_t kh_version, struct u2f_ec_point *pubKey) +int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len) { - uint8_t *kh_hmac, *kh_origin_seed; - int generate_key_pair_rc; - /* Generated public keys associated with key handle. */ - p256_int opk_x, opk_y; - - /* Compute constants for request key handler version. */ - if (kh_version == 0) { - kh_hmac = kh->v0.hmac; - kh_origin_seed = kh->v0.origin_seed; - } else if (kh_version == 1) { - kh_hmac = kh->v1.kh_hmac; - kh_origin_seed = kh->v1.origin_seed; - /** - * This may overwrite input parameters if shared - * request/response buffer is used by caller. - */ - kh->v1.version = kh_version; - } else - return EC_ERROR_INVAL; - - /* Generate key handle candidates and origin-specific key pair. */ - do { - p256_int od; - /* Generate random origin seed for key handle candidate. */ - if (!fips_rand_bytes(kh_origin_seed, U2F_ORIGIN_SEED_SIZE)) - return EC_ERROR_HW_INTERNAL; - - u2f_origin_user_mac(state, user, origin, kh_origin_seed, - kh_version, kh_hmac); - - /** - * Try to generate key pair using key handle. This may fail if - * key handle results in private key which is out of allowed - * range. If this is the case, repeat with another origin seed. - */ - generate_key_pair_rc = u2f_origin_user_key_pair( - state, kh, kh_version, &od, &opk_x, &opk_y); - - p256_clear(&od); - } while (generate_key_pair_rc == EC_ERROR_TRY_AGAIN); + uint32_t buf[P256_NDIGITS]; - if (generate_key_pair_rc != EC_SUCCESS) - return generate_key_pair_rc; + struct u2f_state *state = get_state(); - if (kh_version == 1) { - if (!fips_rand_bytes(kh->v1.authorization_salt, - U2F_AUTHORIZATION_SALT_SIZE)) - return EC_ERROR_HW_INTERNAL; - - u2f_authorization_mac(state, kh, kh_version, authTimeSecretHash, - kh->v1.authorization_hmac); - } + if (!state) + return EC_ERROR_UNKNOWN; - pubKey->pointFormat = U2F_POINT_UNCOMPRESSED; - p256_to_bin(&opk_x, pubKey->x); /* endianness */ - p256_to_bin(&opk_y, pubKey->y); /* endianness */ + if (key_len != sizeof(buf)) + return EC_ERROR_UNKNOWN; + if (!_derive_key(U2F_WRAP, state->salt_kek, buf)) + return EC_ERROR_UNKNOWN; + memcpy(kek, buf, key_len); return EC_SUCCESS; } -enum ec_error_list u2f_authorize_keyhandle( - const struct u2f_state *state, const union u2f_key_handle_variant *kh, - uint8_t kh_version, const uint8_t *user, const uint8_t *origin, - const uint8_t *authTimeSecretHash) -{ - /* Re-created key handle. */ - uint8_t recreated_hmac[SHA256_DIGEST_SIZE]; - const uint8_t *origin_seed, *kh_hmac; - int result = 0; - - /* - * Re-create the key handle and compare against that which - * was provided. This allows us to verify that the key handle - * is owned by this combination of device, current user and origin. - */ - if (kh_version == 0) { - origin_seed = kh->v0.origin_seed; - kh_hmac = kh->v0.hmac; - } else { - origin_seed = kh->v1.origin_seed; - kh_hmac = kh->v1.kh_hmac; - } - /* First, check inner part. */ - u2f_origin_user_mac(state, user, origin, origin_seed, kh_version, - recreated_hmac); - - /** - * DCRYPTO_equals return 1 if success, by subtracting 1 we make it - * zero, and other results - zero or non-zero will be detected. - */ - result |= DCRYPTO_equals(&recreated_hmac, kh_hmac, - sizeof(recreated_hmac)) - - 1; - - always_memset(recreated_hmac, 0, sizeof(recreated_hmac)); - - if ((kh_version != 0) && (authTimeSecretHash != NULL)) { - u2f_authorization_mac(state, kh, kh_version, authTimeSecretHash, - recreated_hmac); - result |= DCRYPTO_equals(&recreated_hmac, - kh->v1.authorization_hmac, - sizeof(recreated_hmac)) - - 1; - always_memset(recreated_hmac, 0, sizeof(recreated_hmac)); - } - - return (result == 0) ? EC_SUCCESS : EC_ERROR_ACCESS_DENIED; -} - -static enum ec_error_list -u2f_attest_keyhandle_pubkey(const struct u2f_state *state, - const union u2f_key_handle_variant *key_handle, - uint8_t kh_version, const uint8_t *user, - const uint8_t *origin, - const uint8_t *authTimeSecretHash, - const struct u2f_ec_point *public_key) -{ - struct u2f_ec_point kh_pubkey; - p256_int od, opk_x, opk_y; - enum ec_error_list result; - - /* Check this is a correct key handle for provided user/origin. */ - result = u2f_authorize_keyhandle(state, key_handle, kh_version, user, - origin, authTimeSecretHash); - - if (result != EC_SUCCESS) - return result; - - /* Recreate public key from key handle. */ - result = u2f_origin_user_key_pair(state, key_handle, kh_version, &od, - &opk_x, &opk_y); - if (result != EC_SUCCESS) - return result; - - p256_clear(&od); - /* Reconstruct the public key. */ - p256_to_bin(&opk_x, kh_pubkey.x); - p256_to_bin(&opk_y, kh_pubkey.y); - kh_pubkey.pointFormat = U2F_POINT_UNCOMPRESSED; - -#ifdef CR50_DEV_U2F_VERBOSE - ccprintf("recreated key %ph\n", HEX_BUF(&kh_pubkey, sizeof(kh_pubkey))); - ccprintf("provided key %ph\n", HEX_BUF(public_key, sizeof(kh_pubkey))); -#endif - return (DCRYPTO_equals(&kh_pubkey, public_key, - sizeof(struct u2f_ec_point)) == 1) ? - EC_SUCCESS : - EC_ERROR_ACCESS_DENIED; -} - -enum ec_error_list u2f_sign(const struct u2f_state *state, - const union u2f_key_handle_variant *kh, - uint8_t kh_version, const uint8_t *user, - const uint8_t *origin, - const uint8_t *authTimeSecretHash, - const uint8_t *hash, struct u2f_signature *sig) +int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y) { - /* Origin private key. */ - p256_int origin_d; - - /* Hash, and corresponding signature. */ - p256_int h, r, s; - - struct drbg_ctx ctx; - enum ec_error_list result; - - result = u2f_authorize_keyhandle(state, kh, kh_version, user, origin, - authTimeSecretHash); - - if (result != EC_SUCCESS) - return result; - - /* Re-create origin-specific key. */ - result = u2f_origin_user_key_pair(state, kh, kh_version, &origin_d, - NULL, NULL); - if (result != EC_SUCCESS) - return result; - - /* Prepare hash to sign. */ - p256_from_bin(hash, &h); - - /* Now, we processed input parameters, so clean-up output. */ - memset(sig, 0, sizeof(*sig)); - - /* Sign. */ - hmac_drbg_init_rfc6979(&ctx, &origin_d, &h); - result = (dcrypto_p256_ecdsa_sign(&ctx, &origin_d, &h, &r, &s) != 0) ? - EC_SUCCESS : - EC_ERROR_HW_INTERNAL; - - p256_clear(&origin_d); - - p256_to_bin(&r, sig->sig_r); - p256_to_bin(&s, sig->sig_s); + uint8_t buf[SHA256_DIGEST_SIZE]; - return result; -} + struct u2f_state *state = get_state(); -/** - * Generate a hardware derived ECDSA key pair for individual attestation. - * - * @param state U2F state parameters - * @param d pointer to ECDSA private key - * @param pk_x pointer to public key point - * @param pk_y pointer to public key point - * - * @return true if a valid key pair was created. - */ -static bool g2f_individual_key_pair(const struct u2f_state *state, p256_int *d, - p256_int *pk_x, p256_int *pk_y) -{ - uint8_t buf[SHA256_DIGEST_SIZE]; + if (!state) + return EC_ERROR_UNKNOWN; - /* Incorporate HIK & diversification constant. */ - if (!app_hw_device_id(U2F_ATTEST, state->salt, (uint32_t *)buf)) - return false; + /* Incorporate HIK & diversification constant */ + if (!_derive_key(U2F_ATTEST, state->salt, (uint32_t *)buf)) + return EC_ERROR_UNKNOWN; - /* Generate unbiased private key (non-FIPS path). */ + /* Generate unbiased private key */ while (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, buf)) { struct sha256_ctx sha; @@ -429,208 +229,22 @@ static bool g2f_individual_key_pair(const struct u2f_state *state, p256_int *d, memcpy(buf, SHA256_final(&sha), sizeof(buf)); } - return true; -} - -#define G2F_CERT_NAME "CrO2" - -size_t g2f_attestation_cert_serial(const struct u2f_state *state, - const uint8_t *serial, uint8_t *buf) -{ - p256_int d, pk_x, pk_y; - - if (g2f_individual_key_pair(state, &d, &pk_x, &pk_y)) - 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, - G2F_ATTESTATION_CERT_MAX_LEN); + return EC_SUCCESS; } -enum ec_error_list u2f_attest(const struct u2f_state *state, - const union u2f_key_handle_variant *kh, - uint8_t kh_version, const uint8_t *user, - const uint8_t *origin, - const uint8_t *authTimeSecretHash, - const struct u2f_ec_point *public_key, - const uint8_t *data, size_t data_size, - struct u2f_signature *sig) +int u2f_gen_kek_seed(int commit) { - struct sha256_ctx h_ctx; - struct drbg_ctx dr_ctx; - - /* Data hash, and corresponding signature. */ - p256_int h, r, s; + struct u2f_state *state = get_state(); - /* Attestation key. */ - p256_int d, pk_x, pk_y; - - enum ec_error_list result; - - result = u2f_attest_keyhandle_pubkey(state, kh, kh_version, user, - origin, authTimeSecretHash, - public_key); - - if (result != EC_SUCCESS) - return result; + if (!state) + return EC_ERROR_UNKNOWN; - /* Derive G2F Attestation Key. */ - if (!g2f_individual_key_pair(state, &d, &pk_x, &pk_y)) { -#ifdef CR50_DEV - ccprintf("G2F Attestation key generation failed\n"); -#endif + if (!DCRYPTO_ladder_random(state->salt_kek)) return EC_ERROR_HW_INTERNAL; - } - - /* Message signature. */ - SHA256_hw_init(&h_ctx); - SHA256_update(&h_ctx, data, data_size); - p256_from_bin(SHA256_final(&h_ctx)->b8, &h); - - /* Now, we processed input parameters, so clean-up output. */ - memset(sig, 0, sizeof(*sig)); - - /* Sign over the response w/ the attestation key. */ - hmac_drbg_init_rfc6979(&dr_ctx, &d, &h); - - result = (dcrypto_p256_ecdsa_sign(&dr_ctx, &d, &h, &r, &s) != 0) ? - EC_SUCCESS : - EC_ERROR_HW_INTERNAL; - p256_clear(&d); - p256_to_bin(&r, sig->sig_r); - p256_to_bin(&s, sig->sig_s); - - return result; -} - -#ifdef CRYPTO_TEST_SETUP -static const char *expect_bool(enum ec_error_list value, - enum ec_error_list expect) -{ - if (value == expect) - return "PASSED"; - return "NOT PASSED"; -} + if (write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, sizeof(state->salt_kek), + state->salt_kek, commit) == TPM_WRITE_FAIL) + return EC_ERROR_UNKNOWN; -static int cmd_u2f_test(int argc, char **argv) -{ - static struct u2f_state state; - static union u2f_key_handle_variant kh; - static const uint8_t origin[32] = { 0xff, 0xfe, 0xfd, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8 }; - static const uint8_t user[32] = { 0x88, 0x8e, 0x8d, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7 }; - static const uint8_t authTime[32] = { 0x99, 0x91, 2, 3, 4, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5 }; - static struct u2f_ec_point pubKey; - static struct u2f_signature sig; - - ccprintf("u2f_generate_hmac_key - %s\n", - expect_bool(u2f_generate_hmac_key(&state), EC_SUCCESS)); - - ccprintf("u2f_generate_g2f_secret - %s\n", - expect_bool(u2f_generate_g2f_secret(&state), EC_SUCCESS)); - - ccprintf("u2f_generate_drbg_entropy - %s\n", - expect_bool(u2f_generate_drbg_entropy(&state), EC_SUCCESS)); - - /* Version 0 key handle. */ - ccprintf("u2f_generate - %s\n", - expect_bool(u2f_generate(&state, user, origin, authTime, &kh, - 0, &pubKey), - EC_SUCCESS)); - ccprintf("kh: %ph\n", HEX_BUF(&kh, sizeof(kh.v0))); - ccprintf("pubKey: %ph\n", HEX_BUF(&pubKey, sizeof(pubKey))); - - ccprintf("u2f_authorize_keyhandle - %s\n", - expect_bool(u2f_authorize_keyhandle(&state, &kh, 0, user, - origin, authTime), - EC_SUCCESS)); - - kh.v0.origin_seed[0] ^= 0x10; - ccprintf("u2f_authorize_keyhandle - %s\n", - expect_bool(u2f_authorize_keyhandle(&state, &kh, 0, user, - origin, authTime), - EC_ERROR_ACCESS_DENIED)); - - kh.v0.origin_seed[0] ^= 0x10; - ccprintf("u2f_sign - %s\n", - expect_bool(u2f_sign(&state, &kh, 0, user, origin, authTime, - authTime, &sig), - EC_SUCCESS)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - ccprintf("u2f_attest - %s\n", - expect_bool(u2f_attest(&state, &kh, 0, user, origin, authTime, - &pubKey, authTime, sizeof(authTime), - &sig), - EC_SUCCESS)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - /* Should fail with incorrect key handle. */ - kh.v0.origin_seed[0] ^= 0x10; - ccprintf("u2f_sign - %s\n", - expect_bool(u2f_sign(&state, &kh, 0, user, origin, authTime, - authTime, &sig), - EC_ERROR_ACCESS_DENIED)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - /* Version 1 key handle. */ - ccprintf("\nVersion 1 tests\n"); - ccprintf("u2f_generate - %s\n", - expect_bool(u2f_generate(&state, user, origin, authTime, &kh, - 1, &pubKey), - EC_SUCCESS)); - ccprintf("kh: %ph\n", HEX_BUF(&kh, sizeof(kh.v1))); - ccprintf("pubKey: %ph\n", HEX_BUF(&pubKey, sizeof(pubKey))); - - ccprintf("u2f_authorize_keyhandle - %s\n", - expect_bool(u2f_authorize_keyhandle(&state, &kh, 1, user, - origin, authTime), - EC_SUCCESS)); - - kh.v1.authorization_salt[0] ^= 0x10; - ccprintf("u2f_authorize_keyhandle - %s\n", - expect_bool(u2f_authorize_keyhandle(&state, &kh, 1, user, - origin, authTime), - EC_ERROR_ACCESS_DENIED)); - - kh.v1.authorization_salt[0] ^= 0x10; - ccprintf("u2f_sign - %s\n", - expect_bool(u2f_sign(&state, &kh, 1, user, origin, authTime, - authTime, &sig), - EC_SUCCESS)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - ccprintf("u2f_attest - %s\n", - expect_bool(u2f_attest(&state, &kh, 1, user, origin, authTime, - &pubKey, authTime, sizeof(authTime), - &sig), - EC_SUCCESS)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - /* Should fail with incorrect key handle. */ - kh.v1.origin_seed[0] ^= 0x10; - ccprintf("u2f_sign - %s\n", - expect_bool(u2f_sign(&state, &kh, 1, user, origin, authTime, - authTime, &sig), - EC_ERROR_ACCESS_DENIED)); - ccprintf("sig: %ph\n", HEX_BUF(&sig, sizeof(sig))); - - cflush(); - - return 0; + return EC_SUCCESS; } - -DECLARE_SAFE_CONSOLE_COMMAND(u2f_test, cmd_u2f_test, NULL, - "Test U2F functionality"); - -#endif |