diff options
author | Vadim Sukhomlinov <sukhomlinov@google.com> | 2021-09-27 17:47:29 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-10-02 04:01:49 +0000 |
commit | 0ad46f2259b79b07a1d4b114fd58472a88c19282 (patch) | |
tree | 8313e9894a779c602cca27fd79b81bcc9a7ca3b6 | |
parent | 7b25ee08172491864900e3a2ba59d761355f4069 (diff) | |
download | chrome-ec-0ad46f2259b79b07a1d4b114fd58472a88c19282.tar.gz |
cr50: provide public crypto API for HMAC/HASH with error reporting.
To implement FIPS mode for Cr50 we should be able to block access to
crypto functions if errors are detected. Historically all HASH/HMAC
functions were declared as void with no return type.
1) Split existing functions into public part (data structs, update and
final parts) and internal part - unchecked init functions.
2) Introduced new functions to start SHA / HMAC operation which returns
status code and block access to crypto in case of FIPS errors.
3) Dcrypto hash algorithms codes updated to match TPM_ALG_ID to simplify
adaptation layer and move checks inside Dcrypto module.
4) Updated all uses of API outside FIPS module to check return code and
act accordingly.
5) As a side effect RSA can now support SHA384 & SHA512 for signing,
board/host mock ups simplified.
BUG=b:197893750
TEST=make buildall -j; make BOARD=cr50 CRYPTO_TEST=1;
test/tpm_test/tpm_test.py
TCG tests
------------------------------ Test Result Summary ---------------------
Test executed on: Tue Sep 28 15:23:35 2021
Performed Tests: 248
Passed Tests: 248
Failed Tests: 0
Errors: 0
Warnings: 0
========================================================================
Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com>
Change-Id: Ibbc38703496f417cba693c37d39a82a662c3f7ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3192137
Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-rw-r--r-- | board/cr50/build.mk | 2 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto.h | 605 | ||||
-rw-r--r-- | board/cr50/dcrypto/hash_api.c | 170 | ||||
-rw-r--r-- | board/cr50/dcrypto/hmacsha2.h | 523 | ||||
-rw-r--r-- | board/cr50/dcrypto/internal.h | 149 | ||||
-rw-r--r-- | board/cr50/dcrypto/rsa.c | 302 | ||||
-rw-r--r-- | board/cr50/dcrypto/sha_hw.c | 4 | ||||
-rw-r--r-- | board/cr50/tpm2/ecc.c | 6 | ||||
-rw-r--r-- | board/cr50/tpm2/endorsement.c | 10 | ||||
-rw-r--r-- | board/cr50/tpm2/hash.c | 83 | ||||
-rw-r--r-- | board/cr50/tpm2/rsa.c | 8 | ||||
-rw-r--r-- | board/cr50/tpm2/virtual_nvmem.c | 8 | ||||
-rw-r--r-- | board/cr50/usb_spi.c | 3 | ||||
-rw-r--r-- | board/host/dcrypto.h | 70 | ||||
-rw-r--r-- | chip/host/build.mk | 4 | ||||
-rw-r--r-- | chip/host/dcrypto/app_cipher.c | 7 | ||||
-rw-r--r-- | chip/host/dcrypto/sha256.c | 13 | ||||
-rw-r--r-- | common/ccd_config.c | 24 | ||||
-rw-r--r-- | common/pinweaver.c | 90 | ||||
-rw-r--r-- | common/rma_auth.c | 45 | ||||
-rw-r--r-- | fuzz/mem_hash_tree.cc | 6 | ||||
-rw-r--r-- | include/pinweaver.h | 7 | ||||
-rw-r--r-- | include/rma_auth.h | 3 | ||||
-rw-r--r-- | test/pinweaver.c | 19 | ||||
-rw-r--r-- | test/u2f.c | 5 |
25 files changed, 1259 insertions, 907 deletions
diff --git a/board/cr50/build.mk b/board/cr50/build.mk index c3ab7a6f53..1fa86307a5 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -116,7 +116,7 @@ ifneq ($(CRYPTO_TEST),) fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/gcm.o fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hkdf.o endif - +fips-${CONFIG_DCRYPTO_BOARD} += dcrypto/hash_api.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 diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index 035ce9b18c..bbb8e0b2ef 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -16,7 +16,7 @@ extern "C" { #include <stdbool.h> #include <stddef.h> -#include "hmacsha2.h" +#include "common.h" /** * Result codes for crypto operations, targeting @@ -39,17 +39,571 @@ enum cipher_mode { 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_SHA1 = 0x0004, /* = TPM_ALG_SHA1 */ + HASH_SHA256 = 0x000B, /* = TPM_ALG_SHA256 */ + HASH_SHA384 = 0x000C, /* = TPM_ALG_SHA384 */ + HASH_SHA512 = 0x000D, /* = TPM_ALG_SHA512 */ + HASH_NULL = 0x0010 /* = TPM_ALG_NULL, Only supported for PKCS#1 */ }; #ifndef __warn_unused_result #define __warn_unused_result __attribute__((warn_unused_result)) #endif +/** + * SHA1/SHA2, HMAC API + */ +#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)) + +#define SHA_DIGEST_WORDS (SHA_DIGEST_SIZE / sizeof(uint32_t)) +#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t)) + +#ifdef CONFIG_UPTO_SHA512 +#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_SIZE +#else +#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_SIZE +#endif + +/** + * 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 + +/** + * Initialize software version of hash computation which explicitly allows + * context switching / serialization. + * + * @param ctx storage for context + * @param mode hashing algorithm + * + * @return DCRYPTO_OK if successful, DCRYPTO_FAIL otherwise. + */ +enum dcrypto_result DCRYPTO_sw_hash_init( + union hash_ctx *ctx, enum hashing_mode mode) __warn_unused_result; + +/** + * Initialize hardware-acceleated or software version of hash computation, + * preferring hardware version when available. + * + * @param ctx storage for context + * @param mode hashing algorithm + * + * @return DCRYPTO_OK if successful, DCRYPTO_FAIL otherwise. + */ +enum dcrypto_result DCRYPTO_hw_hash_init( + union hash_ctx *ctx, enum hashing_mode mode) __warn_unused_result; + +/** + * Return hash size for specified hash algorithm + * @param mode hash algorithm + * @return non-zero if algorithm is supported, 0 otherwise + */ +size_t DCRYPTO_hash_size(enum hashing_mode mode); + +/** + * Initialize software version of hash computation which explicitly allows + * context switching / serialization. + * + * @param ctx storage for context + * @param key HMAC key + * @param len length of HMAC key + * @param mode hashing algorithm + * + * @return DCRYPTO_OK if successful, DCRYPTO_FAIL otherwise. + */ +enum dcrypto_result DCRYPTO_sw_hmac_init(union hmac_ctx *ctx, const void *key, + size_t len, enum hashing_mode mode) + __warn_unused_result; + +/** + * Initialize hardware-acceleated or software version of HMAC computation, + * preferring hardware version when available. + * + * @param ctx storage for context + * @param key HMAC key + * @param len length of HMAC key + * @param mode hashing algorithm + * + * @return DCRYPTO_OK if successful, DCRYPTO_FAIL otherwise. + */ +enum dcrypto_result DCRYPTO_hw_hmac_init(union hmac_ctx *ctx, const void *key, + size_t len, enum hashing_mode mode) + __warn_unused_result; + +/** + * Compute SHA256 using preferably hardware implementation. + * API maintained compatible with RO code. + * + * @param data input data + * @param n length of data + * @param digest destination + * @return NULL if failure, digest if successful + */ +const uint8_t *DCRYPTO_SHA256_hash(const void *data, size_t n, uint8_t *digest); + +/** + * Compute SHA256 using preferably hardware implementation. + * API maintained compatible with RO code. + * + * @param data input data + * @param n length of data + * @param digest destination + * @return NULL if failure, digest if successful + */ +const uint8_t *DCRYPTO_SHA1_hash(const void *data, size_t n, uint8_t *digest); + +/** + * Convenience wrappers with type checks. + */ +#ifndef CONFIG_DCRYPTO_MOCK + +/** + * Add data to message, call configured transform function when block + * is full. + * @param ctx digest context (can be one of union subtypes). + * @param data input data + * @param len length of data + */ +static inline void HASH_update(union hash_ctx *const ctx, const void *data, + size_t len) +{ + ctx->f->update(ctx, data, len); +} +/** + * Finalize hash computation by adding padding, message length. + * Returns pointer to computed digest stored inside provided context. + * + * @param ctx digest context (can be one of union subtypes). + * + * @return pointer to computed digest inside ctx. + */ +static inline const union sha_digests *HASH_final(union hash_ctx *const ctx) +{ + return ctx->f->final(ctx); +} + +/** + * Add data to message, call configured transform function when block + * is full. + * @param ctx SHA256 digest context + * @param data input data + * @param len length of data + */ +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. + * + * @param ctx SHA256 digest context. + * + * @return pointer to computed digest inside ctx. + */ +static inline const struct sha256_digest *SHA256_final( + struct sha256_ctx *const ctx) +{ + return &ctx->f->final((union hash_ctx *)ctx)->sha256; +} +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; +} +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 const struct sha1_digest *SHA1_final(struct sha1_ctx *const ctx) +{ + return &ctx->f->final((union hash_ctx *)ctx)->sha1; +} + +/** + * Initialize SHA2-256 computation + * + * @param ctx SHA256 context + + * @return DCRYPTO_OK if successful + */ +static inline __warn_unused_result enum dcrypto_result DCRYPTO_hw_sha256_init( + struct sha256_ctx *ctx) +{ + return DCRYPTO_hw_hash_init((union hash_ctx *)ctx, HASH_SHA256); +} + +/** + * Initialize HMAC SHA2-256 computation + * + * @param ctx HMAC SHA256 context + * @param key HMAC key + * @param len length of key + * @return DCRYPTO_OK if successful + */ +static inline __warn_unused_result enum dcrypto_result +DCRYPTO_hw_hmac_sha256_init(struct hmac_sha256_ctx *ctx, const void *key, + size_t len) +{ + return DCRYPTO_hw_hmac_init((union hmac_ctx *)ctx, key, len, + HASH_SHA256); +} + +#else +/* To enable DCRYPTO mocks just provide prototypes. */ +void HASH_update(union hash_ctx *const ctx, const void *data, size_t len); +const union sha_digests *HASH_final(union hash_ctx *const ctx); +void SHA256_update(struct sha256_ctx *const ctx, const void *data, size_t len); +const struct sha256_digest *SHA256_final(struct sha256_ctx *const ctx); +void HMAC_SHA256_update(struct hmac_sha256_ctx *const ctx, const void *data, + size_t len); +const struct sha256_digest *HMAC_SHA256_final(struct hmac_sha256_ctx *ctx); +void SHA1_update(struct sha1_ctx *const ctx, const void *data, size_t len); +const struct sha1_digest *SHA1_final(struct sha1_ctx *const ctx); +enum dcrypto_result DCRYPTO_hw_sha256_init(struct sha256_ctx *ctx); +enum dcrypto_result DCRYPTO_hw_hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *key, size_t len); +#endif + +/** + * 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; +} + +/* HMAC_update() is same as HASH_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); +} + +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; +} + +#ifdef CONFIG_UPTO_SHA512 +static inline void SHA384_update(struct sha384_ctx *const ctx, const void *data, + size_t len) +{ + ctx->f->update((union hash_ctx *)ctx, data, len); +} + +static inline const struct sha384_digest *SHA384_final( + struct sha384_ctx *const ctx) +{ + return &ctx->f->final((union hash_ctx *)ctx)->sha384; +} + +static inline void SHA512_update(struct sha512_ctx *const ctx, const void *data, + size_t len) +{ + ctx->f->update((union hash_ctx *)ctx, data, len); +} + +static inline const struct sha512_digest *SHA512_final( + struct sha512_ctx *const ctx) +{ + return &ctx->f->final((union hash_ctx *)ctx)->sha512; +} + +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; +} + +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 + /* * AES implementation, based on a hardware AES block. * FIPS Publication 197, The Advanced Encryption Standard (AES) @@ -132,45 +686,6 @@ int DCRYPTO_aes_cmac_verify(const uint8_t *key, const uint8_t *M, const int len, const uint32_t T[4]); /* - * SHA implementation. This abstraction is backed by either a - * software or hardware implementation. - * - * There could be only a single hardware SHA context in progress. The init - * functions will try using the HW context, if available, unless 'sw_required' - * is TRUE, in which case there will be no attempt to use the hardware for - * this particular hashing session. - */ - -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 HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key, - size_t len); -/* DCRYPTO HMAC-SHA256 final */ -const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx); - -/* * BIGNUM utility methods. */ diff --git a/board/cr50/dcrypto/hash_api.c b/board/cr50/dcrypto/hash_api.c new file mode 100644 index 0000000000..34b5d88d55 --- /dev/null +++ b/board/cr50/dcrypto/hash_api.c @@ -0,0 +1,170 @@ +/* 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 "internal.h" + +size_t DCRYPTO_hash_size(enum hashing_mode mode) +{ + if (!fips_crypto_allowed()) + return 0; + + switch (mode) { + case HASH_SHA1: + return SHA1_DIGEST_SIZE; + case HASH_SHA256: + return SHA256_DIGEST_SIZE; +#ifdef CONFIG_UPTO_SHA512 + case HASH_SHA384: + return SHA384_DIGEST_SIZE; + case HASH_SHA512: + return SHA512_DIGEST_SIZE; +#endif + default: + return 0; + } + return 0; +} + +enum dcrypto_result DCRYPTO_sw_hash_init(union hash_ctx *ctx, + enum hashing_mode mode) +{ + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + switch (mode) { + case HASH_SHA1: + SHA1_sw_init(&ctx->sha1); + break; + case HASH_SHA256: + SHA256_sw_init(&ctx->sha256); + break; +#ifdef CONFIG_UPTO_SHA512 + case HASH_SHA384: + SHA384_sw_init(&ctx->sha384); + break; + case HASH_SHA512: + SHA512_sw_init(&ctx->sha512); + break; +#endif + default: + return DCRYPTO_FAIL; + } + return DCRYPTO_OK; +} + +enum dcrypto_result DCRYPTO_hw_hash_init(union hash_ctx *ctx, + enum hashing_mode mode) +{ + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + switch (mode) { + case HASH_SHA1: + SHA1_hw_init(&ctx->sha1); + break; + case HASH_SHA256: + SHA256_hw_init(&ctx->sha256); + break; +#ifdef CONFIG_UPTO_SHA512 + case HASH_SHA384: + SHA384_hw_init(&ctx->sha384); + break; + case HASH_SHA512: + SHA512_hw_init(&ctx->sha512); + break; +#endif + default: + return DCRYPTO_FAIL; + } + return DCRYPTO_OK; +} + +enum dcrypto_result DCRYPTO_sw_hmac_init(union hmac_ctx *ctx, const void *key, + size_t len, enum hashing_mode mode) +{ + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + switch (mode) { + case HASH_SHA1: + SHA1_sw_init(&ctx->hmac_sha1.hash); + break; + case HASH_SHA256: + SHA256_sw_init(&ctx->hmac_sha256.hash); + break; +#ifdef CONFIG_UPTO_SHA512 + case HASH_SHA384: + SHA384_sw_init(&ctx->hmac_sha384.hash); + break; + case HASH_SHA512: + SHA512_sw_init(&ctx->hmac_sha512.hash); + break; +#endif + default: + return DCRYPTO_FAIL; + } + HMAC_sw_init(ctx, key, len); + return DCRYPTO_OK; +} + +enum dcrypto_result DCRYPTO_hw_hmac_init(union hmac_ctx *ctx, const void *key, + size_t len, enum hashing_mode mode) +{ + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + switch (mode) { + case HASH_SHA1: + SHA1_hw_init(&ctx->hmac_sha1.hash); + HMAC_sw_init(ctx, key, len); + break; + case HASH_SHA256: + HMAC_SHA256_hw_init(&ctx->hmac_sha256, key, len); + break; +#ifdef CONFIG_UPTO_SHA512 + case HASH_SHA384: + SHA384_hw_init(&ctx->hmac_sha384.hash); + HMAC_sw_init(ctx, key, len); + break; + case HASH_SHA512: + SHA512_hw_init(&ctx->hmac_sha512.hash); + HMAC_sw_init(ctx, key, len); + break; +#endif + default: + return DCRYPTO_FAIL; + } + return DCRYPTO_OK; +} + +const uint8_t *DCRYPTO_SHA1_hash(const void *data, size_t n, uint8_t *digest) +{ + if (!fips_crypto_allowed()) + return NULL; + + if (is_not_aligned(digest)) { + struct sha1_digest d; + + SHA1_hw_hash(data, n, &d); + memcpy(digest, d.b8, sizeof(d)); + } else + SHA1_hw_hash(data, n, (struct sha1_digest *)digest); + return digest; +} + +const uint8_t *DCRYPTO_SHA256_hash(const void *data, size_t n, uint8_t *digest) +{ + if (!fips_crypto_allowed()) + return NULL; + + if (is_not_aligned(digest)) { + struct sha256_digest d; + + SHA256_hw_hash(data, n, &d); + memcpy(digest, d.b8, sizeof(d)); + } else + SHA256_hw_hash(data, n, (struct sha256_digest *)digest); + return digest; +} diff --git a/board/cr50/dcrypto/hmacsha2.h b/board/cr50/dcrypto/hmacsha2.h deleted file mode 100644 index 5e34b99189..0000000000 --- a/board/cr50/dcrypto/hmacsha2.h +++ /dev/null @@ -1,523 +0,0 @@ -/* 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)) - -#define SHA_DIGEST_WORDS (SHA_DIGEST_SIZE / sizeof(uint32_t)) -#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t)) - -#ifdef CONFIG_UPTO_SHA512 -#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_SIZE -#else -#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_SIZE -#endif - -/** - * 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); - -static inline void SHA384_update(struct sha384_ctx *const ctx, const void *data, - size_t len) -{ - ctx->f->update((union hash_ctx *)ctx, data, len); -} - -static inline const struct sha384_digest *SHA384_final( - struct sha384_ctx *const ctx) -{ - return &ctx->f->final((union hash_ctx *)ctx)->sha384; -} - -static inline void SHA512_update(struct sha512_ctx *const ctx, const void *data, - size_t len) -{ - ctx->f->update((union hash_ctx *)ctx, data, len); -} - -static inline const struct sha512_digest *SHA512_final( - struct sha512_ctx *const ctx) -{ - return &ctx->f->final((union hash_ctx *)ctx)->sha512; -} - -/** - * 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 ed1f324079..638c6357f8 100644 --- a/board/cr50/dcrypto/internal.h +++ b/board/cr50/dcrypto/internal.h @@ -12,7 +12,6 @@ #include "dcrypto.h" #include "fips.h" #include "fips_rand.h" -#include "hmacsha2.h" #include "util.h" #ifdef __cplusplus @@ -41,6 +40,154 @@ void dcrypto_release_sha_hw(void); void dcrypto_sha_fifo_load(const void *data, size_t n); /* + * SHA implementation. This abstraction is backed by either a + * software or hardware implementation. + * + * There could be only a single hardware SHA context in progress. The init + * functions will try using the HW context, if available, unless 'sw_required' + * is TRUE, in which case there will be no attempt to use the hardware for + * this particular hashing session. + */ + +/** + * 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); +} + +/* 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 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); +} + + +/** + * 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); +} + +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_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); + +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); + + +/** + * 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); +} +/** + * 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); +} +#endif + +/* + * HMAC. FIPS 198-1 + */ +void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key, + size_t len); +/* DCRYPTO HMAC-SHA256 final */ +const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx); + +/* * BIGNUM. */ #define LITE_BN_BITS2 32 diff --git a/board/cr50/dcrypto/rsa.c b/board/cr50/dcrypto/rsa.c index 9c721abc5e..524d3d14f4 100644 --- a/board/cr50/dcrypto/rsa.c +++ b/board/cr50/dcrypto/rsa.c @@ -31,9 +31,9 @@ static uint32_t select(uint32_t mask, uint32_t a, uint32_t 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) +static enum dcrypto_result MGF1_xor(uint8_t *dst, uint32_t dst_len, + const uint8_t *seed, uint32_t seed_len, + enum hashing_mode hashing) { union hash_ctx ctx; @@ -44,17 +44,19 @@ 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) ? SHA1_DIGEST_SIZE : - SHA256_DIGEST_SIZE; + const size_t hash_size = DCRYPTO_hash_size(hashing); + + if (!hash_size) + return DCRYPTO_FAIL; cnt.b0 = cnt.b1 = cnt.b2 = cnt.b3 = 0; while (dst_len) { size_t i; + enum dcrypto_result result; - if (hashing == HASH_SHA1) - SHA1_hw_init(&ctx.sha1); - else - SHA256_hw_init(&ctx.sha256); + result = DCRYPTO_hw_hash_init(&ctx, hashing); + if (result != DCRYPTO_OK) + return result; HASH_update(&ctx, seed, seed_len); HASH_update(&ctx, (uint8_t *)&cnt, sizeof(cnt)); @@ -65,6 +67,7 @@ static void MGF1_xor(uint8_t *dst, uint32_t dst_len, if (!++cnt.b0) ++cnt.b1; } + return DCRYPTO_OK; } /* @@ -78,12 +81,12 @@ static void MGF1_xor(uint8_t *dst, uint32_t dst_len, * }; */ /* encrypt */ -static int oaep_pad(uint8_t *output, uint32_t output_len, - const uint8_t *msg, uint32_t msg_len, - enum hashing_mode hashing, const char *label) +static enum dcrypto_result oaep_pad(uint8_t *output, uint32_t output_len, + const uint8_t *msg, uint32_t msg_len, + enum hashing_mode hashing, + const char *label) { - const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE - : SHA256_DIGEST_SIZE; + const size_t hash_size = DCRYPTO_hash_size(hashing); uint8_t *const seed = output + 1; uint8_t *const phash = seed + hash_size; uint8_t *const PS = phash + hash_size; @@ -91,39 +94,44 @@ static int oaep_pad(uint8_t *output, uint32_t output_len, const uint32_t ps_len = max_msg_len - msg_len; uint8_t *const one = PS + ps_len; union hash_ctx ctx; + enum dcrypto_result result; + if (!hash_size) + return DCRYPTO_FAIL; if (output_len < 2 + 2 * hash_size) - return 0; /* Key size too small for chosen hash. */ + return DCRYPTO_FAIL; /* Key size too small for chosen hash. */ if (msg_len > output_len - 2 - 2 * hash_size) - return 0; /* Input message too large for key size. */ + return DCRYPTO_FAIL; /* Input message too large for key size. */ always_memset(output, 0, output_len); if (!fips_rand_bytes(seed, hash_size)) - return 0; + return DCRYPTO_FAIL; - if (hashing == HASH_SHA1) - SHA1_hw_init(&ctx.sha1); - else - SHA256_hw_init(&ctx.sha256); + result = DCRYPTO_hw_hash_init(&ctx, hashing); + if (result != DCRYPTO_OK) + return result; HASH_update(&ctx, label, label ? strlen(label) + 1 : 0); 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, - seed, hash_size, hashing); - MGF1_xor(seed, hash_size, phash, hash_size + 1 + max_msg_len, - hashing); - return 1; + result = MGF1_xor(phash, hash_size + 1 + max_msg_len, seed, hash_size, + hashing); + result |= MGF1_xor(seed, hash_size, phash, hash_size + 1 + max_msg_len, + hashing); + + if (result != DCRYPTO_OK) + return DCRYPTO_FAIL; + + return result; } /* decrypt */ -static int check_oaep_pad(uint8_t *out, size_t *out_len, +static enum dcrypto_result check_oaep_pad(uint8_t *out, size_t *out_len, uint8_t *padded, size_t padded_len, enum hashing_mode hashing, const char *label) { - const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE - : SHA256_DIGEST_SIZE; + const size_t hash_size = DCRYPTO_hash_size(hashing); uint8_t *seed = padded + 1; uint8_t *phash = seed + hash_size; uint8_t *PS = phash + hash_size; @@ -133,27 +141,35 @@ static int check_oaep_pad(uint8_t *out, size_t *out_len, uint32_t looking_for_one_byte = ~0; int bad; size_t i; + enum dcrypto_result result; + + if (!hash_size) + return DCRYPTO_FAIL; if (padded_len < 2 + 2 * hash_size) - return 0; /* Invalid input size. */ + return DCRYPTO_FAIL; /* Invalid input size. */ /* Recover seed. */ - MGF1_xor(seed, hash_size, phash, hash_size + 1 + max_msg_len, hashing); + result = MGF1_xor(seed, hash_size, phash, hash_size + 1 + max_msg_len, + hashing); /* Recover db. */ - MGF1_xor(phash, hash_size + 1 + max_msg_len, seed, hash_size, hashing); + result |= MGF1_xor(phash, hash_size + 1 + max_msg_len, seed, hash_size, + hashing); + + if (result != DCRYPTO_OK) + return DCRYPTO_FAIL; - if (hashing == HASH_SHA1) - SHA1_hw_init(&ctx.sha1); - else - SHA256_hw_init(&ctx.sha256); + result = DCRYPTO_hw_hash_init(&ctx, hashing); + if (result != DCRYPTO_OK) + return result; HASH_update(&ctx, label, label ? strlen(label) + 1 : 0); - /* bad should be zero if CRYPTO_OK is returned. */ - bad = DCRYPTO_equals(phash, HASH_final(&ctx)->b8, hash_size) - - DCRYPTO_OK; + /* bad should be zero if DCRYPTO_OK is returned. */ + result = DCRYPTO_equals(phash, HASH_final(&ctx)->b8, hash_size); + bad = result - DCRYPTO_OK; /* bad = 0 if result == DCRYPTO_OK */ bad |= padded[0]; - for (i = PS - padded; i < padded_len; i++) { + for (i = PS - padded; i < padded_len; i++) { uint32_t equals0 = is_zero(padded[i]); uint32_t equals1 = is_zero(padded[i] ^ 1); @@ -168,29 +184,30 @@ static int check_oaep_pad(uint8_t *out, size_t *out_len, bad |= looking_for_one_byte; if (bad) - return 0; + return DCRYPTO_FAIL; one_index++; if (*out_len < padded_len - one_index) - return 0; + return DCRYPTO_FAIL; memcpy(out, padded + one_index, padded_len - one_index); *out_len = padded_len - one_index; - return 1; + /* Result should be DCRYPTO_OK after DCRYPTO_equals() */ + return result; } /* Constants from RFC 3447. */ #define RSA_PKCS1_PADDING_SIZE 11 /* encrypt */ -static int pkcs1_type2_pad(uint8_t *padded, size_t padded_len, - const uint8_t *in, size_t in_len) +static enum dcrypto_result pkcs1_type2_pad(uint8_t *padded, size_t padded_len, + const uint8_t *in, size_t in_len) { size_t PS_len; if (padded_len < RSA_PKCS1_PADDING_SIZE) - return 0; + return DCRYPTO_FAIL; if (in_len > padded_len - RSA_PKCS1_PADDING_SIZE) - return 0; + return DCRYPTO_FAIL; PS_len = padded_len - 3 - in_len; *(padded++) = 0; @@ -200,7 +217,7 @@ static int pkcs1_type2_pad(uint8_t *padded, size_t padded_len, uint8_t r[SHA256_DIGEST_SIZE]; if (!fips_rand_bytes(r, sizeof(r))) - return 0; + return DCRYPTO_FAIL; /** * zero byte has special meaning in PKCS1, so copy @@ -215,11 +232,11 @@ static int pkcs1_type2_pad(uint8_t *padded, size_t padded_len, } *(padded++) = 0; memcpy(padded, in, in_len); - return 1; + return DCRYPTO_OK; } /* decrypt */ -static int check_pkcs1_type2_pad(uint8_t *out, size_t *out_len, +static enum dcrypto_result check_pkcs1_type2_pad(uint8_t *out, size_t *out_len, const uint8_t *padded, size_t padded_len) { size_t i; @@ -228,7 +245,7 @@ static int check_pkcs1_type2_pad(uint8_t *out, size_t *out_len, uint32_t looking_for_index = ~0; if (padded_len < RSA_PKCS1_PADDING_SIZE) - return 0; + return DCRYPTO_FAIL; valid = (padded[0] == 0); valid &= (padded[1] == 2); @@ -245,13 +262,14 @@ static int check_pkcs1_type2_pad(uint8_t *out, size_t *out_len, valid &= ~looking_for_index; valid &= (zero_index >= RSA_PKCS1_PADDING_SIZE); if (!valid) - return 0; + return DCRYPTO_FAIL; if (*out_len < padded_len - zero_index) - return 0; + return DCRYPTO_FAIL; + memcpy(out, &padded[zero_index], padded_len - zero_index); *out_len = padded_len - zero_index; - return 1; + return DCRYPTO_OK; } static const uint8_t SHA1_DER[] = { @@ -274,8 +292,9 @@ static const uint8_t SHA512_DER[] = { 0x00, 0x04, 0x40 }; -static int pkcs1_get_der(enum hashing_mode hashing, const uint8_t **der, - size_t *der_size, size_t *hash_size) +static enum dcrypto_result pkcs1_get_der(enum hashing_mode hashing, + const uint8_t **der, size_t *der_size, + size_t *hash_size) { switch (hashing) { case HASH_SHA1: @@ -301,33 +320,35 @@ static int pkcs1_get_der(enum hashing_mode hashing, const uint8_t **der, case HASH_NULL: *der = NULL; *der_size = 0; - *hash_size = 0; /* any size allowed */ + *hash_size = 0; /* any size allowed */ break; default: - return 0; + return DCRYPTO_FAIL; } - return 1; + return DCRYPTO_OK; } /* sign */ -static int pkcs1_type1_pad(uint8_t *padded, size_t padded_len, - const uint8_t *in, size_t in_len, - enum hashing_mode hashing) +static enum dcrypto_result pkcs1_type1_pad(uint8_t *padded, size_t padded_len, + const uint8_t *in, size_t in_len, + enum hashing_mode hashing) { const uint8_t *der; size_t der_size; size_t hash_size; size_t ps_len; + enum dcrypto_result result; - if (!pkcs1_get_der(hashing, &der, &der_size, &hash_size)) - return 0; + result = pkcs1_get_der(hashing, &der, &der_size, &hash_size); + if (result != DCRYPTO_OK) + return result; if (padded_len < RSA_PKCS1_PADDING_SIZE + der_size) - return 0; + return DCRYPTO_FAIL; if (!in_len || (hash_size && in_len != hash_size)) - return 0; + return DCRYPTO_FAIL; if (in_len > padded_len - RSA_PKCS1_PADDING_SIZE - der_size) - return 0; + return DCRYPTO_FAIL; ps_len = padded_len - 3 - der_size - in_len; *(padded++) = 0; @@ -338,73 +359,83 @@ static int pkcs1_type1_pad(uint8_t *padded, size_t padded_len, memcpy(padded, der, der_size); padded += der_size; memcpy(padded, in, in_len); - return 1; + return DCRYPTO_OK; } /* verify */ -static int check_pkcs1_type1_pad(const uint8_t *msg, size_t msg_len, - const uint8_t *padded, size_t padded_len, - enum hashing_mode hashing) +static enum dcrypto_result check_pkcs1_type1_pad(const uint8_t *msg, + size_t msg_len, + const uint8_t *padded, + size_t padded_len, + enum hashing_mode hashing) { size_t i; const uint8_t *der; size_t der_size; size_t hash_size; size_t ps_len; + enum dcrypto_result result; - if (!pkcs1_get_der(hashing, &der, &der_size, &hash_size)) - return 0; + result = pkcs1_get_der(hashing, &der, &der_size, &hash_size); + if (result != DCRYPTO_OK) + return result; if (msg_len != hash_size) - return 0; + return DCRYPTO_FAIL; if (padded_len < RSA_PKCS1_PADDING_SIZE + der_size + hash_size) - return 0; + return DCRYPTO_FAIL; ps_len = padded_len - 3 - der_size - hash_size; if (padded[0] != 0 || padded[1] != 1) - return 0; + return DCRYPTO_FAIL; for (i = 2; i < ps_len + 2; i++) { if (padded[i] != 0xFF) - return 0; + return DCRYPTO_FAIL; } if (padded[i++] != 0) - return 0; - if (DCRYPTO_equals(&padded[i], der, der_size) != DCRYPTO_OK) - return 0; + return DCRYPTO_FAIL; + + result = DCRYPTO_equals(&padded[i], der, der_size); i += der_size; - return DCRYPTO_equals(msg, &padded[i], hash_size) == DCRYPTO_OK; + result |= DCRYPTO_equals(msg, &padded[i], hash_size); + if (result != DCRYPTO_OK) + return DCRYPTO_FAIL; + return result; } /* sign */ -static int pkcs1_pss_pad(uint8_t *padded, size_t padded_len, - const uint8_t *in, size_t in_len, - enum hashing_mode hashing) +static enum dcrypto_result pkcs1_pss_pad(uint8_t *padded, size_t padded_len, + const uint8_t *in, size_t in_len, + enum hashing_mode hashing) { - const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_SIZE - : SHA256_DIGEST_SIZE; + const uint32_t hash_size = DCRYPTO_hash_size(hashing); const uint32_t salt_len = MIN(padded_len - hash_size - 2, hash_size); size_t db_len; size_t ps_len; union hash_ctx ctx; + enum dcrypto_result result; + if (!hash_size) + return DCRYPTO_FAIL; if (in_len != hash_size) - return 0; + return DCRYPTO_FAIL; if (padded_len < hash_size + 2) - return 0; + return DCRYPTO_FAIL; db_len = padded_len - hash_size - 1; - if (hashing == HASH_SHA1) - SHA1_hw_init(&ctx.sha1); - else - SHA256_hw_init(&ctx.sha256); + result = DCRYPTO_hw_hash_init(&ctx, hashing); + if (result != DCRYPTO_OK) + return result; /* Pilfer bits of output for temporary use. */ memset(padded, 0, 8); HASH_update(&ctx, padded, 8); HASH_update(&ctx, in, in_len); /* Pilfer bits of output for temporary use. */ - if (!fips_rand_bytes(padded, salt_len)) - return 0; + if (!fips_rand_bytes(padded, salt_len)) { + HASH_final(&ctx); /* free up SHA engine */ + return DCRYPTO_FAIL; + } HASH_update(&ctx, padded, salt_len); /* Output hash. */ @@ -415,22 +446,22 @@ static int pkcs1_pss_pad(uint8_t *padded, size_t padded_len, memmove(padded + ps_len + 1, padded, salt_len); memset(padded, 0, ps_len); padded[ps_len] = 0x01; - MGF1_xor(padded, db_len, padded + db_len, hash_size, hashing); + result = MGF1_xor(padded, db_len, padded + db_len, hash_size, hashing); /* Clear most significant bit. */ padded[0] &= 0x7F; /* Set trailing byte. */ padded[padded_len - 1] = 0xBC; - return 1; + return result; } /* verify */ -static int check_pkcs1_pss_pad(const uint8_t *in, size_t in_len, - uint8_t *padded, size_t padded_len, - enum hashing_mode hashing) +static enum dcrypto_result check_pkcs1_pss_pad(const uint8_t *in, size_t in_len, + uint8_t *padded, + size_t padded_len, + enum hashing_mode hashing) { - const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_SIZE - : SHA256_DIGEST_SIZE; + const uint32_t hash_size = DCRYPTO_hash_size(hashing); const uint8_t zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t db_len; uint32_t max_ps_len; @@ -438,11 +469,14 @@ static int check_pkcs1_pss_pad(const uint8_t *in, size_t in_len, union hash_ctx ctx; int bad = 0; size_t i; + enum dcrypto_result result; + if (!hash_size) + return DCRYPTO_FAIL; if (in_len != hash_size) - return 0; + return DCRYPTO_FAIL; if (padded_len < hash_size + 2) - return 0; + return DCRYPTO_FAIL; db_len = padded_len - hash_size - 1; /* Top bit should be zero. */ @@ -451,7 +485,9 @@ static int check_pkcs1_pss_pad(const uint8_t *in, size_t in_len, bad |= padded[padded_len - 1] ^ 0xBC; /* Recover DB. */ - MGF1_xor(padded, db_len, padded + db_len, hash_size, hashing); + result = MGF1_xor(padded, db_len, padded + db_len, hash_size, hashing); + bad |= result - DCRYPTO_OK; + /* Clear top bit. */ padded[0] &= 0x7F; /* Verify padding2. */ @@ -466,16 +502,18 @@ static int check_pkcs1_pss_pad(const uint8_t *in, size_t in_len, /* Continue with zero-length salt if 0x01 was not found. */ salt_len = max_ps_len - i; - if (hashing == HASH_SHA1) - SHA1_hw_init(&ctx.sha1); - else - SHA256_hw_init(&ctx.sha256); + result |= DCRYPTO_hw_hash_init(&ctx, hashing); + if (result != DCRYPTO_OK) + return DCRYPTO_FAIL; + HASH_update(&ctx, zeros, sizeof(zeros)); HASH_update(&ctx, in, in_len); HASH_update(&ctx, padded + db_len - salt_len, salt_len); - bad |= DCRYPTO_equals(padded + db_len, HASH_final(&ctx), hash_size) - - DCRYPTO_OK; - return !bad; + result |= DCRYPTO_equals(padded + db_len, HASH_final(&ctx), hash_size); + bad |= result - DCRYPTO_OK; + if (bad) + result = DCRYPTO_FAIL; + return result; } static int check_modulus_params( @@ -511,13 +549,14 @@ int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_OAEP: - if (!oaep_pad((uint8_t *) padded.d, bn_size(&padded), - (const uint8_t *) in, in_len, hashing, label)) + if (oaep_pad((uint8_t *)padded.d, bn_size(&padded), + (const uint8_t *)in, in_len, hashing, + label) != DCRYPTO_OK) return 0; break; case PADDING_MODE_PKCS1: - if (!pkcs1_type2_pad((uint8_t *) padded.d, bn_size(&padded), - (const uint8_t *) in, in_len)) + if (pkcs1_type2_pad((uint8_t *)padded.d, bn_size(&padded), + (const uint8_t *)in, in_len) != DCRYPTO_OK) return 0; break; case PADDING_MODE_NULL: @@ -579,14 +618,15 @@ int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_OAEP: - if (!check_oaep_pad(out, out_len, (uint8_t *) padded.d, - bn_size(&padded), hashing, label)) + if (check_oaep_pad(out, out_len, (uint8_t *)padded.d, + bn_size(&padded), hashing, + label) != DCRYPTO_OK) ret = 0; break; case PADDING_MODE_PKCS1: - if (!check_pkcs1_type2_pad( - out, out_len, (const uint8_t *) padded.d, - bn_size(&padded))) + if (check_pkcs1_type2_pad(out, out_len, + (const uint8_t *)padded.d, + bn_size(&padded)) != DCRYPTO_OK) ret = 0; break; case PADDING_MODE_NULL: @@ -626,13 +666,15 @@ int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_PKCS1: - if (!pkcs1_type1_pad((uint8_t *) padded.d, bn_size(&padded), - (const uint8_t *) in, in_len, hashing)) + if (pkcs1_type1_pad((uint8_t *)padded.d, bn_size(&padded), + (const uint8_t *)in, in_len, + hashing) != DCRYPTO_OK) return 0; break; case PADDING_MODE_PSS: - if (!pkcs1_pss_pad((uint8_t *) padded.d, bn_size(&padded), - (const uint8_t *) in, in_len, hashing)) + if (pkcs1_pss_pad((uint8_t *)padded.d, bn_size(&padded), + (const uint8_t *)in, in_len, + hashing) != DCRYPTO_OK) return 0; break; default: @@ -679,15 +721,15 @@ int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, switch (padding) { case PADDING_MODE_PKCS1: - if (!check_pkcs1_type1_pad( - digest, digest_len, (uint8_t *) padded.d, - bn_size(&padded), hashing)) + if (check_pkcs1_type1_pad(digest, digest_len, + (uint8_t *)padded.d, bn_size(&padded), + hashing) != DCRYPTO_OK) ret = 0; break; case PADDING_MODE_PSS: - if (!check_pkcs1_pss_pad( - digest, digest_len, (uint8_t *) padded.d, - bn_size(&padded), hashing)) + if (check_pkcs1_pss_pad(digest, digest_len, (uint8_t *)padded.d, + bn_size(&padded), + hashing) != DCRYPTO_OK) ret = 0; break; default: diff --git a/board/cr50/dcrypto/sha_hw.c b/board/cr50/dcrypto/sha_hw.c index 7d70d71c86..28ede02143 100644 --- a/board/cr50/dcrypto/sha_hw.c +++ b/board/cr50/dcrypto/sha_hw.c @@ -354,10 +354,6 @@ const struct sha256_digest *SHA256_hw_hash(const void *data, size_t n, 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); - const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx) { return HMAC_SHA256_final(ctx); diff --git a/board/cr50/tpm2/ecc.c b/board/cr50/tpm2/ecc.c index 6e8f5792ed..c7fe1c15b2 100644 --- a/board/cr50/tpm2/ecc.c +++ b/board/cr50/tpm2/ecc.c @@ -141,8 +141,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. */ - HMAC_SHA256_hw_init(&hmac, seed->buffer, - seed->size); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, seed->buffer, seed->size) != + DCRYPTO_OK) + return CRYPT_FAIL; + HMAC_SHA256_update(&hmac, "ECC", 4); memcpy(local_seed.t.buffer, HMAC_SHA256_final(&hmac), local_seed.t.size); diff --git a/board/cr50/tpm2/endorsement.c b/board/cr50/tpm2/endorsement.c index f929f1c405..b4d2b91775 100644 --- a/board/cr50/tpm2/endorsement.c +++ b/board/cr50/tpm2/endorsement.c @@ -590,12 +590,16 @@ enum manufacturing_status tpm_endorse(void) * * This will fail if we are not running w/ expected keyladder. */ - HMAC_SHA256_hw_init(&hmac, eps, sizeof(eps)); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, eps, sizeof(eps)) != + DCRYPTO_OK) + return mnf_hmac_mismatch; HMAC_SHA256_update(&hmac, "RSA", 4); - HMAC_SHA256_hw_init(&hmac, HMAC_SHA256_hw_final(&hmac), 32); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, HMAC_SHA256_final(&hmac), + 32) != DCRYPTO_OK) + return mnf_hmac_mismatch; HMAC_SHA256_update(&hmac, p, RO_CERTS_REGION_SIZE - 32); if (DCRYPTO_equals(p + RO_CERTS_REGION_SIZE - 32, - HMAC_SHA256_hw_final(&hmac), + HMAC_SHA256_final(&hmac), 32) != DCRYPTO_OK) { 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 4494451844..98b60e760b 100644 --- a/board/cr50/tpm2/hash.c +++ b/board/cr50/tpm2/hash.c @@ -54,45 +54,38 @@ void _cpri__ImportExportHashState(CPRI_HASH_STATE *osslFmt, memcpy(externalFmt, osslFmt, sizeof(CPRI_HASH_STATE)); } +/* We try to use same encoding for TPM & Dcrypto. */ +BUILD_ASSERT(TPM_ALG_SHA1 == HASH_SHA1); +BUILD_ASSERT(TPM_ALG_SHA256 == HASH_SHA256); +BUILD_ASSERT(TPM_ALG_SHA384 == HASH_SHA384); +BUILD_ASSERT(TPM_ALG_SHA512 == HASH_SHA512); +BUILD_ASSERT(TPM_ALG_NULL == HASH_NULL); + uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in, - uint32_t out_len, uint8_t *out) + uint32_t out_len, uint8_t *out) { - union sha_digests digest; const uint16_t digest_len = _cpri__GetDigestSize(alg); + union hash_ctx ctx; if (digest_len == 0) return 0; - switch (alg) { - case TPM_ALG_SHA1: - SHA1_hw_hash(in, in_len, &digest.sha1); - break; - - case TPM_ALG_SHA256: - SHA256_hw_hash(in, in_len, &digest.sha256); - break; - case TPM_ALG_SHA384: - SHA384_hw_hash(in, in_len, &digest.sha384); - break; - case TPM_ALG_SHA512: - SHA512_hw_hash(in, in_len, &digest.sha512); - break; - default: + if (DCRYPTO_hw_hash_init(&ctx, alg) != DCRYPTO_OK) { FAIL(FATAL_ERROR_INTERNAL); - break; + return 0; } - + HASH_update(&ctx, in, in_len); out_len = MIN(out_len, digest_len); - memcpy(out, digest.b8, out_len); + memcpy(out, HASH_final(&ctx), out_len); return out_len; } 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) + +uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence, CPRI_HASH_STATE *state) { - union hash_ctx *ctx = (union 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 @@ -101,28 +94,10 @@ uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence, * that the key-ladder will not be used between SHA_init() and * final(). */ - switch (alg) { - case TPM_ALG_SHA1: - SHA1_sw_init(&ctx->sha1); - result = HASH_size(ctx); - break; - case TPM_ALG_SHA256: - SHA256_sw_init(&ctx->sha256); - result = HASH_size(ctx); - break; + if (DCRYPTO_sw_hash_init(ctx, (enum hashing_mode)alg) != DCRYPTO_OK) + return 0; - case TPM_ALG_SHA384: - SHA384_sw_init(&ctx->sha384); - result = HASH_size(ctx); - break; - case TPM_ALG_SHA512: - SHA512_sw_init(&ctx->sha512); - result = HASH_size(ctx); - break; - default: - result = 0; - break; - } + result = HASH_size(ctx); if (result > 0) state->hashAlg = alg; @@ -291,23 +266,23 @@ static uint16_t do_software_hmac(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in, return out_len; } -static uint16_t do_dcrypto_hmac(TPM_ALG_ID alg, uint32_t in_len, - uint8_t *in, int32_t out_len, uint8_t *out) +static uint16_t do_dcrypto_hmac(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in, + int32_t out_len, uint8_t *out) { - struct hmac_sha256_ctx ctx; + union hmac_ctx ctx; uint8_t *key; uint32_t key_len; - /* Dcrypto only support SHA-256 */ - if (alg != TPM_ALG_SHA256) - return 0; key = in + in_len; key_len = *key++; key_len = key_len * 256 + *key++; - 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, HMAC_SHA256_hw_final(&ctx), out_len); + /* Check if requested algorithm is supported. */ + if (DCRYPTO_hw_hmac_init(&ctx, key, key_len, (enum hashing_mode)alg) != + DCRYPTO_OK) + return 0; + HMAC_update(&ctx, in, in_len); + out_len = MIN(out_len, DCRYPTO_hash_size((enum hashing_mode)alg)); + memcpy(out, HMAC_final(&ctx), out_len); return out_len; } diff --git a/board/cr50/tpm2/rsa.c b/board/cr50/tpm2/rsa.c index 78cc3562de..97797d440a 100644 --- a/board/cr50/tpm2/rsa.c +++ b/board/cr50/tpm2/rsa.c @@ -397,10 +397,12 @@ CRYPT_RESULT _cpri__GenerateKeyRSA( { struct hmac_sha256_ctx hmac; - HMAC_SHA256_hw_init(&hmac, seed->buffer, seed->size); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, seed->buffer, + seed->size) != DCRYPTO_OK) + return CRYPT_FAIL; HMAC_SHA256_update(&hmac, "RSA", 4); - memcpy(local_seed.t.buffer, HMAC_SHA256_hw_final(&hmac), - local_seed.t.size); + memcpy(local_seed.t.buffer, HMAC_SHA256_final(&hmac), + local_seed.t.size); } if (e_buf == 0) diff --git a/board/cr50/tpm2/virtual_nvmem.c b/board/cr50/tpm2/virtual_nvmem.c index 3ddaed067d..16a4028be9 100644 --- a/board/cr50/tpm2/virtual_nvmem.c +++ b/board/cr50/tpm2/virtual_nvmem.c @@ -304,9 +304,11 @@ static void GetRSUDevID(BYTE *to, size_t offset, size_t size) uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]; const uint8_t *rsu_device_id; - get_rma_device_id(rma_device_id); - - SHA256_hw_init(&ctx); + if (get_rma_device_id(rma_device_id) != EC_SUCCESS || + DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK) { + memset(to, 0, size); + return; + }; SHA256_update(&ctx, rma_device_id, sizeof(rma_device_id)); SHA256_update(&ctx, kRsuSalt, RSU_SALT_SIZE); rsu_device_id = SHA256_final(&ctx)->b8; diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c index 4aede92f19..32ef2b00c4 100644 --- a/board/cr50/usb_spi.c +++ b/board/cr50/usb_spi.c @@ -678,7 +678,8 @@ int usb_spi_sha256_start(struct sha256_ctx *ctx) return EC_ERROR_BUSY; } - SHA256_hw_init(ctx); + if (DCRYPTO_hw_sha256_init(ctx) != DCRYPTO_OK) + return EC_ERROR_HW_INTERNAL; return EC_SUCCESS; } diff --git a/board/host/dcrypto.h b/board/host/dcrypto.h index b9bd5b8be8..030e8bbb23 100644 --- a/board/host/dcrypto.h +++ b/board/host/dcrypto.h @@ -18,74 +18,12 @@ * this is not set, a combination of cryptoc and openssl are used for the * dcrypto implementation. */ -#ifndef CONFIG_DCRYPTO_MOCK -/* If not using the mock struct definitions, use the ones from Cr50. */ +#ifndef CONFIG_DCRYPTO_MOCK #include "board/cr50/dcrypto/dcrypto.h" +#else +#include "board/cr50/dcrypto/internal.h" +#endif -#else /* defined(CONFIG_DCRYPTO_MOCK) */ - -#include "board/cr50/dcrypto/hmacsha2.h" - -#define AES256_BLOCK_CIPHER_KEY_SIZE 32 - -enum dcrypto_appid { - RESERVED = 0, - NVMEM = 1, - U2F_ATTEST = 2, - U2F_ORIGIN = 3, - U2F_WRAP = 4, - PERSO_AUTH = 5, - PINWEAVER = 6, - /* This enum value should not exceed 7. */ -}; - -void SHA256_hw_init(struct sha256_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); - - -int DCRYPTO_appkey_init(enum dcrypto_appid appid); - -void DCRYPTO_appkey_finish(void); - -int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8], - uint32_t output[8]); - -#include "cryptoc/p256.h" - -int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x, - const p256_int *pk_y, const p256_int *serial, - const char *name, uint8_t *cert, - const int n); - -int DCRYPTO_ladder_random(void *output); - -#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t)) - -struct drbg_ctx { - uint32_t k[SHA256_DIGEST_WORDS]; - uint32_t v[SHA256_DIGEST_WORDS]; - uint32_t reseed_counter; -}; - -enum dcrypto_result dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, - const p256_int *key, - const p256_int *message, - p256_int *r, p256_int *s); - -void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key, - const p256_int *message); - -bool fips_rand_bytes(void *buffer, size_t len); - -bool fips_crypto_allowed(void); - -#endif /* CONFIG_DCRYPTO_MOCK */ #endif /* __CROS_EC_HOST_DCRYPTO_H */ diff --git a/chip/host/build.mk b/chip/host/build.mk index 6cdd9807d4..4355a47673 100644 --- a/chip/host/build.mk +++ b/chip/host/build.mk @@ -34,8 +34,12 @@ chip-$(CONFIG_DCRYPTO)+= dcrypto/sha256.o # Object files that can be shared with the Cr50 dcrypto implementation chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/hmac_sw.o +chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/hash_api.o chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/sha1.o chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/sha256.o +ifeq ($(CONFIG_UPTO_SHA512),y) +chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/sha512.o +endif chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/hmac_drbg.o chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/p256.o chip-$(CONFIG_DCRYPTO)+= ../../board/cr50/dcrypto/compare.o diff --git a/chip/host/dcrypto/app_cipher.c b/chip/host/dcrypto/app_cipher.c index a3ce4e3184..6ce25b6199 100644 --- a/chip/host/dcrypto/app_cipher.c +++ b/chip/host/dcrypto/app_cipher.c @@ -15,7 +15,7 @@ void app_compute_hash(const void *p_buf, size_t num_bytes, void *p_hash, * Use the built in dcrypto engine to generate the sha1 hash of the * buffer. */ - SHA256_hw_hash(p_buf, num_bytes, &digest); + DCRYPTO_SHA256_hash(p_buf, num_bytes, digest.b8); memcpy(p_hash, digest.b8, MIN(hash_len, sizeof(digest))); @@ -46,3 +46,8 @@ int crypto_enabled(void) { return 1; } + +bool fips_crypto_allowed(void) +{ + return true; +} diff --git a/chip/host/dcrypto/sha256.c b/chip/host/dcrypto/sha256.c index 1c9fda27c2..ec2638ffc3 100644 --- a/chip/host/dcrypto/sha256.c +++ b/chip/host/dcrypto/sha256.c @@ -3,7 +3,18 @@ * found in the LICENSE file. */ -#include "dcrypto.h" +#include "internal.h" + +void SHA1_hw_init(struct sha1_ctx *ctx) +{ + SHA1_sw_init(ctx); +} + +const struct sha1_digest *SHA1_hw_hash(const void *data, size_t n, + struct sha1_digest *digest) +{ + return SHA1_sw_hash(data, n, digest); +} void SHA256_hw_init(struct sha256_ctx *ctx) { diff --git a/common/ccd_config.c b/common/ccd_config.c index 12e88689ad..d87842a055 100644 --- a/common/ccd_config.c +++ b/common/ccd_config.c @@ -236,7 +236,8 @@ static int raw_has_password(void) * @param digest Pointer to a CCD_PASSWORD_DIGEST_SIZE buffer * @param password The password to digest */ -static void ccd_password_digest(uint8_t *digest, const char *password) +static enum ec_error_list ccd_password_digest(uint8_t *digest, + const char *password) { struct sha256_ctx sha; uint8_t *unique_id; @@ -244,11 +245,13 @@ static void ccd_password_digest(uint8_t *digest, const char *password) unique_id_len = system_get_chip_unique_id(&unique_id); - SHA256_hw_init(&sha); + if (DCRYPTO_hw_sha256_init(&sha) != DCRYPTO_OK) + return EC_ERROR_HW_INTERNAL; SHA256_update(&sha, config.password_salt, sizeof(config.password_salt)); SHA256_update(&sha, unique_id, unique_id_len); SHA256_update(&sha, password, strlen(password)); memcpy(digest, SHA256_final(&sha)->b8, CCD_PASSWORD_DIGEST_SIZE); + return EC_SUCCESS; } /** @@ -258,7 +261,7 @@ static void ccd_password_digest(uint8_t *digest, const char *password) * @return EC_SUCCESS, EC_ERROR_BUSY if too soon since last attempt, or * EC_ERROR_ACCESS_DENIED if mismatch. */ -static int raw_check_password(const char *password) +static enum ec_error_list raw_check_password(const char *password) { /* * Time of last password attempt; initialized to 0 at boot. Yes, we're @@ -272,6 +275,7 @@ static int raw_check_password(const char *password) uint8_t digest[CCD_PASSWORD_DIGEST_SIZE]; uint32_t t; + enum ec_error_list result; /* If no password is set, match only an empty password */ if (!raw_has_password()) @@ -284,7 +288,9 @@ static int raw_check_password(const char *password) last_password_time = t; /* Calculate the digest of the password */ - ccd_password_digest(digest, password); + result = ccd_password_digest(digest, password); + if (result != EC_SUCCESS) + return result; if (safe_memcmp(digest, config.password_digest, sizeof(config.password_digest))) @@ -312,19 +318,23 @@ static void raw_reset_password(void) * @param password New password; must be non-empty * @return EC_SUCCESS if successful */ -static int raw_set_password(const char *password) +static enum ec_error_list raw_set_password(const char *password) { + enum ec_error_list result; + /* Get a new salt */ if (!fips_rand_bytes(config.password_salt, sizeof(config.password_salt))) return EC_ERROR_HW_INTERNAL; /* Update the password digest */ - ccd_password_digest(config.password_digest, password); + result = ccd_password_digest(config.password_digest, password); + if (result != EC_SUCCESS) + return result; /* Track whether we were opened when we set the password */ raw_set_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED, - ccd_state == CCD_STATE_UNLOCKED); + ccd_state == CCD_STATE_UNLOCKED); return EC_SUCCESS; } diff --git a/common/pinweaver.c b/common/pinweaver.c index 0bcd752ab6..9b7ad0b6d6 100644 --- a/common/pinweaver.c +++ b/common/pinweaver.c @@ -164,7 +164,8 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level, /* Initialize the root hash. */ for (hx = 0; hx < height.v; ++hx) { - SHA256_hw_init(&ctx); + if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK) + return PW_ERR_CRYPTO_FAILURE; for (kx = 0; kx < fan_out; ++kx) HASH_update((union hash_ctx *)&ctx, temp_hash, PW_HASH_SIZE); @@ -180,29 +181,31 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level, } /* Computes the HMAC for an encrypted leaf using the key in the merkle_tree. */ -static void compute_hmac(const struct merkle_tree_t *merkle_tree, +static int compute_hmac(const struct merkle_tree_t *merkle_tree, const struct imported_leaf_data_t *imported_leaf_data, uint8_t result[PW_HASH_SIZE]) { struct hmac_sha256_ctx hmac; - HMAC_SHA256_hw_init(&hmac, merkle_tree->hmac_key, - sizeof(merkle_tree->hmac_key)); - /* use HASH_update() vs. HMAC_update() due limits of dcrypto mock. */ - HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->head, - sizeof(*imported_leaf_data->head)); - HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->iv, - sizeof(PW_WRAP_BLOCK_SIZE)); - HASH_update((union hash_ctx *)&hmac.hash, imported_leaf_data->pub, - imported_leaf_data->head->pub_len); - HASH_update((union hash_ctx *)&hmac.hash, - imported_leaf_data->cipher_text, - imported_leaf_data->head->sec_len); - memcpy(result, HMAC_SHA256_hw_final(&hmac), PW_HASH_SIZE); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, merkle_tree->hmac_key, + sizeof(merkle_tree->hmac_key)) != + DCRYPTO_OK) + return PW_ERR_CRYPTO_FAILURE; + + HMAC_SHA256_update(&hmac, imported_leaf_data->head, + sizeof(*imported_leaf_data->head)); + HMAC_SHA256_update(&hmac, imported_leaf_data->iv, + sizeof(PW_WRAP_BLOCK_SIZE)); + HMAC_SHA256_update(&hmac, imported_leaf_data->pub, + imported_leaf_data->head->pub_len); + HMAC_SHA256_update(&hmac, imported_leaf_data->cipher_text, + imported_leaf_data->head->sec_len); + memcpy(result, HMAC_SHA256_final(&hmac), PW_HASH_SIZE); + return EC_SUCCESS; } /* Computes the root hash for the specified path and child hash. */ -static void compute_root_hash(const struct merkle_tree_t *merkle_tree, +static int compute_root_hash(const struct merkle_tree_t *merkle_tree, struct label_t path, const uint8_t hashes[][PW_HASH_SIZE], const uint8_t child_hash[PW_HASH_SIZE], @@ -214,18 +217,25 @@ static void compute_root_hash(const struct merkle_tree_t *merkle_tree, uint8_t temp_hash[PW_HASH_SIZE]; uint8_t hx = 0; uint64_t index = path.v; + int ret; + + ret = compute_hash(hashes, num_aux, + (struct index_t){ index & path_suffix_mask }, + child_hash, temp_hash); + if (ret != EC_SUCCESS) + return ret; - compute_hash(hashes, num_aux, - (struct index_t){index & path_suffix_mask}, - child_hash, temp_hash); for (hx = 1; hx < merkle_tree->height.v; ++hx) { hashes += num_aux; index = index >> merkle_tree->bits_per_level.v; - compute_hash(hashes, num_aux, - (struct index_t){index & path_suffix_mask}, - temp_hash, temp_hash); + ret = compute_hash(hashes, num_aux, + (struct index_t){ index & path_suffix_mask }, + temp_hash, temp_hash); + if (ret != EC_SUCCESS) + return ret; } memcpy(new_root, temp_hash, sizeof(temp_hash)); + return EC_SUCCESS; } /* Checks to see the specified path is valid. The length of the path should be @@ -239,8 +249,11 @@ static int authenticate_path(const struct merkle_tree_t *merkle_tree, const uint8_t child_hash[PW_HASH_SIZE]) { uint8_t parent[PW_HASH_SIZE]; + int ret; - compute_root_hash(merkle_tree, path, hashes, child_hash, parent); + ret = compute_root_hash(merkle_tree, path, hashes, child_hash, parent); + if (ret != EC_SUCCESS) + return ret; if (memcmp(parent, merkle_tree->root, sizeof(parent)) != 0) return PW_ERR_PATH_AUTH_FAILED; return EC_SUCCESS; @@ -334,13 +347,13 @@ static int handle_leaf_update( import_leaf((const struct unimported_leaf_data_t *)wrapped_leaf_data, &ptrs); - compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac); - compute_root_hash(merkle_tree, leaf_data->pub.label, - hashes, wrapped_leaf_data->hmac, - new_root); + ret = compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac); + if (ret != EC_SUCCESS) + return ret; - return EC_SUCCESS; + return compute_root_hash(merkle_tree, leaf_data->pub.label, hashes, + wrapped_leaf_data->hmac, new_root); } /******************************************************************************/ @@ -532,7 +545,9 @@ static int validate_request_with_wrapped_leaf( if (ret != EC_SUCCESS) return ret; - compute_hmac(merkle_tree, imported_leaf_data, hmac); + ret = compute_hmac(merkle_tree, imported_leaf_data, hmac); + if (ret != EC_SUCCESS) + return ret; /* Safe memcmp is used here to prevent an attacker from being able to * brute force a valid HMAC for a crafted wrapped_leaf_data. * memcmp provides an attacker a timing side-channel they can use to @@ -994,8 +1009,10 @@ static int pw_handle_remove_leaf(struct merkle_tree_t *merkle_tree, if (ret != EC_SUCCESS) return ret; - compute_root_hash(merkle_tree, request->leaf_location, - request->path_hashes, empty_hash, new_root); + ret = compute_root_hash(merkle_tree, request->leaf_location, + request->path_hashes, empty_hash, new_root); + if (ret != EC_SUCCESS) + return ret; ret = log_remove_leaf(request->leaf_location, new_root); if (ret != EC_SUCCESS) @@ -1283,7 +1300,10 @@ static int pw_handle_log_replay(const struct merkle_tree_t *merkle_tree, if (log.entries[x].type.v != PW_TRY_AUTH) return PW_ERR_TYPE_INVALID; - compute_hmac(merkle_tree, &imported_leaf_data, hmac); + ret = compute_hmac(merkle_tree, &imported_leaf_data, hmac); + if (ret != EC_SUCCESS) + return ret; + if (safe_memcmp(hmac, request->unimported_leaf_data.hmac, sizeof(hmac))) return PW_ERR_HMAC_AUTH_FAILED; @@ -1385,14 +1405,15 @@ int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree) * ARRAY_SIZE(hashes) == num_hashes * 0 <= location <= num_hashes */ -void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, +int compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, struct index_t location, const uint8_t child_hash[PW_HASH_SIZE], uint8_t result[PW_HASH_SIZE]) { struct sha256_ctx ctx; - SHA256_hw_init(&ctx); + if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK) + return PW_ERR_CRYPTO_FAILURE; if (location.v > 0) HASH_update((union hash_ctx *)&ctx, hashes[0], PW_HASH_SIZE * location.v); @@ -1401,6 +1422,7 @@ void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, HASH_update((union hash_ctx *)&ctx, hashes[location.v], PW_HASH_SIZE * (num_hashes - location.v)); memcpy(result, HASH_final((union hash_ctx *)&ctx), PW_HASH_SIZE); + return EC_SUCCESS; } /* If a request from older protocol comes, this method should make it diff --git a/common/rma_auth.c b/common/rma_auth.c index 9de2d9984b..01c3ff827e 100644 --- a/common/rma_auth.c +++ b/common/rma_auth.c @@ -75,31 +75,38 @@ static char authcode[RMA_AUTHCODE_BUF_SIZE]; static int tries_left; static uint64_t last_challenge_time; -static void get_hmac_sha256(void *hmac_out, const uint8_t *secret, +static enum ec_error_list get_hmac_sha256(void *hmac_out, const uint8_t *secret, size_t secret_size, const void *ch_ptr, size_t ch_size) { #ifdef USE_DCRYPTO struct hmac_sha256_ctx hmac; - HMAC_SHA256_hw_init(&hmac, secret, secret_size); + if (DCRYPTO_hw_hmac_sha256_init(&hmac, secret, secret_size) != + DCRYPTO_OK) + return EC_ERROR_HW_INTERNAL; HMAC_SHA256_update(&hmac, ch_ptr, ch_size); - memcpy(hmac_out, HMAC_SHA256_hw_final(&hmac), 32); + memcpy(hmac_out, HMAC_SHA256_final(&hmac), 32); #else hmac_SHA256(hmac_out, secret, secret_size, ch_ptr, ch_size); #endif + return EC_SUCCESS; } -static void hash_buffer(void *dest, size_t dest_size, - const void *buffer, size_t buf_size) +static enum ec_error_list hash_buffer(void *dest, size_t dest_size, + const void *buffer, size_t buf_size) { /* We know that the destination is no larger than 32 bytes. */ uint8_t temp[32]; + enum ec_error_list ret; - get_hmac_sha256(temp, buffer, buf_size, buffer, buf_size); + ret = get_hmac_sha256(temp, buffer, buf_size, buffer, buf_size); + if (ret) + return ret; /* Or should we do XOR of the temp modulo dest size? */ memcpy(dest, temp, dest_size); + return EC_SUCCESS; } #ifdef CONFIG_RMA_AUTH_USE_P256 @@ -148,7 +155,8 @@ static int p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], } /* Did not succeed, rehash the private key and try again. */ - SHA256_hw_init(&sha); + if (DCRYPTO_hw_sha256_init(&sha) != DCRYPTO_OK) + return EC_ERROR_HW_INTERNAL; SHA256_update(&sha, buf, sizeof(buf)); memcpy(buf, SHA256_final(&sha), sizeof(buf)); } @@ -177,10 +185,11 @@ static int p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], } #endif -void get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]) +int get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]) { uint8_t *chip_unique_id; int chip_unique_id_size = system_get_chip_unique_id(&chip_unique_id); + enum ec_error_list ret; if (chip_unique_id_size < 0) chip_unique_id_size = 0; @@ -198,9 +207,12 @@ void get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]) * rma_challenge:device_id, let's use first few bytes of * its hash. */ - hash_buffer(rma_device_id, RMA_DEVICE_ID_SIZE, - chip_unique_id, chip_unique_id_size); + ret = hash_buffer(rma_device_id, RMA_DEVICE_ID_SIZE, + chip_unique_id, chip_unique_id_size); + if (ret != EC_SUCCESS) + return ret; } + return EC_SUCCESS; } /** @@ -217,6 +229,7 @@ int rma_create_challenge(void) struct board_id bid; uint8_t *cptr = (uint8_t *)&c; uint64_t t; + int ret; /* Clear the current challenge and authcode, if any */ memset(challenge, 0, sizeof(challenge)); @@ -236,9 +249,11 @@ int rma_create_challenge(void) return EC_ERROR_UNKNOWN; memcpy(c.board_id, &bid.type, sizeof(c.board_id)); - get_rma_device_id(c.device_id); + ret = get_rma_device_id(c.device_id); + if (ret != EC_SUCCESS) + return ret; - /* Calculate a new ephemeral key pair and the shared secret. */ + /* Calculate a new ephemeral key pair and the shared secret. */ #ifdef CONFIG_RMA_AUTH_USE_P256 if (p256_get_pub_key_and_secret(c.device_pub_key, secret) != EC_SUCCESS) return EC_ERROR_UNKNOWN; @@ -251,13 +266,15 @@ int rma_create_challenge(void) if (base32_encode(challenge, sizeof(challenge), cptr, 8 * sizeof(c), 9)) return EC_ERROR_UNKNOWN; - /* * Auth code is a truncated HMAC of the ephemeral public key, BoardID, * and DeviceID. Those are all in the right order in the challenge * struct, after the version/key id byte. */ - get_hmac_sha256(temp, secret, sizeof(secret), cptr + 1, sizeof(c) - 1); + ret = get_hmac_sha256(temp, secret, sizeof(secret), cptr + 1, + sizeof(c) - 1); + if (ret != EC_SUCCESS) + return ret; if (base32_encode(authcode, sizeof(authcode), temp, RMA_AUTHCODE_CHARS * 5, 0)) return EC_ERROR_UNKNOWN; diff --git a/fuzz/mem_hash_tree.cc b/fuzz/mem_hash_tree.cc index 88e85b87cf..3aceb28518 100644 --- a/fuzz/mem_hash_tree.cc +++ b/fuzz/mem_hash_tree.cc @@ -73,7 +73,8 @@ void MemHashTree::UpdatePath(uint64_t label, shifted_parent_label &= ~child_index_mask; struct sha256_ctx ctx; - SHA256_hw_init(&ctx); + if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK) + return; int empty_nodes = 0; for (int index = 0; index < fan_out; ++index) { auto itr = @@ -119,7 +120,8 @@ 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) { struct sha256_ctx ctx; - SHA256_hw_init(&ctx); + if (DCRYPTO_hw_sha256_init(&ctx) != DCRYPTO_OK) + return; for (int index = 0; index < fan_out; ++index) { SHA256_update(&ctx, hash.data(), hash.size()); } diff --git a/include/pinweaver.h b/include/pinweaver.h index 21571da7b0..6eb1f46092 100644 --- a/include/pinweaver.h +++ b/include/pinweaver.h @@ -163,8 +163,11 @@ void import_leaf(const struct unimported_leaf_data_t *unimported, /* Computes the total number of the sibling hashes along a path. */ int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree); -/* Computes the parent hash for an array of child hashes. */ -void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, +/** + * Computes the parent hash for an array of child hashes. + * Return EC_SUCCESS if successful. + */ +int compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, struct index_t location, const uint8_t child_hash[PW_HASH_SIZE], uint8_t result[PW_HASH_SIZE]); diff --git a/include/rma_auth.h b/include/rma_auth.h index 0a4d7c7e71..caca9d07cc 100644 --- a/include/rma_auth.h +++ b/include/rma_auth.h @@ -75,7 +75,8 @@ int rma_try_authcode(const char *code); * * @param rma_device_id Pointer to the buffer that will be filled with * the ID. The buffer must be of size RMA_DEVICE_ID_SIZE. + * @return EC_SUCCESS if successful */ -void get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]); +int get_rma_device_id(uint8_t rma_device_id[RMA_DEVICE_ID_SIZE]); #endif diff --git a/test/pinweaver.c b/test/pinweaver.c index 21bd30396d..df7327887f 100644 --- a/test/pinweaver.c +++ b/test/pinweaver.c @@ -894,29 +894,40 @@ void HASH_update(union hash_ctx *ctx, const void *data, size_t len) SHA256_sw_update(&ctx->sha256, data, len); } +void HMAC_SHA256_update(struct hmac_sha256_ctx *ctx, const void *data, + size_t len) +{ + if (MOCK_hash_update_cb) + MOCK_hash_update_cb(data, len); + if (ctx) + SHA256_sw_update(&ctx->hash, data, len); +} + const union sha_digests *HASH_final(union hash_ctx *ctx) { ++MOCK_DECRYPTO_release_counter; return (union sha_digests *)SHA256_sw_final(&ctx->sha256); } -void SHA256_hw_init(struct sha256_ctx *ctx) +enum dcrypto_result DCRYPTO_hw_sha256_init(struct sha256_ctx *ctx) { SHA256_sw_init(ctx); ++MOCK_DECRYPTO_init_counter; + return DCRYPTO_OK; } -void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key, - size_t len) +enum dcrypto_result DCRYPTO_hw_hmac_sha256_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_sw_init(&ctx->hash); ++MOCK_DECRYPTO_init_counter; + return DCRYPTO_OK; } -const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx) +const struct sha256_digest *HMAC_SHA256_final(struct hmac_sha256_ctx *ctx) { ++MOCK_DECRYPTO_release_counter; return (struct sha256_digest *)MOCK_hmac; diff --git a/test/u2f.c b/test/u2f.c index 21c5d6ea69..3ddf38616b 100644 --- a/test/u2f.c +++ b/test/u2f.c @@ -41,11 +41,6 @@ bool fips_trng_bytes(void *buffer, size_t len) return true; } -bool fips_crypto_allowed(void) -{ - return true; -} - int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x, const p256_int *pk_y, const p256_int *serial, const char *name, uint8_t *cert, const int n) |