summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-09-27 17:47:29 -0700
committerCommit Bot <commit-bot@chromium.org>2021-10-02 04:01:49 +0000
commit0ad46f2259b79b07a1d4b114fd58472a88c19282 (patch)
tree8313e9894a779c602cca27fd79b81bcc9a7ca3b6 /common
parent7b25ee08172491864900e3a2ba59d761355f4069 (diff)
downloadchrome-ec-0ad46f2259b79b07a1d4b114fd58472a88c19282.tar.gz
cr50: provide public crypto API for HMAC/HASH with error reporting.
To implement FIPS mode for Cr50 we should be able to block access to crypto functions if errors are detected. Historically all HASH/HMAC functions were declared as void with no return type. 1) Split existing functions into public part (data structs, update and final parts) and internal part - unchecked init functions. 2) Introduced new functions to start SHA / HMAC operation which returns status code and block access to crypto in case of FIPS errors. 3) Dcrypto hash algorithms codes updated to match TPM_ALG_ID to simplify adaptation layer and move checks inside Dcrypto module. 4) Updated all uses of API outside FIPS module to check return code and act accordingly. 5) As a side effect RSA can now support SHA384 & SHA512 for signing, board/host mock ups simplified. BUG=b:197893750 TEST=make buildall -j; make BOARD=cr50 CRYPTO_TEST=1; test/tpm_test/tpm_test.py TCG tests ------------------------------ Test Result Summary --------------------- Test executed on: Tue Sep 28 15:23:35 2021 Performed Tests: 248 Passed Tests: 248 Failed Tests: 0 Errors: 0 Warnings: 0 ======================================================================== Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: Ibbc38703496f417cba693c37d39a82a662c3f7ee Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3192137 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/ccd_config.c24
-rw-r--r--common/pinweaver.c90
-rw-r--r--common/rma_auth.c45
3 files changed, 104 insertions, 55 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 12e88689ad..d87842a055 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -236,7 +236,8 @@ static int raw_has_password(void)
* @param digest Pointer to a CCD_PASSWORD_DIGEST_SIZE buffer
* @param password The password to digest
*/
-static void ccd_password_digest(uint8_t *digest, const char *password)
+static enum ec_error_list ccd_password_digest(uint8_t *digest,
+ const char *password)
{
struct sha256_ctx sha;
uint8_t *unique_id;
@@ -244,11 +245,13 @@ static void ccd_password_digest(uint8_t *digest, const char *password)
unique_id_len = system_get_chip_unique_id(&unique_id);
- SHA256_hw_init(&sha);
+ if (DCRYPTO_hw_sha256_init(&sha) != DCRYPTO_OK)
+ return EC_ERROR_HW_INTERNAL;
SHA256_update(&sha, config.password_salt, sizeof(config.password_salt));
SHA256_update(&sha, unique_id, unique_id_len);
SHA256_update(&sha, password, strlen(password));
memcpy(digest, SHA256_final(&sha)->b8, CCD_PASSWORD_DIGEST_SIZE);
+ return EC_SUCCESS;
}
/**
@@ -258,7 +261,7 @@ static void ccd_password_digest(uint8_t *digest, const char *password)
* @return EC_SUCCESS, EC_ERROR_BUSY if too soon since last attempt, or
* EC_ERROR_ACCESS_DENIED if mismatch.
*/
-static int raw_check_password(const char *password)
+static enum ec_error_list raw_check_password(const char *password)
{
/*
* Time of last password attempt; initialized to 0 at boot. Yes, we're
@@ -272,6 +275,7 @@ static int raw_check_password(const char *password)
uint8_t digest[CCD_PASSWORD_DIGEST_SIZE];
uint32_t t;
+ enum ec_error_list result;
/* If no password is set, match only an empty password */
if (!raw_has_password())
@@ -284,7 +288,9 @@ static int raw_check_password(const char *password)
last_password_time = t;
/* Calculate the digest of the password */
- ccd_password_digest(digest, password);
+ result = ccd_password_digest(digest, password);
+ if (result != EC_SUCCESS)
+ return result;
if (safe_memcmp(digest, config.password_digest,
sizeof(config.password_digest)))
@@ -312,19 +318,23 @@ static void raw_reset_password(void)
* @param password New password; must be non-empty
* @return EC_SUCCESS if successful
*/
-static int raw_set_password(const char *password)
+static enum ec_error_list raw_set_password(const char *password)
{
+ enum ec_error_list result;
+
/* Get a new salt */
if (!fips_rand_bytes(config.password_salt,
sizeof(config.password_salt)))
return EC_ERROR_HW_INTERNAL;
/* Update the password digest */
- ccd_password_digest(config.password_digest, password);
+ result = ccd_password_digest(config.password_digest, password);
+ if (result != EC_SUCCESS)
+ return result;
/* Track whether we were opened when we set the password */
raw_set_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED,
- ccd_state == CCD_STATE_UNLOCKED);
+ ccd_state == CCD_STATE_UNLOCKED);
return EC_SUCCESS;
}
diff --git a/common/pinweaver.c b/common/pinweaver.c
index 0bcd752ab6..9b7ad0b6d6 100644
--- a/common/pinweaver.c
+++ b/common/pinweaver.c
@@ -164,7 +164,8 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level,
/* Initialize the root hash. */
for (hx = 0; hx < height.v; ++hx) {
- SHA256_hw_init(&ctx);
+ if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK)
+ return PW_ERR_CRYPTO_FAILURE;
for (kx = 0; kx < fan_out; ++kx)
HASH_update((union hash_ctx *)&ctx, temp_hash,
PW_HASH_SIZE);
@@ -180,29 +181,31 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level,
}
/* Computes the HMAC for an encrypted leaf using the key in the merkle_tree. */
-static void compute_hmac(const struct merkle_tree_t *merkle_tree,
+static int compute_hmac(const struct merkle_tree_t *merkle_tree,
const struct imported_leaf_data_t *imported_leaf_data,
uint8_t result[PW_HASH_SIZE])
{
struct hmac_sha256_ctx hmac;
- HMAC_SHA256_hw_init(&hmac, merkle_tree->hmac_key,
- sizeof(merkle_tree->hmac_key));
- /* use HASH_update() vs. HMAC_update() due limits of dcrypto mock. */
- HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->head,
- sizeof(*imported_leaf_data->head));
- HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->iv,
- sizeof(PW_WRAP_BLOCK_SIZE));
- HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->pub,
- imported_leaf_data->head->pub_len);
- HASH_update((union hash_ctx *)&hmac.hash,
- imported_leaf_data->cipher_text,
- imported_leaf_data->head->sec_len);
- memcpy(result, HMAC_SHA256_hw_final(&hmac), PW_HASH_SIZE);
+ if (DCRYPTO_hw_hmac_sha256_init(&hmac, merkle_tree->hmac_key,
+ sizeof(merkle_tree->hmac_key)) !=
+ DCRYPTO_OK)
+ return PW_ERR_CRYPTO_FAILURE;
+
+ HMAC_SHA256_update(&hmac, imported_leaf_data->head,
+ sizeof(*imported_leaf_data->head));
+ HMAC_SHA256_update(&hmac, imported_leaf_data->iv,
+ sizeof(PW_WRAP_BLOCK_SIZE));
+ HMAC_SHA256_update(&hmac, imported_leaf_data->pub,
+ imported_leaf_data->head->pub_len);
+ HMAC_SHA256_update(&hmac, imported_leaf_data->cipher_text,
+ imported_leaf_data->head->sec_len);
+ memcpy(result, HMAC_SHA256_final(&hmac), PW_HASH_SIZE);
+ return EC_SUCCESS;
}
/* Computes the root hash for the specified path and child hash. */
-static void compute_root_hash(const struct merkle_tree_t *merkle_tree,
+static int compute_root_hash(const struct merkle_tree_t *merkle_tree,
struct label_t path,
const uint8_t hashes[][PW_HASH_SIZE],
const uint8_t child_hash[PW_HASH_SIZE],
@@ -214,18 +217,25 @@ static void compute_root_hash(const struct merkle_tree_t *merkle_tree,
uint8_t temp_hash[PW_HASH_SIZE];
uint8_t hx = 0;
uint64_t index = path.v;
+ int ret;
+
+ ret = compute_hash(hashes, num_aux,
+ (struct index_t){ index & path_suffix_mask },
+ child_hash, temp_hash);
+ if (ret != EC_SUCCESS)
+ return ret;
- compute_hash(hashes, num_aux,
- (struct index_t){index & path_suffix_mask},
- child_hash, temp_hash);
for (hx = 1; hx < merkle_tree->height.v; ++hx) {
hashes += num_aux;
index = index >> merkle_tree->bits_per_level.v;
- compute_hash(hashes, num_aux,
- (struct index_t){index & path_suffix_mask},
- temp_hash, temp_hash);
+ ret = compute_hash(hashes, num_aux,
+ (struct index_t){ index & path_suffix_mask },
+ temp_hash, temp_hash);
+ if (ret != EC_SUCCESS)
+ return ret;
}
memcpy(new_root, temp_hash, sizeof(temp_hash));
+ return EC_SUCCESS;
}
/* Checks to see the specified path is valid. The length of the path should be
@@ -239,8 +249,11 @@ static int authenticate_path(const struct merkle_tree_t *merkle_tree,
const uint8_t child_hash[PW_HASH_SIZE])
{
uint8_t parent[PW_HASH_SIZE];
+ int ret;
- compute_root_hash(merkle_tree, path, hashes, child_hash, parent);
+ ret = compute_root_hash(merkle_tree, path, hashes, child_hash, parent);
+ if (ret != EC_SUCCESS)
+ return ret;
if (memcmp(parent, merkle_tree->root, sizeof(parent)) != 0)
return PW_ERR_PATH_AUTH_FAILED;
return EC_SUCCESS;
@@ -334,13 +347,13 @@ static int handle_leaf_update(
import_leaf((const struct unimported_leaf_data_t *)wrapped_leaf_data,
&ptrs);
- compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac);
- compute_root_hash(merkle_tree, leaf_data->pub.label,
- hashes, wrapped_leaf_data->hmac,
- new_root);
+ ret = compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac);
+ if (ret != EC_SUCCESS)
+ return ret;
- return EC_SUCCESS;
+ return compute_root_hash(merkle_tree, leaf_data->pub.label, hashes,
+ wrapped_leaf_data->hmac, new_root);
}
/******************************************************************************/
@@ -532,7 +545,9 @@ static int validate_request_with_wrapped_leaf(
if (ret != EC_SUCCESS)
return ret;
- compute_hmac(merkle_tree, imported_leaf_data, hmac);
+ ret = compute_hmac(merkle_tree, imported_leaf_data, hmac);
+ if (ret != EC_SUCCESS)
+ return ret;
/* Safe memcmp is used here to prevent an attacker from being able to
* brute force a valid HMAC for a crafted wrapped_leaf_data.
* memcmp provides an attacker a timing side-channel they can use to
@@ -994,8 +1009,10 @@ static int pw_handle_remove_leaf(struct merkle_tree_t *merkle_tree,
if (ret != EC_SUCCESS)
return ret;
- compute_root_hash(merkle_tree, request->leaf_location,
- request->path_hashes, empty_hash, new_root);
+ ret = compute_root_hash(merkle_tree, request->leaf_location,
+ request->path_hashes, empty_hash, new_root);
+ if (ret != EC_SUCCESS)
+ return ret;
ret = log_remove_leaf(request->leaf_location, new_root);
if (ret != EC_SUCCESS)
@@ -1283,7 +1300,10 @@ static int pw_handle_log_replay(const struct merkle_tree_t *merkle_tree,
if (log.entries[x].type.v != PW_TRY_AUTH)
return PW_ERR_TYPE_INVALID;
- compute_hmac(merkle_tree, &imported_leaf_data, hmac);
+ ret = compute_hmac(merkle_tree, &imported_leaf_data, hmac);
+ if (ret != EC_SUCCESS)
+ return ret;
+
if (safe_memcmp(hmac, request->unimported_leaf_data.hmac, sizeof(hmac)))
return PW_ERR_HMAC_AUTH_FAILED;
@@ -1385,14 +1405,15 @@ int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree)
* ARRAY_SIZE(hashes) == num_hashes
* 0 <= location <= num_hashes
*/
-void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
+int compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
struct index_t location,
const uint8_t child_hash[PW_HASH_SIZE],
uint8_t result[PW_HASH_SIZE])
{
struct sha256_ctx ctx;
- SHA256_hw_init(&ctx);
+ if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK)
+ return PW_ERR_CRYPTO_FAILURE;
if (location.v > 0)
HASH_update((union hash_ctx *)&ctx, hashes[0],
PW_HASH_SIZE * location.v);
@@ -1401,6 +1422,7 @@ void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
HASH_update((union hash_ctx *)&ctx, hashes[location.v],
PW_HASH_SIZE * (num_hashes - location.v));
memcpy(result, HASH_final((union hash_ctx *)&ctx), PW_HASH_SIZE);
+ return EC_SUCCESS;
}
/* If a request from older protocol comes, this method should make it
diff --git a/common/rma_auth.c b/common/rma_auth.c
index 9de2d9984b..01c3ff827e 100644
--- a/common/rma_auth.c
+++ b/common/rma_auth.c
@@ -75,31 +75,38 @@ static char authcode[RMA_AUTHCODE_BUF_SIZE];
static int tries_left;
static uint64_t last_challenge_time;
-static void get_hmac_sha256(void *hmac_out, const uint8_t *secret,
+static enum ec_error_list get_hmac_sha256(void *hmac_out, const uint8_t *secret,
size_t secret_size, const void *ch_ptr,
size_t ch_size)
{
#ifdef USE_DCRYPTO
struct hmac_sha256_ctx hmac;
- HMAC_SHA256_hw_init(&hmac, secret, secret_size);
+ if (DCRYPTO_hw_hmac_sha256_init(&hmac, secret, secret_size) !=
+ DCRYPTO_OK)
+ return EC_ERROR_HW_INTERNAL;
HMAC_SHA256_update(&hmac, ch_ptr, ch_size);
- memcpy(hmac_out, HMAC_SHA256_hw_final(&hmac), 32);
+ memcpy(hmac_out, HMAC_SHA256_final(&hmac), 32);
#else
hmac_SHA256(hmac_out, secret, secret_size, ch_ptr, ch_size);
#endif
+ return EC_SUCCESS;
}
-static void hash_buffer(void *dest, size_t dest_size,
- const void *buffer, size_t buf_size)
+static enum ec_error_list hash_buffer(void *dest, size_t dest_size,
+ const void *buffer, size_t buf_size)
{
/* We know that the destination is no larger than 32 bytes. */
uint8_t temp[32];
+ enum ec_error_list ret;
- get_hmac_sha256(temp, buffer, buf_size, buffer, buf_size);
+ ret = get_hmac_sha256(temp, buffer, buf_size, buffer, buf_size);
+ if (ret)
+ return ret;
/* Or should we do XOR of the temp modulo dest size? */
memcpy(dest, temp, dest_size);
+ return EC_SUCCESS;
}
#ifdef CONFIG_RMA_AUTH_USE_P256
@@ -148,7 +155,8 @@ static int p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES],
}
/* Did not succeed, rehash the private key and try again. */
- SHA256_hw_init(&sha);
+ if (DCRYPTO_hw_sha256_init(&sha) != DCRYPTO_OK)
+ return EC_ERROR_HW_INTERNAL;
SHA256_update(&sha, buf, sizeof(buf));
memcpy(buf, SHA256_final(&sha), sizeof(buf));
}
@@ -177,10 +185,11 @@ static int p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES],
}
#endif
-void get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE])
+int get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE])
{
uint8_t *chip_unique_id;
int chip_unique_id_size = system_get_chip_unique_id(&chip_unique_id);
+ enum ec_error_list ret;
if (chip_unique_id_size < 0)
chip_unique_id_size = 0;
@@ -198,9 +207,12 @@ void get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE])
* rma_challenge:device_id, let's use first few bytes of
* its hash.
*/
- hash_buffer(rma_device_id, RMA_DEVICE_ID_SIZE,
- chip_unique_id, chip_unique_id_size);
+ ret = hash_buffer(rma_device_id, RMA_DEVICE_ID_SIZE,
+ chip_unique_id, chip_unique_id_size);
+ if (ret != EC_SUCCESS)
+ return ret;
}
+ return EC_SUCCESS;
}
/**
@@ -217,6 +229,7 @@ int rma_create_challenge(void)
struct board_id bid;
uint8_t *cptr = (uint8_t *)&c;
uint64_t t;
+ int ret;
/* Clear the current challenge and authcode, if any */
memset(challenge, 0, sizeof(challenge));
@@ -236,9 +249,11 @@ int rma_create_challenge(void)
return EC_ERROR_UNKNOWN;
memcpy(c.board_id, &bid.type, sizeof(c.board_id));
- get_rma_device_id(c.device_id);
+ ret = get_rma_device_id(c.device_id);
+ if (ret != EC_SUCCESS)
+ return ret;
- /* Calculate a new ephemeral key pair and the shared secret. */
+ /* Calculate a new ephemeral key pair and the shared secret. */
#ifdef CONFIG_RMA_AUTH_USE_P256
if (p256_get_pub_key_and_secret(c.device_pub_key, secret) != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
@@ -251,13 +266,15 @@ int rma_create_challenge(void)
if (base32_encode(challenge, sizeof(challenge), cptr, 8 * sizeof(c), 9))
return EC_ERROR_UNKNOWN;
-
/*
* Auth code is a truncated HMAC of the ephemeral public key, BoardID,
* and DeviceID. Those are all in the right order in the challenge
* struct, after the version/key id byte.
*/
- get_hmac_sha256(temp, secret, sizeof(secret), cptr + 1, sizeof(c) - 1);
+ ret = get_hmac_sha256(temp, secret, sizeof(secret), cptr + 1,
+ sizeof(c) - 1);
+ if (ret != EC_SUCCESS)
+ return ret;
if (base32_encode(authcode, sizeof(authcode), temp,
RMA_AUTHCODE_CHARS * 5, 0))
return EC_ERROR_UNKNOWN;