diff options
author | Yicheng Li <yichengli@chromium.org> | 2019-06-11 16:46:36 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-08 02:31:05 +0000 |
commit | 762f51eeca42b906e220418188b751b99ae7182d (patch) | |
tree | a68400455dfc3ed3925034e2ad1e98a96191a6ab /common/fpsensor | |
parent | 0df7fdbf07a7d64a13416dc28e1a7538907216c5 (diff) | |
download | chrome-ec-762f51eeca42b906e220418188b751b99ae7182d.tar.gz |
fpsensor: Prepare derivation of positive match secret.
Implement derivation of positive match secret for a template. This
derivation will be used when biod sends a command to ask for
positive match secret and the secret readable bit is set. Also add
unit tests for this derivation.
BRANCH=nocturne
BUG=chromium:927095
TEST=make -j buildall
TEST=tested enrollment, matching and multifinger on DUT nocturne
Change-Id: Ife477a98573284f69c5fb07e814d9a3d09f92127
Signed-off-by: Yicheng Li <yichengli@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1639440
Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Diffstat (limited to 'common/fpsensor')
-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; |