summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2015-11-19 16:15:35 -0800
committerchrome-bot <chrome-bot@chromium.org>2015-11-25 11:17:13 -0800
commitae89bb6f49f30186e300e0b60c6384b37da8c72f (patch)
treefccdd5ba91b0481f06f68b81a26c7fd33ce1f76b
parentf01d71eb5b0ee8f15e2c85e9302c24bc5fe3ebcd (diff)
downloadchrome-ec-ae89bb6f49f30186e300e0b60c6384b37da8c72f.tar.gz
cr50: SHA1 and SHA256 implementation with hardware support
This change includes hardware and software support for SHA1/256 on CR50. When running in the RO image, only hardware sha256 support is included. When running in the RW image, the code auto-selects between the software and hardware implementation. Software implementation path is taken if the hardware is currently in use by some other context. Refactor the CR50 loader to use this abstraction. The existing software implementation for SHA1 and SHA256 is used for the software path. CQ-DEPEND=CL:*239385 BRANCH=none TEST=EC shell boots fine (implies that SHA256 works) BUG=chrome-os-partner:43025 Change-Id: I7bcefc12fcef869dac2e48793bd0cb5ce8e80d5b Signed-off-by: nagendra modadugu <ngm@google.com> Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/313011
-rw-r--r--board/cr50/board.h5
-rw-r--r--board/cr50/build.mk2
-rw-r--r--board/cr50/tpm2/aes.c1
-rw-r--r--board/cr50/tpm2/hash.c138
-rw-r--r--board/cr50/tpm2/hash_data.c11
-rw-r--r--board/cr50/tpm2/stubs.c82
-rw-r--r--chip/g/build.mk10
-rw-r--r--chip/g/dcrypto/dcrypto.h60
-rw-r--r--chip/g/dcrypto/internal.h47
-rw-r--r--chip/g/dcrypto/sha1.c98
-rw-r--r--chip/g/dcrypto/sha256.c216
-rw-r--r--chip/g/loader/hw_sha256.c75
-rw-r--r--chip/g/loader/hw_sha256.h25
-rw-r--r--chip/g/loader/launch.c17
-rw-r--r--chip/g/loader/verify.c5
-rw-r--r--chip/g/registers.h4
-rw-r--r--common/build.mk2
-rw-r--r--include/config.h5
18 files changed, 597 insertions, 206 deletions
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 320b6fe133..c6462b56ec 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -49,6 +49,11 @@
#define CONFIG_SPS_TEST
+/* Include crypto stuff, both software and hardware. */
+#define CONFIG_DCRYPTO
+#define CONFIG_SHA1
+#define CONFIG_SHA256
+
#ifndef __ASSEMBLER__
#include "gpio_signal.h"
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index fce011d0ec..aa84171346 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -31,6 +31,8 @@ dirs-y += $(BDIR)/tpm2
board-y = board.o
board-y += tpm2/NVMem.o
board-y += tpm2/aes.o
+board-y += tpm2/hash.o
+board-y += tpm2/hash_data.o
board-y += tpm2/platform.o
board-y += tpm2/stubs.o
diff --git a/board/cr50/tpm2/aes.c b/board/cr50/tpm2/aes.c
index 29348ad2ab..a751e9134e 100644
--- a/board/cr50/tpm2/aes.c
+++ b/board/cr50/tpm2/aes.c
@@ -7,7 +7,6 @@
#include "dcrypto.h"
#include <assert.h>
-#include <string.h>
static CRYPT_RESULT _cpri__AESBlock(
uint8_t *out, uint32_t len, uint8_t *in);
diff --git a/board/cr50/tpm2/hash.c b/board/cr50/tpm2/hash.c
new file mode 100644
index 0000000000..8d3dc9a05d
--- /dev/null
+++ b/board/cr50/tpm2/hash.c
@@ -0,0 +1,138 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "CryptoEngine.h"
+
+#include "util.h"
+#include "dcrypto.h"
+
+static const HASH_INFO *lookup_hash_info(TPM_ALG_ID alg)
+{
+ int i;
+ const int num_algs = ARRAY_SIZE(g_hashData);
+
+ for (i = 0; i < num_algs - 1; i++) {
+ if (g_hashData[i].alg == alg)
+ return &g_hashData[i];
+ }
+ return &g_hashData[num_algs - 1];
+}
+
+TPM_ALG_ID _cpri__GetContextAlg(CPRI_HASH_STATE *hash_state)
+{
+ return hash_state->hashAlg;
+}
+
+TPM_ALG_ID _cpri__GetHashAlgByIndex(uint32_t index)
+{
+ if (index >= HASH_COUNT)
+ return TPM_ALG_NULL;
+ return g_hashData[index].alg;
+}
+
+uint16_t _cpri__GetDigestSize(TPM_ALG_ID alg)
+{
+ return lookup_hash_info(alg)->digestSize;
+}
+
+uint16_t _cpri__GetHashBlockSize(TPM_ALG_ID alg)
+{
+ return lookup_hash_info(alg)->blockSize;
+}
+
+void _cpri__ImportExportHashState(CPRI_HASH_STATE *osslFmt,
+ EXPORT_HASH_STATE *externalFmt,
+ IMPORT_EXPORT direction)
+{
+ pAssert(sizeof(CPRI_HASH_STATE) == sizeof(EXPORT_HASH_STATE));
+ if (direction == IMPORT_STATE)
+ memcpy(osslFmt, externalFmt, sizeof(CPRI_HASH_STATE));
+ else
+ memcpy(externalFmt, osslFmt, sizeof(CPRI_HASH_STATE));
+}
+
+uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
+ uint32_t out_len, uint8_t *out)
+{
+ uint8_t digest[SHA_DIGEST_MAX_BYTES];
+ const uint16_t digest_len = _cpri__GetDigestSize(alg);
+
+ if (digest_len == 0)
+ return 0;
+
+ switch (alg) {
+ case TPM_ALG_SHA1:
+ DCRYPTO_SHA1_hash(in, in_len, digest);
+ break;
+
+ case TPM_ALG_SHA256:
+ DCRYPTO_SHA256_hash(in, in_len, digest);
+ break;
+/* TODO: add support for SHA384 and SHA512
+ *
+ * case TPM_ALG_SHA384:
+ * DCRYPTO_SHA384_hash(in, in_len, p);
+ * break;
+ * case TPM_ALG_SHA512:
+ * DCRYPTO_SHA512_hash(in, in_len, p);
+ * break; */
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+
+ out_len = MIN(out_len, digest_len);
+ memcpy(out, digest, out_len);
+ return out_len;
+}
+
+uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence,
+ CPRI_HASH_STATE *state)
+{
+ struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+ uint16_t result;
+
+ pAssert(sizeof(struct HASH_CTX) < sizeof(state->state));
+ switch (alg) {
+ case TPM_ALG_SHA1:
+ DCRYPTO_SHA1_init(ctx, sequence);
+ result = DCRYPTO_HASH_size(ctx);
+ break;
+ case TPM_ALG_SHA256:
+ DCRYPTO_SHA256_init(ctx, sequence);
+ result = DCRYPTO_HASH_size(ctx);
+ break;
+/* TODO: add support for SHA384 and SHA512
+ * case TPM_ALG_SHA384:
+ * DCRYPTO_SHA384_init(in, in_len, p);
+ * break;
+ * case TPM_ALG_SHA512:
+ * DCRYPTO_SHA512_init(in, in_len, p);
+ * break; */
+ default:
+ result = 0;
+ break;
+ }
+
+ return result;
+}
+
+void _cpri__UpdateHash(CPRI_HASH_STATE *state, uint32_t in_len,
+ BYTE *in)
+{
+ struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+
+ DCRYPTO_HASH_update(ctx, in, in_len);
+}
+
+uint16_t _cpri__CompleteHash(CPRI_HASH_STATE *state,
+ uint32_t out_len, uint8_t *out)
+{
+ struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
+
+ out_len = MIN(DCRYPTO_HASH_size(ctx), out_len);
+ memcpy(out, DCRYPTO_HASH_final(ctx), out_len);
+ return out_len;
+}
diff --git a/board/cr50/tpm2/hash_data.c b/board/cr50/tpm2/hash_data.c
new file mode 100644
index 0000000000..6e6ad8aa4d
--- /dev/null
+++ b/board/cr50/tpm2/hash_data.c
@@ -0,0 +1,11 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "CryptoEngine.h"
+
+/*
+ * This is unfortunate, but this is the only way to bring in necessary data
+ * from the TPM2 library, as this file is not compiled in embedded mode.
+ */
+#include "CpriHashData.c"
diff --git a/board/cr50/tpm2/stubs.c b/board/cr50/tpm2/stubs.c
index abfe07185c..a75ece04be 100644
--- a/board/cr50/tpm2/stubs.c
+++ b/board/cr50/tpm2/stubs.c
@@ -33,16 +33,6 @@ UINT16 _cpri__CompleteHMAC(
return -1;
}
-UINT16 _cpri__CompleteHash(
- CPRI_HASH_STATE * hashState, // IN: the state of hash stack
- UINT32 dOutSize, // IN: size of digest buffer
- BYTE * dOut // OUT: hash digest
- )
-{
- ecprintf("%s called\n", __func__);
- return -1;
-}
-
CRYPT_RESULT _cpri__DecryptRSA(
UINT32 * dOutSize, // OUT: the size of the decrypted data
BYTE * dOut, // OUT: the decrypted data
@@ -182,13 +172,6 @@ UINT16 _cpri__GenerateSeededRandom(
return -1;
}
-TPM_ALG_ID _cpri__GetContextAlg(
- CPRI_HASH_STATE * hashState)
-{
- ecprintf("%s called\n", __func__);
- return TPM_ALG_ERROR;
-}
-
TPM_ECC_CURVE _cpri__GetCurveIdByIndex(
UINT16 i)
{
@@ -196,14 +179,6 @@ TPM_ECC_CURVE _cpri__GetCurveIdByIndex(
return TPM_ECC_NONE;
}
-UINT16 _cpri__GetDigestSize(
- TPM_ALG_ID hashAlg // IN: hash algorithm to look up
- )
-{
- ecprintf("%s called\n", __func__);
- return -1;
-}
-
CRYPT_RESULT _cpri__GetEphemeralEcc(
TPMS_ECC_POINT * Qout, // OUT: the public point
TPM2B_ECC_PARAMETER * dOut, // OUT: the private scalar
@@ -214,21 +189,6 @@ CRYPT_RESULT _cpri__GetEphemeralEcc(
return CRYPT_FAIL;
}
-LIB_EXPORT TPM_ALG_ID _cpri__GetHashAlgByIndex(
- UINT32 index) // IN: the index
-{
- ecprintf("%s called\n", __func__);
- return TPM_ALG_ERROR;
-}
-
-UINT16 _cpri__GetHashBlockSize(
- TPM_ALG_ID hashAlg // IN: hash algorithm to look up
- )
-{
- ecprintf("%s called\n", __func__);
- return -1;
-}
-
INT16 _cpri__GetSymmetricBlockSize(
TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm
UINT16 keySizeInBits // IN: the key size
@@ -238,28 +198,6 @@ INT16 _cpri__GetSymmetricBlockSize(
return -1;
}
-UINT16 _cpri__HashBlock(
- TPM_ALG_ID hashAlg, // IN: The hash algorithm
- UINT32 dataSize, // IN: size of buffer to hash
- BYTE * data, // IN: the buffer to hash
- UINT32 digestSize, // IN: size of the digest buffer
- BYTE * digest // OUT: hash digest
- )
-{
- ecprintf("%s called\n", __func__);
- return -1;
-}
-
-void _cpri__ImportExportHashState(
- CPRI_HASH_STATE * osslFmt, // IN/OUT: the hash state formated for use
- // by openSSL
- EXPORT_HASH_STATE * externalFmt, // IN/OUT: the exported hash state
- IMPORT_EXPORT direction //
- )
-{
- ecprintf("%s called\n", __func__);
-}
-
UINT16 _cpri__KDFa(
TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC
TPM2B * key, // IN: HMAC key
@@ -335,16 +273,6 @@ UINT16 _cpri__StartHMAC(
return -1;
}
-UINT16 _cpri__StartHash(
- TPM_ALG_ID hashAlg, // IN: hash algorithm
- BOOL sequence, // IN: TRUE if the state should be saved
- CPRI_HASH_STATE * hashState // OUT: the state of hash stack.
- )
-{
- ecprintf("%s called\n", __func__);
- return -1;
-}
-
BOOL _cpri__Startup(
void)
{
@@ -374,16 +302,6 @@ CRYPT_RESULT _cpri__TestKeyRSA(
return CRYPT_FAIL;
}
-void _cpri__UpdateHash(
- CPRI_HASH_STATE * hashState, // IN: the hash context information
- UINT32 dataSize, // IN: the size of data to be added
- // to the digest
- BYTE * data // IN: data to be hashed
- )
-{
- ecprintf("%s called\n", __func__);
-}
-
CRYPT_RESULT _cpri__ValidateSignatureEcc(
TPM2B_ECC_PARAMETER * rIn, // IN: r component of the signature
TPM2B_ECC_PARAMETER * sIn, // IN: s component of the signature
diff --git a/chip/g/build.mk b/chip/g/build.mk
index 45b4867fbd..4dc40cd556 100644
--- a/chip/g/build.mk
+++ b/chip/g/build.mk
@@ -24,7 +24,11 @@ chip-y += polling_uart.o
else
chip-y += uart.o
endif
-chip-y += dcrypto/aes.o
+
+chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o
+chip-$(CONFIG_DCRYPTO)+= dcrypto/sha1.o
+chip-$(CONFIG_DCRYPTO)+= dcrypto/sha256.o
+
chip-y+= pmu.o
chip-y+= trng.o
chip-$(CONFIG_SPS)+= sps.o
@@ -38,10 +42,11 @@ chip-$(CONFIG_USB_HID)+=usb_hid.o
chip-$(CONFIG_USB_BLOB)+=usb_blob.o
chip-$(CONFIG_FLASH)+=flash.o
+dirs-y += chip/g/dcrypto
ifneq ($(CONFIG_CUSTOMIZED_RO),)
custom-ro_objs-y = chip/g/clock.o
-custom-ro_objs-y += chip/g/loader/hw_sha256.o
+custom-ro_objs-y += chip/g/dcrypto/sha256.o
custom-ro_objs-y += chip/g/loader/key_ladder.o
custom-ro_objs-y += chip/g/loader/launch.o
custom-ro_objs-y += chip/g/loader/main.o
@@ -56,6 +61,7 @@ custom-ro_objs-y += common/printf.o
custom-ro_objs-y += common/util.o
custom-ro_objs-y += core/cortex-m/init.o
custom-ro_objs-y += core/cortex-m/panic.o
+dirs-y += chip/g/dcrypto
dirs-y += chip/g/loader
endif
diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h
index 1dab319392..7cafb224da 100644
--- a/chip/g/dcrypto/dcrypto.h
+++ b/chip/g/dcrypto/dcrypto.h
@@ -4,15 +4,15 @@
*/
/*
- * Crypto wrapper library for CR50.
+ * Crypto wrapper library for the g chip.
*/
-#ifndef EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_
-#define EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_
+#ifndef __EC_CHIP_G_DCRYPTO_DCRYPTO_H
+#define __EC_CHIP_G_DCRYPTO_DCRYPTO_H
/* TODO(vbendeb) don't forget to disable this for prod builds. */
#define CRYPTO_TEST_SETUP
-#include <inttypes.h>
+#include "internal.h"
enum cipher_mode {
CIPHER_MODE_ECB = 0,
@@ -26,6 +26,36 @@ enum encrypt_mode {
ENCRYPT_MODE = 1
};
+#define SHA1_DIGEST_BYTES 20
+#define SHA256_DIGEST_BYTES 32
+#define SHA384_DIGEST_BYTES 48
+#define SHA512_DIGEST_BYTES 64
+#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_BYTES
+
+#define SHA1_DIGEST_WORDS (SHA1_DIGEST_BYTES / sizeof(uint32_t))
+#define SHA256_DIGEST_WORDS (SHA256_DIGEST_BYTES / sizeof(uint32_t))
+#define SHA384_DIGEST_WORDS (SHA384_DIGEST_BYTES / sizeof(uint32_t))
+#define SHA512_DIGEST_WORDS (SHA512_DIGEST_BYTES / sizeof(uint32_t))
+
+struct HASH_CTX; /* Forward declaration. */
+
+typedef struct HASH_CTX SHA1_CTX;
+typedef struct HASH_CTX SHA256_CTX;
+
+#define DCRYPTO_HASH_update(ctx, data, len) \
+ ((ctx)->vtab->update((ctx), (data), (len)))
+#define DCRYPTO_HASH_final(ctx) \
+ ((ctx)->vtab->final((ctx)))
+#define DCRYPTO_HASH_size(ctx) \
+ ((ctx)->vtab->size)
+
+#define DCRYPTO_SHA1_update(ctx, data, n) \
+ DCRYPTO_HASH_update((ctx), (data), (n))
+#define DCRYPTO_SHA1_final(ctx) DCRYPTO_HASH_final((ctx))
+
+/*
+ * AES implementation, based on a hardware AES block.
+ */
int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv,
enum cipher_mode c_mode, enum encrypt_mode e_mode);
int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out);
@@ -33,4 +63,24 @@ int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out);
void DCRYPTO_aes_write_iv(const uint8_t *iv);
void DCRYPTO_aes_read_iv(uint8_t *iv);
-#endif /* ! EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ */
+/*
+ * 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 DCRYPTO_SHA1_init(SHA1_CTX *ctx, uint32_t sw_required);
+void DCRYPTO_SHA256_init(SHA256_CTX *ctx, uint32_t sw_required);
+const uint8_t *DCRYPTO_SHA1_hash(const uint8_t *data, uint32_t n,
+ uint8_t *digest);
+
+#define DCRYPTO_SHA256_update(ctx, data, n) \
+ DCRYPTO_HASH_update((ctx), (data), (n))
+#define DCRYPTO_SHA256_final(ctx) DCRYPTO_HASH_final((ctx))
+const uint8_t *DCRYPTO_SHA256_hash(const uint8_t *data, uint32_t n,
+ uint8_t *digest);
+
+#endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */
diff --git a/chip/g/dcrypto/internal.h b/chip/g/dcrypto/internal.h
index 5eb76ecc8a..279b2798e7 100644
--- a/chip/g/dcrypto/internal.h
+++ b/chip/g/dcrypto/internal.h
@@ -3,19 +3,43 @@
* found in the LICENSE file.
*/
-/*
- * Crypto wrapper library for CR50.
- */
-#ifndef EC_BOARD_CR50_DCRYPTO_INTERNAL_H_
-#define EC_BOARD_CR50_DCRYPTO_INTERNAL_H_
+#ifndef __EC_CHIP_G_DCRYPTO_INTERNAL_H
+#define __EC_CHIP_G_DCRYPTO_INTERNAL_H
+
+#include <inttypes.h>
#include "common.h"
+#include "sha1.h"
+#include "sha256.h"
#define CTRL_CTR_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define CTRL_ENABLE 1
#define CTRL_ENCRYPT 1
#define CTRL_NO_SOFT_RESET 0
+struct HASH_CTX; /* Forward declaration. */
+
+struct HASH_VTAB {
+ void (* const update)(struct HASH_CTX *, const uint8_t *, uint32_t);
+ const uint8_t *(* const final)(struct HASH_CTX *);
+ const uint8_t *(* const hash)(const uint8_t *, uint32_t, uint8_t *);
+ uint32_t size;
+};
+
+struct HASH_CTX {
+ const struct HASH_VTAB *vtab;
+ union {
+ uint8_t buf[64];
+ struct sha1_ctx sw_sha1;
+ struct sha256_ctx sw_sha256;
+ } u;
+};
+
+enum sha_mode {
+ SHA1_MODE = 0,
+ SHA256_MODE = 1
+};
+
/*
* Use this structure to avoid alignment problems with input and output
* pointers.
@@ -24,4 +48,15 @@ struct access_helper {
uint32_t udata;
} __packed;
-#endif /* ! EC_BOARD_CR50_DCRYPTO_INTERNAL_H_ */
+#ifndef SECTION_IS_RO
+int dcrypto_grab_sha_hw(void);
+void dcrypto_release_sha_hw(void);
+#endif
+void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data,
+ uint32_t n, uint8_t *digest);
+void dcrypto_sha_init(enum sha_mode mode);
+void dcrypto_sha_update(struct HASH_CTX *unused,
+ const uint8_t *data, uint32_t n);
+void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest);
+
+#endif /* ! __EC_CHIP_G_DCRYPTO_INTERNAL_H */
diff --git a/chip/g/dcrypto/sha1.c b/chip/g/dcrypto/sha1.c
new file mode 100644
index 0000000000..9721a9c2d9
--- /dev/null
+++ b/chip/g/dcrypto/sha1.c
@@ -0,0 +1,98 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "dcrypto.h"
+#include "internal.h"
+#include "registers.h"
+
+static void sw_sha1_init(SHA1_CTX *ctx);
+static void sw_sha1_update(SHA1_CTX *ctx, const uint8_t *data, uint32_t len);
+static const uint8_t *sw_sha1_final(SHA1_CTX *ctx);
+static const uint8_t *sha1_hash(const uint8_t *data, uint32_t len,
+ uint8_t *digest);
+static const uint8_t *dcrypto_sha1_final(SHA1_CTX *unused);
+
+/* Software SHA1 implementation. */
+static const struct HASH_VTAB SW_SHA1_VTAB = {
+ sw_sha1_update,
+ sw_sha1_final,
+ sha1_hash,
+ SHA1_DIGEST_BYTES
+};
+
+static void sw_sha1_init(SHA1_CTX *ctx)
+{
+ ctx->vtab = &SW_SHA1_VTAB;
+ sha1_init(&ctx->u.sw_sha1);
+}
+
+static void sw_sha1_update(SHA1_CTX *ctx, const uint8_t *data, uint32_t len)
+{
+ sha1_update(&ctx->u.sw_sha1, data, len);
+}
+
+static const uint8_t *sw_sha1_final(SHA1_CTX *ctx)
+{
+ return sha1_final(&ctx->u.sw_sha1);
+}
+
+static const uint8_t *sha1_hash(const uint8_t *data, uint32_t len,
+ uint8_t *digest)
+{
+ SHA1_CTX ctx;
+
+ sw_sha1_init(&ctx);
+ sw_sha1_update(&ctx, data, len);
+ memcpy(digest, sw_sha1_final(&ctx), SHA1_DIGEST_BYTES);
+ return digest;
+}
+
+
+/*
+ * Hardware SHA implementation.
+ */
+static const struct HASH_VTAB HW_SHA1_VTAB = {
+ dcrypto_sha_update,
+ dcrypto_sha1_final,
+ DCRYPTO_SHA1_hash,
+ SHA1_DIGEST_BYTES
+};
+
+/* Select and initialize either the software or hardware
+ * implementation. If "multi-threaded" behaviour is required, then
+ * callers must set sw_required to 1. This is because SHA1 state
+ * internal to the hardware cannot be extracted, so it is not possible
+ * to suspend and resume a hardware based SHA operation.
+ *
+ * If the caller has no preference as to implementation, then hardware
+ * is preferred based on availability. Hardware is considered to be
+ * in use between init() and finished() calls. */
+void DCRYPTO_SHA1_init(SHA1_CTX *ctx, uint32_t sw_required)
+{
+ if (!sw_required && dcrypto_grab_sha_hw()) {
+ ctx->vtab = &HW_SHA1_VTAB;
+ dcrypto_sha_init(SHA1_MODE);
+ } else {
+ sw_sha1_init(ctx);
+ }
+}
+
+static const uint8_t *dcrypto_sha1_final(SHA1_CTX *ctx)
+{
+ dcrypto_sha_wait(SHA1_MODE, (uint32_t *) ctx->u.buf);
+ return ctx->u.buf;
+}
+
+const uint8_t *DCRYPTO_SHA1_hash(const uint8_t *data, uint32_t n,
+ uint8_t *digest)
+{
+ if (dcrypto_grab_sha_hw())
+ /* dcrypto_sha_wait() will release the hw. */
+ dcrypto_sha_hash(SHA1_MODE, data, n, digest);
+ else
+ sha1_hash(data, n, digest);
+ return digest;
+}
+
diff --git a/chip/g/dcrypto/sha256.c b/chip/g/dcrypto/sha256.c
new file mode 100644
index 0000000000..19025f3503
--- /dev/null
+++ b/chip/g/dcrypto/sha256.c
@@ -0,0 +1,216 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "dcrypto.h"
+#include "internal.h"
+#include "registers.h"
+#include "util.h"
+
+static const uint8_t *dcrypto_sha256_final(SHA256_CTX *ctx);
+
+#ifdef SECTION_IS_RO
+/* RO is single threaded. */
+#define mutex_lock(x)
+#define mutex_unlock(x)
+static inline int dcrypto_grab_sha_hw(void)
+{
+ return 1;
+}
+static inline void dcrypto_release_sha_hw(void)
+{
+}
+#else
+#include "task.h"
+static struct mutex hw_busy_mutex;
+
+static void sha256_init(SHA256_CTX *ctx);
+static void sha256_update(SHA256_CTX *ctx, const uint8_t *data, uint32_t len);
+static const uint8_t *sha256_final(SHA256_CTX *ctx);
+static const uint8_t *sha256_hash(const uint8_t *data, uint32_t len,
+ uint8_t *digest);
+
+static const struct HASH_VTAB SW_SHA256_VTAB = {
+ sha256_update,
+ sha256_final,
+ sha256_hash,
+ SHA256_DIGEST_BYTES
+};
+
+static void sha256_init(SHA256_CTX *ctx)
+{
+ ctx->vtab = &SW_SHA256_VTAB;
+ SHA256_init(&ctx->u.sw_sha256);
+}
+
+static void sha256_update(SHA256_CTX *ctx, const uint8_t *data, uint32_t len)
+{
+ SHA256_update(&ctx->u.sw_sha256, data, len);
+}
+
+static const uint8_t *sha256_final(SHA256_CTX *ctx)
+{
+ return SHA256_final(&ctx->u.sw_sha256);
+}
+
+static const uint8_t *sha256_hash(const uint8_t *data, uint32_t len,
+ uint8_t *digest)
+{
+ SHA256_CTX ctx;
+
+ sha256_init(&ctx);
+ sha256_update(&ctx, data, len);
+ sha256_final(&ctx);
+
+ memcpy(digest, ctx.u.sw_sha256.buf, SHA256_DIGEST_WORDS);
+
+ return digest;
+}
+
+static int hw_busy;
+
+int dcrypto_grab_sha_hw(void)
+{
+ int rv = 0;
+
+ mutex_lock(&hw_busy_mutex);
+ if (!hw_busy) {
+ rv = 1;
+ hw_busy = 1;
+ }
+ mutex_unlock(&hw_busy_mutex);
+
+ return rv;
+}
+
+void dcrypto_release_sha_hw(void)
+{
+ mutex_lock(&hw_busy_mutex);
+ hw_busy = 0;
+ mutex_unlock(&hw_busy_mutex);
+}
+
+#endif /* ! SECTION_IS_RO */
+
+void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest)
+{
+ int i;
+ const int digest_len = (mode == SHA1_MODE) ?
+ SHA1_DIGEST_BYTES :
+ SHA256_DIGEST_BYTES;
+
+ /* Stop LIVESTREAM mode. */
+ GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_STOP, 1);
+ /* Wait for SHA DONE interrupt. */
+ while (!GREG32(KEYMGR, SHA_ITOP))
+ ;
+
+ /* Read out final digest. */
+ for (i = 0; i < digest_len / 4; ++i)
+ *digest++ = GR_KEYMGR_SHA_HASH(i);
+ dcrypto_release_sha_hw();
+}
+
+/* Hardware SHA implementation. */
+static const struct HASH_VTAB HW_SHA256_VTAB = {
+ dcrypto_sha_update,
+ dcrypto_sha256_final,
+ DCRYPTO_SHA256_hash,
+ SHA256_DIGEST_BYTES
+};
+
+void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data, uint32_t n,
+ uint8_t *digest)
+{
+ dcrypto_sha_init(mode);
+ dcrypto_sha_update(NULL, data, n);
+ dcrypto_sha_wait(mode, (uint32_t *) digest);
+}
+
+void dcrypto_sha_update(struct HASH_CTX *unused,
+ const uint8_t *data, uint32_t n)
+{
+ const uint8_t *bp = (const uint8_t *) data;
+ const uint32_t *wp;
+
+ /* Feed unaligned start bytes. */
+ while (n != 0 && ((uint32_t)bp & 3)) {
+ GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
+ n -= 1;
+ }
+
+ /* Feed groups of aligned words. */
+ wp = (uint32_t *)bp;
+ while (n >= 8*4) {
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ n -= 8*4;
+ }
+ /* Feed individual aligned words. */
+ while (n >= 4) {
+ GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
+ n -= 4;
+ }
+
+ /* Feed remaing bytes. */
+ bp = (uint8_t *) wp;
+ while (n != 0) {
+ GREG8(KEYMGR, SHA_INPUT_FIFO) = *bp++;
+ n -= 1;
+ }
+}
+
+void dcrypto_sha_init(enum sha_mode mode)
+{
+ /* Stop LIVESTREAM mode, in case final() was not called. */
+ GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_STOP, 1);
+ /* Clear interrupt status. */
+ GREG32(KEYMGR, SHA_ITOP) = 0;
+ /* SHA1 or SHA256 mode */
+ GWRITE_FIELD(KEYMGR, SHA_CFG_EN, SHA1, mode == SHA1_MODE ? 1 : 0);
+ /* Enable streaming mode. */
+ GWRITE_FIELD(KEYMGR, SHA_CFG_EN, LIVESTREAM, 1);
+ /* Enable the SHA DONE interrupt. */
+ GWRITE_FIELD(KEYMGR, SHA_CFG_EN, INT_EN_DONE, 1);
+ /* Start SHA engine. */
+ GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_GO, 1);
+}
+
+void DCRYPTO_SHA256_init(SHA256_CTX *ctx, uint32_t sw_required)
+{
+ if (!sw_required && dcrypto_grab_sha_hw()) {
+ ctx->vtab = &HW_SHA256_VTAB;
+ dcrypto_sha_init(SHA1_MODE);
+ }
+#ifndef SECTION_IS_RO
+ else
+ sha256_init(ctx);
+#endif
+}
+
+static const uint8_t *dcrypto_sha256_final(SHA256_CTX *ctx)
+{
+ dcrypto_sha_wait(SHA256_MODE, (uint32_t *) ctx->u.buf);
+ dcrypto_release_sha_hw();
+ return ctx->u.buf;
+}
+
+const uint8_t *DCRYPTO_SHA256_hash(const uint8_t *data, uint32_t n,
+ uint8_t *digest)
+{
+ if (dcrypto_grab_sha_hw())
+ /* dcrypto_sha_wait() will release the hw. */
+ dcrypto_sha_hash(SHA256_MODE, data, n, digest);
+#ifndef SECTION_IS_RO
+ else
+ sha256_hash(data, n, digest);
+#endif
+ return digest;
+}
diff --git a/chip/g/loader/hw_sha256.c b/chip/g/loader/hw_sha256.c
deleted file mode 100644
index fb930f7d17..0000000000
--- a/chip/g/loader/hw_sha256.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright 2015 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "debug_printf.h"
-#include "registers.h"
-#include "setup.h"
-
-static void _sha_write(const void *data, size_t n)
-{
- const uint8_t *bp = (const uint8_t *)data;
- const uint32_t *wp;
-
- while (n && ((uint32_t)bp & 3)) { /* Feed unaligned start bytes. */
- *((uint8_t *)GREG32_ADDR(KEYMGR, SHA_INPUT_FIFO)) = *bp++;
- n -= 1;
- }
-
- wp = (uint32_t *)bp;
- while (n >= 32) { /* Feed groups of aligned words. */
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- n -= 32;
- }
-
- while (n >= 4) { /* Feed individual aligned words. */
- GREG32(KEYMGR, SHA_INPUT_FIFO) = *wp++;
- n -= 4;
- }
-
- bp = (uint8_t *)wp;
- while (n) { /* Feed remaing bytes. */
- *((uint8_t *)GREG32_ADDR(KEYMGR, SHA_INPUT_FIFO)) = *bp++;
- n -= 1;
- }
-}
-
-static void _sha_wait(uint32_t *digest)
-{
- int i;
-
- /*
- * Wait for result. TODO: what harm does glitching do? Read out
- * non-digest? Old digest?
- */
- while (!GREG32(KEYMGR, SHA_ITOP))
- ;
-
- /* Read out final digest. */
- for (i = 0; i < 8; ++i)
- *digest++ = GREG32_ADDR(KEYMGR, SHA_STS_H0)[i];
-
- GREG32(KEYMGR, SHA_ITOP) = 0; /* Clear status. */
-}
-
-void hwSHA256(const void *data, size_t n, uint32_t *digest)
-{
- GREG32(KEYMGR, SHA_ITOP) = 0; /* Clear status. */
-
- GREG32(KEYMGR, SHA_CFG_MSGLEN_LO) = n;
- GREG32(KEYMGR, SHA_CFG_MSGLEN_HI) = 0;
-
- GWRITE_FIELD(KEYMGR, SHA_CFG_EN, INT_EN_DONE, 1);
- GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_GO, 1);
-
- _sha_write(data, n);
- _sha_wait(digest);
-}
diff --git a/chip/g/loader/hw_sha256.h b/chip/g/loader/hw_sha256.h
deleted file mode 100644
index b52af6f857..0000000000
--- a/chip/g/loader/hw_sha256.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2015 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef __EC_CHIP_G_LOADER_HW_SHA256_H
-#define __EC_CHIP_G_LOADER_HW_SHA256_H
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#define SHA256_DIGEST_BYTES 32
-#define SHA256_DIGEST_WORDS (SHA256_DIGEST_BYTES / sizeof(uint32_t))
-
-typedef struct {
- uint32_t digest[SHA256_DIGEST_WORDS];
-} hwSHA256_CTX;
-
-void hwSHA256_init(hwSHA256_CTX *ctx);
-void hwSHA256_update(hwSHA256_CTX *ctx, const void *data, size_t len);
-const uint8_t *hwSHA256_final(hwSHA256_CTX *ctx);
-
-void hwSHA256(const void *data, size_t len, uint32_t *digest);
-
-#endif /* __EC_CHIP_G_LOADER_HW_SHA256_H */
diff --git a/chip/g/loader/launch.c b/chip/g/loader/launch.c
index 5ef3ba8c62..3e41756ae9 100644
--- a/chip/g/loader/launch.c
+++ b/chip/g/loader/launch.c
@@ -3,8 +3,8 @@
* found in the LICENSE file.
*/
+#include "dcrypto.h"
#include "debug_printf.h"
-#include "hw_sha256.h"
#include "key_ladder.h"
#include "registers.h"
#include "rom_flash.h"
@@ -76,9 +76,9 @@ void tryLaunch(uint32_t adr, size_t max_size)
hdr->rx_max - hdr->rx_base - 1;
GWRITE_FIELD(GLOBALSEC, CPU0_I_STAGING_REGION1_CTRL, EN, 1);
GWRITE_FIELD(GLOBALSEC, CPU0_I_STAGING_REGION1_CTRL, RD_EN, 1);
- hwSHA256(&hdr->tag,
- hdr->image_size - offsetof(SignedHeader, tag),
- hashes.img_hash);
+ DCRYPTO_SHA256_hash((uint8_t *) &hdr->tag,
+ hdr->image_size - offsetof(SignedHeader, tag),
+ (uint8_t *) hashes.img_hash);
VERBOSE("img_hash : %.32h\n", hashes.img_hash);
@@ -102,7 +102,8 @@ void tryLaunch(uint32_t adr, size_t max_size)
}
}
- hwSHA256(fuses, sizeof(fuses), hashes.fuses_hash);
+ DCRYPTO_SHA256_hash((uint8_t *) fuses, sizeof(fuses),
+ (uint8_t *) hashes.fuses_hash);
VERBOSE("fuses_hash: %.32h\n", hashes.fuses_hash);
@@ -120,11 +121,13 @@ void tryLaunch(uint32_t adr, size_t max_size)
}
}
- hwSHA256(info, sizeof(info), hashes.info_hash);
+ DCRYPTO_SHA256_hash((uint8_t *) info, sizeof(info),
+ (uint8_t *) hashes.info_hash);
VERBOSE("info_hash : %.32h\n", hashes.info_hash);
/* Hash our set of hashes to get final hash. */
- hwSHA256(&hashes, sizeof(hashes), hash);
+ DCRYPTO_SHA256_hash((uint8_t *) &hashes, sizeof(hashes),
+ (uint8_t *) hash);
/*
* Write measured hash to unlock register to try and unlock execution.
diff --git a/chip/g/loader/verify.c b/chip/g/loader/verify.c
index d852f16c9a..6700ca8ca3 100644
--- a/chip/g/loader/verify.c
+++ b/chip/g/loader/verify.c
@@ -2,8 +2,9 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
+#include "dcrypto.h"
#include "debug_printf.h"
-#include "hw_sha256.h"
#include "registers.h"
#include "setup.h"
#include "trng.h"
@@ -181,7 +182,7 @@ void LOADERKEY_verify(uint32_t keyid, const uint32_t *signature,
VERBOSE("\nsig^ %.384h\n\n", buf);
/* Hash resulting buffer. */
- hwSHA256(buf, RSA_NUM_BYTES, hash);
+ DCRYPTO_SHA256_hash((uint8_t *) buf, RSA_NUM_BYTES, (uint8_t *) hash);
VERBOSE("hash %.32h\n", hash);
diff --git a/chip/g/registers.h b/chip/g/registers.h
index ccadca163f..7d3464b1fd 100644
--- a/chip/g/registers.h
+++ b/chip/g/registers.h
@@ -25,6 +25,8 @@
#define GOFFSET(mname, rname) \
GC_ ## mname ## _ ## rname ## _OFFSET
+#define GREG8(mname, rname) \
+ REG8(GBASE(mname) + GOFFSET(mname, rname))
#define GREG32(mname, rname) \
REG32(GBASE(mname) + GOFFSET(mname, rname))
#define GREG32_ADDR(mname, rname) \
@@ -332,6 +334,8 @@ static inline int x_timehs_addr(unsigned int module, unsigned int timer,
/* Key manager */
#define GR_KEYMGR_AES_KEY(n) REG32(GREG32_ADDR(KEYMGR, AES_KEY0) + (n))
#define GR_KEYMGR_AES_CTR(n) REG32(GREG32_ADDR(KEYMGR, AES_CTR0) + (n))
+#define GR_KEYMGR_SHA_HASH(n) REG32(GREG32_ADDR(KEYMGR, SHA_STS_H0) \
+ + (n))
/* USB device controller */
#define GR_USB_REG(off) REG32(GC_USB0_BASE_ADDR + (off))
diff --git a/common/build.mk b/common/build.mk
index b889b641f9..c7fd49a5f1 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -69,7 +69,7 @@ common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o
common-$(CONFIG_RSA)+=rsa.o
common-$(CONFIG_RWSIG)+=rwsig.o
common-$(CONFIG_MATH_UTIL)+=math_util.o
-common-$(CONFIG_SHA1)+=sha1.o
+common-$(CONFIG_SHA1)+= sha1.o
common-$(CONFIG_SHA256)+=sha256.o
common-$(CONFIG_SMBUS)+= smbus.o
common-$(CONFIG_SOFTWARE_CLZ)+=clz.o
diff --git a/include/config.h b/include/config.h
index 4c8c4a492c..6a63cd6adb 100644
--- a/include/config.h
+++ b/include/config.h
@@ -623,6 +623,11 @@
*/
#undef CONFIG_CUSTOMIZED_RO
+/*
+ * When enabled, build in support for hardware crypto; only supported on CR50.
+ */
+#undef CONFIG_DCRYPTO
+
/*****************************************************************************/
/*
* Debugging config