summaryrefslogtreecommitdiff
path: root/include/u2f_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/u2f_impl.h')
-rw-r--r--include/u2f_impl.h296
1 files changed, 91 insertions, 205 deletions
diff --git a/include/u2f_impl.h b/include/u2f_impl.h
index fa59424595..75e50cc6c7 100644
--- a/include/u2f_impl.h
+++ b/include/u2f_impl.h
@@ -9,246 +9,121 @@
#define __CROS_EC_U2F_IMPL_H
#include "common.h"
-#include "dcrypto.h"
-
-/* ---- platform cryptography hooks ---- */
-
-#define U2F_MAX_KH_SIZE 128 /* Max size of key handle */
-
-/* ---- 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;
-};
-
-/* Forward declarations to reduce dependencies. */
-/* EC (uncompressed) point */
-#define U2F_EC_KEY_SIZE P256_NBYTES /* EC key size in bytes */
-#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) /* Size of EC point */
-#define U2F_POINT_UNCOMPRESSED 0x04 /* Uncompressed point format */
-
-struct u2f_ec_point {
- uint8_t pointFormat; /* Point type */
- uint8_t x[U2F_EC_KEY_SIZE]; /* X-value */
- uint8_t y[U2F_EC_KEY_SIZE]; /* Y-value */
-};
-
-BUILD_ASSERT(sizeof(struct u2f_ec_point) == U2F_EC_POINT_SIZE);
-
-struct u2f_signature {
- uint8_t sig_r[U2F_EC_KEY_SIZE]; /* Signature */
- uint8_t sig_s[U2F_EC_KEY_SIZE]; /* Signature */
-};
+#include "dcrypto.h"
-/* Origin seed is a random nonce generated during key handle creation. */
-#define U2F_ORIGIN_SEED_SIZE 32
-#define U2F_AUTHORIZATION_SALT_SIZE 16
+#include "tpm_vendor_cmds.h"
+#include "u2f.h"
-#define U2F_V0_KH_SIZE 64
+/* ---- Physical presence ---- */
-/* Key handle version = 0, only bound to device. */
-struct u2f_key_handle_v0 {
- uint8_t origin_seed[U2F_ORIGIN_SEED_SIZE];
- uint8_t hmac[SHA256_DIGEST_SIZE];
+enum touch_state {
+ POP_TOUCH_NO = 0, /* waiting for a user touch */
+ POP_TOUCH_YES = 1, /* touch recorded and latched */
};
-BUILD_ASSERT(sizeof(struct u2f_key_handle_v0) <= U2F_MAX_KH_SIZE);
-BUILD_ASSERT(sizeof(struct u2f_key_handle_v0) == U2F_V0_KH_SIZE);
-
-/**
- * Key handle version = 1 for WebAuthn, bound to device and user.
+/*
+ * Check whether the user presence event was latched.
+ *
+ * @param consume reset the latched touch event and the presence LED.
+ * @return POP_TOUCH_NO or POP_TOUCH_YES.
*/
-#define U2F_V1_KH_SIZE 113
+enum touch_state pop_check_presence(int consume);
-/* Header is composed of version || origin_seed || kh_hmac */
-#define U2F_V1_KH_HEADER_SIZE (U2F_ORIGIN_SEED_SIZE + SHA256_DIGEST_SIZE + 1)
+/* ---- non-volatile U2F state ---- */
-struct u2f_key_handle_v1 {
- uint8_t version;
- uint8_t origin_seed[U2F_ORIGIN_SEED_SIZE];
- uint8_t kh_hmac[SHA256_DIGEST_SIZE];
- /* Optionally checked in u2f_sign. */
- uint8_t authorization_salt[U2F_AUTHORIZATION_SALT_SIZE];
- uint8_t authorization_hmac[SHA256_DIGEST_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);
-
-union u2f_key_handle_variant {
- struct u2f_key_handle_v0 v0;
- struct u2f_key_handle_v1 v1;
+struct u2f_state {
+ uint32_t salt[8];
+ uint32_t salt_kek[8];
+ uint32_t salt_kh[8];
};
-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
+ * Get the current u2f state from the board.
*/
-enum ec_error_list u2f_generate_hmac_key(struct u2f_state *state);
+struct u2f_state *get_state(void);
-/**
- * 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);
+/* ---- platform cryptography hooks ---- */
/**
- * Create a randomized key handle for specified origin, user secret.
- * Generate associated signing key.
+ * Pack the specified origin, user secret and origin-specific seed
+ * into a key handle.
*
- * @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
+ * @param seed pointer to origin-specific random seed
+ * @param key_handle buffer to hold the output key handle
*
- * @return EC_SUCCESS if successful
+ * @return EC_SUCCESS if a valid keypair was created.
*/
-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_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
+ const uint8_t *seed,
+ struct u2f_key_handle *key_handle);
/**
- * Create a randomized key handle for specified origin, user secret.
- * Generate associated signing key.
+ * Pack the specified origin, user secret, origin-specific seed and version
+ * byte into a key handle.
*
- * @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
+ * @param seed pointer to origin-specific random seed
+ * @param version the version byte to pack; should be greater than 0.
+ * @param key_handle_header buffer to hold the output key handle header
*
- * @return EC_SUCCESS if a valid key pair was created
- * EC_ACCESS_DENIED if key handle can't authenticated
+ * @return EC_SUCCESS if a valid keypair was created.
*/
-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 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);
/**
- * 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.
+ * Generate an origin and user-specific ECDSA keypair from the specified
+ * key handle.
*
- * @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 uint8_t *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
+ * If pk_x and pk_y are NULL, public key generation will be skipped.
*
- * @param r part of generated signature
- * @param s part of generated signature
+ * @param key_handle pointer to the key handle
+ * @param key_handle_size size of the key handle in bytes
+ * @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 public key matches key handle,
- * (r,s) set to valid signature
- * EC_ACCESS_DENIED if key handle can't authenticated
+ * @return EC_SUCCESS if a valid keypair was created.
*/
-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_origin_user_keypair(const uint8_t *key_handle, size_t key_handle_size,
+ p256_int *d, p256_int *pk_x, p256_int *pk_y);
/**
- *
- * Board U2F key management part implemented.
- *
+ * Derive an hmac from the given salt, key handle and hash. The salt is to make
+ * sure the hmac is different for different key handles of one user. The key
+ * handle header is encoded into the authorization hmac to protect against
+ * swapping auth time secret.
*/
+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);
-/**
- * Get the current u2f state from the board.
+/***
+ * Generate a hardware derived 256b private key.
*
- * @return pointer to static state if successful, NULL otherwise
+ * @param kek ptr to store the generated key.
+ * @param key_len size of the storage buffer. Should be 32 bytes.
+ * @return EC_SUCCESS if a valid key was created.
*/
-struct u2f_state *u2f_get_state(void);
+int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len);
/**
- * Try to load U2F keys or create if failed.
+ * Generate a hardware derived ECDSA keypair for individual attestation.
*
- * @param state - buffer for state to load/create
- * @param force_create - if true, always create all keys
+ * @param seed ptr to store 32-byte seed to regenerate this key on this chip
+ * @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 state is properly initialized and will persist in flash.
+ * @return EC_SUCCESS if a valid keypair was created.
*/
-bool u2f_load_or_create_state(struct u2f_state *state, bool force_create);
+int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y);
/***
* Generates and persists to nvram a new seed that will be used to
@@ -258,22 +133,33 @@ bool u2f_load_or_create_state(struct u2f_state *state, bool force_create);
* @return EC_SUCCESS if seed was successfully created
* (and persisted if requested).
*/
-enum ec_error_list u2f_gen_kek_seed(int commit);
+int u2f_gen_kek_seed(int commit);
+
+/* Maximum size in bytes of G2F attestation certificate. */
+#define G2F_ATTESTATION_CERT_MAX_LEN 315
/**
- * Zeroize U2F keys. Can be used to switch to FIPS-compliant path by
- * destroying old keys.
+ * Gets the x509 certificate for the attestation keypair returned
+ * by g2f_individual_keypair().
*
- * @return true if state is properly initialized and will persist in flash.
+ * @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.
*/
-enum ec_error_list u2f_zeroize_keys(void);
+int g2f_attestation_cert(uint8_t *buf);
/**
- * Update keys to a newer (FIPS-compliant) version if needed. Do nothing if
- * keys are already updated.
- *
- * @return EC_SUCCESS or error code.
+ * 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);
+
+/**
+ * U2F_SIGN command handler. Verifies a key handle is owned and signs data with
+ * it.
*/
-enum ec_error_list u2f_update_keys(void);
+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 */