summaryrefslogtreecommitdiff
path: root/common/fpsensor
diff options
context:
space:
mode:
authorYicheng Li <yichengli@chromium.org>2019-06-06 18:27:42 -0700
committerCommit Bot <commit-bot@chromium.org>2019-06-13 19:13:57 +0000
commit35d0e17de6d76699c4fac850d39ed4c4b5488cb2 (patch)
treec527fec2dd43909f444f6f12a2d9c8336ce9720a /common/fpsensor
parent2fb0ff65ecac63829d93d1d9ae0994ebf7a5883d (diff)
downloadchrome-ec-35d0e17de6d76699c4fac850d39ed4c4b5488cb2.tar.gz
fpsensor: Move crypto-related code to fpsensor_crypto.c
Move crypto-related code to common/fpsensor/fpsensor_state.c. This facilitates unittesting because we can control whether to link in crypto-related code, and also facilitates mocking the encryption engine. BRANCH=nocturne BUG=chromium:927095 TEST=ran unittests TEST=tested enrollment, matching and multifinger on DUT nocturne Change-Id: I5bffc1460cbe2c9e3d6294ea5fff41f14019f0eb Signed-off-by: Yicheng Li <yichengli@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1648922 Reviewed-by: Nicolas Norvez <norvez@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'common/fpsensor')
-rw-r--r--common/fpsensor/build.mk1
-rw-r--r--common/fpsensor/fpsensor.c139
-rw-r--r--common/fpsensor/fpsensor_crypto.c142
-rw-r--r--common/fpsensor/fpsensor_private.h14
-rw-r--r--common/fpsensor/fpsensor_state.c4
5 files changed, 162 insertions, 138 deletions
diff --git a/common/fpsensor/build.mk b/common/fpsensor/build.mk
index 3b03152b05..c684dd01b9 100644
--- a/common/fpsensor/build.mk
+++ b/common/fpsensor/build.mk
@@ -10,4 +10,5 @@ _fpsensor_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)/fpsensor_state.o
ifneq ($(CONFIG_SPI_FP_PORT),)
all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)/fpsensor.o
+all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)/fpsensor_crypto.o
endif
diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c
index e0fe146949..f1b31e43c7 100644
--- a/common/fpsensor/fpsensor.c
+++ b/common/fpsensor/fpsensor.c
@@ -3,21 +3,19 @@
* found in the LICENSE file.
*/
-#include "aes.h"
-#include "aes-gcm.h"
#include "atomic.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "ec_commands.h"
#include "fpsensor.h"
+#include "fpsensor_crypto.h"
+#include "fpsensor_private.h"
#include "fpsensor_state.h"
#include "gpio.h"
#include "host_command.h"
#include "link_defs.h"
#include "mkbp_event.h"
-#include "rollback.h"
-#include "sha256.h"
#include "spi.h"
#include "system.h"
#include "task.h"
@@ -26,17 +24,13 @@
#include "util.h"
#include "watchdog.h"
-#if !defined(CONFIG_AES) || !defined(CONFIG_AES_GCM) || \
- !defined(CONFIG_ROLLBACK_SECRET_SIZE) || !defined(CONFIG_RNG)
-#error "fpsensor requires AES, AES_GCM, ROLLBACK_SECRET_SIZE and RNG"
+#if !defined(CONFIG_RNG)
+#error "fpsensor requires RNG"
#endif
/* Ready to encrypt a template. */
static timestamp_t encryption_deadline;
-#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
-
/* raw image offset inside the acquired frame */
#ifndef FP_SENSOR_IMAGE_OFFSET
#define FP_SENSOR_IMAGE_OFFSET 0
@@ -295,62 +289,6 @@ void fp_task(void)
#endif /* !HAVE_FP_PRIVATE_DRIVER */
}
-static int derive_encryption_key(uint8_t *out_key, uint8_t *salt)
-{
- 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.");
- return EC_RES_ERROR;
- }
-
- /*
- * 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_RES_ERROR;
- }
- /*
- * 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));
-
- /*
- * 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));
- 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
- */
- 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));
- 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;
-}
-
static int fp_command_passthru(struct host_cmd_handler_args *args)
{
const struct ec_params_fp_passthru *params = args->params;
@@ -408,75 +346,6 @@ DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info,
BUILD_ASSERT(FP_CONTEXT_NONCE_BYTES == 12);
-static int aes_gcm_encrypt(const uint8_t *key, int key_size,
- const uint8_t *plaintext,
- uint8_t *ciphertext, int plaintext_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_RES_INVALID_PARAM;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set encryption key: %d", res);
- return EC_RES_ERROR;
- }
- 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,
- plaintext_size);
- if (!res) {
- CPRINTS("Failed to encrypt: %d", res);
- return EC_RES_ERROR;
- }
- CRYPTO_gcm128_tag(&ctx, tag, tag_size);
- return EC_RES_SUCCESS;
-}
-
-static int aes_gcm_decrypt(const uint8_t *key, int key_size, uint8_t *plaintext,
- const uint8_t *ciphertext, int plaintext_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_RES_INVALID_PARAM;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set decryption key: %d", res);
- return EC_RES_ERROR;
- }
- 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,
- plaintext_size);
- if (!res) {
- CPRINTS("Failed to decrypt: %d", res);
- return EC_RES_ERROR;
- }
- res = CRYPTO_gcm128_finish(&ctx, tag, tag_size);
- if (!res) {
- CPRINTS("Found incorrect tag: %d", res);
- return EC_RES_ERROR;
- }
- return EC_RES_SUCCESS;
-}
-
static int validate_fp_buffer_offset(const uint32_t buffer_size,
const uint32_t offset, const uint32_t size)
{
diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c
new file mode 100644
index 0000000000..5c5715a462
--- /dev/null
+++ b/common/fpsensor/fpsensor_crypto.c
@@ -0,0 +1,142 @@
+/* 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 "aes.h"
+#include "aes-gcm.h"
+#include "fpsensor_crypto.h"
+#include "fpsensor_private.h"
+#include "fpsensor_state.h"
+#include "rollback.h"
+#include "sha256.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
+
+int derive_encryption_key(uint8_t *out_key, uint8_t *salt)
+{
+ 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.");
+ return EC_RES_ERROR;
+ }
+
+ /*
+ * 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_RES_ERROR;
+ }
+ /*
+ * 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));
+
+ /*
+ * 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));
+ 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
+ */
+ 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));
+ 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;
+}
+
+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_RES_INVALID_PARAM;
+ }
+
+ res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
+ if (res) {
+ CPRINTS("Failed to set encryption key: %d", res);
+ return EC_RES_ERROR;
+ }
+ 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_RES_ERROR;
+ }
+ CRYPTO_gcm128_tag(&ctx, tag, tag_size);
+ return EC_RES_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_RES_INVALID_PARAM;
+ }
+
+ res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
+ if (res) {
+ CPRINTS("Failed to set decryption key: %d", res);
+ return EC_RES_ERROR;
+ }
+ 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_RES_ERROR;
+ }
+ res = CRYPTO_gcm128_finish(&ctx, tag, tag_size);
+ if (!res) {
+ CPRINTS("Found incorrect tag: %d", res);
+ return EC_RES_ERROR;
+ }
+ return EC_RES_SUCCESS;
+}
diff --git a/common/fpsensor/fpsensor_private.h b/common/fpsensor/fpsensor_private.h
new file mode 100644
index 0000000000..fb97fb3bfd
--- /dev/null
+++ b/common/fpsensor/fpsensor_private.h
@@ -0,0 +1,14 @@
+/* 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.
+ */
+
+/* Internal header file for common/fpsensor directory */
+
+#ifndef __CROS_EC_FPSENSOR_PRIVATE_H
+#define __CROS_EC_FPSENSOR_PRIVATE_H
+
+#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
+
+#endif /* __CROS_EC_FPSENSOR_PRIVATE_H */
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c
index f8016b49e9..4e634e2785 100644
--- a/common/fpsensor/fpsensor_state.c
+++ b/common/fpsensor/fpsensor_state.c
@@ -6,15 +6,13 @@
#include "common.h"
#include "ec_commands.h"
#include "fpsensor.h"
+#include "fpsensor_private.h"
#include "fpsensor_state.h"
#include "host_command.h"
#include "system.h"
#include "task.h"
#include "util.h"
-#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
-
/* Last acquired frame (aligned as it is used by arbitrary binary libraries) */
uint8_t fp_buffer[FP_SENSOR_IMAGE_SIZE] FP_FRAME_SECTION __aligned(4);
/* Fingers templates for the current user */