summaryrefslogtreecommitdiff
path: root/common/fpsensor/fpsensor_crypto.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /common/fpsensor/fpsensor_crypto.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-wristpin-14469.59.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'common/fpsensor/fpsensor_crypto.c')
-rw-r--r--common/fpsensor/fpsensor_crypto.c286
1 files changed, 0 insertions, 286 deletions
diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c
deleted file mode 100644
index 73d7aca681..0000000000
--- a/common/fpsensor/fpsensor_crypto.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* Copyright 2019 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.
- */
-#include <stdbool.h>
-
-#include "aes.h"
-#include "aes-gcm.h"
-#include "cryptoc/util.h"
-#include "fpsensor_crypto.h"
-#include "fpsensor_private.h"
-#include "fpsensor_state.h"
-#include "rollback.h"
-
-#if !defined(CONFIG_AES) || !defined(CONFIG_AES_GCM) || \
- !defined(CONFIG_ROLLBACK_SECRET_SIZE)
-#error "fpsensor requires AES, AES_GCM and ROLLBACK_SECRET_SIZE"
-#endif
-
-static int get_ikm(uint8_t *ikm)
-{
- int ret;
-
- if (!fp_tpm_seed_is_set()) {
- CPRINTS("Seed hasn't been set.");
- return EC_ERROR_ACCESS_DENIED;
- }
-
- /*
- * The first CONFIG_ROLLBACK_SECRET_SIZE bytes of IKM are read from the
- * anti-rollback blocks.
- */
- ret = rollback_get_secret(ikm);
- if (ret != EC_SUCCESS) {
- CPRINTS("Failed to read rollback secret: %d", ret);
- return EC_ERROR_HW_INTERNAL;
- }
- /*
- * IKM is the concatenation of the rollback secret and the seed from
- * the TPM.
- */
- memcpy(ikm + CONFIG_ROLLBACK_SECRET_SIZE, tpm_seed, sizeof(tpm_seed));
-
- return EC_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, 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_ERROR_INVAL;
- }
-
- if (info_size > SHA256_DIGEST_SIZE) {
- CPRINTS("Info size too big for HKDF.");
- return EC_ERROR_INVAL;
- }
-
- 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);
- always_memset(key_buf, 0, sizeof(key_buf));
-
- return EC_SUCCESS;
-}
-
-int hkdf_expand(uint8_t *out_key, size_t L, const uint8_t *prk,
- size_t prk_size, const uint8_t *info, size_t info_size)
-{
- /*
- * "Expand" step of HKDF.
- * https://tools.ietf.org/html/rfc5869#section-2.3
- */
-#define HASH_LEN SHA256_DIGEST_SIZE
- uint8_t count = 1;
- const uint8_t *T = out_key;
- size_t T_len = 0;
- uint8_t T_buffer[HASH_LEN];
- /* Number of blocks. */
- const uint32_t N = DIV_ROUND_UP(L, HASH_LEN);
- uint8_t info_buffer[HASH_LEN + HKDF_MAX_INFO_SIZE + sizeof(count)];
- bool arguments_valid = false;
-
- if (out_key == NULL || L == 0)
- CPRINTS("HKDF expand: output buffer not valid.");
- else if (prk == NULL)
- CPRINTS("HKDF expand: prk is NULL.");
- else if (info == NULL && info_size > 0)
- CPRINTS("HKDF expand: info is NULL but info size is not zero.");
- else if (info_size > HKDF_MAX_INFO_SIZE)
- CPRINTF("HKDF expand: info size larger than %d bytes.\n",
- HKDF_MAX_INFO_SIZE);
- else if (N > HKDF_SHA256_MAX_BLOCK_COUNT)
- CPRINTS("HKDF expand: output key size too large.");
- else
- arguments_valid = true;
-
- if (!arguments_valid)
- return EC_ERROR_INVAL;
-
- while (L > 0) {
- const size_t block_size = L < HASH_LEN ? L : HASH_LEN;
-
- memcpy(info_buffer, T, T_len);
- memcpy(info_buffer + T_len, info, info_size);
- info_buffer[T_len + info_size] = count;
- hmac_SHA256(T_buffer, prk, prk_size, info_buffer,
- T_len + info_size + sizeof(count));
- memcpy(out_key, T_buffer, block_size);
-
- T += T_len;
- T_len = HASH_LEN;
- count++;
- out_key += block_size;
- L -= block_size;
- }
- always_memset(T_buffer, 0, sizeof(T_buffer));
- always_memset(info_buffer, 0, sizeof(info_buffer));
- return EC_SUCCESS;
-#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;
- 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_SUCCESS) {
- CPRINTS("Failed to get IKM: %d", ret);
- return ret;
- }
-
- /* "Extract step of HKDF. */
- hkdf_extract(prk, salt, FP_CONTEXT_ENCRYPTION_SALT_BYTES, ikm,
- sizeof(ikm));
- always_memset(ikm, 0, sizeof(ikm));
-
- /*
- * Only 1 "expand" step of HKDF since the size of the "info" context
- * (user_id in our case) is exactly SHA256_DIGEST_SIZE.
- * https://tools.ietf.org/html/rfc5869#section-2.3
- */
- ret = hkdf_expand_one_step(out_key, SBP_ENC_KEY_LEN, prk, sizeof(prk),
- (uint8_t *)user_id, sizeof(user_id));
- always_memset(prk, 0, sizeof(prk));
-
- return ret;
-}
-
-int aes_gcm_encrypt(const uint8_t *key, int key_size,
- const uint8_t *plaintext,
- uint8_t *ciphertext, int text_size,
- const uint8_t *nonce, int nonce_size,
- uint8_t *tag, int tag_size)
-{
- int res;
- AES_KEY aes_key;
- GCM128_CONTEXT ctx;
-
- if (nonce_size != FP_CONTEXT_NONCE_BYTES) {
- CPRINTS("Invalid nonce size %d bytes", nonce_size);
- return EC_ERROR_INVAL;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set encryption key: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0);
- CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size);
- /* CRYPTO functions return 1 on success, 0 on error. */
- res = CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, ciphertext,
- text_size);
- if (!res) {
- CPRINTS("Failed to encrypt: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_tag(&ctx, tag, tag_size);
- return EC_SUCCESS;
-}
-
-int aes_gcm_decrypt(const uint8_t *key, int key_size, uint8_t *plaintext,
- const uint8_t *ciphertext, int text_size,
- const uint8_t *nonce, int nonce_size,
- const uint8_t *tag, int tag_size)
-{
- int res;
- AES_KEY aes_key;
- GCM128_CONTEXT ctx;
-
- if (nonce_size != FP_CONTEXT_NONCE_BYTES) {
- CPRINTS("Invalid nonce size %d bytes", nonce_size);
- return EC_ERROR_INVAL;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set decryption key: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0);
- CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size);
- /* CRYPTO functions return 1 on success, 0 on error. */
- res = CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, plaintext,
- text_size);
- if (!res) {
- CPRINTS("Failed to decrypt: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- res = CRYPTO_gcm128_finish(&ctx, tag, tag_size);
- if (!res) {
- CPRINTS("Found incorrect tag: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- return EC_SUCCESS;
-}