summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-07-30 08:40:32 -0700
committerCommit Bot <commit-bot@chromium.org>2021-08-12 14:18:48 +0000
commit7ddbd2a9eab0dc54897d6b5bb8ee1d4b3be1fe27 (patch)
tree43356bb71d38ea7f5ea1639855ac3b322d460176
parent43f6e7be087720507e57cf27e9460aae64c3b69a (diff)
downloadchrome-ec-release-R94-14150.49.B-cr50_stab.tar.gz
To implement FIPS module we need to bring many crypto functions in the module boundary. Unfortunately, cryptoc is a third-party library used by dcrypto code in cr50. Cryptoc is also not well-maintained and shared with other projects. While just making local copy of cryptoc would solve an issue, it's suboptimal as prevents from many optimizations and improvements. Provided SHA & HMAC implementations from Ti50 project. This provides better performance (500us vs. 670us earlier for HMAC DRBG) and reduce code size. This implementation also enables stack use savings when only specific digest is needed. Earlier SHA512 context was allocated when only SHA256 is needed greatly increasing stack consumption for code using HMAC_DRBG and others. However, it introduce subtle API changes which require handling. As for tests, since core implementation is hardware-independent, make it available for BOARD=host too. Before change (with cryptoc): *** 12368 bytes in flash and 5784 bytes in RAM After: *** 13136 bytes in flash and 5796 bytes in RAM BUG=b:138578318 TEST=make BOARD=cr50 CRYPTO_TEST=1; test/tpm_test/tpmtest.py Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: I2ff5362aee9078ce83dc1f8081943a5101d5f666 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3064201 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Auto-Submit: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-rw-r--r--board/cr50/board.c2
-rw-r--r--board/cr50/build.mk11
-rw-r--r--board/cr50/dcrypto/app_key.c37
-rw-r--r--board/cr50/dcrypto/dcrypto.h168
-rw-r--r--board/cr50/dcrypto/dcrypto_runtime.c8
-rw-r--r--board/cr50/dcrypto/hkdf.c22
-rw-r--r--board/cr50/dcrypto/hmac.c62
-rw-r--r--board/cr50/dcrypto/hmac_drbg.c40
-rw-r--r--board/cr50/dcrypto/hmac_sw.c72
-rw-r--r--board/cr50/dcrypto/hmacsha2.h490
-rw-r--r--board/cr50/dcrypto/internal.h56
-rw-r--r--board/cr50/dcrypto/p256_ecies.c8
-rw-r--r--board/cr50/dcrypto/rsa.c59
-rw-r--r--board/cr50/dcrypto/sha1.c158
-rw-r--r--board/cr50/dcrypto/sha256.c337
-rw-r--r--board/cr50/dcrypto/sha384.c20
-rw-r--r--board/cr50/dcrypto/sha512.c249
-rw-r--r--board/cr50/dcrypto/sha_hw.c265
-rw-r--r--board/cr50/dcrypto/x509.c14
-rw-r--r--board/cr50/fips.c35
-rw-r--r--board/cr50/tpm2/ecc.c9
-rw-r--r--board/cr50/tpm2/endorsement.c14
-rw-r--r--board/cr50/tpm2/hash.c42
-rw-r--r--board/cr50/tpm2/rsa.c8
-rw-r--r--board/cr50/tpm2/virtual_nvmem.c12
-rw-r--r--board/cr50/u2f.c8
-rw-r--r--board/cr50/usb_spi.c17
-rw-r--r--board/cr50/usb_spi_board.h11
-rw-r--r--board/host/dcrypto.h27
-rw-r--r--builtin/endian.h4
-rw-r--r--chip/g/usb_spi.h6
-rw-r--r--chip/host/build.mk20
-rw-r--r--chip/host/dcrypto/app_cipher.c6
-rw-r--r--chip/host/dcrypto/sha256.c22
-rw-r--r--common/ap_ro_integrity_check.c4
-rw-r--r--common/ccd_config.c13
-rw-r--r--common/pinweaver.c46
-rw-r--r--common/rma_auth.c16
-rw-r--r--common/u2f.c54
-rw-r--r--fuzz/mem_hash_tree.cc18
-rw-r--r--test/pinweaver.c23
-rw-r--r--test/test_config.h2
-rw-r--r--test/u2f.c34
43 files changed, 1799 insertions, 730 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 71453e888e..80ec7b623e 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -48,8 +48,6 @@
/* Define interrupt and gpio structs */
#include "gpio_list.h"
-#include "cryptoc/sha.h"
-
/*
* Need to include Implementation.h here to make sure that NVRAM size
* definitions match across different git repos.
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index d1bbc4a517..6d5996ddc5 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -70,16 +70,16 @@ ifneq ($(CRYPTO_TEST),)
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/gcm.o
endif
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hkdf.o
-fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hmac.o
+fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hmac_sw.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hmac_drbg.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/key_ladder.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/p256.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/p256_ec.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/rsa.o
+fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/sha_hw.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/sha1.o
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/sha256.o
ifeq ($(CONFIG_UPTO_SHA512),y)
-fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/sha384.o
ifeq ($(CONFIG_DCRYPTO_SHA512),y)
fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/dcrypto_sha512.o
else
@@ -145,16 +145,13 @@ CPPFLAGS += -I$(abspath .)
CPPFLAGS += -I$(abspath $(BDIR))
CPPFLAGS += -I$(abspath ./fuzz)
CPPFLAGS += -I$(abspath ./test)
-ifeq ($(CONFIG_UPTO_SHA512),y)
-CPPFLAGS += -DSHA512_SUPPORT
-endif
# Make sure the context of the software sha512 implementation fits. If it ever
# increases, a compile time assert will fire in tpm2/hash.c.
ifeq ($(CONFIG_UPTO_SHA512),y)
-CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=208
+CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=200
else
-CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=112
+CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=104
endif
# Configure TPM2 headers accordingly.
CFLAGS += -DEMBEDDED_MODE=1
diff --git a/board/cr50/dcrypto/app_key.c b/board/cr50/dcrypto/app_key.c
index f655471f69..0bc7620ed7 100644
--- a/board/cr50/dcrypto/app_key.c
+++ b/board/cr50/dcrypto/app_key.c
@@ -21,9 +21,8 @@ const char *const dcrypto_app_names[] = {
};
static void name_hash(enum dcrypto_appid appid,
- uint32_t digest[SHA256_DIGEST_WORDS])
+ struct sha256_digest *digest)
{
- LITE_SHA256_CTX ctx;
const char *name = dcrypto_app_names[appid];
size_t x;
@@ -31,20 +30,18 @@ static void name_hash(enum dcrypto_appid appid,
* exists to prevent data loss.
*/
if (appid == PERSO_AUTH) {
- digest[0] = 0x2019da34;
- digest[1] = 0xf1a01a13;
- digest[2] = 0x0fb9f73f;
- digest[3] = 0xf2e85f76;
- digest[4] = 0x5ecb7690;
- digest[5] = 0x09f732c9;
- digest[6] = 0xe540bf14;
- digest[7] = 0xcc46799a;
+ digest->b32[0] = 0x2019da34;
+ digest->b32[1] = 0xf1a01a13;
+ digest->b32[2] = 0x0fb9f73f;
+ digest->b32[3] = 0xf2e85f76;
+ digest->b32[4] = 0x5ecb7690;
+ digest->b32[5] = 0x09f732c9;
+ digest->b32[6] = 0xe540bf14;
+ digest->b32[7] = 0xcc46799a;
return;
}
- DCRYPTO_SHA256_init(&ctx, 0);
- HASH_update(&ctx, name, strlen(name));
- memcpy(digest, HASH_final(&ctx), SHA256_DIGEST_SIZE);
+ SHA256_hw_hash(name, strlen(name), digest);
/* The digests were originally endian swapped because xxd was used to
* print them so this operation is needed to keep the derived keys the
@@ -53,17 +50,17 @@ static void name_hash(enum dcrypto_appid appid,
* effectively be reset and user data will be lost by the key change.
*/
for (x = 0; x < SHA256_DIGEST_WORDS; ++x)
- digest[x] = __builtin_bswap32(digest[x]);
+ digest->b32[x] = __builtin_bswap32(digest->b32[x]);
}
int DCRYPTO_appkey_init(enum dcrypto_appid appid, struct APPKEY_CTX *ctx)
{
- uint32_t digest[SHA256_DIGEST_WORDS];
+ struct sha256_digest digest;
memset(ctx, 0, sizeof(*ctx));
- name_hash(appid, digest);
+ name_hash(appid, &digest);
- if (!dcrypto_ladder_compute_usr(appid, digest))
+ if (!dcrypto_ladder_compute_usr(appid, digest.b32))
return 0;
return 1;
@@ -78,8 +75,8 @@ void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx)
int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
uint32_t output[8])
{
- uint32_t digest[SHA256_DIGEST_WORDS];
+ struct sha256_digest digest;
- name_hash(appid, digest);
- return !!dcrypto_ladder_derive(appid, digest, input, output);
+ name_hash(appid, &digest);
+ return !!dcrypto_ladder_derive(appid, digest.b32, input, output);
}
diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h
index 8cf1071090..ef3c778398 100644
--- a/board/cr50/dcrypto/dcrypto.h
+++ b/board/cr50/dcrypto/dcrypto.h
@@ -6,51 +6,44 @@
/*
* Crypto wrapper library for the g chip.
*/
-#ifndef __EC_CHIP_G_DCRYPTO_DCRYPTO_H
-#define __EC_CHIP_G_DCRYPTO_DCRYPTO_H
+#ifndef __EC_BOARD_CR50_DCRYPTO_DCRYPTO_H
+#define __EC_BOARD_CR50_DCRYPTO_DCRYPTO_H
#ifdef __cplusplus
extern "C" {
#endif
-#if defined(TEST_FUZZ) || !defined(TEST_BUILD)
-
#include "internal.h"
#include "crypto_api.h"
#include <stddef.h>
-#include "cryptoc/hmac.h"
-
enum cipher_mode {
CIPHER_MODE_ECB = 0, /* NIST SP 800-38A */
CIPHER_MODE_CTR = 1, /* NIST SP 800-38A */
CIPHER_MODE_CBC = 2, /* NIST SP 800-38A */
- CIPHER_MODE_GCM = 3 /* NIST SP 800-38D */
+ CIPHER_MODE_GCM = 3 /* NIST SP 800-38D */
};
-enum encrypt_mode {
- DECRYPT_MODE = 0,
- ENCRYPT_MODE = 1
-};
+enum encrypt_mode { DECRYPT_MODE = 0, ENCRYPT_MODE = 1 };
enum hashing_mode {
HASH_SHA1 = 0,
HASH_SHA256 = 1,
- HASH_SHA384 = 2, /* Only supported for PKCS#1 signing */
- HASH_SHA512 = 3, /* Only supported for PKCS#1 signing */
- HASH_NULL = 4 /* Only supported for PKCS#1 signing */
+ HASH_SHA384 = 2, /* Only supported for PKCS#1 signing */
+ HASH_SHA512 = 3, /* Only supported for PKCS#1 signing */
+ HASH_NULL = 4 /* Only supported for PKCS#1 signing */
};
/*
* AES implementation, based on a hardware AES block.
* FIPS Publication 197, The Advanced Encryption Standard (AES)
*/
-#define AES256_BLOCK_CIPHER_KEY_SIZE 32
+#define AES256_BLOCK_CIPHER_KEY_SIZE 32
int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv,
- enum cipher_mode c_mode, enum encrypt_mode e_mode);
+ enum cipher_mode c_mode, enum encrypt_mode e_mode);
int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out);
void DCRYPTO_aes_write_iv(const uint8_t *iv);
@@ -60,7 +53,7 @@ void DCRYPTO_aes_read_iv(uint8_t *iv);
* NIST Special Publication 800-38A
*/
int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
- const uint8_t *iv, const uint8_t *in, size_t in_len);
+ const uint8_t *iv, const uint8_t *in, size_t in_len);
/* AES-GCM-128/192/256
* NIST Special Publication 800-38D, IV is provided externally
@@ -81,7 +74,7 @@ struct GCM_CTX {
/* 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);
+ 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
@@ -98,10 +91,10 @@ int DCRYPTO_gcm_decrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_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);
+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.
*/
@@ -116,13 +109,13 @@ void DCRYPTO_gcm_finish(struct GCM_CTX *ctx);
* otherwise.
*/
int DCRYPTO_aes_cmac(const uint8_t *K, const uint8_t *M, const uint32_t len,
- uint32_t T[4]);
+ 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.
*/
int DCRYPTO_aes_cmac_verify(const uint8_t *key, const uint8_t *M, const int len,
- const uint32_t T[4]);
+ const uint32_t T[4]);
/*
* SHA implementation. This abstraction is backed by either a
@@ -133,27 +126,35 @@ int DCRYPTO_aes_cmac_verify(const uint8_t *key, const uint8_t *M, const int len,
* is TRUE, in which case there will be no attempt to use the hardware for
* this particular hashing session.
*/
-void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required);
-/* SHA256/384/512 FIPS 180-4
- */
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required);
-void DCRYPTO_SHA384_init(LITE_SHA384_CTX *ctx);
-void DCRYPTO_SHA512_init(LITE_SHA512_CTX *ctx);
-const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n,
- uint8_t *digest);
-const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
- uint8_t *digest);
-const uint8_t *DCRYPTO_SHA384_hash(const void *data, uint32_t n,
- uint8_t *digest);
-const uint8_t *DCRYPTO_SHA512_hash(const void *data, uint32_t n,
- uint8_t *digest);
+
+void SHA1_hw_init(struct sha1_ctx *ctx);
+void SHA256_hw_init(struct sha256_ctx *ctx);
+const struct sha1_digest *SHA1_hw_hash(const void *data, size_t len,
+ struct sha1_digest *digest);
+const struct sha256_digest *SHA256_hw_hash(const void *data, size_t len,
+ struct sha256_digest *digest);
+#ifdef CONFIG_UPTO_SHA512
+void SHA384_hw_init(struct sha384_ctx *ctx);
+void SHA512_hw_init(struct sha512_ctx *ctx);
+const struct sha384_digest *SHA384_hw_hash(const void *data, size_t len,
+ struct sha384_digest *digest);
+
+const struct sha512_digest *SHA512_hw_hash(const void *data, size_t len,
+ struct sha512_digest *digest);
+#endif
+
+const uint8_t *DCRYPTO_SHA1_hash(const void *data, size_t n, uint8_t *digest);
+
+/* TODO: remove dependency on board/cr50/dcrypto/dcrypto.h for RO. */
+const uint8_t *DCRYPTO_SHA256_hash(const void *data, size_t n, uint8_t *digest);
+
/*
* HMAC. FIPS 198-1
*/
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len);
+void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
+ size_t len);
/* DCRYPTO HMAC-SHA256 final */
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx);
+const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx);
/*
* BIGNUM utility methods.
@@ -170,15 +171,15 @@ void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len);
* is not required, and enabling support would result in increased
* stack usage for all key sizes.)
*/
-#define RSA_BYTES_2K 256
-#define RSA_BYTES_4K 512
-#define RSA_WORDS_2K (RSA_BYTES_2K / sizeof(uint32_t))
-#define RSA_WORDS_4K (RSA_BYTES_4K / sizeof(uint32_t))
+#define RSA_BYTES_2K 256
+#define RSA_BYTES_4K 512
+#define RSA_WORDS_2K (RSA_BYTES_2K / sizeof(uint32_t))
+#define RSA_WORDS_4K (RSA_BYTES_4K / sizeof(uint32_t))
#ifndef RSA_MAX_BYTES
-#define RSA_MAX_BYTES RSA_BYTES_2K
+#define RSA_MAX_BYTES RSA_BYTES_2K
#endif
-#define RSA_MAX_WORDS (RSA_MAX_BYTES / sizeof(uint32_t))
-#define RSA_F4 65537
+#define RSA_MAX_WORDS (RSA_MAX_BYTES / sizeof(uint32_t))
+#define RSA_F4 65537
struct RSA {
uint32_t e;
@@ -188,11 +189,11 @@ struct RSA {
enum padding_mode {
PADDING_MODE_PKCS1 = 0,
- PADDING_MODE_OAEP = 1,
+ PADDING_MODE_OAEP = 1,
PADDING_MODE_PSS = 2,
/* USE OF NULL PADDING IS NOT RECOMMENDED.
* SUPPORT EXISTS AS A REQUIREMENT FOR TPM2 OPERATION. */
- PADDING_MODE_NULL = 3
+ PADDING_MODE_NULL = 3
};
/* RSA support, FIPS PUB 186-4 *
@@ -215,21 +216,21 @@ int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
* return 0 if error
*/
int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
- const uint8_t *in, const uint32_t in_len,
- enum padding_mode padding, enum hashing_mode hashing);
+ const uint8_t *in, const uint32_t in_len,
+ enum padding_mode padding, enum hashing_mode hashing);
/* Calculate r = m ^ e mod N
* return 0 if error
*/
int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest,
- uint32_t digest_len, const uint8_t *sig,
- const uint32_t sig_len, enum padding_mode padding,
- enum hashing_mode hashing);
+ uint32_t digest_len, const uint8_t *sig,
+ const uint32_t sig_len, enum padding_mode padding,
+ enum hashing_mode hashing);
/* Calculate n = p * q, d = e ^ -1 mod phi. */
int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d,
- struct LITE_BIGNUM *p, struct LITE_BIGNUM *q,
- uint32_t e);
+ struct LITE_BIGNUM *p, struct LITE_BIGNUM *q,
+ uint32_t e);
/*
* EC.
@@ -244,9 +245,8 @@ int DCRYPTO_p256_base_point_mul(p256_int *out_x, p256_int *out_y,
/* DCRYPTO_p256_point_mul sets {out_x,out_y} = n*{in_x,in_y}, where n is <
* the order of the group.
*/
-int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
- const p256_int *n, const p256_int *in_x,
- const p256_int *in_y);
+int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y, const p256_int *n,
+ const p256_int *in_x, const p256_int *in_y);
/*
* Key selection based on FIPS-186-4, section B.4.2 (Key Pair
* Generation by Testing Candidates).
@@ -257,7 +257,6 @@ int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d,
const uint8_t bytes[P256_NBYTES]);
-
/* 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
@@ -267,18 +266,17 @@ int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d,
* 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);
+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
@@ -286,10 +284,9 @@ size_t DCRYPTO_ecies_decrypt(
* 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);
+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.
@@ -301,10 +298,10 @@ int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len,
int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p);
void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len);
void DCRYPTO_bn_mul(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a,
- const struct LITE_BIGNUM *b);
+ const struct LITE_BIGNUM *b);
int DCRYPTO_bn_div(struct LITE_BIGNUM *quotient, struct LITE_BIGNUM *remainder,
- const struct LITE_BIGNUM *input,
- const struct LITE_BIGNUM *divisor);
+ const struct LITE_BIGNUM *input,
+ const struct LITE_BIGNUM *divisor);
/*
* ASN.1 DER
@@ -362,8 +359,8 @@ int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x,
* @param n: max size of cert
*/
int DCRYPTO_x509_gen_u2f_cert(const p256_int *d, const p256_int *pk_x,
- const p256_int *pk_y, const p256_int *serial,
- uint8_t *cert, const int n);
+ const p256_int *pk_y, const p256_int *serial,
+ uint8_t *cert, const int n);
/*
* Memory related functions.
@@ -427,10 +424,9 @@ BUILD_ASSERT(DCRYPTO_CIPHER_SALT_SIZE == CIPHER_SALT_SIZE);
* @param len Number of bytes to read from in / write to out.
* @return non-zero on success, and zero otherwise.
*/
-int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt,
- void *out, const void *in, size_t len);
+int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt, void *out,
+ const void *in, size_t len);
-#endif /* ^^^^^^^^^^^^^^^^^^^^^ !TEST_BUILD */
/*
* Query whether Key Ladder is enabled.
*
@@ -442,4 +438,4 @@ int DCRYPTO_ladder_is_enabled(void);
}
#endif
-#endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */
+#endif /* ! __EC_BOARD_CR50_DCRYPTO_DCRYPTO_H */
diff --git a/board/cr50/dcrypto/dcrypto_runtime.c b/board/cr50/dcrypto/dcrypto_runtime.c
index 394293ab83..60a0365c92 100644
--- a/board/cr50/dcrypto/dcrypto_runtime.c
+++ b/board/cr50/dcrypto/dcrypto_runtime.c
@@ -413,7 +413,7 @@ exit:
static int command_dcrypto_ecdsa_test(int argc, char *argv[])
{
p256_int entropy, message, r, s;
- LITE_SHA256_CTX hsh;
+ struct sha256_ctx hsh;
int result = 0;
char *new_stack;
const uint32_t new_stack_size = 2 * 1024;
@@ -424,9 +424,9 @@ static int command_dcrypto_ecdsa_test(int argc, char *argv[])
for (uint8_t i = 0; i < 8; i++)
entropy.a[i] = i;
- DCRYPTO_SHA256_init(&hsh, 0);
- HASH_update(&hsh, &ten, sizeof(ten));
- p256_from_bin(HASH_final(&hsh), &message);
+ SHA256_hw_init(&hsh);
+ SHA256_update(&hsh, &ten, sizeof(ten));
+ p256_from_bin(SHA256_final(&hsh)->b8, &message);
r = entropy;
s = message;
diff --git a/board/cr50/dcrypto/hkdf.c b/board/cr50/dcrypto/hkdf.c
index c6692ef554..8e06455337 100644
--- a/board/cr50/dcrypto/hkdf.c
+++ b/board/cr50/dcrypto/hkdf.c
@@ -7,12 +7,10 @@
#include "dcrypto.h"
#include "internal.h"
-#include "cryptoc/sha256.h"
-
static int hkdf_extract(uint8_t *PRK, const uint8_t *salt, size_t salt_len,
const uint8_t *IKM, size_t IKM_len)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
if (PRK == NULL)
return 0;
@@ -21,9 +19,9 @@ static int hkdf_extract(uint8_t *PRK, const uint8_t *salt, size_t salt_len,
if (IKM == NULL && IKM_len > 0)
return 0;
- DCRYPTO_HMAC_SHA256_init(&ctx, salt, salt_len);
- HASH_update(&ctx.hash, IKM, IKM_len);
- memcpy(PRK, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+ HMAC_SHA256_hw_init(&ctx, salt, salt_len);
+ HMAC_SHA256_update(&ctx, IKM, IKM_len);
+ memcpy(PRK, HMAC_SHA256_hw_final(&ctx), SHA256_DIGEST_SIZE);
return 1;
}
@@ -46,15 +44,15 @@ static int hkdf_expand(uint8_t *OKM, size_t OKM_len, const uint8_t *PRK,
return 0;
while (OKM_len > 0) {
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
const size_t block_size = OKM_len < SHA256_DIGEST_SIZE ?
OKM_len : SHA256_DIGEST_SIZE;
- DCRYPTO_HMAC_SHA256_init(&ctx, PRK, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, T, T_len);
- HASH_update(&ctx.hash, info, info_len);
- HASH_update(&ctx.hash, &count, sizeof(count));
- memcpy(OKM, DCRYPTO_HMAC_final(&ctx), block_size);
+ HMAC_SHA256_hw_init(&ctx, PRK, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, T, T_len);
+ HMAC_SHA256_update(&ctx, info, info_len);
+ HMAC_SHA256_update(&ctx, &count, sizeof(count));
+ memcpy(OKM, HMAC_SHA256_hw_final(&ctx), block_size);
T += T_len;
T_len = SHA256_DIGEST_SIZE;
diff --git a/board/cr50/dcrypto/hmac.c b/board/cr50/dcrypto/hmac.c
deleted file mode 100644
index 72d4296422..0000000000
--- a/board/cr50/dcrypto/hmac.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright 2015 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 "internal.h"
-#include "dcrypto.h"
-
-#include <stdint.h>
-
-#include "cryptoc/sha256.h"
-
-/* TODO(sukhomlinov): add support for hardware hmac. */
-static void hmac_sha256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len)
-{
- unsigned int i;
-
- BUILD_ASSERT(sizeof(ctx->opad) >= SHA256_BLOCK_SIZE);
-
- memset(&ctx->opad[0], 0, SHA256_BLOCK_SIZE);
-
- if (len > SHA256_BLOCK_SIZE) {
- DCRYPTO_SHA256_init(&ctx->hash, 0);
- HASH_update(&ctx->hash, key, len);
- memcpy(&ctx->opad[0], HASH_final(&ctx->hash),
- HASH_size(&ctx->hash));
- } else {
- memcpy(&ctx->opad[0], key, len);
- }
-
- for (i = 0; i < SHA256_BLOCK_SIZE; ++i)
- ctx->opad[i] ^= 0x36;
-
- DCRYPTO_SHA256_init(&ctx->hash, 0);
- /* hash ipad */
- HASH_update(&ctx->hash, ctx->opad, SHA256_BLOCK_SIZE);
-
- for (i = 0; i < SHA256_BLOCK_SIZE; ++i)
- ctx->opad[i] ^= (0x36 ^ 0x5c);
-}
-
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len)
-{
- hmac_sha256_init(ctx, key, len);
-}
-
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
-{
- uint8_t digest[SHA256_DIGEST_SIZE]; /* up to SHA256 */
-
- memcpy(digest, HASH_final(&ctx->hash),
- (HASH_size(&ctx->hash) <= sizeof(digest) ?
- HASH_size(&ctx->hash) :
- sizeof(digest)));
- DCRYPTO_SHA256_init(&ctx->hash, 0);
- HASH_update(&ctx->hash, ctx->opad, SHA256_BLOCK_SIZE);
- HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash));
- always_memset(&ctx->opad[0], 0, SHA256_BLOCK_SIZE); /* wipe key */
- return HASH_final(&ctx->hash);
-}
diff --git a/board/cr50/dcrypto/hmac_drbg.c b/board/cr50/dcrypto/hmac_drbg.c
index d601e721de..85c0fe863a 100644
--- a/board/cr50/dcrypto/hmac_drbg.c
+++ b/board/cr50/dcrypto/hmac_drbg.c
@@ -14,30 +14,28 @@
/* V = HMAC(K, V) */
static void update_v(const uint32_t *k, uint32_t *v)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
- DCRYPTO_HMAC_SHA256_init(&ctx, k, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, v, SHA256_DIGEST_SIZE);
- memcpy(v, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+ HMAC_SHA256_hw_init(&ctx, k, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, v, SHA256_DIGEST_SIZE);
+ memcpy(v, HMAC_SHA256_final(&ctx), SHA256_DIGEST_SIZE);
}
/* K = HMAC(K, V || tag || p0 || p1 || p2) */
/* V = HMAC(K, V) */
-static void update_kv(uint32_t *k, uint32_t *v, uint8_t tag,
- const void *p0, size_t p0_len,
- const void *p1, size_t p1_len,
+static void update_kv(uint32_t *k, uint32_t *v, uint8_t tag, const void *p0,
+ size_t p0_len, const void *p1, size_t p1_len,
const void *p2, size_t p2_len)
{
- LITE_HMAC_CTX ctx;
-
- DCRYPTO_HMAC_SHA256_init(&ctx, k, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, v, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, &tag, 1);
- HASH_update(&ctx.hash, p0, p0_len);
- HASH_update(&ctx.hash, p1, p1_len);
- HASH_update(&ctx.hash, p2, p2_len);
- memcpy(k, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
-
+ struct hmac_sha256_ctx ctx;
+
+ HMAC_SHA256_hw_init(&ctx, k, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, v, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, &tag, 1);
+ HMAC_SHA256_update(&ctx, p0, p0_len);
+ HMAC_SHA256_update(&ctx, p1, p1_len);
+ HMAC_SHA256_update(&ctx, p2, p2_len);
+ memcpy(k, HMAC_SHA256_final(&ctx), SHA256_DIGEST_SIZE);
update_v(k, v);
}
@@ -179,7 +177,7 @@ static int cmd_rfc6979(int argc, char **argv)
static const char message[] = "sample";
static struct drbg_ctx drbg;
- static HASH_CTX ctx;
+ static struct sha256_ctx ctx;
int result;
static const uint8_t priv_from_rfc[] = {
0xC9, 0xAF, 0xA9, 0xD8, 0x45, 0xBA, 0x75, 0x16,
@@ -197,9 +195,9 @@ static int cmd_rfc6979(int argc, char **argv)
p256_int *reference_k = (p256_int *)k_from_rfc;
/* h1 = H(m) */
- DCRYPTO_SHA256_init(&ctx, 1);
- HASH_update(&ctx, message, sizeof(message) - 1);
- memcpy(&h1, HASH_final(&ctx), SHA256_DIGEST_SIZE);
+ SHA256_hw_init(&ctx);
+ SHA256_update(&ctx, message, sizeof(message) - 1);
+ memcpy(&h1, SHA256_final(&ctx)->b8, SHA256_DIGEST_SIZE);
hmac_drbg_init_rfc6979(&drbg, x, &h1);
do {
diff --git a/board/cr50/dcrypto/hmac_sw.c b/board/cr50/dcrypto/hmac_sw.c
new file mode 100644
index 0000000000..91e056546d
--- /dev/null
+++ b/board/cr50/dcrypto/hmac_sw.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 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 "internal.h"
+
+#include <stdint.h>
+
+#include "cryptoc/util.h"
+
+/**
+ * Generic software HMAC support for any type of hash.
+ */
+
+/* Calculate location of storage for ipad/opad in generic way */
+static inline uint32_t *HMAC_opad(union hmac_ctx *const ctx)
+{
+ return (uint32_t *)((uint8_t *)ctx + ctx->f->context_size);
+}
+/**
+ * Initialize HMAC for pre-configured hash function.
+ * This is generic function which can initialize HMAC with any supported
+ * hash function.
+ */
+void HMAC_sw_init(union hmac_ctx *const ctx, const void *key, size_t len)
+{
+ uint32_t *const opad = HMAC_opad(ctx);
+ const size_t block_size = HASH_block_size(&ctx->hash);
+ size_t i;
+ /* inner padding with zeros */
+ memset(opad, 0, block_size);
+ /**
+ * HMAC (K, m) = H( (K' ⊕ opad) || H ((K' ⊕ ipad) || m) )
+ * K' = H(K) if K is longer than block size for H, or
+ * = K padded with zeroes otherwise
+ */
+ if (len > block_size) {
+ /* ctx already contains proper vtable for hash functions */
+ /* But we need to reinit it after use. */
+ HASH_update(&ctx->hash, key, len);
+ memcpy(opad, HASH_final(&ctx->hash), HASH_size(&ctx->hash));
+ HASH_reinit(&ctx->hash);
+ } else {
+ memcpy(opad, key, len);
+ }
+ /* inner pad is K ⊕ 0x36, computed at word level */
+ for (i = 0; i < block_size / sizeof(opad[0]); ++i)
+ opad[i] ^= 0x36363636;
+
+ HASH_update(&ctx->hash, opad, block_size); /* hash ipad */
+ /* compute outer padding from the inner. */
+ for (i = 0; i < block_size / sizeof(opad[0]); ++i)
+ opad[i] ^= (0x36363636 ^ 0x5c5c5c5c);
+}
+
+const union sha_digests *HMAC_sw_final(union hmac_ctx *const ctx)
+{
+ uint32_t *const opad = HMAC_opad(ctx);
+ uint32_t *digest; /* storage for intermediate digest */
+ const size_t block_size = HASH_block_size(&ctx->hash);
+ const size_t hash_size = HASH_size(&ctx->hash);
+ /* allocate storage dynamically, just enough for particular hash. */
+ digest = alloca(hash_size);
+ memcpy(digest, HASH_final(&ctx->hash), hash_size);
+ HASH_reinit(&ctx->hash);
+ HASH_update(&ctx->hash, opad, block_size);
+ HASH_update(&ctx->hash, digest, hash_size);
+ memset(opad, 0, block_size); /* wipe key */
+ return HASH_final(&ctx->hash);
+}
diff --git a/board/cr50/dcrypto/hmacsha2.h b/board/cr50/dcrypto/hmacsha2.h
new file mode 100644
index 0000000000..6d9c842c1e
--- /dev/null
+++ b/board/cr50/dcrypto/hmacsha2.h
@@ -0,0 +1,490 @@
+/* Copyright 2021 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.
+ */
+#pragma once
+#include "common.h"
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA_DIGEST_SIZE SHA1_DIGEST_SIZE
+
+#define SHA224_DIGEST_SIZE 28
+#define SHA256_DIGEST_SIZE 32
+#define SHA1_BLOCK_SIZE 64
+#define SHA1_BLOCK_WORDS (SHA1_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA1_BLOCK_DWORDS (SHA1_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA1_DIGEST_WORDS (SHA1_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA224_BLOCK_SIZE 64
+#define SHA224_BLOCK_WORDS (SHA224_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA224_BLOCK_DWORDS (SHA224_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA224_DIGEST_WORDS (SHA224_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA256_BLOCK_SIZE 64
+#define SHA256_BLOCK_WORDS (SHA256_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA256_BLOCK_DWORDS (SHA256_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))
+
+/**
+ * Hash contexts. Each context starts with pointer to vtable containing
+ * functions to perform implementation specific operations.
+ * It is designed to support both software and hardware implementations.
+ * Contexts for different digest types can overlap, but vtable stores
+ * actual size of context which enables stack-efficient implementation of
+ * HMAC - say HMAC SHA2-256 shouldn't reserve space as for HMAC SHA2-512.
+ */
+union hash_ctx; /* forward declaration of generic hash context type */
+union hmac_ctx; /* forward declaration of generic HMAC context type */
+
+union sha_digests; /* forward declaration of generic digest type */
+
+/* Combined HASH & HMAC vtable to support SW & HW implementations. */
+struct hash_vtable {
+ /* SHA init function, used primarily by SW HMAC implementation. */
+ void (*const init)(union hash_ctx *const);
+ /* Update function for SHA & HMAC, assuming it's the same. */
+ void (*const update)(union hash_ctx *const, const void *, size_t);
+ /* SHA final function, digest specific. */
+ const union sha_digests *(*const final)(union hash_ctx *const);
+
+ /* HW HMAC support may require special ending. */
+ const union sha_digests *(*const hmac_final)(union hmac_ctx *const);
+
+ /* Digest size of in bytes. */
+ size_t digest_size;
+
+ /* Digest block size in bytes. */
+ size_t block_size;
+
+ /* Offset of first byte after context, used for HMAC */
+ size_t context_size;
+};
+
+struct sha256_digest {
+ union {
+ uint8_t b8[SHA256_DIGEST_SIZE];
+ uint32_t b32[SHA256_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha256_digest) == SHA256_DIGEST_SIZE);
+
+struct sha224_digest {
+ union {
+ uint8_t b8[SHA224_DIGEST_SIZE];
+ uint32_t b32[SHA224_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha224_digest) == SHA224_DIGEST_SIZE);
+
+struct sha1_digest {
+ union {
+ uint8_t b8[SHA1_DIGEST_SIZE];
+ uint32_t b32[SHA1_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha1_digest) == SHA1_DIGEST_SIZE);
+
+
+/* SHA256 specific type to allocate just enough memory. */
+struct sha256_ctx {
+ const struct hash_vtable *f; /* metadata & vtable */
+ size_t count; /* number of bytes processed */
+ uint32_t state[SHA256_DIGEST_WORDS]; /* up to SHA2-256 */
+ union {
+ uint8_t b8[SHA256_BLOCK_SIZE];
+ uint32_t b32[SHA256_BLOCK_WORDS];
+ uint64_t b64[SHA256_BLOCK_DWORDS];
+ struct sha256_digest digest;
+ };
+};
+
+#define sha224_ctx sha256_ctx
+
+struct sha1_ctx {
+ const struct hash_vtable *f; /* metadata & vtable. */
+ size_t count; /* number of bytes processed. */
+ uint32_t state[SHA1_DIGEST_WORDS];
+ union {
+ uint8_t b8[SHA1_BLOCK_SIZE];
+ uint32_t b32[SHA1_BLOCK_WORDS];
+ uint64_t b64[SHA1_BLOCK_DWORDS];
+ struct sha1_digest digest;
+ };
+};
+
+#ifdef CONFIG_UPTO_SHA512
+#define SHA384_DIGEST_SIZE 48
+#define SHA512_DIGEST_SIZE 64
+
+#define SHA384_BLOCK_SIZE 128
+#define SHA512_BLOCK_SIZE 128
+
+#define SHA384_BLOCK_WORDS (SHA384_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA384_BLOCK_DWORDS (SHA384_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA384_DIGEST_WORDS (SHA384_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA384_DIGEST_DWORDS (SHA384_DIGEST_SIZE / sizeof(uint64_t))
+
+#define SHA512_BLOCK_WORDS (SHA512_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA512_BLOCK_DWORDS (SHA512_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA512_DIGEST_WORDS (SHA512_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA512_DIGEST_DWORDS (SHA512_DIGEST_SIZE / sizeof(uint64_t))
+
+struct sha384_digest {
+ union {
+ uint8_t b8[SHA384_DIGEST_SIZE];
+ uint32_t b32[SHA384_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha384_digest) == SHA384_DIGEST_SIZE);
+
+struct sha512_digest {
+ union {
+ uint8_t b8[SHA512_DIGEST_SIZE];
+ uint32_t b32[SHA512_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha512_digest) == SHA512_DIGEST_SIZE);
+
+struct sha512_ctx {
+ const struct hash_vtable *f; /* metadata & vtable. */
+ size_t count; /* number of bytes processed. */
+ uint64_t state[SHA512_DIGEST_DWORDS]; /* up to SHA2-512. */
+ union {
+ uint8_t b8[SHA512_BLOCK_SIZE];
+ uint32_t b32[SHA512_BLOCK_WORDS];
+ uint64_t b64[SHA512_BLOCK_DWORDS];
+ struct sha512_digest digest;
+ };
+};
+
+#define sha384_ctx sha512_ctx
+#endif
+
+/**
+ * Generic hash type, allocating memory for any supported hash context
+ * Each context should have header at known location.
+ */
+union hash_ctx {
+ const struct hash_vtable *f; /* common metadata & vtable */
+ struct sha1_ctx sha1;
+ struct sha256_ctx sha256;
+ struct sha224_ctx sha224;
+#ifdef CONFIG_UPTO_SHA512
+ struct sha384_ctx sha384;
+ struct sha512_ctx sha512;
+#endif
+};
+
+union sha_digests {
+ struct sha1_digest sha1;
+ struct sha224_digest sha224;
+ struct sha256_digest sha256;
+#ifdef CONFIG_UPTO_SHA512
+ struct sha384_digest sha384;
+ struct sha512_digest sha512;
+#endif
+ /* Convenience accessor to bytes. */
+ uint8_t b8[SHA256_DIGEST_SIZE];
+};
+
+/* Header should be at constant offset to safely cast types to smaller size */
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha1_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha256_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha224_ctx, f));
+
+#ifdef CONFIG_UPTO_SHA512
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha384_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha512_ctx, f));
+#endif
+
+struct hmac_sha1_ctx {
+ struct sha1_ctx hash;
+ uint32_t opad[SHA1_BLOCK_WORDS];
+};
+
+struct hmac_sha224_ctx {
+ struct sha224_ctx hash;
+ uint32_t opad[SHA224_BLOCK_WORDS];
+};
+
+struct hmac_sha256_ctx {
+ struct sha256_ctx hash;
+ uint32_t opad[SHA256_BLOCK_WORDS];
+};
+
+#ifdef CONFIG_UPTO_SHA512
+struct hmac_sha384_ctx {
+ struct sha384_ctx hash;
+ uint32_t opad[SHA384_BLOCK_WORDS];
+};
+
+struct hmac_sha512_ctx {
+ struct sha512_ctx hash;
+ uint32_t opad[SHA512_BLOCK_WORDS];
+};
+#endif
+
+/**
+ * HMAC context reserving memory for any supported hash type.
+ * It's SHA context following storage for ipad/opad
+ */
+union hmac_ctx {
+ const struct hash_vtable *f; /* common metadata & vtable */
+ union hash_ctx hash; /* access as hash */
+ /* hmac contexts */
+ struct hmac_sha1_ctx hmac_sha1;
+ struct hmac_sha256_ctx hmac_sha256;
+ struct hmac_sha224_ctx hmac_sha224;
+#ifdef CONFIG_UPTO_SHA512
+ struct hmac_sha384_ctx hmac_sha384;
+ struct hmac_sha512_ctx hmac_sha512;
+#endif
+};
+
+/* Header should be at constant offset to safely cast types to smaller size */
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha1_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha256_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha224_ctx, f));
+
+#ifdef CONFIG_UPTO_SHA512
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha384_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha512_ctx, f));
+#endif
+
+/**
+ * Reset hash context with the same hash function as configured.
+ * Will crash if previously not configured! Used for HMAC.
+ */
+static inline void HASH_reinit(union hash_ctx *const ctx)
+{
+ ctx->f->init(ctx);
+}
+
+#ifndef CONFIG_DCRYPTO_MOCK
+/**
+ * Add data to message, call configured transform function when block
+ * is full.
+ */
+static inline void HASH_update(union hash_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update(ctx, data, len);
+}
+#else
+void HASH_update(union hash_ctx *const ctx, const void *data, size_t len);
+#endif
+
+static inline void SHA1_update(struct sha1_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update((union hash_ctx *)ctx, data, len);
+}
+
+static inline void SHA256_update(struct sha256_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update((union hash_ctx *)ctx, data, len);
+}
+
+/**
+ * Finalize hash computation by adding padding, message length.
+ * Returns pointer to computed digest stored inside provided context.
+ */
+#ifndef CONFIG_DCRYPTO_MOCK
+static inline const union sha_digests *HASH_final(union hash_ctx *const ctx)
+{
+ return ctx->f->final(ctx);
+}
+#else
+const union sha_digests *HASH_final(union hash_ctx *const ctx);
+#endif
+
+static inline const struct sha1_digest *SHA1_final(struct sha1_ctx *const ctx)
+{
+ return &ctx->f->final((union hash_ctx *)ctx)->sha1;
+}
+
+static inline const struct sha256_digest *
+SHA256_final(struct sha256_ctx *const ctx)
+{
+ return &ctx->f->final((union hash_ctx *)ctx)->sha256;
+}
+
+/**
+ * Returns digest size for configured hash.
+ */
+static inline size_t HASH_size(union hash_ctx *const ctx)
+{
+ return ctx->f->digest_size;
+}
+
+/**
+ * Return block size for configured hash.
+ */
+static inline size_t HASH_block_size(union hash_ctx *const ctx)
+{
+ return ctx->f->block_size;
+}
+
+/* Software implementations of hash functions. */
+void SHA1_sw_init(struct sha1_ctx *const ctx);
+void SHA1_sw_update(struct sha1_ctx *const ctx, const void *data, size_t len);
+const struct sha1_digest *SHA1_sw_final(struct sha1_ctx *const ctx);
+const struct sha1_digest *SHA1_sw_hash(const void *data, size_t len,
+ struct sha1_digest *digest);
+void SHA256_sw_init(struct sha256_ctx *const ctx);
+void SHA256_sw_update(struct sha256_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha256_digest *SHA256_sw_final(struct sha256_ctx *const ctx);
+const struct sha256_digest *SHA256_sw_hash(const void *data, size_t len,
+ struct sha256_digest *digest);
+void SHA224_sw_init(struct sha224_ctx *const ctx);
+void SHA224_sw_update(struct sha224_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha224_digest *SHA224_sw_final(struct sha224_ctx *const ctx);
+const struct sha224_digest *SHA224_sw_hash(const void *data, size_t len,
+ struct sha224_digest *digest);
+
+/**
+ * Initialize HMAC for pre-configured hash.
+ * This is generic function which can initialize HMAC with any supported
+ * hash function.
+ */
+void HMAC_sw_init(union hmac_ctx *const ctx, const void *key, size_t len);
+const union sha_digests *HMAC_sw_final(union hmac_ctx *const ctx);
+
+/* HMAC update is same as SHA update. */
+static inline void HMAC_update(union hmac_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update(&ctx->hash, data, len);
+}
+
+static inline size_t HMAC_size(union hmac_ctx *const ctx)
+{
+ return ctx->f->digest_size;
+}
+
+static inline const union sha_digests *HMAC_final(union hmac_ctx *const ctx)
+{
+ return ctx->f->hmac_final(ctx);
+}
+
+/**
+ * HMAC SHA1 initialization.
+ */
+static inline void HMAC_SHA1_sw_init(struct hmac_sha1_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA1_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA1_update(struct hmac_sha1_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha1_digest *
+HMAC_SHA1_final(struct hmac_sha1_ctx *const ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha1;
+}
+
+/**
+ * HMAC SHA2-224 initialization.
+ */
+static inline void HMAC_SHA224_sw_init(struct hmac_sha224_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA224_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA224_update(struct hmac_sha224_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha224_digest *
+HMAC_SHA224_final(struct hmac_sha224_ctx *const ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha224;
+}
+
+/**
+ * HMAC SHA2-256 initialization.
+ */
+static inline void HMAC_SHA256_sw_init(struct hmac_sha256_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA256_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA256_update(struct hmac_sha256_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha256_digest *
+HMAC_SHA256_final(struct hmac_sha256_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha256;
+}
+
+#ifdef CONFIG_UPTO_SHA512
+void SHA384_sw_init(struct sha384_ctx *const ctx);
+void SHA384_sw_update(struct sha384_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha384_digest *SHA384_sw_final(struct sha384_ctx *const ctx);
+const struct sha384_digest *SHA384_sw_hash(const void *data, size_t len,
+ struct sha384_digest *digest);
+void SHA512_sw_init(struct sha512_ctx *const ctx);
+void SHA512_sw_update(struct sha512_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha512_digest *SHA512_sw_final(struct sha512_ctx *ctx);
+const struct sha512_digest *SHA512_sw_hash(const void *data, size_t len,
+ struct sha512_digest *digest);
+
+/**
+ * HMAC SHA2-384 initialization.
+ */
+static inline void HMAC_SHA384_sw_init(struct hmac_sha384_ctx *ctx,
+ const void *key, size_t len)
+{
+ SHA384_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA384_update(struct hmac_sha384_ctx *ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+static inline const struct sha384_digest *
+HMAC_SHA384_final(struct hmac_sha384_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha384;
+}
+/**
+ * HMAC SHA2-512 initialization.
+ */
+static inline void HMAC_SHA512_sw_init(struct hmac_sha512_ctx *ctx,
+ const void *key, size_t len)
+{
+ SHA512_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+static inline void HMAC_SHA512_update(struct hmac_sha512_ctx *ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+static inline const struct sha512_digest *
+HMAC_SHA512_final(struct hmac_sha512_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha512;
+}
+#endif
diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h
index 2e6f62e2e8..17430036cb 100644
--- a/board/cr50/dcrypto/internal.h
+++ b/board/cr50/dcrypto/internal.h
@@ -2,7 +2,6 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
#ifndef __EC_CHIP_G_DCRYPTO_INTERNAL_H
#define __EC_CHIP_G_DCRYPTO_INTERNAL_H
@@ -13,10 +12,7 @@
#include "util.h"
#include "cryptoc/p256.h"
-#include "cryptoc/sha.h"
-#include "cryptoc/sha256.h"
-#include "cryptoc/sha384.h"
-#include "cryptoc/sha512.h"
+#include "hmacsha2.h"
#ifdef __cplusplus
extern "C" {
@@ -33,12 +29,16 @@ extern "C" {
#define SHA_DIGEST_WORDS (SHA_DIGEST_SIZE / sizeof(uint32_t))
#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))
-#ifdef SHA512_SUPPORT
+#ifdef CONFIG_UPTO_SHA512
#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_SIZE
#else
#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_SIZE
#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
enum sha_mode {
SHA1_MODE = 0,
SHA256_MODE = 1
@@ -56,12 +56,6 @@ struct access_helper {
int dcrypto_grab_sha_hw(void);
void dcrypto_release_sha_hw(void);
#endif
-void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data,
- uint32_t n, uint8_t *digest);
-void dcrypto_sha_init(enum sha_mode mode);
-void dcrypto_sha_update(struct HASH_CTX *unused,
- const void *data, uint32_t n);
-void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest);
/*
* BIGNUM.
@@ -206,6 +200,44 @@ uint32_t dcrypto_dmem_load(size_t offset, const void *words, size_t n_words);
*/
void *always_memset(void *s, int c, size_t n);
+#ifndef __alias
+#define __alias(func) __attribute__((alias(#func)))
+#endif
+
+/* rotate 32-bit value right */
+static inline uint32_t ror(uint32_t value, int bits)
+{
+ /* return __builtin_rotateright32(value, bits); */
+ return (value >> bits) | (value << (32 - bits));
+}
+
+/* rotate 64-bit value right */
+static inline uint64_t ror64(uint64_t value, int bits)
+{
+ /* return __builtin_rotateright64(value, bits); */
+ return (value >> bits) | (value << (64 - bits));
+}
+
+/* rotate 32-bit value left */
+static inline uint32_t rol(uint32_t value, int bits)
+{
+ /* return __builtin_rotateleft32(value, bits); */
+ return (value << bits) | (value >> (32 - bits));
+}
+
+/* rotate 64-bit value left */
+static inline uint64_t rol64(uint64_t value, int bits)
+{
+ /* return __builtin_rotateleft64(value, bits); */
+ return (value << bits) | (value >> (64 - bits));
+}
+
+/* stack based allocation */
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+
+
/*
* Key ladder.
*/
diff --git a/board/cr50/dcrypto/p256_ecies.c b/board/cr50/dcrypto/p256_ecies.c
index 30a410d828..7b77efd507 100644
--- a/board/cr50/dcrypto/p256_ecies.c
+++ b/board/cr50/dcrypto/p256_ecies.c
@@ -98,10 +98,10 @@ size_t DCRYPTO_ecies_encrypt(
outp += P256_NBYTES;
/* Calculate HMAC(auth_data || ciphertext). */
- DCRYPTO_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
+ HMAC_SHA256_hw_init(&ctx, hmac_key, HMAC_KEY_BYTES);
HASH_update(&ctx.hash, outp, in_len);
outp += in_len;
- memcpy(outp, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+ memcpy(outp, HMAC_SHA256_hw_final(&ctx), SHA256_DIGEST_SIZE);
outp += SHA256_DIGEST_SIZE;
return outp - (uint8_t *) out;
@@ -159,9 +159,9 @@ size_t DCRYPTO_ecies_decrypt(
aes_key = &key[0];
hmac_key = &key[AES_KEY_BYTES];
- DCRYPTO_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
+ HMAC_SHA256_hw_init(&ctx, hmac_key, HMAC_KEY_BYTES);
HASH_update(&ctx.hash, inp, in_len);
- if (!DCRYPTO_equals(inp + in_len, DCRYPTO_HMAC_final(&ctx),
+ if (!DCRYPTO_equals(inp + in_len, HMAC_SHA256_hw_final(&ctx),
SHA256_DIGEST_SIZE))
return 0;
diff --git a/board/cr50/dcrypto/rsa.c b/board/cr50/dcrypto/rsa.c
index 053c75f16e..6b7146068d 100644
--- a/board/cr50/dcrypto/rsa.c
+++ b/board/cr50/dcrypto/rsa.c
@@ -11,11 +11,6 @@
#include <assert.h>
-#include "cryptoc/sha.h"
-#include "cryptoc/sha256.h"
-#include "cryptoc/sha384.h"
-#include "cryptoc/sha512.h"
-
/* Extend the MSB throughout the word. */
static uint32_t msb_extend(uint32_t a)
{
@@ -34,11 +29,15 @@ static uint32_t select(uint32_t mask, uint32_t a, uint32_t b)
return (mask & a) | (~mask & b);
}
+/* We use SHA256 context to store SHA1 context, so make sure it's ok. */
+BUILD_ASSERT(sizeof(struct sha256_ctx) >= sizeof(struct sha1_ctx));
+
static void MGF1_xor(uint8_t *dst, uint32_t dst_len,
const uint8_t *seed, uint32_t seed_len,
enum hashing_mode hashing)
{
- HASH_CTX ctx;
+ union hash_ctx ctx;
+
struct {
uint8_t b3;
uint8_t b2;
@@ -46,21 +45,21 @@ static void MGF1_xor(uint8_t *dst, uint32_t dst_len,
uint8_t b0;
} cnt;
const uint8_t *digest;
- const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
- : SHA256_DIGEST_SIZE;
+ const size_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_SIZE :
+ SHA256_DIGEST_SIZE;
cnt.b0 = cnt.b1 = cnt.b2 = cnt.b3 = 0;
while (dst_len) {
int i;
if (hashing == HASH_SHA1)
- DCRYPTO_SHA1_init(&ctx, 0);
+ SHA1_hw_init(&ctx.sha1);
else
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx.sha256);
HASH_update(&ctx, seed, seed_len);
- HASH_update(&ctx, (uint8_t *) &cnt, sizeof(cnt));
- digest = HASH_final(&ctx);
+ HASH_update(&ctx, (uint8_t *)&cnt, sizeof(cnt));
+ digest = HASH_final(&ctx)->b8;
for (i = 0; i < dst_len && i < hash_size; ++i)
*dst++ ^= *digest++;
dst_len -= i;
@@ -93,7 +92,7 @@ static int oaep_pad(uint8_t *output, uint32_t output_len,
const uint32_t max_msg_len = output_len - 2 - 2 * hash_size;
const uint32_t ps_len = max_msg_len - msg_len;
uint8_t *const one = PS + ps_len;
- struct HASH_CTX ctx;
+ union hash_ctx ctx;
if (output_len < 2 + 2 * hash_size)
return 0; /* Key size too small for chosen hash. */
@@ -111,12 +110,12 @@ static int oaep_pad(uint8_t *output, uint32_t output_len,
}
if (hashing == HASH_SHA1)
- DCRYPTO_SHA1_init(&ctx, 0);
+ SHA1_hw_init(&ctx.sha1);
else
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx.sha256);
HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
- memcpy(phash, HASH_final(&ctx), hash_size);
+ memcpy(phash, HASH_final(&ctx)->b8, hash_size);
*one = 1;
memcpy(one + 1, msg, msg_len);
MGF1_xor(phash, hash_size + 1 + max_msg_len,
@@ -137,7 +136,7 @@ static int check_oaep_pad(uint8_t *out, uint32_t *out_len,
uint8_t *phash = seed + hash_size;
uint8_t *PS = phash + hash_size;
const uint32_t max_msg_len = padded_len - 2 - 2 * hash_size;
- struct HASH_CTX ctx;
+ union hash_ctx ctx;
size_t one_index = 0;
uint32_t looking_for_one_byte = ~0;
int bad;
@@ -152,12 +151,12 @@ static int check_oaep_pad(uint8_t *out, uint32_t *out_len,
MGF1_xor(phash, hash_size + 1 + max_msg_len, seed, hash_size, hashing);
if (hashing == HASH_SHA1)
- DCRYPTO_SHA1_init(&ctx, 0);
+ SHA1_hw_init(&ctx.sha1);
else
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx.sha256);
HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
- bad = !DCRYPTO_equals(phash, HASH_final(&ctx), hash_size);
+ bad = !DCRYPTO_equals(phash, HASH_final(&ctx)->b8, hash_size);
bad |= padded[0];
for (i = PS - padded; i < padded_len; i++) {
@@ -283,7 +282,7 @@ static int pkcs1_get_der(enum hashing_mode hashing, const uint8_t **der,
case HASH_SHA1:
*der = &SHA1_DER[0];
*der_size = sizeof(SHA1_DER);
- *hash_size = SHA_DIGEST_SIZE;
+ *hash_size = SHA1_DIGEST_SIZE;
break;
case HASH_SHA256:
*der = &SHA256_DER[0];
@@ -382,12 +381,12 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len,
const uint8_t *in, uint32_t in_len,
enum hashing_mode hashing)
{
- const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
+ const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
const uint32_t salt_len = MIN(padded_len - hash_size - 2, hash_size);
uint32_t db_len;
uint32_t ps_len;
- struct HASH_CTX ctx;
+ union hash_ctx ctx;
if (in_len != hash_size)
return 0;
@@ -396,9 +395,9 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len,
db_len = padded_len - hash_size - 1;
if (hashing == HASH_SHA1)
- DCRYPTO_SHA1_init(&ctx, 0);
+ SHA1_hw_init(&ctx.sha1);
else
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx.sha256);
/* Pilfer bits of output for temporary use. */
memset(padded, 0, 8);
@@ -409,7 +408,7 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len,
HASH_update(&ctx, padded, salt_len);
/* Output hash. */
- memcpy(padded + db_len, HASH_final(&ctx), hash_size);
+ memcpy(padded + db_len, HASH_final(&ctx)->b8, hash_size);
/* Prepare DB. */
ps_len = db_len - salt_len - 1;
@@ -430,13 +429,13 @@ static int check_pkcs1_pss_pad(const uint8_t *in, uint32_t in_len,
uint8_t *padded, uint32_t padded_len,
enum hashing_mode hashing)
{
- const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
+ const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
const uint8_t zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t db_len;
uint32_t max_ps_len;
uint32_t salt_len;
- HASH_CTX ctx;
+ union hash_ctx ctx;
int bad = 0;
int i;
@@ -468,9 +467,9 @@ static int check_pkcs1_pss_pad(const uint8_t *in, uint32_t in_len,
salt_len = max_ps_len - i;
if (hashing == HASH_SHA1)
- DCRYPTO_SHA1_init(&ctx, 0);
+ SHA1_hw_init(&ctx.sha1);
else
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx.sha256);
HASH_update(&ctx, zeros, sizeof(zeros));
HASH_update(&ctx, in, in_len);
HASH_update(&ctx, padded + db_len - salt_len, salt_len);
diff --git a/board/cr50/dcrypto/sha1.c b/board/cr50/dcrypto/sha1.c
index 07ef3a34ef..e0f576d758 100644
--- a/board/cr50/dcrypto/sha1.c
+++ b/board/cr50/dcrypto/sha1.c
@@ -1,65 +1,137 @@
-/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+/* Copyright 2021 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 "endian.h"
#include "internal.h"
-#include "registers.h"
-#include "cryptoc/sha.h"
+static void SHA1_transform(struct sha1_ctx *const ctx)
+{
+ uint32_t W[80];
+ uint32_t A, B, C, D, E;
+ size_t t;
+ static const uint32_t K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC,
+ 0xCA62C1D6 };
+
+ for (t = 0; t < 16; ++t)
+ W[t] = be32toh(ctx->b32[t]);
+ for (; t < 80; t++)
+ W[t] = rol(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
-static void dcrypto_sha1_init(SHA_CTX *ctx);
-static const uint8_t *dcrypto_sha1_final(SHA_CTX *unused);
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ for (t = 0; t < 80; t++) {
+ uint32_t tmp = rol(A, 5) + E + W[t];
-/*
- * Hardware SHA implementation.
+ if (t < 20)
+ tmp += (D ^ (B & (C ^ D))) + K[0];
+ else if (t < 40)
+ tmp += (B ^ C ^ D) + K[1];
+ else if (t < 60)
+ tmp += ((B & C) | (D & (B | C))) + K[2];
+ else
+ tmp += (B ^ C ^ D) + K[3];
+ E = D;
+ D = C;
+ C = rol(B, 30);
+ B = A;
+ A = tmp;
+ }
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+/**
+ * Define aliases taking union type as parameter. This is safe
+ * as union type has header in same place and is not less than original type.
+ * Equal to:
+ * void SHA1_init_as_hash(hash_ctx_t *const ctx) {SHA1_init(&ctx.sha1);}
+ * but save some space for embedded uses.
*/
-static const HASH_VTAB HW_SHA1_VTAB = {
- dcrypto_sha1_init,
- dcrypto_sha_update,
- dcrypto_sha1_final,
- DCRYPTO_SHA1_hash,
- SHA_DIGEST_SIZE
-};
+BUILD_ASSERT(sizeof(union hash_ctx) >= sizeof(struct sha1_ctx));
+static void SHA1_init_as_hash(union hash_ctx *const ctx) __alias(SHA1_sw_init);
+static void SHA1_update_as_hash(union hash_ctx *const ctx, const void *data,
+ size_t len) __alias(SHA1_sw_update);
+static const union sha_digests *SHA1_final_as_hash(union hash_ctx *const ctx)
+ __alias(SHA1_sw_final);
-/* Requires dcrypto_grab_sha_hw() to be called first. */
-static void dcrypto_sha1_init(SHA_CTX *ctx)
+void SHA1_sw_init(struct sha1_ctx *const ctx)
{
- ctx->f = &HW_SHA1_VTAB;
- dcrypto_sha_init(SHA1_MODE);
+ static const struct hash_vtable sha1_vtab = {
+ SHA1_init_as_hash, SHA1_update_as_hash, SHA1_final_as_hash,
+ HMAC_sw_final, SHA1_DIGEST_SIZE, SHA1_BLOCK_SIZE,
+ sizeof(struct sha1_ctx)
+ };
+ static const uint32_t sha1_init[SHA1_DIGEST_WORDS] = {
+ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
+ };
+
+ ctx->f = &sha1_vtab;
+ memcpy(ctx->state, sha1_init, sizeof(ctx->state));
+ ctx->count = 0;
}
-/* Select and initialize either the software or hardware
- * implementation. If "multi-threaded" behaviour is required, then
- * callers must set sw_required to 1. This is because SHA1 state
- * internal to the hardware cannot be extracted, so it is not possible
- * to suspend and resume a hardware based SHA operation.
- *
- * If the caller has no preference as to implementation, then hardware
- * is preferred based on availability. Hardware is considered to be
- * in use between init() and finished() calls. */
-void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required)
+void SHA1_sw_update(struct sha1_ctx *const ctx, const void *data, size_t len)
{
- if (!sw_required && dcrypto_grab_sha_hw())
- dcrypto_sha1_init(ctx);
- else
- SHA_init(ctx);
+ size_t i = ctx->count & (SHA1_BLOCK_SIZE - 1);
+ const uint8_t *p = (const uint8_t *)data;
+
+ ctx->count += len;
+ while (len--) {
+ ctx->b8[i++] = *p++;
+ if (i == SHA1_BLOCK_SIZE) {
+ SHA1_transform(ctx);
+ i = 0;
+ }
+ }
}
-static const uint8_t *dcrypto_sha1_final(SHA_CTX *ctx)
+const struct sha1_digest *SHA1_sw_final(struct sha1_ctx *const ctx)
{
- dcrypto_sha_wait(SHA1_MODE, (uint32_t *) ctx->buf);
- return ctx->buf;
+ uint64_t cnt = (uint64_t)ctx->count * CHAR_BIT;
+ size_t i = ctx->count & (SHA1_BLOCK_SIZE - 1);
+
+ /**
+ * append the bit '1' to the message which would be 0x80 if message
+ * length is a multiple of 8 bits.
+ */
+ ctx->b8[i++] = 0x80;
+ /**
+ * append 0 ≤ k < 512 bits '0', such that the resulting message length
+ * in bits is congruent to −64 ≡ 448 (mod 512)
+ */
+ if (i > (SHA1_BLOCK_SIZE - sizeof(cnt))) {
+ /* current block won't fit length, so move to next */
+ while (i < SHA1_BLOCK_SIZE)
+ ctx->b8[i++] = 0;
+ SHA1_transform(ctx);
+ i = 0;
+ }
+ /* pad rest of zeros */
+ while (i < (SHA1_BLOCK_SIZE - sizeof(cnt)))
+ ctx->b8[i++] = 0;
+ /* place big-endian 64-bit bit counter at the end of block */
+ ctx->b64[SHA1_BLOCK_DWORDS - 1] = htobe64(cnt);
+ SHA1_transform(ctx);
+ for (i = 0; i < 5; i++)
+ ctx->b32[i] = htobe32(ctx->state[i]);
+ return &ctx->digest;
}
-const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n,
- uint8_t *digest)
+/* One shot SHA1 calculation */
+const struct sha1_digest *SHA1_sw_hash(const void *data, size_t len,
+ struct sha1_digest *digest)
{
- if (dcrypto_grab_sha_hw())
- /* dcrypto_sha_wait() will release the hw. */
- dcrypto_sha_hash(SHA1_MODE, data, n, digest);
- else
- SHA_hash(data, n, digest);
+ struct sha1_ctx ctx;
+
+ SHA1_sw_init(&ctx);
+ SHA1_sw_update(&ctx, data, len);
+ memcpy(digest->b8, SHA1_sw_final(&ctx)->b8, SHA1_DIGEST_SIZE);
return digest;
}
diff --git a/board/cr50/dcrypto/sha256.c b/board/cr50/dcrypto/sha256.c
index f127ab445a..2df4514081 100644
--- a/board/cr50/dcrypto/sha256.c
+++ b/board/cr50/dcrypto/sha256.c
@@ -4,192 +4,205 @@
*/
#include "dcrypto.h"
+#include "endian.h"
#include "internal.h"
#include "registers.h"
#include "util.h"
-#include "cryptoc/sha256.h"
-
-static void dcrypto_sha256_init(LITE_SHA256_CTX *ctx);
-static const uint8_t *dcrypto_sha256_final(LITE_SHA256_CTX *ctx);
-
-#ifdef SECTION_IS_RO
-/* RO is single threaded. */
-#define mutex_lock(x)
-#define mutex_unlock(x)
-static inline int dcrypto_grab_sha_hw(void)
-{
- return 1;
-}
-static inline void dcrypto_release_sha_hw(void)
-{
-}
-#else
-#include "task.h"
-static struct mutex hw_busy_mutex;
-
-static int hw_busy;
-
-int dcrypto_grab_sha_hw(void)
+static void SHA256_transform(struct sha256_ctx *const ctx)
{
- int rv = 0;
-
- mutex_lock(&hw_busy_mutex);
- if (!hw_busy) {
- rv = 1;
- hw_busy = 1;
+ static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
+ 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
+ 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
+ 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
+ 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
+ 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
+ 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+ uint32_t W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+ size_t t;
+
+ for (t = 0; t < 16; ++t)
+ W[t] = be32toh(ctx->b32[t]);
+ for (; t < 64; t++) {
+ uint32_t s0 = ror(W[t - 15], 7) ^ ror(W[t - 15], 18) ^
+ (W[t - 15] >> 3);
+ uint32_t s1 = ror(W[t - 2], 17) ^ ror(W[t - 2], 19) ^
+ (W[t - 2] >> 10);
+
+ W[t] = W[t - 16] + s0 + W[t - 7] + s1;
}
- mutex_unlock(&hw_busy_mutex);
-
- return rv;
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+ for (t = 0; t < 64; t++) {
+ uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
+ uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
+ uint32_t t2 = s0 + maj;
+ uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
+ uint32_t ch = (E & F) ^ ((~E) & G);
+ uint32_t t1 = H + s1 + ch + K[t] + W[t];
+
+ H = G;
+ G = F;
+ F = E;
+ E = D + t1;
+ D = C;
+ C = B;
+ B = A;
+ A = t1 + t2;
+ }
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
}
-
-void dcrypto_release_sha_hw(void)
+/**
+ * Define aliases taking union type as parameter. This is safe
+ * as union type has header in same place and is not less than original type.
+ * Equal to:
+ * void SHA256_init_as_hash(HASH_CTX *const ctx) {SHA256_init(&ctx.sha256);}
+ * but save some space for embedded uses.
+ */
+BUILD_ASSERT(sizeof(union hash_ctx) >= sizeof(struct sha256_ctx));
+BUILD_ASSERT(sizeof(union hash_ctx) >= sizeof(struct sha224_ctx));
+
+static void SHA256_init_as_hash(union hash_ctx *const ctx)
+ __alias(SHA256_sw_init);
+static void SHA256_update_as_hash(union hash_ctx *const ctx, const void *data,
+ size_t len) __alias(SHA256_sw_update);
+static const union sha_digests *SHA256_final_as_hash(union hash_ctx *const ctx)
+ __alias(SHA256_sw_final);
+static void SHA224_init_as_hash(union hash_ctx *const ctx)
+ __alias(SHA224_sw_init);
+
+void SHA256_sw_init(struct sha256_ctx *const ctx)
{
- mutex_lock(&hw_busy_mutex);
- hw_busy = 0;
- mutex_unlock(&hw_busy_mutex);
+ static const struct hash_vtable sha256_vtable = {
+ SHA256_init_as_hash, SHA256_update_as_hash,
+ SHA256_final_as_hash, HMAC_sw_final,
+ SHA256_DIGEST_SIZE, SHA256_BLOCK_SIZE,
+ sizeof(struct sha256_ctx)
+ };
+ static const uint32_t sha256_init[SHA256_DIGEST_WORDS] = {
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ };
+
+ ctx->f = &sha256_vtable;
+ memcpy(ctx->state, sha256_init, sizeof(ctx->state));
+ ctx->count = 0;
}
-#endif /* ! SECTION_IS_RO */
-
-void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest)
-{
- int i;
- const int digest_len = (mode == SHA1_MODE) ?
- SHA_DIGEST_SIZE :
- SHA256_DIGEST_SIZE;
-
- /* Stop LIVESTREAM mode. */
- GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_STOP_MASK;
-
- /* Wait for SHA DONE interrupt. */
- while (!GREG32(KEYMGR, SHA_ITOP))
- ;
-
- /* Read out final digest. */
- for (i = 0; i < digest_len / 4; ++i)
- *digest++ = GR_KEYMGR_SHA_HASH(i);
- dcrypto_release_sha_hw();
-}
+/* SHA2-224 and SHA2-256 use same internal context. */
+BUILD_ASSERT(sizeof(struct sha224_ctx) == sizeof(struct sha256_ctx));
+void SHA224_sw_update(struct sha224_ctx *ctx, const void *data, size_t len)
+ __alias(SHA256_sw_update);
-/* Hardware SHA implementation. */
-static const HASH_VTAB HW_SHA256_VTAB = {
- dcrypto_sha256_init,
- dcrypto_sha_update,
- dcrypto_sha256_final,
- DCRYPTO_SHA256_hash,
- SHA256_DIGEST_SIZE
-};
-
-void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data, uint32_t n,
- uint8_t *digest)
+void SHA256_sw_update(struct sha256_ctx *ctx, const void *data, size_t len)
{
- dcrypto_sha_init(mode);
- dcrypto_sha_update(NULL, data, n);
- dcrypto_sha_wait(mode, (uint32_t *) digest);
+ size_t i = ctx->count & (SHA256_BLOCK_SIZE - 1);
+ const uint8_t *p = (const uint8_t *)data;
+
+ ctx->count += len;
+ while (len--) {
+ ctx->b8[i++] = *p++;
+ if (i == SHA256_BLOCK_SIZE) {
+ SHA256_transform(ctx);
+ i = 0;
+ }
+ }
}
-
-void dcrypto_sha_update(struct HASH_CTX *unused,
- const void *data, uint32_t n)
+const struct sha224_digest *SHA224_sw_final(struct sha224_ctx *const ctx)
+ __alias(SHA256_sw_final);
+const struct sha256_digest *SHA256_sw_final(struct sha256_ctx *const ctx)
{
- const uint8_t *bp = (const uint8_t *) data;
- const uint32_t *wp;
-
- /* Feed unaligned start bytes. */
- while (n != 0 && ((uint32_t)bp & 3)) {
- GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
- n -= 1;
- }
-
- /* Feed groups of aligned words. */
- wp = (uint32_t *)bp;
- while (n >= 8*4) {
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- n -= 8*4;
- }
- /* Feed individual aligned words. */
- while (n >= 4) {
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- n -= 4;
- }
-
- /* Feed remaing bytes. */
- bp = (uint8_t *) wp;
- while (n != 0) {
- GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
- n -= 1;
+ uint64_t cnt = (uint64_t)ctx->count * CHAR_BIT;
+ size_t i = ctx->count & (SHA256_BLOCK_SIZE - 1);
+
+ /**
+ * append the bit '1' to the message which would be 0x80 if message
+ * length is a multiple of 8 bits.
+ */
+ ctx->b8[i++] = 0x80;
+ /**
+ * Append 0 ≤ k < 512 bits '0', such that the resulting message length
+ * in bits is congruent to −64 ≡ 448 (mod 512).
+ */
+ if (i > (SHA256_BLOCK_SIZE - sizeof(cnt))) {
+ /* Current block won't fit length, so move to next. */
+ while (i < SHA256_BLOCK_SIZE)
+ ctx->b8[i++] = 0;
+ SHA256_transform(ctx);
+ i = 0;
}
+ /* Pad rest of zeros. */
+ while (i < (SHA256_BLOCK_SIZE - sizeof(cnt)))
+ ctx->b8[i++] = 0;
+
+ /* Place big-endian 64-bit bit counter at the end of block. */
+ ctx->b64[SHA256_BLOCK_DWORDS - 1] = htobe64(cnt);
+ SHA256_transform(ctx);
+ for (i = 0; i < 8; i++)
+ ctx->b32[i] = htobe32(ctx->state[i]);
+ return &ctx->digest;
}
-void dcrypto_sha_init(enum sha_mode mode)
+void SHA224_sw_init(struct sha224_ctx *const ctx)
{
- int val;
-
- /* Stop LIVESTREAM mode, in case final() was not called. */
- GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_STOP_MASK;
- /* Clear interrupt status. */
- GREG32(KEYMGR, SHA_ITOP) = 0;
-
- /* Enable streaming mode. */
- val = GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK;
- /* Enable SHA DONE interrupt. */
- val |= GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK;
- /* Select SHA mode. */
- if (mode == SHA1_MODE)
- val |= GC_KEYMGR_SHA_CFG_EN_SHA1_MASK;
- GREG32(KEYMGR, SHA_CFG_EN) = val;
-
- /* Turn off random nops (which are enabled by default). */
- GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, STALL_EN, 0);
- /* Configure random nop percentage at 12%. */
- GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, FREQ, 2);
- /* Now turn on random nops. */
- GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, STALL_EN, 1);
-
- /* Start SHA engine. */
- GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_GO_MASK;
+ /* SHA2-224 differs from SHA2-256 only in initialization. */
+ static const struct hash_vtable sha224_vtable = {
+ SHA224_init_as_hash, SHA256_update_as_hash,
+ SHA256_final_as_hash, HMAC_sw_final,
+ SHA224_DIGEST_SIZE, SHA224_BLOCK_SIZE,
+ sizeof(struct sha224_ctx)
+ };
+ static const uint32_t sha224_init[SHA256_DIGEST_WORDS] = {
+ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+ };
+
+ ctx->f = &sha224_vtable;
+ memcpy(ctx->state, sha224_init, sizeof(ctx->state));
+ ctx->count = 0;
}
-static void dcrypto_sha256_init(LITE_SHA256_CTX *ctx)
+/* One shot hash computation. */
+const struct sha224_digest *SHA224_sw_hash(const void *data, size_t len,
+ struct sha224_digest *digest)
{
- ctx->f = &HW_SHA256_VTAB;
- dcrypto_sha_init(SHA256_MODE);
-}
+ struct sha224_ctx ctx;
-/* Requires dcrypto_grab_sha_hw() to be called first. */
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
-{
- if (!sw_required && dcrypto_grab_sha_hw())
- dcrypto_sha256_init(ctx);
-#ifndef SECTION_IS_RO
- else
- SHA256_init(ctx);
-#endif
+ SHA224_sw_init(&ctx);
+ SHA224_sw_update(&ctx, data, len);
+ memcpy(digest->b8, SHA224_sw_final(&ctx), SHA224_DIGEST_SIZE);
+ return digest;
}
-
-static const uint8_t *dcrypto_sha256_final(LITE_SHA256_CTX *ctx)
+/* One shot hash computation */
+const struct sha256_digest *SHA256_sw_hash(const void *data, size_t len,
+ struct sha256_digest *digest)
{
- dcrypto_sha_wait(SHA256_MODE, (uint32_t *) ctx->buf);
- return ctx->buf;
-}
+ struct sha256_ctx ctx;
-const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
- uint8_t *digest)
-{
- if (dcrypto_grab_sha_hw())
- /* dcrypto_sha_wait() will release the hw. */
- dcrypto_sha_hash(SHA256_MODE, data, n, digest);
-#ifndef SECTION_IS_RO
- else
- SHA256_hash(data, n, digest);
-#endif
+ SHA256_sw_init(&ctx);
+ SHA256_sw_update(&ctx, data, len);
+ memcpy(digest->b8, SHA256_sw_final(&ctx)->b8, SHA256_DIGEST_SIZE);
return digest;
}
diff --git a/board/cr50/dcrypto/sha384.c b/board/cr50/dcrypto/sha384.c
deleted file mode 100644
index 6f3c6ca096..0000000000
--- a/board/cr50/dcrypto/sha384.c
+++ /dev/null
@@ -1,20 +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 "internal.h"
-
-#include "cryptoc/sha384.h"
-
-void DCRYPTO_SHA384_init(LITE_SHA512_CTX *ctx)
-{
- SHA384_init(ctx);
-}
-
-const uint8_t *DCRYPTO_SHA384_hash(const void *data, uint32_t n,
- uint8_t *digest)
-{
- return SHA384_hash(data, n, digest);
-}
diff --git a/board/cr50/dcrypto/sha512.c b/board/cr50/dcrypto/sha512.c
index 1446970174..31b0d47c1a 100644
--- a/board/cr50/dcrypto/sha512.c
+++ b/board/cr50/dcrypto/sha512.c
@@ -4,17 +4,254 @@
*/
#include "dcrypto.h"
+#include "endian.h"
#include "internal.h"
-#include "cryptoc/sha512.h"
+static void SHA512_transform(struct sha512_ctx *ctx)
+{
+ static const uint64_t K[80] = {
+ 0x428A2F98D728AE22ll, 0x7137449123EF65CDll,
+ 0xB5C0FBCFEC4D3B2Fll, 0xE9B5DBA58189DBBCll,
+ 0x3956C25BF348B538ll, 0x59F111F1B605D019ll,
+ 0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll,
+ 0xD807AA98A3030242ll, 0x12835B0145706FBEll,
+ 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll,
+ 0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll,
+ 0x9BDC06A725C71235ll, 0xC19BF174CF692694ll,
+ 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll,
+ 0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll,
+ 0x2DE92C6F592B0275ll, 0x4A7484AA6EA6E483ll,
+ 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll,
+ 0x983E5152EE66DFABll, 0xA831C66D2DB43210ll,
+ 0xB00327C898FB213Fll, 0xBF597FC7BEEF0EE4ll,
+ 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll,
+ 0x06CA6351E003826Fll, 0x142929670A0E6E70ll,
+ 0x27B70A8546D22FFCll, 0x2E1B21385C26C926ll,
+ 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll,
+ 0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll,
+ 0x81C2C92E47EDAEE6ll, 0x92722C851482353Bll,
+ 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll,
+ 0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll,
+ 0xD192E819D6EF5218ll, 0xD69906245565A910ll,
+ 0xF40E35855771202All, 0x106AA07032BBD1B8ll,
+ 0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll,
+ 0x2748774CDF8EEB99ll, 0x34B0BCB5E19B48A8ll,
+ 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll,
+ 0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll,
+ 0x748F82EE5DEFB2FCll, 0x78A5636F43172F60ll,
+ 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll,
+ 0x90BEFFFA23631E28ll, 0xA4506CEBDE82BDE9ll,
+ 0xBEF9A3F7B2C67915ll, 0xC67178F2E372532Bll,
+ 0xCA273ECEEA26619Cll, 0xD186B8C721C0C207ll,
+ 0xEADA7DD6CDE0EB1Ell, 0xF57D4F7FEE6ED178ll,
+ 0x06F067AA72176FBAll, 0x0A637DC5A2C898A6ll,
+ 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll,
+ 0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll,
+ 0x3C9EBE0A15C9BEBCll, 0x431D67C49C100D4Cll,
+ 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All,
+ 0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll
+ };
+ uint64_t W[80];
+ uint64_t A, B, C, D, E, F, G, H;
+ size_t t;
+
+ for (t = 0; t < 16; t++)
+ W[t] = be64toh(ctx->b64[t]);
+
+ for (; t < 80; t++) {
+ uint64_t Wt2 = W[t - 2];
+ uint64_t Wt7 = W[t - 7];
+ uint64_t Wt15 = W[t - 15];
+ uint64_t Wt16 = W[t - 16];
+ uint64_t s0 = ror64(Wt15, 1) ^ ror64(Wt15, 8) ^ (Wt15 >> 7);
+ uint64_t s1 = ror64(Wt2, 19) ^ ror64(Wt2, 61) ^ (Wt2 >> 6);
+
+ W[t] = s1 + Wt7 + s0 + Wt16;
+ }
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+ for (t = 0; t < 80; t++) {
+ uint64_t s0 = ror64(A, 28) ^ ror64(A, 34) ^ ror64(A, 39);
+ uint64_t maj = (A & B) ^ (A & C) ^ (B & C);
+ uint64_t t2 = s0 + maj;
+ uint64_t s1 = ror64(E, 14) ^ ror64(E, 18) ^ ror64(E, 41);
+ uint64_t ch = (E & F) ^ ((~E) & G);
+ uint64_t t1 = H + s1 + ch + W[t] + K[t];
+
+ H = G;
+ G = F;
+ F = E;
+ E = D + t1;
+ D = C;
+ C = B;
+ B = A;
+ A = t1 + t2;
+ }
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/**
+ * Define aliases taking union type as parameter. This is safe
+ * as union type has header in same place and is not less than original type.
+ * Equal to:
+ * void SHA512_init_as_hash(HASH_CTX *const ctx) {SHA512_init(&ctx.sha512);}
+ * but save some space for embedded uses.
+ */
+BUILD_ASSERT(sizeof(union hash_ctx) >= sizeof(struct sha512_ctx));
+BUILD_ASSERT(sizeof(union hash_ctx) >= sizeof(struct sha384_ctx));
+
+static void SHA512_init_as_hash(union hash_ctx *const ctx)
+ __alias(SHA512_sw_init);
+static void SHA512_update_as_hash(union hash_ctx *const ctx, const void *data,
+ size_t len) __alias(SHA512_sw_update);
+static const union sha_digests *SHA512_final_as_hash(union hash_ctx *const ctx)
+ __alias(SHA512_sw_final);
+static void SHA384_init_as_hash(union hash_ctx *const ctx)
+ __alias(SHA384_sw_init);
+
+void SHA512_sw_init(struct sha512_ctx *const ctx)
+{
+ static const struct hash_vtable sha512_vtable = {
+ SHA512_init_as_hash, SHA512_update_as_hash,
+ SHA512_final_as_hash, HMAC_sw_final,
+ SHA512_DIGEST_SIZE, SHA512_BLOCK_SIZE,
+ sizeof(struct sha512_ctx)
+ };
+ static const uint64_t sha512_init[SHA512_DIGEST_DWORDS] = {
+ 0x6a09e667f3bcc908ll, 0xbb67ae8584caa73bll,
+ 0x3c6ef372fe94f82bll, 0xa54ff53a5f1d36f1ll,
+ 0x510e527fade682d1ll, 0x9b05688c2b3e6c1fll,
+ 0x1f83d9abfb41bd6bll, 0x5be0cd19137e2179ll
+ };
+
+ memcpy(ctx->state, sha512_init, sizeof(ctx->state));
+ ctx->f = &sha512_vtable;
+ ctx->count = 0;
+}
+
+/* SHA2-384 and SHA2-512 use same internal context. */
+BUILD_ASSERT(sizeof(struct sha384_ctx) == sizeof(struct sha512_ctx));
+
+void SHA384_sw_update(struct sha384_ctx *const ctx, const void *data,
+ size_t len) __alias(SHA512_sw_update);
+
+void SHA512_sw_update(struct sha512_ctx *const ctx, const void *data,
+ size_t len)
+{
+ size_t i = ctx->count & (SHA512_BLOCK_SIZE - 1);
+ const uint8_t *p = (const uint8_t *)data;
-void DCRYPTO_SHA512_init(LITE_SHA512_CTX *ctx)
+ ctx->count += len;
+ while (len--) {
+ ctx->b8[i++] = *p++;
+ if (i == SHA512_BLOCK_SIZE) {
+ SHA512_transform(ctx);
+ i = 0;
+ }
+ }
+}
+
+const struct sha384_digest *SHA384_sw_final(struct sha384_ctx *const ctx)
+ __alias(SHA512_sw_final);
+
+const struct sha512_digest *SHA512_sw_final(struct sha512_ctx *const ctx)
{
- SHA512_init(ctx);
+ uint64_t cnt = (uint64_t)ctx->count * CHAR_BIT;
+ size_t i = ctx->count & (SHA512_BLOCK_SIZE - 1);
+
+ /**
+ * Append the bit '1' to the message which would be 0x80 if message
+ * length is a multiple of 8 bits.
+ */
+ ctx->b8[i++] = 0x80;
+ /**
+ * Append 0 ≤ k < 1024 bits '0', such that the resulting message
+ * length in bits is congruent to −64 ≡ 896 (mod 1024).
+ */
+ if (i > (SHA512_BLOCK_SIZE - 2 * sizeof(cnt))) {
+ /* Current block won't fit length, so move to next. */
+ while (i < SHA512_BLOCK_SIZE)
+ ctx->b8[i++] = 0;
+ SHA512_transform(ctx);
+ i = 0;
+ }
+ /* pad rest of zeros, including 8 bytes of 128-bit counter */
+ while (i < (SHA512_BLOCK_SIZE - sizeof(cnt)))
+ ctx->b8[i++] = 0;
+ /* place big-endian 64-bit bit counter at the end of block */
+ ctx->b64[SHA512_BLOCK_DWORDS - 1] = htobe64(cnt);
+ SHA512_transform(ctx);
+ for (i = 0; i < 8; i++)
+ ctx->b64[i] = htobe64(ctx->state[i]);
+ return &ctx->digest;
}
-const uint8_t *DCRYPTO_SHA512_hash(const void *data, uint32_t n,
- uint8_t *digest)
+const struct sha512_digest *SHA512_sw_hash(const void *data, size_t len,
+ struct sha512_digest *digest)
{
- return SHA512_hash(data, n, digest);
+ struct sha512_ctx ctx;
+
+ SHA512_sw_init(&ctx);
+ SHA512_sw_update(&ctx, data, len);
+ memcpy(digest->b8, SHA512_sw_final(&ctx)->b8, SHA512_DIGEST_SIZE);
+ return digest;
+}
+
+void SHA384_sw_init(struct sha384_ctx *ctx)
+{
+ /* SHA2-384 differs from SHA2-512 only in initialization. */
+ static const struct hash_vtable sha384_vtable = {
+ SHA384_init_as_hash, SHA512_update_as_hash,
+ SHA512_final_as_hash, HMAC_sw_final,
+ SHA384_DIGEST_SIZE, SHA384_BLOCK_SIZE,
+ sizeof(struct sha384_ctx)
+ };
+ static const uint64_t sha384_init[SHA512_DIGEST_DWORDS] = {
+ 0xcbbb9d5dc1059ed8ll, 0x629a292a367cd507ll,
+ 0x9159015a3070dd17ll, 0x152fecd8f70e5939ll,
+ 0x67332667ffc00b31ll, 0x8eb44a8768581511ll,
+ 0xdb0c2e0d64f98fa7ll, 0x47b5481dbefa4fa4ll
+ };
+
+ memcpy(ctx->state, sha384_init, sizeof(ctx->state));
+ ctx->count = 0;
+ ctx->f = &sha384_vtable;
}
+
+const struct sha384_digest *SHA384_sw_hash(const void *data, size_t len,
+ struct sha384_digest *digest)
+{
+ struct sha384_ctx ctx;
+
+ SHA384_sw_init(&ctx);
+ SHA384_sw_update(&ctx, data, len);
+ memcpy(digest->b8, SHA384_sw_final(&ctx)->b8, SHA384_DIGEST_SIZE);
+ return digest;
+}
+
+/**
+ * We don't support HW-accelerated SHA384/SHA512 yet, so alias it to software.
+ */
+const struct sha512_digest *SHA512_hw_hash(const void *data, size_t len,
+ struct sha512_digest *digest)
+ __alias(SHA512_sw_hash);
+
+const struct sha384_digest *SHA384_hw_hash(const void *data, size_t len,
+ struct sha384_digest *digest)
+ __alias(SHA384_sw_hash);
+
+void SHA512_hw_init(struct sha512_ctx *const ctx) __alias(SHA512_sw_init);
+void SHA384_hw_init(struct sha384_ctx *const ctx) __alias(SHA384_sw_init);
diff --git a/board/cr50/dcrypto/sha_hw.c b/board/cr50/dcrypto/sha_hw.c
new file mode 100644
index 0000000000..acad1ba29d
--- /dev/null
+++ b/board/cr50/dcrypto/sha_hw.c
@@ -0,0 +1,265 @@
+/* Copyright 2021 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 "internal.h"
+#include "registers.h"
+
+#ifdef SECTION_IS_RO
+/* RO is single threaded. */
+#define mutex_lock(x)
+#define mutex_unlock(x)
+static inline int dcrypto_grab_sha_hw(void)
+{
+ return 1;
+}
+static inline void dcrypto_release_sha_hw(void)
+{
+}
+#else
+#include "task.h"
+static struct mutex hw_busy_mutex;
+
+static bool hw_busy;
+
+int dcrypto_grab_sha_hw(void)
+{
+ int rv = 0;
+
+ mutex_lock(&hw_busy_mutex);
+ if (!hw_busy) {
+ rv = 1;
+ hw_busy = true;
+ }
+ mutex_unlock(&hw_busy_mutex);
+
+ return rv;
+}
+
+void dcrypto_release_sha_hw(void)
+{
+ mutex_lock(&hw_busy_mutex);
+ hw_busy = false;
+ mutex_unlock(&hw_busy_mutex);
+}
+
+#endif /* ! SECTION_IS_RO */
+
+static void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest)
+{
+ int i;
+ const int digest_len = (mode == SHA1_MODE) ? SHA1_DIGEST_SIZE :
+ SHA256_DIGEST_SIZE;
+
+ /* Stop LIVESTREAM mode. */
+ GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_STOP_MASK;
+
+ /* Wait for SHA DONE interrupt. */
+ while (!GREG32(KEYMGR, SHA_ITOP))
+ ;
+
+ /* Read out final digest. */
+ for (i = 0; i < digest_len / 4; ++i)
+ *digest++ = GR_KEYMGR_SHA_HASH(i);
+ dcrypto_release_sha_hw();
+}
+
+static void dcrypto_sha_update(union hash_ctx *unused, const void *data,
+ size_t n)
+{
+ const uint8_t *bp = (const uint8_t *)data;
+ const uint32_t *wp;
+
+ /* Feed unaligned start bytes. */
+ while (n != 0 && ((uint32_t)bp & 3)) {
+ GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
+ n -= 1;
+ }
+
+ /* Feed groups of aligned words. */
+ wp = (uint32_t *)bp;
+ while (n >= 8 * 4) {
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ n -= 8 * 4;
+ }
+ /* Feed individual aligned words. */
+ while (n >= 4) {
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ n -= 4;
+ }
+
+ /* Feed remaining bytes. */
+ bp = (uint8_t *)wp;
+ while (n != 0) {
+ GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
+ n -= 1;
+ }
+}
+
+static void dcrypto_sha_init(enum sha_mode mode)
+{
+ int val;
+
+ /* Stop LIVESTREAM mode, in case final() was not called. */
+ GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_STOP_MASK;
+ /* Clear interrupt status. */
+ GREG32(KEYMGR, SHA_ITOP) = 0;
+
+ /* Enable streaming mode. */
+ val = GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK;
+ /* Enable SHA DONE interrupt. */
+ val |= GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK;
+ /* Select SHA mode. */
+ if (mode == SHA1_MODE)
+ val |= GC_KEYMGR_SHA_CFG_EN_SHA1_MASK;
+ GREG32(KEYMGR, SHA_CFG_EN) = val;
+
+ /* Turn off random nops (which are enabled by default). */
+ GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, STALL_EN, 0);
+ /* Configure random nop percentage at 12%. */
+ GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, FREQ, 2);
+ /* Now turn on random nops. */
+ GWRITE_FIELD(KEYMGR, SHA_RAND_STALL_CTL, STALL_EN, 1);
+
+ /* Start SHA engine. */
+ GREG32(KEYMGR, SHA_TRIG) = GC_KEYMGR_SHA_TRIG_TRIG_GO_MASK;
+}
+
+static const struct sha1_digest *dcrypto_sha1_final(union hash_ctx *ctx)
+{
+ dcrypto_sha_wait(SHA1_MODE, ctx->sha1.digest.b32);
+ return &ctx->sha1.digest;
+}
+
+static const struct sha256_digest *dcrypto_sha256_final(union hash_ctx *ctx)
+{
+ dcrypto_sha_wait(SHA256_MODE, ctx->sha256.digest.b32);
+ return &ctx->sha256.digest;
+}
+
+static const union sha_digests *dcrypto_sha256_final_as_hash(
+ union hash_ctx *const ctx) __alias(dcrypto_sha256_final);
+static const union sha_digests *dcrypto_sha1_final_as_hash(
+ union hash_ctx *const ctx) __alias(dcrypto_sha1_final);
+
+static void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data, size_t n,
+ uint32_t *digest)
+{
+ dcrypto_sha_init(mode);
+ dcrypto_sha_update(NULL, data, n);
+ dcrypto_sha_wait(mode, digest);
+}
+
+/* Requires dcrypto_grab_sha_hw() to be called first. */
+static void dcrypto_sha1_init(union hash_ctx *ctx)
+{
+ static const struct hash_vtable hw_sha1_vtab = {
+ dcrypto_sha1_init, dcrypto_sha_update,
+ dcrypto_sha1_final_as_hash, HMAC_sw_final,
+ SHA1_DIGEST_SIZE, SHA1_BLOCK_SIZE,
+ sizeof(struct sha1_ctx)
+ };
+
+ ctx->f = &hw_sha1_vtab;
+ dcrypto_sha_init(SHA1_MODE);
+}
+
+static void dcrypto_sha256_init(union hash_ctx *ctx)
+{
+ /* Hardware SHA implementation. */
+ static const struct hash_vtable HW_SHA256_VTAB = {
+ dcrypto_sha256_init, dcrypto_sha_update,
+ dcrypto_sha256_final_as_hash, HMAC_sw_final,
+ SHA256_DIGEST_SIZE, SHA256_BLOCK_SIZE,
+ sizeof(struct sha256_ctx)
+ };
+
+ ctx->f = &HW_SHA256_VTAB;
+ dcrypto_sha_init(SHA256_MODE);
+}
+
+/**
+ * Select and initialize either the software or hardware
+ * implementation. If "multi-threaded" behaviour is required, then
+ * callers must specifically use software version SHA1_sw_init(). This
+ * is because SHA1 state internal to the hardware cannot be extracted, so
+ * it is not possible to suspend and resume a hardware based SHA operation.
+ *
+ * Hardware implementation is selected based on availability. Hardware is
+ * considered to be in use between init() and finished() calls. If hardware
+ * is not available, fall back to software implementation.
+ */
+void SHA1_hw_init(struct sha1_ctx *ctx)
+{
+ if (dcrypto_grab_sha_hw())
+ dcrypto_sha1_init((union hash_ctx *)ctx);
+ else
+ SHA1_sw_init(ctx);
+}
+
+/**
+ * Select and initialize either the software or hardware
+ * implementation. If "multi-threaded" behaviour is required, then
+ * callers must specifically use software version SHA256_sw_init(). This
+ * is because SHA256 state internal to the hardware cannot be extracted, so
+ * it is not possible to suspend and resume a hardware based SHA operation.
+ *
+ * Hardware implementation is selected based on availability. Hardware is
+ * considered to be in use between init() and finished() calls. If hardware
+ * is not available, fall back to software implementation.
+ */
+void SHA256_hw_init(struct sha256_ctx *ctx)
+{
+ if (dcrypto_grab_sha_hw())
+ dcrypto_sha256_init((union hash_ctx *)ctx);
+ else
+ SHA256_sw_init(ctx);
+}
+
+const struct sha1_digest *SHA1_hw_hash(const void *data, size_t n,
+ struct sha1_digest *digest)
+{
+ if (dcrypto_grab_sha_hw())
+ /* dcrypto_sha_wait() will release the hw. */
+ dcrypto_sha_hash(SHA1_MODE, data, n, digest->b32);
+ else
+ SHA1_sw_hash(data, n, digest);
+ return digest;
+}
+
+const struct sha256_digest *SHA256_hw_hash(const void *data, size_t n,
+ struct sha256_digest *digest)
+{
+ if (dcrypto_grab_sha_hw())
+ /* dcrypto_sha_wait() will release the hw. */
+ dcrypto_sha_hash(SHA256_MODE, data, n, digest->b32);
+ else
+ SHA256_sw_hash(data, n, digest);
+ return digest;
+}
+
+/* For compatibility with chip/g code. */
+const uint8_t *DCRYPTO_SHA1_hash(const void *data, size_t n, uint8_t *digest)
+ __alias(SHA1_hw_hash);
+
+/* TODO(b/195092622): initialize HW HMAC instead. */
+void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
+ size_t len)
+{
+ SHA256_hw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+const struct sha256_digest *
+HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx)
+{
+ return HMAC_SHA256_final(ctx);
+}
diff --git a/board/cr50/dcrypto/x509.c b/board/cr50/dcrypto/x509.c
index 81f1674db1..3850100443 100644
--- a/board/cr50/dcrypto/x509.c
+++ b/board/cr50/dcrypto/x509.c
@@ -366,7 +366,7 @@ int DCRYPTO_x509_verify(const uint8_t *cert, size_t len,
const uint8_t *sig;
size_t sig_len;
- uint8_t digest[SHA256_DIGEST_SIZE];
+ struct sha256_digest digest;
/* Read Certificate SEQUENCE. */
if (!asn1_parse_certificate(&p, &len))
@@ -398,8 +398,8 @@ int DCRYPTO_x509_verify(const uint8_t *cert, size_t len,
sig_len--;
}
- DCRYPTO_SHA256_hash(tbs, tbs_len, digest);
- return DCRYPTO_rsa_verify(ca_pub_key, digest, sizeof(digest),
+ SHA256_hw_hash(tbs, tbs_len, &digest);
+ return DCRYPTO_rsa_verify(ca_pub_key, digest.b8, sizeof(digest),
sig, sig_len, PADDING_MODE_PKCS1, HASH_SHA256);
}
@@ -425,7 +425,7 @@ int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x,
const char *name, uint8_t *cert, const int n)
{
struct asn1 ctx = {cert, 0};
- HASH_CTX sha;
+ struct sha256_ctx sha;
p256_int h, r, s;
struct drbg_ctx drbg;
@@ -513,9 +513,9 @@ int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x,
SEQ_END(ctx); /* Cert body */
/* Sign all of cert body */
- DCRYPTO_SHA256_init(&sha, 0);
- HASH_update(&sha, body, (ctx.p + ctx.n) - body);
- p256_from_bin(HASH_final(&sha), &h);
+ SHA256_hw_init(&sha);
+ SHA256_update(&sha, body, (ctx.p + ctx.n) - body);
+ p256_from_bin(SHA256_final(&sha)->b8, &h);
hmac_drbg_init_rfc6979(&drbg, d, &h);
if (!dcrypto_p256_ecdsa_sign(&drbg, d, &h, &r, &s))
return 0;
diff --git a/board/cr50/fips.c b/board/cr50/fips.c
index 51a392e2ac..948bd2fba4 100644
--- a/board/cr50/fips.c
+++ b/board/cr50/fips.c
@@ -153,7 +153,7 @@ void fips_throw_err(enum fips_status err)
/* KAT for SHA256, test values from OpenSSL. */
static bool fips_sha256_kat(void)
{
- struct HASH_CTX ctx;
+ struct sha256_ctx ctx;
static const uint8_t in[] = /* "etaonrishd" */ { 0x65, 0x74, 0x61, 0x6f,
0x6e, 0x72, 0x69, 0x73,
@@ -164,16 +164,16 @@ static bool fips_sha256_kat(void)
0xc8, 0x5d, 0x1c, 0xaf, 0x64, 0x22, 0xe6,
0x50, 0x4f, 0x47, 0x57 };
- DCRYPTO_SHA256_init(&ctx, 0);
- HASH_update(&ctx, in, sizeof(in));
+ SHA256_hw_init(&ctx);
+ SHA256_update(&ctx, in, sizeof(in));
return !(fips_break_cmd == FIPS_BREAK_SHA256) &&
- (memcmp(HASH_final(&ctx), ans, SHA256_DIGEST_SIZE) == 0);
+ (memcmp(SHA256_final(&ctx), ans, SHA256_DIGEST_SIZE) == 0);
}
/* KAT for HMAC-SHA256, test values from OpenSSL. */
static bool fips_hmac_sha256_kat(void)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
static const uint8_t k[SHA256_DIGEST_SIZE] =
/* "etaonrishd" */ { 0x65, 0x74, 0x61, 0x6f, 0x6e, 0x72, 0x69,
@@ -190,10 +190,11 @@ static bool fips_hmac_sha256_kat(void)
0xa8, 0xea, 0xaa, 0x9f, 0xba, 0xee, 0x51,
0xff, 0xda, 0x24, 0xf4 };
- DCRYPTO_HMAC_SHA256_init(&ctx, k, sizeof(k));
- HASH_update(&ctx.hash, in, sizeof(in));
+ HMAC_SHA256_hw_init(&ctx, k, sizeof(k));
+ HMAC_SHA256_update(&ctx, in, sizeof(in));
return !(fips_break_cmd == FIPS_BREAK_HMAC_SHA256) &&
- (memcmp(DCRYPTO_HMAC_final(&ctx), ans, SHA256_DIGEST_SIZE) == 0);
+ (memcmp(HMAC_SHA256_hw_final(&ctx), ans, SHA256_DIGEST_SIZE) ==
+ 0);
}
/**
@@ -397,12 +398,12 @@ static bool fips_ecdsa_verify_kat(void)
};
p256_int p256_digest;
- uint8_t digest[SHA256_DIGEST_SIZE];
+ struct sha256_digest digest;
uint8_t bad_msg[128];
int passed;
- DCRYPTO_SHA256_hash(msg, sizeof(msg), digest);
- p256_from_bin(digest, &p256_digest);
+ SHA256_hw_hash(msg, sizeof(msg), &digest);
+ p256_from_bin(digest.b8, &p256_digest);
passed = dcrypto_p256_ecdsa_verify(&qx, &qy, &p256_digest, &r, &s);
if (!passed)
return false;
@@ -413,8 +414,8 @@ static bool fips_ecdsa_verify_kat(void)
*/
memcpy(bad_msg, msg, sizeof(msg));
bad_msg[92] ^= 0x10;
- DCRYPTO_SHA256_hash(bad_msg, sizeof(bad_msg), digest);
- p256_from_bin(digest, &p256_digest);
+ SHA256_hw_hash(bad_msg, sizeof(bad_msg), &digest);
+ p256_from_bin(digest.b8, &p256_digest);
passed = dcrypto_p256_ecdsa_verify(&qx, &qy, &p256_digest, &r, &s);
return !(fips_break_cmd == FIPS_BREAK_ECDSA) && (passed == 0);
}
@@ -580,19 +581,19 @@ static bool call_on_stack(void *new_stack, bool (*func)(void))
}
/* Placeholder for SHA256 digest of module computed during build time. */
-const uint8_t fips_integrity[SHA256_DIGEST_SIZE]
+const struct sha256_digest fips_integrity
__attribute__((section(".rodata.fips.checksum")));
static bool fips_self_integrity(void)
{
- uint8_t digest[SHA256_DIGEST_SIZE];
+ struct sha256_digest digest;
size_t module_length = &__fips_module_end - &__fips_module_start;
#ifdef CR50_DEV
CPRINTS("FIPS self-integrity start %x, length %u",
(uintptr_t)&__fips_module_start, module_length);
#endif
- DCRYPTO_SHA256_hash(&__fips_module_start, module_length, digest);
+ SHA256_hw_hash(&__fips_module_start, module_length, &digest);
#ifdef CR50_DEV
CPRINTS("Stored, %ph, computed %ph",
@@ -600,7 +601,7 @@ static bool fips_self_integrity(void)
HEX_BUF(digest, sizeof(digest)));
#endif
- return DCRYPTO_equals(fips_integrity, digest, sizeof(digest));
+ return DCRYPTO_equals(fips_integrity.b8, digest.b8, sizeof(digest));
}
/**
diff --git a/board/cr50/tpm2/ecc.c b/board/cr50/tpm2/ecc.c
index 1bcf2d5c5a..5607aaff87 100644
--- a/board/cr50/tpm2/ecc.c
+++ b/board/cr50/tpm2/ecc.c
@@ -192,7 +192,7 @@ CRYPT_RESULT _cpri__GenerateKeyEcc(
TPM2B *local_extra;
uint32_t count = 0;
uint8_t key_bytes[P256_NBYTES];
- LITE_HMAC_CTX hmac;
+ struct hmac_sha256_ctx hmac;
if (curve_id != TPM_ECC_NIST_P256)
return CRYPT_PARAMETER;
@@ -208,9 +208,10 @@ CRYPT_RESULT _cpri__GenerateKeyEcc(
/* Hash down the primary seed for ECC key generation, so that
* the derivation tree is distinct from RSA key derivation. */
- DCRYPTO_HMAC_SHA256_init(&hmac, seed->buffer, seed->size);
- HASH_update(&hmac.hash, "ECC", 4);
- memcpy(local_seed.t.buffer, DCRYPTO_HMAC_final(&hmac),
+ HMAC_SHA256_hw_init(&hmac, seed->buffer,
+ seed->size);
+ HMAC_SHA256_update(&hmac, "ECC", 4);
+ memcpy(local_seed.t.buffer, HMAC_SHA256_final(&hmac),
local_seed.t.size);
always_memset(&hmac, 0, sizeof(hmac));
/* b/35576109: the personalize code uses only the first 4 bytes
diff --git a/board/cr50/tpm2/endorsement.c b/board/cr50/tpm2/endorsement.c
index 844d07e2a6..49f542f782 100644
--- a/board/cr50/tpm2/endorsement.c
+++ b/board/cr50/tpm2/endorsement.c
@@ -30,8 +30,6 @@
#include "dcrypto.h"
-#include <cryptoc/sha256.h>
-
#include <endian.h>
#include <string.h>
@@ -548,7 +546,7 @@ enum manufacturing_status tpm_endorse(void)
enum manufacturing_status result;
uint8_t eps[PRIMARY_SEED_SIZE];
- LITE_HMAC_CTX hmac;
+ struct hmac_sha256_ctx hmac;
flash_cert_region_enable();
@@ -592,12 +590,12 @@ enum manufacturing_status tpm_endorse(void)
*
* This will fail if we are not running w/ expected keyladder.
*/
- DCRYPTO_HMAC_SHA256_init(&hmac, eps, sizeof(eps));
- HASH_update(&hmac.hash, "RSA", 4);
- DCRYPTO_HMAC_SHA256_init(&hmac, DCRYPTO_HMAC_final(&hmac), 32);
- HASH_update(&hmac.hash, p, RO_CERTS_REGION_SIZE - 32);
+ HMAC_SHA256_hw_init(&hmac, eps, sizeof(eps));
+ HMAC_SHA256_update(&hmac, "RSA", 4);
+ HMAC_SHA256_hw_init(&hmac, HMAC_SHA256_hw_final(&hmac), 32);
+ HMAC_SHA256_update(&hmac, p, RO_CERTS_REGION_SIZE - 32);
if (!DCRYPTO_equals(p + RO_CERTS_REGION_SIZE - 32,
- DCRYPTO_HMAC_final(&hmac), 32)) {
+ HMAC_SHA256_hw_final(&hmac), 32)) {
CPRINTF("%s: bad cert region hmac;", __func__);
#ifdef CR50_INCLUDE_FALLBACK_CERT
diff --git a/board/cr50/tpm2/hash.c b/board/cr50/tpm2/hash.c
index 7774a6f819..4494451844 100644
--- a/board/cr50/tpm2/hash.c
+++ b/board/cr50/tpm2/hash.c
@@ -42,7 +42,7 @@ uint16_t _cpri__GetHashBlockSize(TPM_ALG_ID alg)
return lookup_hash_info(alg)->blockSize;
}
-BUILD_ASSERT(sizeof(LITE_SHA256_CTX) == USER_MIN_HASH_STATE_SIZE);
+BUILD_ASSERT(sizeof(struct sha256_ctx) <= USER_MIN_HASH_STATE_SIZE);
BUILD_ASSERT(sizeof(CPRI_HASH_STATE) == sizeof(EXPORT_HASH_STATE));
void _cpri__ImportExportHashState(CPRI_HASH_STATE *osslFmt,
EXPORT_HASH_STATE *externalFmt,
@@ -57,7 +57,7 @@ void _cpri__ImportExportHashState(CPRI_HASH_STATE *osslFmt,
uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
uint32_t out_len, uint8_t *out)
{
- uint8_t digest[SHA_DIGEST_MAX_BYTES];
+ union sha_digests digest;
const uint16_t digest_len = _cpri__GetDigestSize(alg);
if (digest_len == 0)
@@ -65,17 +65,17 @@ uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
switch (alg) {
case TPM_ALG_SHA1:
- DCRYPTO_SHA1_hash(in, in_len, digest);
+ SHA1_hw_hash(in, in_len, &digest.sha1);
break;
case TPM_ALG_SHA256:
- DCRYPTO_SHA256_hash(in, in_len, digest);
+ SHA256_hw_hash(in, in_len, &digest.sha256);
break;
case TPM_ALG_SHA384:
- DCRYPTO_SHA384_hash(in, in_len, digest);
+ SHA384_hw_hash(in, in_len, &digest.sha384);
break;
case TPM_ALG_SHA512:
- DCRYPTO_SHA512_hash(in, in_len, digest);
+ SHA512_hw_hash(in, in_len, &digest.sha512);
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
@@ -83,16 +83,16 @@ uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
}
out_len = MIN(out_len, digest_len);
- memcpy(out, digest, out_len);
+ memcpy(out, digest.b8, out_len);
return out_len;
}
-BUILD_ASSERT(sizeof(struct HASH_CTX) <=
+BUILD_ASSERT(sizeof(union hash_ctx) <=
sizeof(((CPRI_HASH_STATE *)0)->state));
uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence,
CPRI_HASH_STATE *state)
{
- struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+ union hash_ctx *ctx = (union hash_ctx *) state->state;
uint16_t result;
/* NOTE: as per bug http://crosbug.com/p/55331#26 (NVMEM
@@ -103,20 +103,20 @@ uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence,
*/
switch (alg) {
case TPM_ALG_SHA1:
- DCRYPTO_SHA1_init(ctx, 1);
+ SHA1_sw_init(&ctx->sha1);
result = HASH_size(ctx);
break;
case TPM_ALG_SHA256:
- DCRYPTO_SHA256_init(ctx, 1);
+ SHA256_sw_init(&ctx->sha256);
result = HASH_size(ctx);
break;
case TPM_ALG_SHA384:
- DCRYPTO_SHA384_init(ctx);
+ SHA384_sw_init(&ctx->sha384);
result = HASH_size(ctx);
break;
case TPM_ALG_SHA512:
- DCRYPTO_SHA512_init(ctx);
+ SHA512_sw_init(&ctx->sha512);
result = HASH_size(ctx);
break;
default:
@@ -133,7 +133,7 @@ uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence,
void _cpri__UpdateHash(CPRI_HASH_STATE *state, uint32_t in_len,
BYTE *in)
{
- struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+ union hash_ctx *ctx = (union hash_ctx *) state->state;
HASH_update(ctx, in, in_len);
}
@@ -141,10 +141,10 @@ void _cpri__UpdateHash(CPRI_HASH_STATE *state, uint32_t in_len,
uint16_t _cpri__CompleteHash(CPRI_HASH_STATE *state,
uint32_t out_len, uint8_t *out)
{
- struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+ union hash_ctx *ctx = (union hash_ctx *) state->state;
out_len = MIN(HASH_size(ctx), out_len);
- memcpy(out, HASH_final(ctx), out_len);
+ memcpy(out, HASH_final(ctx)->b8, out_len);
return out_len;
}
@@ -294,7 +294,7 @@ static uint16_t do_software_hmac(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
static uint16_t do_dcrypto_hmac(TPM_ALG_ID alg, uint32_t in_len,
uint8_t *in, int32_t out_len, uint8_t *out)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
uint8_t *key;
uint32_t key_len;
@@ -304,10 +304,10 @@ static uint16_t do_dcrypto_hmac(TPM_ALG_ID alg, uint32_t in_len,
key = in + in_len;
key_len = *key++;
key_len = key_len * 256 + *key++;
- DCRYPTO_HMAC_SHA256_init(&ctx, key, key_len);
- HASH_update(&ctx.hash, in, in_len);
+ HMAC_SHA256_hw_init(&ctx, key, key_len);
+ HMAC_SHA256_update(&ctx, in, in_len);
out_len = MIN(out_len, SHA256_DIGEST_SIZE);
- memcpy(out, DCRYPTO_HMAC_final(&ctx), out_len);
+ memcpy(out, HMAC_SHA256_hw_final(&ctx), out_len);
return out_len;
}
@@ -382,7 +382,7 @@ static void hash_command_handler(void *cmd_body,
case HASH_ALG_SHA256:
alg = TPM_ALG_SHA256;
break;
-#ifdef SHA512_SUPPORT
+#ifdef CONFIG_UPTO_SHA512
case HASH_ALG_SHA384:
alg = TPM_ALG_SHA384;
break;
diff --git a/board/cr50/tpm2/rsa.c b/board/cr50/tpm2/rsa.c
index 70e14fba97..9d15d66823 100644
--- a/board/cr50/tpm2/rsa.c
+++ b/board/cr50/tpm2/rsa.c
@@ -396,11 +396,11 @@ CRYPT_RESULT _cpri__GenerateKeyRSA(
} else
#endif
{
- LITE_HMAC_CTX hmac;
+ struct hmac_sha256_ctx hmac;
- DCRYPTO_HMAC_SHA256_init(&hmac, seed->buffer, seed->size);
- HASH_update(&hmac.hash, "RSA", 4);
- memcpy(local_seed.t.buffer, DCRYPTO_HMAC_final(&hmac),
+ HMAC_SHA256_hw_init(&hmac, seed->buffer, seed->size);
+ HMAC_SHA256_update(&hmac, "RSA", 4);
+ memcpy(local_seed.t.buffer, HMAC_SHA256_hw_final(&hmac),
local_seed.t.size);
}
diff --git a/board/cr50/tpm2/virtual_nvmem.c b/board/cr50/tpm2/virtual_nvmem.c
index ef2bf62300..dc65d75f46 100644
--- a/board/cr50/tpm2/virtual_nvmem.c
+++ b/board/cr50/tpm2/virtual_nvmem.c
@@ -9,7 +9,7 @@
#include "board_id.h"
#include "console.h"
-#include "cryptoc/sha256.h"
+#include "dcrypto.h"
#include "link_defs.h"
#include "rma_auth.h"
#include "sn_bits.h"
@@ -300,16 +300,16 @@ BUILD_ASSERT(VIRTUAL_NV_INDEX_G2F_CERT_SIZE == G2F_ATTESTATION_CERT_MAX_LEN);
static void GetRSUDevID(BYTE *to, size_t offset, size_t size)
{
- LITE_SHA256_CTX ctx;
+ struct sha256_ctx ctx;
uint8_t rma_device_id[RMA_DEVICE_ID_SIZE];
const uint8_t *rsu_device_id;
get_rma_device_id(rma_device_id);
- SHA256_init(&ctx);
- HASH_update(&ctx, rma_device_id, sizeof(rma_device_id));
- HASH_update(&ctx, kRsuSalt, RSU_SALT_SIZE);
- rsu_device_id = HASH_final(&ctx);
+ SHA256_hw_init(&ctx);
+ SHA256_update(&ctx, rma_device_id, sizeof(rma_device_id));
+ SHA256_update(&ctx, kRsuSalt, RSU_SALT_SIZE);
+ rsu_device_id = SHA256_final(&ctx)->b8;
memcpy(to, rsu_device_id + offset, size);
}
diff --git a/board/cr50/u2f.c b/board/cr50/u2f.c
index d1d44a2ffa..43082d5008 100644
--- a/board/cr50/u2f.c
+++ b/board/cr50/u2f.c
@@ -222,11 +222,11 @@ int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y)
/* Generate unbiased private key */
while (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, buf)) {
- HASH_CTX sha;
+ struct sha256_ctx sha;
- DCRYPTO_SHA256_init(&sha, 0);
- HASH_update(&sha, buf, sizeof(buf));
- memcpy(buf, HASH_final(&sha), sizeof(buf));
+ SHA256_hw_init(&sha);
+ SHA256_update(&sha, buf, sizeof(buf));
+ memcpy(buf, SHA256_final(&sha), sizeof(buf));
}
return EC_SUCCESS;
diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c
index 8988ed30e1..6876272297 100644
--- a/board/cr50/usb_spi.c
+++ b/board/cr50/usb_spi.c
@@ -20,6 +20,7 @@
#include "tpm_registers.h"
#include "tpm_vendor_cmds.h"
#include "usb_spi.h"
+#include "usb_spi_board.h"
#include "watchdog.h"
#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
@@ -670,19 +671,20 @@ static enum vendor_cmd_rc spi_hash_dump(uint8_t *dest, uint32_t offset,
return VENDOR_RC_SUCCESS;
}
-int usb_spi_sha256_start(HASH_CTX *ctx)
+int usb_spi_sha256_start(struct sha256_ctx *ctx)
{
if (get_spi_bus_user() != SPI_BUS_USER_HASH) {
CPRINTS("%s: not enabled", __func__);
return EC_ERROR_BUSY;
}
- DCRYPTO_SHA256_init(ctx, 0);
+ SHA256_hw_init(ctx);
return EC_SUCCESS;
}
-int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size)
+int usb_spi_sha256_update(struct sha256_ctx *ctx, uint32_t offset,
+ uint32_t size)
{
uint8_t data[SPI_HASH_CHUNK_SIZE];
@@ -695,7 +697,7 @@ int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size)
return VENDOR_RC_READ_FLASH_FAIL;
}
/* Update hash */
- HASH_update(ctx, data, this_chunk);
+ SHA256_update(ctx, data, this_chunk);
/* Kick the watchdog every 128 chunks. */
if (((size / SPI_HASH_CHUNK_SIZE) % 128) == 127) {
@@ -709,12 +711,13 @@ int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size)
return EC_SUCCESS;
}
-void usb_spi_sha256_final(HASH_CTX *ctx, void *digest, size_t digest_size)
+void usb_spi_sha256_final(struct sha256_ctx *ctx, void *digest,
+ size_t digest_size)
{
size_t copy_size;
copy_size = MIN(digest_size, SHA256_DIGEST_SIZE);
- memcpy(digest, HASH_final(ctx), copy_size);
+ memcpy(digest, SHA256_final(ctx), copy_size);
if (copy_size < digest_size)
memset((uint8_t *)digest + copy_size, 0,
@@ -724,7 +727,7 @@ void usb_spi_sha256_final(HASH_CTX *ctx, void *digest, size_t digest_size)
static enum vendor_cmd_rc spi_hash_sha256(uint8_t *dest, uint32_t offset,
uint32_t size)
{
- HASH_CTX sha;
+ struct sha256_ctx sha;
CPRINTS("%s: 0x%x 0x%x", __func__, offset, size);
if (size > MAX_SPI_HASH_SIZE)
diff --git a/board/cr50/usb_spi_board.h b/board/cr50/usb_spi_board.h
new file mode 100644
index 0000000000..1c40f0814d
--- /dev/null
+++ b/board/cr50/usb_spi_board.h
@@ -0,0 +1,11 @@
+/* Copyright 2021 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"
+
+int usb_spi_sha256_start(struct sha256_ctx *ctx);
+int usb_spi_sha256_update(struct sha256_ctx *ctx, uint32_t offset,
+ uint32_t size);
+void usb_spi_sha256_final(struct sha256_ctx *ctx, void *digest,
+ size_t digest_size);
diff --git a/board/host/dcrypto.h b/board/host/dcrypto.h
index ce924e64fa..9c56674413 100644
--- a/board/host/dcrypto.h
+++ b/board/host/dcrypto.h
@@ -21,28 +21,13 @@
#ifndef CONFIG_DCRYPTO_MOCK
/* If not using the mock struct definitions, use the ones from Cr50. */
-#include "chip/g/dcrypto/dcrypto.h"
+#include "board/cr50/dcrypto/dcrypto.h"
#else /* defined(CONFIG_DCRYPTO_MOCK) */
-#include <sha256.h>
-
-#define HASH_CTX sha256_ctx
-
-/* Used as a replacement for declarations in cryptoc that are used by Cr50, but
- * add unnecessary complexity to the test code.
- */
-struct dcrypto_mock_ctx_t {
- struct HASH_CTX hash;
-};
-#define LITE_HMAC_CTX struct dcrypto_mock_ctx_t
-#define LITE_SHA256_CTX struct HASH_CTX
-
-void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len);
-uint8_t *HASH_final(struct HASH_CTX *ctx);
+#include "board/cr50/dcrypto/hmacsha2.h"
#define AES256_BLOCK_CIPHER_KEY_SIZE 32
-#define SHA256_DIGEST_SIZE 32
enum dcrypto_appid {
RESERVED = 0,
@@ -55,11 +40,11 @@ enum dcrypto_appid {
/* This enum value should not exceed 7. */
};
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required);
+void SHA256_hw_init(struct sha256_ctx *ctx);
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len);
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx);
+void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
+ size_t len);
+const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx);
int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
const uint8_t *iv, const uint8_t *in, size_t in_len);
diff --git a/builtin/endian.h b/builtin/endian.h
index 8a50cb4815..8ea6cb2da9 100644
--- a/builtin/endian.h
+++ b/builtin/endian.h
@@ -32,12 +32,12 @@ static inline uint64_t be64toh(uint64_t in)
return __builtin_bswap64(in);
}
+#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+
#define htobe16 be16toh
#define htobe32 be32toh
#define htobe64 be64toh
-#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
-
#ifdef __cplusplus
}
#endif
diff --git a/chip/g/usb_spi.h b/chip/g/usb_spi.h
index 2432dc2cd9..4cf38742af 100644
--- a/chip/g/usb_spi.h
+++ b/chip/g/usb_spi.h
@@ -8,7 +8,7 @@
/* USB SPI driver for Chrome EC */
#include "compile_time_macros.h"
-#include "cryptoc/sha256.h"
+#include "dcrypto.h"
#include "hooks.h"
#include "queue.h"
#include "queue_policies.h"
@@ -280,8 +280,4 @@ static inline bool usb_spi_shortcut_active(void) { return false; }
void enable_ap_spi_hash_shortcut(void);
void disable_ap_spi_hash_shortcut(void);
-int usb_spi_sha256_start(HASH_CTX *ctx);
-int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size);
-void usb_spi_sha256_final(HASH_CTX *ctx, void *digest, size_t digest_size);
-
#endif /* __CROS_EC_USB_SPI_H */
diff --git a/chip/host/build.mk b/chip/host/build.mk
index 8b7ab0efc2..0ea6027533 100644
--- a/chip/host/build.mk
+++ b/chip/host/build.mk
@@ -15,9 +15,16 @@ chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
endif
ifeq ($(CONFIG_DCRYPTO),y)
-CPPFLAGS += -I$(abspath ./chip/g)
-dirs-y += chip/g/dcrypto
+CPPFLAGS += -I$(abspath ./board/cr50)
+dirs-y += board/cr50/dcrypto
+LDFLAGS_EXTRA += -lcrypto
endif
+
+ifeq ($(CONFIG_DCRYPTO_MOCK),y)
+CPPFLAGS += -I$(abspath ./board/cr50)
+dirs-y += board/cr50/dcrypto
+endif
+
dirs-y += chip/host/dcrypto
chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o
@@ -26,4 +33,11 @@ chip-$(CONFIG_DCRYPTO)+= dcrypto/app_key.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/sha256.o
# Object files that can be shared with the Cr50 dcrypto implementation
-chip-$(CONFIG_DCRYPTO)+= ../g/dcrypto/hmac.o
+chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/hmac_sw.o
+chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/sha1.o
+chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/sha256.o
+chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/hmac_drbg.o
+
+# We still want raw SHA & HMAC implementations for mocked dcrypto
+chip-$(CONFIG_DCRYPTO_MOCK)+= ../../board/cr50/dcrypto/sha256.o
+chip-$(CONFIG_DCRYPTO_MOCK)+= ../../board/cr50/dcrypto/hmac_sw.o \ No newline at end of file
diff --git a/chip/host/dcrypto/app_cipher.c b/chip/host/dcrypto/app_cipher.c
index 4c4809005c..a3ce4e3184 100644
--- a/chip/host/dcrypto/app_cipher.c
+++ b/chip/host/dcrypto/app_cipher.c
@@ -9,15 +9,15 @@
void app_compute_hash(const void *p_buf, size_t num_bytes, void *p_hash,
size_t hash_len)
{
- uint8_t digest[SHA256_DIGEST_SIZE];
+ struct sha256_digest digest;
/*
* Use the built in dcrypto engine to generate the sha1 hash of the
* buffer.
*/
- DCRYPTO_SHA256_hash(p_buf, num_bytes, digest);
+ SHA256_hw_hash(p_buf, num_bytes, &digest);
- memcpy(p_hash, digest, MIN(hash_len, sizeof(digest)));
+ memcpy(p_hash, digest.b8, MIN(hash_len, sizeof(digest)));
if (hash_len > sizeof(digest))
memset((uint8_t *)p_hash + sizeof(digest), 0,
diff --git a/chip/host/dcrypto/sha256.c b/chip/host/dcrypto/sha256.c
index 429588c8ac..1c9fda27c2 100644
--- a/chip/host/dcrypto/sha256.c
+++ b/chip/host/dcrypto/sha256.c
@@ -5,14 +5,26 @@
#include "dcrypto.h"
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
+void SHA256_hw_init(struct sha256_ctx *ctx)
{
- SHA256_init(ctx);
+ SHA256_sw_init(ctx);
}
-const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
- uint8_t *digest)
+const struct sha256_digest *SHA256_hw_hash(const void *data, size_t n,
+ struct sha256_digest *digest)
{
- SHA256_hash(data, n, digest);
+ SHA256_sw_hash(data, n, digest);
return digest;
}
+
+void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
+ size_t len)
+{
+ SHA256_hw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx)
+{
+ return HMAC_SHA256_final(ctx);
+}
diff --git a/common/ap_ro_integrity_check.c b/common/ap_ro_integrity_check.c
index f6592d1ca9..ea0456ad5a 100644
--- a/common/ap_ro_integrity_check.c
+++ b/common/ap_ro_integrity_check.c
@@ -12,11 +12,11 @@
#include "extension.h"
#include "flash.h"
#include "flash_info.h"
-#include "cryptoc/sha256.h"
#include "stddef.h"
#include "stdint.h"
#include "timer.h"
#include "usb_spi.h"
+#include "usb_spi_board.h"
#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args)
#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args)
@@ -269,7 +269,7 @@ static enum ap_ro_check_vc_errors ap_ro_check_unsupported(int add_flash_event)
int validate_ap_ro(void)
{
uint32_t i;
- HASH_CTX ctx;
+ struct sha256_ctx ctx;
uint8_t digest[SHA256_DIGEST_SIZE];
int rv;
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 3433766b7c..b3b12e12a7 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -9,7 +9,6 @@
#include "byteorder.h"
#include "ccd_config.h"
#include "console.h"
-#include "cryptoc/sha256.h"
#include "dcrypto.h"
#include "extension.h"
#include "hooks.h"
@@ -239,17 +238,17 @@ static int raw_has_password(void)
*/
static void ccd_password_digest(uint8_t *digest, const char *password)
{
- HASH_CTX sha;
+ struct sha256_ctx sha;
uint8_t *unique_id;
int unique_id_len;
unique_id_len = system_get_chip_unique_id(&unique_id);
- DCRYPTO_SHA256_init(&sha, 0);
- HASH_update(&sha, config.password_salt, sizeof(config.password_salt));
- HASH_update(&sha, unique_id, unique_id_len);
- HASH_update(&sha, password, strlen(password));
- memcpy(digest, HASH_final(&sha), CCD_PASSWORD_DIGEST_SIZE);
+ SHA256_hw_init(&sha);
+ 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);
}
/**
diff --git a/common/pinweaver.c b/common/pinweaver.c
index 2cc4118c7d..7cea0ca1b0 100644
--- a/common/pinweaver.c
+++ b/common/pinweaver.c
@@ -159,17 +159,19 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level,
uint8_t temp_hash[PW_HASH_SIZE] = {};
uint8_t hx;
uint16_t kx;
- LITE_SHA256_CTX ctx;
+ struct sha256_ctx ctx;
merkle_tree->bits_per_level = bits_per_level;
merkle_tree->height = height;
/* Initialize the root hash. */
for (hx = 0; hx < height.v; ++hx) {
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx);
for (kx = 0; kx < fan_out; ++kx)
- HASH_update(&ctx, temp_hash, PW_HASH_SIZE);
- memcpy(temp_hash, HASH_final(&ctx), PW_HASH_SIZE);
+ HASH_update((union hash_ctx *)&ctx, temp_hash,
+ PW_HASH_SIZE);
+ memcpy(temp_hash, HASH_final((union hash_ctx *)&ctx),
+ PW_HASH_SIZE);
}
memcpy(merkle_tree->root, temp_hash, PW_HASH_SIZE);
@@ -179,24 +181,25 @@ 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,
- const struct imported_leaf_data_t *imported_leaf_data,
- uint8_t result[PW_HASH_SIZE])
+static void compute_hmac(const struct merkle_tree_t *merkle_tree,
+ const struct imported_leaf_data_t *imported_leaf_data,
+ uint8_t result[PW_HASH_SIZE])
{
- LITE_HMAC_CTX hmac;
+ struct hmac_sha256_ctx hmac;
- DCRYPTO_HMAC_SHA256_init(&hmac, merkle_tree->hmac_key,
+ HMAC_SHA256_hw_init(&hmac, merkle_tree->hmac_key,
sizeof(merkle_tree->hmac_key));
- HASH_update(&hmac.hash, imported_leaf_data->head,
+ /* 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(&hmac.hash, imported_leaf_data->iv,
+ HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->iv,
sizeof(PW_WRAP_BLOCK_SIZE));
- HASH_update(&hmac.hash, imported_leaf_data->pub,
+ HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->pub,
imported_leaf_data->head->pub_len);
- HASH_update(&hmac.hash, imported_leaf_data->cipher_text,
+ HASH_update((union hash_ctx *)&hmac.hash,
+ imported_leaf_data->cipher_text,
imported_leaf_data->head->sec_len);
- memcpy(result, DCRYPTO_HMAC_final(&hmac), PW_HASH_SIZE);
+ memcpy(result, HMAC_SHA256_hw_final(&hmac), PW_HASH_SIZE);
}
/* Computes the root hash for the specified path and child hash. */
@@ -1386,16 +1389,17 @@ void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
const uint8_t child_hash[PW_HASH_SIZE],
uint8_t result[PW_HASH_SIZE])
{
- LITE_SHA256_CTX ctx;
+ struct sha256_ctx ctx;
- DCRYPTO_SHA256_init(&ctx, 0);
+ SHA256_hw_init(&ctx);
if (location.v > 0)
- HASH_update(&ctx, hashes[0], PW_HASH_SIZE * location.v);
- HASH_update(&ctx, child_hash, PW_HASH_SIZE);
+ HASH_update((union hash_ctx *)&ctx, hashes[0],
+ PW_HASH_SIZE * location.v);
+ HASH_update((union hash_ctx *)&ctx, child_hash, PW_HASH_SIZE);
if (location.v < num_hashes)
- HASH_update(&ctx, hashes[location.v],
+ HASH_update((union hash_ctx *)&ctx, hashes[location.v],
PW_HASH_SIZE * (num_hashes - location.v));
- memcpy(result, HASH_final(&ctx), PW_HASH_SIZE);
+ memcpy(result, HASH_final((union hash_ctx *)&ctx), PW_HASH_SIZE);
}
/* 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 7a34396acd..09539c537b 100644
--- a/common/rma_auth.c
+++ b/common/rma_auth.c
@@ -80,11 +80,11 @@ static void get_hmac_sha256(void *hmac_out, const uint8_t *secret,
size_t ch_size)
{
#ifdef USE_DCRYPTO
- LITE_HMAC_CTX hmac;
+ struct hmac_sha256_ctx hmac;
- DCRYPTO_HMAC_SHA256_init(&hmac, secret, secret_size);
- HASH_update(&hmac.hash, ch_ptr, ch_size);
- memcpy(hmac_out, DCRYPTO_HMAC_final(&hmac), 32);
+ HMAC_SHA256_hw_init(&hmac, secret, secret_size);
+ HMAC_SHA256_update(&hmac, ch_ptr, ch_size);
+ memcpy(hmac_out, HMAC_SHA256_hw_final(&hmac), 32);
#else
hmac_SHA256(hmac_out, secret, secret_size, ch_ptr, ch_size);
#endif
@@ -131,7 +131,7 @@ static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES],
* until the genreated bublic key has the compliant Y coordinate.
*/
while (1) {
- HASH_CTX sha;
+ struct sha256_ctx sha;
if (DCRYPTO_p256_key_from_bytes(&pk_x, &pk_y, &d, buf)) {
@@ -141,9 +141,9 @@ static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES],
}
/* Did not succeed, rehash the private key and try again. */
- DCRYPTO_SHA256_init(&sha, 0);
- HASH_update(&sha, buf, sizeof(buf));
- memcpy(buf, HASH_final(&sha), sizeof(buf));
+ SHA256_hw_init(&sha);
+ SHA256_update(&sha, buf, sizeof(buf));
+ memcpy(buf, SHA256_final(&sha), sizeof(buf));
}
/* X coordinate is passed to the server as the public key. */
diff --git a/common/u2f.c b/common/u2f.c
index 7a5b3e5945..c209be466e 100644
--- a/common/u2f.c
+++ b/common/u2f.c
@@ -8,10 +8,6 @@
#include "console.h"
#include "cryptoc/p256.h"
-#ifndef TEST_BUILD
-#include "cryptoc/sha256.h"
-#endif
-
#include "dcrypto.h"
#include "extension.h"
#include "system.h"
@@ -444,7 +440,7 @@ static enum vendor_cmd_rc u2f_attest(enum vendor_cmd_cc code, void *buf,
int verify_ret;
- struct HASH_CTX h_ctx;
+ struct sha256_ctx h_ctx;
struct drbg_ctx dr_ctx;
/* Data hash, and corresponding signature. */
@@ -471,9 +467,9 @@ static enum vendor_cmd_rc u2f_attest(enum vendor_cmd_cc code, void *buf,
return verify_ret;
/* Message signature */
- DCRYPTO_SHA256_init(&h_ctx, 0);
- HASH_update(&h_ctx, req->data, u2f_attest_format_size(req->format));
- p256_from_bin(HASH_final(&h_ctx), &h);
+ SHA256_hw_init(&h_ctx);
+ SHA256_update(&h_ctx, req->data, u2f_attest_format_size(req->format));
+ p256_from_bin(SHA256_final(&h_ctx)->b8, &h);
/* Derive G2F Attestation Key */
if (g2f_individual_keypair(&d, &pk_x, &pk_y)) {
@@ -509,7 +505,7 @@ int u2f_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
const uint8_t *origin_seed,
struct u2f_key_handle *key_handle)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
struct u2f_state *state = get_state();
if (!state)
@@ -517,12 +513,13 @@ int u2f_origin_user_keyhandle(const uint8_t *origin, const uint8_t *user,
memcpy(key_handle->origin_seed, origin_seed, P256_NBYTES);
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, origin, P256_NBYTES);
- HASH_update(&ctx.hash, user, P256_NBYTES);
- HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
+ HMAC_SHA256_hw_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, origin, P256_NBYTES);
+ HMAC_SHA256_update(&ctx, user, P256_NBYTES);
+ HMAC_SHA256_update(&ctx, origin_seed, P256_NBYTES);
- memcpy(key_handle->hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+ memcpy(key_handle->hmac, HMAC_SHA256_hw_final(&ctx),
+ SHA256_DIGEST_SIZE);
return EC_SUCCESS;
}
@@ -532,7 +529,7 @@ int u2f_origin_user_versioned_keyhandle(
uint8_t version,
struct u2f_versioned_key_handle_header *key_handle_header)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
struct u2f_state *state = get_state();
if (!state)
@@ -541,13 +538,13 @@ int u2f_origin_user_versioned_keyhandle(
key_handle_header->version = version;
memcpy(key_handle_header->origin_seed, origin_seed, P256_NBYTES);
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, origin, P256_NBYTES);
- HASH_update(&ctx.hash, user, P256_NBYTES);
- HASH_update(&ctx.hash, origin_seed, P256_NBYTES);
- HASH_update(&ctx.hash, &version, sizeof(key_handle_header->version));
+ HMAC_SHA256_hw_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, origin, P256_NBYTES);
+ HMAC_SHA256_update(&ctx, user, P256_NBYTES);
+ HMAC_SHA256_update(&ctx, origin_seed, P256_NBYTES);
+ HMAC_SHA256_update(&ctx, &version, sizeof(key_handle_header->version));
- memcpy(key_handle_header->kh_hmac, DCRYPTO_HMAC_final(&ctx),
+ memcpy(key_handle_header->kh_hmac, HMAC_SHA256_hw_final(&ctx),
SHA256_DIGEST_SIZE);
return EC_SUCCESS;
@@ -557,19 +554,20 @@ int u2f_authorization_hmac(const uint8_t *authorization_salt,
const struct u2f_versioned_key_handle_header *header,
const uint8_t *auth_time_secret_hash, uint8_t *hmac)
{
- LITE_HMAC_CTX ctx;
+ struct hmac_sha256_ctx ctx;
struct u2f_state *state = get_state();
if (!state)
return EC_ERROR_UNKNOWN;
- DCRYPTO_HMAC_SHA256_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
- HASH_update(&ctx.hash, authorization_salt, U2F_AUTHORIZATION_SALT_SIZE);
- HASH_update(&ctx.hash, (uint8_t *)header,
- sizeof(struct u2f_versioned_key_handle_header));
- HASH_update(&ctx.hash, auth_time_secret_hash, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_hw_init(&ctx, state->salt_kek, SHA256_DIGEST_SIZE);
+ HMAC_SHA256_update(&ctx, authorization_salt,
+ U2F_AUTHORIZATION_SALT_SIZE);
+ HMAC_SHA256_update(&ctx, (uint8_t *)header,
+ sizeof(struct u2f_versioned_key_handle_header));
+ HMAC_SHA256_update(&ctx, auth_time_secret_hash, SHA256_DIGEST_SIZE);
- memcpy(hmac, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
+ memcpy(hmac, HMAC_SHA256_hw_final(&ctx), SHA256_DIGEST_SIZE);
return EC_SUCCESS;
}
diff --git a/fuzz/mem_hash_tree.cc b/fuzz/mem_hash_tree.cc
index 15c9de4142..88e85b87cf 100644
--- a/fuzz/mem_hash_tree.cc
+++ b/fuzz/mem_hash_tree.cc
@@ -72,23 +72,23 @@ void MemHashTree::UpdatePath(uint64_t label,
for (int level = 0; level < height_; ++level) {
shifted_parent_label &= ~child_index_mask;
- LITE_SHA256_CTX ctx;
- DCRYPTO_SHA256_init(&ctx, 1);
+ struct sha256_ctx ctx;
+ SHA256_hw_init(&ctx);
int empty_nodes = 0;
for (int index = 0; index < fan_out; ++index) {
auto itr =
hash_tree_.find(MaskedLabel(shifted_parent_label | index, level));
if (itr == hash_tree_.end()) {
- HASH_update(&ctx, empty_node_hashes_[level].data(),
+ SHA256_update(&ctx, empty_node_hashes_[level].data(),
empty_node_hashes_[level].size());
++empty_nodes;
} else {
- HASH_update(&ctx, itr->second.data(), itr->second.size());
+ SHA256_update(&ctx, itr->second.data(), itr->second.size());
}
}
shifted_parent_label = shifted_parent_label >> bits_per_level_;
- const uint8_t* temp = HASH_final(&ctx);
+ const uint8_t* temp = SHA256_final(&ctx)->b8;
std::copy(temp, temp + SHA256_DIGEST_SIZE, hash.begin());
MaskedLabel node_key(shifted_parent_label, level + 1);
if (empty_nodes == fan_out) {
@@ -118,12 +118,12 @@ void MemHashTree::Reset(uint8_t bits_per_level, uint8_t height) {
uint8_t fan_out = 1 << bits_per_level;
for (int level = 1; level < height; ++level) {
- LITE_SHA256_CTX ctx;
- DCRYPTO_SHA256_init(&ctx, 1);
+ struct sha256_ctx ctx;
+ SHA256_hw_init(&ctx);
for (int index = 0; index < fan_out; ++index) {
- HASH_update(&ctx, hash.data(), hash.size());
+ SHA256_update(&ctx, hash.data(), hash.size());
}
- const uint8_t* temp = HASH_final(&ctx);
+ const uint8_t* temp = SHA256_final(&ctx)->b8;
std::copy(temp, temp + SHA256_DIGEST_SIZE, hash.begin());
empty_node_hashes_[level] = hash;
}
diff --git a/test/pinweaver.c b/test/pinweaver.c
index 63a7e2e067..d6df149135 100644
--- a/test/pinweaver.c
+++ b/test/pinweaver.c
@@ -7,7 +7,6 @@
#include <dcrypto.h>
#include <nvmem_vars.h>
-#include <sha256.h>
#include <stdint.h>
#include <string.h>
#include <timer.h>
@@ -885,40 +884,40 @@ void rand_bytes(void *buffer, size_t len)
/* Mock implementations of Dcrypto functionality.
*/
-void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len)
+void HASH_update(union hash_ctx *ctx, const void *data, size_t len)
{
if (MOCK_hash_update_cb)
MOCK_hash_update_cb(data, len);
if (ctx)
- SHA256_update(ctx, data, len);
+ SHA256_sw_update(&ctx->sha256, data, len);
}
-uint8_t *HASH_final(struct HASH_CTX *ctx)
+const union sha_digests *HASH_final(union hash_ctx *ctx)
{
++MOCK_DECRYPTO_release_counter;
- return SHA256_final(ctx);
+ return (union sha_digests *)SHA256_sw_final(&ctx->sha256);
}
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
+void SHA256_hw_init(struct sha256_ctx *ctx)
{
- SHA256_init(ctx);
+ SHA256_sw_init(ctx);
++MOCK_DECRYPTO_init_counter;
}
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len)
+void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
+ size_t len)
{
TEST_ASRT_NORET(len == sizeof(EMPTY_TREE.hmac_key));
TEST_ASRT_NORET(memcmp(key, EMPTY_TREE.hmac_key,
sizeof(EMPTY_TREE.hmac_key)) == 0);
- SHA256_init(&ctx->hash);
+ SHA256_sw_init(&ctx->hash);
++MOCK_DECRYPTO_init_counter;
}
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
+const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx)
{
++MOCK_DECRYPTO_release_counter;
- return MOCK_hmac;
+ return (struct sha256_digest *)MOCK_hmac;
}
/* Perform a symmetric transformation of the data to simulate AES without
diff --git a/test/test_config.h b/test/test_config.h
index 33c65322c6..f7b222302f 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -190,7 +190,7 @@ enum nvmem_users { NVMEM_TPM = 0, NVMEM_CR50, NVMEM_NUM_USERS };
#endif
#ifdef TEST_U2F
-#define CONFIG_DCRYPTO_MOCK
+#define CONFIG_DCRYPTO
#define CONFIG_U2F
#define CC_EXTENSION CC_COMMAND
#endif
diff --git a/test/u2f.c b/test/u2f.c
index 56ae0cf65e..c74bc847a3 100644
--- a/test/u2f.c
+++ b/test/u2f.c
@@ -42,40 +42,6 @@ int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key,
return 1;
}
-void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx,
- const p256_int *key,
- const p256_int *message)
-{
- memset(ctx, 0, sizeof(struct drbg_ctx));
-}
-
-void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len)
-{
- if (ctx)
- SHA256_update(ctx, data, len);
-}
-
-uint8_t *HASH_final(struct HASH_CTX *ctx)
-{
- return SHA256_final(ctx);
-}
-
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
-{
- SHA256_init(ctx);
-}
-
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len)
-{
- SHA256_init(&ctx->hash);
-}
-
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
-{
- return SHA256_final(&ctx->hash);
-}
-
/******************************************************************************/
/* Mock implementations of U2F functionality.
*/