/* Copyright 2017 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. */ /* U2F implementation-specific callbacks and parameters. */ #ifndef __CROS_EC_U2F_IMPL_H #define __CROS_EC_U2F_IMPL_H #include "common.h" #include "dcrypto.h" #include "u2f.h" /* ---- platform cryptography hooks ---- */ /* ---- non-volatile U2F state, shared with common code ---- */ struct u2f_state { /* G2F key gen seed. */ uint32_t salt[8]; /* HMAC key for U2F key handle authentication. */ uint32_t hmac_key[SHA256_DIGEST_SIZE / sizeof(uint32_t)]; /* Stored DRBG entropy. */ uint32_t drbg_entropy[16]; size_t drbg_entropy_size; }; /* Make sure common declaration is compatible. */ BUILD_ASSERT(U2F_EC_KEY_SIZE == P256_NBYTES); BUILD_ASSERT(sizeof(struct u2f_ec_point) == U2F_EC_POINT_SIZE); BUILD_ASSERT(sizeof(struct u2f_key_handle_v0) <= U2F_MAX_KH_SIZE); BUILD_ASSERT(sizeof(struct u2f_key_handle_v0) == U2F_V0_KH_SIZE); BUILD_ASSERT(sizeof(struct u2f_key_handle_v1) <= U2F_MAX_KH_SIZE); BUILD_ASSERT(sizeof(struct u2f_key_handle_v1) == U2F_V1_KH_SIZE); BUILD_ASSERT(sizeof(union u2f_key_handle_variant) <= U2F_MAX_KH_SIZE); /** * Create or update DRBG entropy in U2F state. Used when changing ownership * to cryptographically discard previously generated keys. * * @param state u2f state to update * * @return EC_SUCCESS if successful */ enum ec_error_list u2f_generate_drbg_entropy(struct u2f_state *state); /** * Create or update HMAC key in U2F state. Used when changing ownership to * cryptographically discard previously generated keys. * * @param state u2f state to update * * @return EC_SUCCESS if successful */ enum ec_error_list u2f_generate_hmac_key(struct u2f_state *state); /** * Create or update G2F secret in U2F state. * * @param state u2f state to update * * @return EC_SUCCESS if successful */ enum ec_error_list u2f_generate_g2f_secret(struct u2f_state *state); /** * Create a randomized key handle for specified origin, user secret. * Generate associated signing key. * * @param state initialized u2f state * @param origin pointer to origin id * @param user pointer to user secret * @param authTimeSecretHash authentication time secret * @param kh output key handle header * @param kh_version - key handle version to generate * @param pubKey - generated public key * * @return EC_SUCCESS if successful */ 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); /** * Create a randomized key handle for specified origin, user secret. * Generate associated signing key. * * @param state initialized u2f state * @param kh output key handle header * @param kh_version - key handle version to generate * @param origin pointer to origin id * @param user pointer to user secret * @param authTimeSecretHash pointer to user's authentication secret. * can be set to NULL if authorization_hmac check is not needed. * @param r - generated part of signature * @param s - generated part of signature * * @return EC_SUCCESS if a valid key pair was created * EC_ACCESS_DENIED if key handle can't authenticated */ 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); /** * Verify that key handle matches provided origin, user and user's * authentication secret and was created on this device (signed with * U2F state HMAC key). * * @param state initialized u2f state * @param kh input key handle * @param kh_version - key handle version to verify * @param user pointer to user secret * @param origin pointer to origin id * @param authTimeSecretHash pointer to user's authentication secret. * can be set to NULL if authorization_hmac check is not needed. * * @return EC_SUCCESS if handle can be authenticated */ 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); /** * Gets the x509 certificate for the attestation key pair returned * by g2f_individual_keypair(). * * @param state U2F state parameters * @param serial Device serial number * @param buf pointer to a buffer that must be at least * * G2F_ATTESTATION_CERT_MAX_LEN bytes. * @return size of certificate written to buf, 0 on error. */ size_t g2f_attestation_cert_serial(const struct u2f_state *state, const p256_int *serial, uint8_t *buf); /** * Verify that provided key handle and public key match. * @param state U2F state parameters * @param key_handle key handle * @param kh_version key handle version (0 - legacy, 1 - versioned) * @param user pointer to user secret * @param origin pointer to origin id * @param authTimeSecretHash pointer to user's authentication secret. * can be set to NULL if authorization_hmac check is not needed. * @param public_key pointer to public key point (big endian) * @param data data to sign * @param data_size data size in bytes * * @param r part of generated signature * @param s part of generated signature * * @return EC_SUCCESS if public key matches key handle, * (r,s) set to valid signature * EC_ACCESS_DENIED if key handle can't authenticated */ 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); /** * * Board U2F key management part implemented. * */ /** * Get the current u2f state from the board. * * @return pointer to static state if successful, NULL otherwise */ struct u2f_state *u2f_get_state(void); /** * Try to load U2F keys or create if failed. * * @param state - buffer for state to load/create * @param force_create - if true, always create all keys * * @return true if state is properly initialized and will persist in flash. */ bool u2f_load_or_create_state(struct u2f_state *state, bool force_create); /*** * Generates and persists to nvram a new seed that will be used to * derive kek in future calls to u2f_gen_kek(). * * @param commit whether to commit nvram changes before returning. * @return EC_SUCCESS if seed was successfully created * (and persisted if requested). */ enum ec_error_list u2f_gen_kek_seed(int commit); /** * Zeroize U2F keys. Can be used to switch to FIPS-compliant path by * destroying old keys. * * @return true if state is properly initialized and will persist in flash. */ enum ec_error_list u2f_zeroize_keys(void); /** * Update keys to a newer (FIPS-compliant) version if needed. Do nothing if * keys are already updated. * * @return EC_SUCCESS or error code. */ enum ec_error_list u2f_update_keys(void); #endif /* __CROS_EC_U2F_IMPL_H */