summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/fpsensor/fpsensor_crypto.c78
1 files changed, 60 insertions, 18 deletions
diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c
index 7e31e3f923..3a5a8b251c 100644
--- a/common/fpsensor/fpsensor_crypto.c
+++ b/common/fpsensor/fpsensor_crypto.c
@@ -16,17 +16,9 @@
#error "fpsensor requires AES, AES_GCM and ROLLBACK_SECRET_SIZE"
#endif
-int derive_encryption_key(uint8_t *out_key, const uint8_t *salt)
+static int get_ikm(uint8_t *ikm)
{
int ret;
- uint8_t key_buf[SHA256_DIGEST_SIZE];
- uint8_t prk[SHA256_DIGEST_SIZE];
- uint8_t message[sizeof(user_id) + 1];
- uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)];
-
- BUILD_ASSERT(SBP_ENC_KEY_LEN <= SHA256_DIGEST_SIZE);
- BUILD_ASSERT(SBP_ENC_KEY_LEN <= CONFIG_ROLLBACK_SECRET_SIZE);
- BUILD_ASSERT(sizeof(user_id) == SHA256_DIGEST_SIZE);
if (!fp_tpm_seed_is_set()) {
CPRINTS("Seed hasn't been set.");
@@ -48,11 +40,66 @@ int derive_encryption_key(uint8_t *out_key, const uint8_t *salt)
*/
memcpy(ikm + CONFIG_ROLLBACK_SECRET_SIZE, tpm_seed, sizeof(tpm_seed));
+ return EC_RES_SUCCESS;
+}
+
+static void hkdf_extract(uint8_t *prk, const uint8_t *salt, size_t salt_size,
+ const uint8_t *ikm, size_t ikm_size)
+{
/*
* Derive a key with the "extract" step of HKDF
* https://tools.ietf.org/html/rfc5869#section-2.2
*/
- hmac_SHA256(prk, salt, FP_CONTEXT_SALT_BYTES, ikm, sizeof(ikm));
+ hmac_SHA256(prk, salt, salt_size, ikm, ikm_size);
+}
+
+static int hkdf_expand_one_step(uint8_t *out_key, size_t out_key_size,
+ uint8_t *prk, size_t prk_size,
+ uint8_t *info, size_t info_size)
+{
+ uint8_t key_buf[SHA256_DIGEST_SIZE];
+ uint8_t message_buf[SHA256_DIGEST_SIZE + 1];
+
+ if (out_key_size > SHA256_DIGEST_SIZE) {
+ CPRINTS("Deriving key material longer than SHA256_DIGEST_SIZE "
+ "requires more steps of HKDF expand.");
+ return EC_RES_ERROR;
+ }
+
+ if (info_size > SHA256_DIGEST_SIZE) {
+ CPRINTS("Info size too big for HKDF.");
+ return EC_RES_ERROR;
+ }
+
+ memcpy(message_buf, info, info_size);
+ /* 1 step, set the counter byte to 1. */
+ message_buf[info_size] = 0x01;
+ hmac_SHA256(key_buf, prk, prk_size, message_buf, info_size + 1);
+
+ memcpy(out_key, key_buf, out_key_size);
+ memset(key_buf, 0, sizeof(key_buf));
+
+ return EC_RES_SUCCESS;
+}
+
+int derive_encryption_key(uint8_t *out_key, const uint8_t *salt)
+{
+ int ret;
+ uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)];
+ uint8_t prk[SHA256_DIGEST_SIZE];
+
+ BUILD_ASSERT(SBP_ENC_KEY_LEN <= SHA256_DIGEST_SIZE);
+ BUILD_ASSERT(SBP_ENC_KEY_LEN <= CONFIG_ROLLBACK_SECRET_SIZE);
+ BUILD_ASSERT(sizeof(user_id) == SHA256_DIGEST_SIZE);
+
+ ret = get_ikm(ikm);
+ if (ret != EC_RES_SUCCESS) {
+ CPRINTS("Failed to get IKM: %d", ret);
+ return EC_RES_ERROR;
+ }
+
+ /* "Extract step of HKDF. */
+ hkdf_extract(prk, salt, FP_CONTEXT_SALT_BYTES, ikm, sizeof(ikm));
memset(ikm, 0, sizeof(ikm));
/*
@@ -60,16 +107,11 @@ int derive_encryption_key(uint8_t *out_key, const uint8_t *salt)
* (user_id in our case) is exactly SHA256_DIGEST_SIZE.
* https://tools.ietf.org/html/rfc5869#section-2.3
*/
- memcpy(message, user_id, sizeof(user_id));
- /* 1 step, set the counter byte to 1. */
- message[sizeof(message) - 1] = 0x01;
- hmac_SHA256(key_buf, prk, sizeof(prk), message, sizeof(message));
+ ret = hkdf_expand_one_step(out_key, SBP_ENC_KEY_LEN, prk, sizeof(prk),
+ (uint8_t *)user_id, sizeof(user_id));
memset(prk, 0, sizeof(prk));
- memcpy(out_key, key_buf, SBP_ENC_KEY_LEN);
- memset(key_buf, 0, sizeof(key_buf));
-
- return EC_RES_SUCCESS;
+ return ret;
}
int aes_gcm_encrypt(const uint8_t *key, int key_size,