diff options
Diffstat (limited to 'common/fpsensor/fpsensor_crypto.c')
-rw-r--r-- | common/fpsensor/fpsensor_crypto.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c index b7c5ea7260..4a2b31c411 100644 --- a/common/fpsensor/fpsensor_crypto.c +++ b/common/fpsensor/fpsensor_crypto.c @@ -139,6 +139,50 @@ int hkdf_expand(uint8_t *out_key, size_t L, const uint8_t *prk, #undef HASH_LEN } +int derive_positive_match_secret(uint8_t *output, + const uint8_t *input_positive_match_salt) +{ + int ret; + uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)]; + uint8_t prk[SHA256_DIGEST_SIZE]; + static const char info_prefix[] = "positive_match_secret for user "; + uint8_t info[sizeof(info_prefix) - 1 + sizeof(user_id)]; + + if (bytes_are_trivial(input_positive_match_salt, + FP_POSITIVE_MATCH_SALT_BYTES)) { + CPRINTS("Failed to derive positive match secret: " + "salt bytes are trivial."); + return EC_ERROR_INVAL; + } + + ret = get_ikm(ikm); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to get IKM: %d", ret); + return ret; + } + + /* "Extract" step of HKDF. */ + hkdf_extract(prk, input_positive_match_salt, + FP_POSITIVE_MATCH_SALT_BYTES, ikm, sizeof(ikm)); + always_memset(ikm, 0, sizeof(ikm)); + + memcpy(info, info_prefix, strlen(info_prefix)); + memcpy(info + strlen(info_prefix), user_id, sizeof(user_id)); + + /* "Expand" step of HKDF. */ + ret = hkdf_expand(output, FP_POSITIVE_MATCH_SECRET_BYTES, prk, + sizeof(prk), info, sizeof(info)); + always_memset(prk, 0, sizeof(prk)); + + /* Check that secret is not full of 0x00 or 0xff. */ + if (bytes_are_trivial(output, FP_POSITIVE_MATCH_SECRET_BYTES)) { + CPRINTS("Failed to derive positive match secret: " + "derived secret bytes are trivial."); + ret = EC_ERROR_HW_INTERNAL; + } + return ret; +} + int derive_encryption_key(uint8_t *out_key, const uint8_t *salt) { int ret; |