summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-10-12 14:53:04 -0700
committerCommit Bot <commit-bot@chromium.org>2021-10-14 00:57:16 +0000
commit1ad3e00b6c6e67676d5a1de9689c18bfca31aa1a (patch)
tree4b2d98b4fa1452c25ee79c4eed04c730712b5bf8
parent307b3dc3c0a294d2245ea7e9475f548077a98c3b (diff)
downloadchrome-ec-1ad3e00b6c6e67676d5a1de9689c18bfca31aa1a.tar.gz
cr50: cleanup public API for FIPS module
Move declarations of AES-GCM, AES-CMAC, ECIES, HKDF and few other functions from dcrypto.h into internal.h. Merge tpm2/hkdf.c into dcrypto/hkdf.c. It contains only function used for testing and HKDF itself is only used for CRYPTO_TEST=1. BUG=b:134594373 TEST=make buildall -j; make BOARD=cr50 CRYPTO_TEST=1 Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: I56c03ff4e8838871cdb28c0d9946c39754d9e054 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3219576 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/build.mk1
-rw-r--r--board/cr50/dcrypto/dcrypto.h128
-rw-r--r--board/cr50/dcrypto/hkdf.c87
-rw-r--r--board/cr50/dcrypto/internal.h108
-rw-r--r--board/cr50/tpm2/aes.c1
-rw-r--r--board/cr50/tpm2/hkdf.c94
6 files changed, 213 insertions, 206 deletions
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index 6080e9c173..a7bde7a688 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -172,7 +172,6 @@ board-y += tpm2/ecc.o
board-y += tpm2/endorsement.o
board-y += tpm2/hash.o
board-y += tpm2/hash_data.o
-board-y += tpm2/hkdf.o
board-y += tpm2/manufacture.o
board-y += tpm2/nvmem_ops.o
board-y += tpm2/platform.o
diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h
index 3712f56fc4..cef877969a 100644
--- a/board/cr50/dcrypto/dcrypto.h
+++ b/board/cr50/dcrypto/dcrypto.h
@@ -315,7 +315,7 @@ enum dcrypto_result DCRYPTO_sw_hash_init(
union hash_ctx *ctx, enum hashing_mode mode) __warn_unused_result;
/**
- * Initialize hardware-acceleated or software version of hash computation,
+ * Initialize hardware-accelerated or software version of hash computation,
* preferring hardware version when available.
*
* @param ctx storage for context
@@ -349,7 +349,7 @@ enum dcrypto_result DCRYPTO_sw_hmac_init(union hmac_ctx *ctx, const void *key,
__warn_unused_result;
/**
- * Initialize hardware-acceleated or software version of HMAC computation,
+ * Initialize hardware-accelerated or software version of HMAC computation,
* preferring hardware version when available.
*
* @param ctx storage for context
@@ -404,7 +404,7 @@ __always_inline void HASH_update(union hash_ctx *const ctx, const void *data,
}
/**
* Finalize hash computation by adding padding, message length.
- * Returns pointer to computed digest stored inside provided context.
+ * Returns pointer to the computed digest stored inside the provided context.
*
* @param ctx digest context (can be one of union subtypes).
*
@@ -430,7 +430,7 @@ __always_inline void SHA256_update(struct sha256_ctx *const ctx,
/**
* Finalize hash computation by adding padding, message length.
- * Returns pointer to computed digest stored inside provided context.
+ * Returns pointer to the computed digest stored inside the provided context.
*
* @param ctx SHA256 digest context.
*
@@ -632,68 +632,6 @@ enum dcrypto_result DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key,
void DCRYPTO_aes_write_iv(const uint8_t *iv);
void DCRYPTO_aes_read_iv(uint8_t *iv);
-/* AES-GCM-128/192/256
- * NIST Special Publication 800-38D, IV is provided externally
- * Caller should use IV length according to section 8.2 of SP 800-38D
- * And choose appropriate IV construction method, constrain number
- * of invocations according to section 8.3 of SP 800-38D
- */
-struct GCM_CTX {
- union {
- uint32_t d[4];
- uint8_t c[16];
- } block, Ej0;
-
- uint64_t aad_len;
- uint64_t count;
- size_t remainder;
-};
-
-/* Initialize the GCM context structure. */
-void DCRYPTO_gcm_init(struct GCM_CTX *ctx, uint32_t key_bits,
- const uint8_t *key, const uint8_t *iv, size_t iv_len);
-/* Additional authentication data to include in the tag calculation. */
-void DCRYPTO_gcm_aad(struct GCM_CTX *ctx, const uint8_t *aad_data, size_t len);
-/* Encrypt & decrypt return the number of bytes written to out
- * (always an integral multiple of 16), or -1 on error. These functions
- * may be called repeatedly with incremental data.
- *
- * NOTE: if in_len is not a integral multiple of 16, then out_len must
- * be atleast in_len - (in_len % 16) + 16 bytes.
- */
-int DCRYPTO_gcm_encrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
- const uint8_t *in, size_t in_len);
-int DCRYPTO_gcm_decrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
- const uint8_t *in, size_t in_len);
-/* Encrypt & decrypt a partial final block, if any. These functions
- * return the number of bytes written to out (<= 15), or -1 on error.
- */
-int DCRYPTO_gcm_encrypt_final(struct GCM_CTX *ctx, uint8_t *out,
- size_t out_len);
-int DCRYPTO_gcm_decrypt_final(struct GCM_CTX *ctx, uint8_t *out,
- size_t out_len);
-/* Compute the tag over AAD + encrypt or decrypt data, and return the
- * number of bytes written to tag. Returns -1 on error.
- */
-int DCRYPTO_gcm_tag(struct GCM_CTX *ctx, uint8_t *tag, size_t tag_len);
-/* Cleanup secrets. */
-void DCRYPTO_gcm_finish(struct GCM_CTX *ctx);
-
-/* AES-CMAC-128
- * NIST Special Publication 800-38B, RFC 4493
- * K: 128-bit key, M: message, len: number of bytes in M
- * Writes 128-bit tag to T; returns 0 if an error is encountered and 1
- * otherwise.
- */
-enum dcrypto_result DCRYPTO_aes_cmac(const uint8_t *K, const uint8_t *M,
- size_t len, uint32_t T[4]);
-/* key: 128-bit key, M: message, len: number of bytes in M,
- * T: tag to be verified
- * Returns 1 if the tag is correct and 0 otherwise.
- */
-enum dcrypto_result DCRYPTO_aes_cmac_verify(const uint8_t *key,
- const uint8_t *M, size_t len,
- const uint32_t T[4]);
/*
* BIGNUM utility methods.
@@ -959,37 +897,6 @@ enum dcrypto_result DCRYPTO_p256_ecdsa_sign(const p256_int *key,
/************************************************************/
-/* P256 based integration encryption (DH+AES128+SHA256).
- * Not FIPS 140-2 compliant, not used other than for tests
- * Authenticated data may be provided, where the first auth_data_len
- * bytes of in will be authenticated but not encrypted. *
- * Supports in-place encryption / decryption. *
- * The output format is:
- * 0x04 || PUBKEY || AUTH_DATA || AES128_CTR(PLAINTEXT) ||
- * HMAC_SHA256(AUTH_DATA || CIPHERTEXT)
- */
-size_t DCRYPTO_ecies_encrypt(void *out, size_t out_len, const void *in,
- size_t in_len, size_t auth_data_len,
- const uint8_t *iv, const p256_int *pub_x,
- const p256_int *pub_y, const uint8_t *salt,
- size_t salt_len, const uint8_t *info,
- size_t info_len);
-size_t DCRYPTO_ecies_decrypt(void *out, size_t out_len, const void *in,
- size_t in_len, size_t auth_data_len,
- const uint8_t *iv, const p256_int *d,
- const uint8_t *salt, size_t salt_len,
- const uint8_t *info, size_t info_len);
-
-/*
- * HKDF as per RFC 5869. Mentioned as conforming NIST SP 800-56C Rev.1
- * [RFC 5869] specifies a version of the above extraction-then-expansion
- * key-derivation procedure using HMAC for both the extraction and expansion
- * steps.
- */
-int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, const uint8_t *salt,
- size_t salt_len, const uint8_t *IKM, size_t IKM_len,
- const uint8_t *info, size_t info_len);
-
/*
* BN.
*/
@@ -998,9 +905,12 @@ int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, const uint8_t *salt,
* Returns DCRYPTO_OK if test passed, DCRYPTO_FAIL otherwise
*/
enum dcrypto_result DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p);
-void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len);
+
+/* Compute c = a * b. */
void DCRYPTO_bn_mul(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a,
const struct LITE_BIGNUM *b);
+
+/* Compute (quotient, remainder) = input / divisor. */
int DCRYPTO_bn_div(struct LITE_BIGNUM *quotient, struct LITE_BIGNUM *remainder,
const struct LITE_BIGNUM *input,
const struct LITE_BIGNUM *divisor);
@@ -1015,7 +925,7 @@ size_t DCRYPTO_asn1_pubp(uint8_t *buf, const p256_int *x, const p256_int *y);
* X509.
*/
/* DCRYPTO_x509_verify verifies that the provided X509 certificate was issued
- * by the specified certifcate authority.
+ * by the specified certificate authority.
*
* cert is a pointer to a DER encoded X509 certificate, as specified
* in https://tools.ietf.org/html/rfc5280#section-4.1. In ASN.1
@@ -1083,11 +993,19 @@ enum dcrypto_appid {
/* This enum value should not exceed 7. */
};
+/* Retrieve Firmware Root Key from hardware key ladder. */
int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2);
+
+/* Revoke access to hardware key ladder. */
void DCRYPTO_ladder_revoke(void);
+/* Preload application specific secret into key ladder register. */
int DCRYPTO_appkey_init(enum dcrypto_appid id);
+
+/* Clean-up secret loaded from key ladder. */
void DCRYPTO_appkey_finish(void);
+
+/* Compute application-specific, hardware-bound constant. */
int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
uint32_t output[8]);
@@ -1139,23 +1057,11 @@ int DCRYPTO_ladder_is_enabled(void);
void fips_init_trng(void);
/**
- * Returns random number from TRNG with indication wherever reading is valid.
- * This is different from rand() which doesn't provide any indication.
- * High 32-bits set to zero in case of error; otherwise value >> 32 == 1
- * Use of uint64_t vs. struct results in more efficient code.
- * Random is passed continuous TRNG health tests.
- *
- * @return uint64_t, low 32 bits - random high 32 bits - validity status
- */
-uint64_t fips_trng_rand32(void);
-
-/**
* Return true if fips_trng_rand() result contains valid random from TRNG.
* @param rand value from fips_trng_rand32() or read_rand()
*
* @return true if rand contains valid random
*/
-
inline bool rand_valid(uint64_t rand)
{
return (rand >> 32) != 0;
diff --git a/board/cr50/dcrypto/hkdf.c b/board/cr50/dcrypto/hkdf.c
index 8e06455337..83c29c865f 100644
--- a/board/cr50/dcrypto/hkdf.c
+++ b/board/cr50/dcrypto/hkdf.c
@@ -78,3 +78,90 @@ int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len,
always_memset(PRK, 0, sizeof(PRK));
return result;
}
+
+#ifdef CRYPTO_TEST_SETUP
+
+#include "extension.h"
+
+enum {
+ TEST_RFC = 0,
+};
+
+#define MAX_OKM_BYTES 1024
+
+static void hkdf_command_handler(void *cmd_body,
+ size_t cmd_size,
+ size_t *response_size)
+{
+ uint8_t *cmd;
+ uint8_t *out;
+ uint8_t op;
+ size_t salt_len;
+ const uint8_t *salt;
+ size_t IKM_len;
+ const uint8_t *IKM;
+ size_t info_len;
+ const uint8_t *info;
+ size_t OKM_len;
+ uint8_t OKM[MAX_OKM_BYTES];
+
+ /* Command format.
+ *
+ * WIDTH FIELD
+ * 1 OP
+ * 1 MSB SALT LEN
+ * 1 LSB SALT LEN
+ * SALT_LEN SALT
+ * 1 MSB IKM LEN
+ * 1 LSB IKM LEN
+ * IKM_LEN IKM
+ * 1 MSB INFO LEN
+ * 1 LSB INFO LEN
+ * INFO_LEN INFO
+ * 1 MSB OKM LEN
+ * 1 LSB OKM LEN
+ */
+ cmd = (uint8_t *) cmd_body;
+ out = (uint8_t *) cmd_body;
+ op = *cmd++;
+
+ salt_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
+ cmd += 2;
+ salt = cmd;
+ cmd += salt_len;
+
+ IKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
+ cmd += 2;
+ IKM = cmd;
+ cmd += IKM_len;
+
+ info_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
+ cmd += 2;
+ info = cmd;
+ cmd += info_len;
+
+ OKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
+
+ if (OKM_len > MAX_OKM_BYTES) {
+ *response_size = 0;
+ return;
+ }
+
+ switch (op) {
+ case TEST_RFC:
+ if (DCRYPTO_hkdf(OKM, OKM_len, salt, salt_len,
+ IKM, IKM_len, info, info_len)) {
+ memcpy(out, OKM, OKM_len);
+ *response_size = OKM_len;
+ } else {
+ *response_size = 0;
+ }
+ break;
+ default:
+ *response_size = 0;
+ }
+}
+
+DECLARE_EXTENSION_COMMAND(EXTENSION_HKDF, hkdf_command_handler);
+
+#endif /* CRYPTO_TEST_SETUP */
diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h
index 1fb66f710c..706baeaa17 100644
--- a/board/cr50/dcrypto/internal.h
+++ b/board/cr50/dcrypto/internal.h
@@ -308,6 +308,19 @@ uint64_t read_rand(void);
*/
bool fips_trng_startup(int stage);
+
+
+/**
+ * Returns random number from TRNG with indication wherever reading is valid.
+ * This is different from rand() which doesn't provide any indication.
+ * High 32-bits set to zero in case of error; otherwise value >> 32 == 1
+ * Use of uint64_t vs. struct results in more efficient code.
+ * Random is passed continuous TRNG health tests.
+ *
+ * @return uint64_t, low 32 bits - random high 32 bits - validity status
+ */
+uint64_t fips_trng_rand32(void);
+
/**
* Check that Cr50-wide HMAC_DRBG seeded according NIST SP 800-90A
* recomendation is properly initialized and can be used.
@@ -494,6 +507,101 @@ void dcrypto_imem_load(size_t offset, const uint32_t *opcodes,
*/
uint32_t dcrypto_dmem_load(size_t offset, const void *words, size_t n_words);
+/* P256 based integration encryption (DH+AES128+SHA256).
+ * Not FIPS 140-2 compliant, not used other than for tests
+ * Authenticated data may be provided, where the first auth_data_len
+ * bytes of in will be authenticated but not encrypted. *
+ * Supports in-place encryption / decryption. *
+ * The output format is:
+ * 0x04 || PUBKEY || AUTH_DATA || AES128_CTR(PLAINTEXT) ||
+ * HMAC_SHA256(AUTH_DATA || CIPHERTEXT)
+ */
+size_t DCRYPTO_ecies_encrypt(void *out, size_t out_len, const void *in,
+ size_t in_len, size_t auth_data_len,
+ const uint8_t *iv, const p256_int *pub_x,
+ const p256_int *pub_y, const uint8_t *salt,
+ size_t salt_len, const uint8_t *info,
+ size_t info_len);
+size_t DCRYPTO_ecies_decrypt(void *out, size_t out_len, const void *in,
+ size_t in_len, size_t auth_data_len,
+ const uint8_t *iv, const p256_int *d,
+ const uint8_t *salt, size_t salt_len,
+ const uint8_t *info, size_t info_len);
+
+/*
+ * HKDF as per RFC 5869. Mentioned as conforming NIST SP 800-56C Rev.1
+ * [RFC 5869] specifies a version of the above extraction-then-expansion
+ * key-derivation procedure using HMAC for both the extraction and expansion
+ * steps.
+ */
+int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, const uint8_t *salt,
+ size_t salt_len, const uint8_t *IKM, size_t IKM_len,
+ const uint8_t *info, size_t info_len);
+
+
+/* AES-GCM-128/192/256
+ * NIST Special Publication 800-38D, IV is provided externally
+ * Caller should use IV length according to section 8.2 of SP 800-38D
+ * And choose appropriate IV construction method, constrain number
+ * of invocations according to section 8.3 of SP 800-38D
+ */
+struct GCM_CTX {
+ union {
+ uint32_t d[4];
+ uint8_t c[16];
+ } block, Ej0;
+
+ uint64_t aad_len;
+ uint64_t count;
+ size_t remainder;
+};
+
+/* Initialize the GCM context structure. */
+void DCRYPTO_gcm_init(struct GCM_CTX *ctx, uint32_t key_bits,
+ const uint8_t *key, const uint8_t *iv, size_t iv_len);
+/* Additional authentication data to include in the tag calculation. */
+void DCRYPTO_gcm_aad(struct GCM_CTX *ctx, const uint8_t *aad_data, size_t len);
+/* Encrypt & decrypt return the number of bytes written to out
+ * (always an integral multiple of 16), or -1 on error. These functions
+ * may be called repeatedly with incremental data.
+ *
+ * NOTE: if in_len is not a integral multiple of 16, then out_len must
+ * be at least in_len - (in_len % 16) + 16 bytes.
+ */
+int DCRYPTO_gcm_encrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
+ const uint8_t *in, size_t in_len);
+int DCRYPTO_gcm_decrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
+ const uint8_t *in, size_t in_len);
+/* Encrypt & decrypt a partial final block, if any. These functions
+ * return the number of bytes written to out (<= 15), or -1 on error.
+ */
+int DCRYPTO_gcm_encrypt_final(struct GCM_CTX *ctx, uint8_t *out,
+ size_t out_len);
+int DCRYPTO_gcm_decrypt_final(struct GCM_CTX *ctx, uint8_t *out,
+ size_t out_len);
+/* Compute the tag over AAD + encrypt or decrypt data, and return the
+ * number of bytes written to tag. Returns -1 on error.
+ */
+int DCRYPTO_gcm_tag(struct GCM_CTX *ctx, uint8_t *tag, size_t tag_len);
+/* Cleanup secrets. */
+void DCRYPTO_gcm_finish(struct GCM_CTX *ctx);
+
+/* AES-CMAC-128
+ * NIST Special Publication 800-38B, RFC 4493
+ * K: 128-bit key, M: message, len: number of bytes in M
+ * Writes 128-bit tag to T; returns 0 if an error is encountered and 1
+ * otherwise.
+ */
+enum dcrypto_result DCRYPTO_aes_cmac(const uint8_t *K, const uint8_t *M,
+ size_t len, uint32_t T[4]);
+/* key: 128-bit key, M: message, len: number of bytes in M,
+ * T: tag to be verified
+ * Returns 1 if the tag is correct and 0 otherwise.
+ */
+enum dcrypto_result DCRYPTO_aes_cmac_verify(const uint8_t *key,
+ const uint8_t *M, size_t len,
+ const uint32_t T[4]);
+
#ifndef __alias
#define __alias(func) __attribute__((alias(#func)))
diff --git a/board/cr50/tpm2/aes.c b/board/cr50/tpm2/aes.c
index f515d0364b..56e3cbbb3b 100644
--- a/board/cr50/tpm2/aes.c
+++ b/board/cr50/tpm2/aes.c
@@ -216,6 +216,7 @@ CRYPT_RESULT _cpri__AESEncryptOFB(
#include "extension.h"
#include "hooks.h"
#include "uart.h"
+#include "internal.h"
enum aes_test_cipher_mode {
TEST_MODE_ECB = 0,
diff --git a/board/cr50/tpm2/hkdf.c b/board/cr50/tpm2/hkdf.c
deleted file mode 100644
index d950d865ab..0000000000
--- a/board/cr50/tpm2/hkdf.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Copyright 2016 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 "dcrypto.h"
-#include "util.h"
-
-#ifdef CRYPTO_TEST_SETUP
-
-#include "extension.h"
-
-enum {
- TEST_RFC = 0,
-};
-
-#define MAX_OKM_BYTES 1024
-
-static void hkdf_command_handler(void *cmd_body,
- size_t cmd_size,
- size_t *response_size)
-{
- uint8_t *cmd;
- uint8_t *out;
- uint8_t op;
- size_t salt_len;
- const uint8_t *salt;
- size_t IKM_len;
- const uint8_t *IKM;
- size_t info_len;
- const uint8_t *info;
- size_t OKM_len;
- uint8_t OKM[MAX_OKM_BYTES];
-
- /* Command format.
- *
- * WIDTH FIELD
- * 1 OP
- * 1 MSB SALT LEN
- * 1 LSB SALT LEN
- * SALT_LEN SALT
- * 1 MSB IKM LEN
- * 1 LSB IKM LEN
- * IKM_LEN IKM
- * 1 MSB INFO LEN
- * 1 LSB INFO LEN
- * INFO_LEN INFO
- * 1 MSB OKM LEN
- * 1 LSB OKM LEN
- */
- cmd = (uint8_t *) cmd_body;
- out = (uint8_t *) cmd_body;
- op = *cmd++;
-
- salt_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
- cmd += 2;
- salt = cmd;
- cmd += salt_len;
-
- IKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
- cmd += 2;
- IKM = cmd;
- cmd += IKM_len;
-
- info_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
- cmd += 2;
- info = cmd;
- cmd += info_len;
-
- OKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
-
- if (OKM_len > MAX_OKM_BYTES) {
- *response_size = 0;
- return;
- }
-
- switch (op) {
- case TEST_RFC:
- if (DCRYPTO_hkdf(OKM, OKM_len, salt, salt_len,
- IKM, IKM_len, info, info_len)) {
- memcpy(out, OKM, OKM_len);
- *response_size = OKM_len;
- } else {
- *response_size = 0;
- }
- break;
- default:
- *response_size = 0;
- }
-}
-
-DECLARE_EXTENSION_COMMAND(EXTENSION_HKDF, hkdf_command_handler);
-
-#endif /* CRYPTO_TEST_SETUP */