From 48e8e3faf082c18000bccd9c2af683a9d7600e7f Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Sun, 15 Jan 2017 11:43:10 -0800 Subject: g: move compute_frk2 function into dcrypto This function belongs in dcrypto as it relies heavily on the crypto hardware; also, it will be handy to be able to use this function in other cases. BRANCH=none BUG=chrome-os-partner:55331 TEST=buildall still builds. TPM manufacturing still works too. Change-Id: If2e70eaa71a76e8374b98f4667cb54ea6253b760 Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/428169 Reviewed-by: Marius Schilder --- board/cr50/tpm2/endorsement.c | 92 ++--------------------------------- chip/g/build.mk | 1 + chip/g/dcrypto/dcrypto.h | 7 +++ chip/g/dcrypto/key_ladder.c | 110 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 89 deletions(-) create mode 100644 chip/g/dcrypto/key_ladder.c diff --git a/board/cr50/tpm2/endorsement.c b/board/cr50/tpm2/endorsement.c index 3b4f0d99c6..617400edc0 100644 --- a/board/cr50/tpm2/endorsement.c +++ b/board/cr50/tpm2/endorsement.c @@ -39,7 +39,6 @@ #define EK_CERT_NV_START_INDEX 0x01C00000 #define INFO1_EPS_SIZE PRIMARY_SEED_SIZE #define INFO1_EPS_OFFSET FLASH_INFO_MANUFACTURE_STATE_OFFSET -#define AES256_BLOCK_CIPHER_KEY_SIZE 32 #define RO_CERTS_START_ADDR 0x43800 #define RO_CERTS_REGION_SIZE 0x0800 @@ -408,93 +407,6 @@ static int store_cert(enum cros_perso_component_type component_type, return 0; } -static uint32_t hw_key_ladder_step(uint32_t cert) -{ - uint32_t itop; - - GREG32(KEYMGR, SHA_ITOP) = 0; /* clear status */ - - GREG32(KEYMGR, SHA_USE_CERT_INDEX) = - (cert << GC_KEYMGR_SHA_USE_CERT_INDEX_LSB) | - GC_KEYMGR_SHA_USE_CERT_ENABLE_MASK; - - GREG32(KEYMGR, SHA_CFG_EN) = - GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK; - GREG32(KEYMGR, SHA_TRIG) = - GC_KEYMGR_SHA_TRIG_TRIG_GO_MASK; - - do { - itop = GREG32(KEYMGR, SHA_ITOP); - } while (!itop); - - GREG32(KEYMGR, SHA_ITOP) = 0; /* clear status */ - - return !!GREG32(KEYMGR, HKEY_ERR_FLAGS); -} - - -#define KEYMGR_CERT_0 0 -#define KEYMGR_CERT_3 3 -#define KEYMGR_CERT_4 4 -#define KEYMGR_CERT_5 5 -#define KEYMGR_CERT_7 7 -#define KEYMGR_CERT_15 15 -#define KEYMGR_CERT_20 20 -#define KEYMGR_CERT_25 25 -#define KEYMGR_CERT_26 26 - -#define K_CROS_FW_MAJOR_VERSION 0 -static const uint8_t k_cr50_max_fw_major_version = 254; - -static int compute_frk2(uint8_t frk2[AES256_BLOCK_CIPHER_KEY_SIZE]) -{ - int i; - - /* TODO(ngm): reading ITOP in hw_key_ladder_step hangs on - * second run of this function (i.e. install of ECC cert, - * which re-generates FRK2) unless the SHA engine is reset. - */ - GREG32(KEYMGR, SHA_TRIG) = - GC_KEYMGR_SHA_TRIG_TRIG_RESET_MASK; - - if (hw_key_ladder_step(KEYMGR_CERT_0)) - return 0; - - /* Derive HC_PHIK --> Deposited into ISR0 */ - if (hw_key_ladder_step(KEYMGR_CERT_3)) - return 0; - - /* Cryptographically mix OBS-FBS --> Deposited into ISR1 */ - if (hw_key_ladder_step(KEYMGR_CERT_4)) - return 0; - - /* Derive HIK_RT --> Deposited into ISR0 */ - if (hw_key_ladder_step(KEYMGR_CERT_5)) - return 0; - - /* Derive BL_HIK --> Deposited into ISR0 */ - if (hw_key_ladder_step(KEYMGR_CERT_7)) - return 0; - - /* Generate FRK2 by executing certs 15, 20, 25, and 26 */ - if (hw_key_ladder_step(KEYMGR_CERT_15)) - return 0; - - if (hw_key_ladder_step(KEYMGR_CERT_20)) - return 0; - - for (i = 0; i < k_cr50_max_fw_major_version - - K_CROS_FW_MAJOR_VERSION; i++) { - if (hw_key_ladder_step(KEYMGR_CERT_25)) - return 0; - } - if (hw_key_ladder_step(KEYMGR_CERT_26)) - return 0; - memcpy(frk2, (void *) GREG32_ADDR(KEYMGR, HKEY_FRR0), - AES256_BLOCK_CIPHER_KEY_SIZE); - return 1; -} - static void flash_info_read_enable(void) { /* Enable R access to INFO. */ @@ -523,6 +435,8 @@ static void flash_cert_region_enable(void) GC_GLOBALSEC_FLASH_REGION6_CTRL_RD_EN_MASK; } +#define K_CROS_FW_MAJOR_VERSION 0 + /* EPS is stored XOR'd with FRK2, so make sure that the sizes match. */ BUILD_ASSERT(AES256_BLOCK_CIPHER_KEY_SIZE == PRIMARY_SEED_SIZE); static int get_decrypted_eps(uint8_t eps[PRIMARY_SEED_SIZE]) @@ -531,7 +445,7 @@ static int get_decrypted_eps(uint8_t eps[PRIMARY_SEED_SIZE]) uint8_t frk2[AES256_BLOCK_CIPHER_KEY_SIZE]; CPRINTF("%s: getting eps\n", __func__); - if (!compute_frk2(frk2)) + if (!DCRYPTO_ladder_compute_frk2(K_CROS_FW_MAJOR_VERSION, frk2)) return 0; /* Setup flash region mapping. */ diff --git a/chip/g/build.mk b/chip/g/build.mk index a123bd173d..4a642ba59a 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -35,6 +35,7 @@ chip-$(CONFIG_DCRYPTO)+= dcrypto/compare.o chip-$(CONFIG_DCRYPTO)+= dcrypto/dcrypto_runtime.o chip-$(CONFIG_DCRYPTO)+= dcrypto/hkdf.o chip-$(CONFIG_DCRYPTO)+= dcrypto/hmac.o +chip-$(CONFIG_DCRYPTO)+= dcrypto/key_ladder.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ec.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ecies.o diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h index fdc03c1361..a5b38acdbc 100644 --- a/chip/g/dcrypto/dcrypto.h +++ b/chip/g/dcrypto/dcrypto.h @@ -42,6 +42,8 @@ enum hashing_mode { /* * AES implementation, based on a hardware AES block. */ +#define AES256_BLOCK_CIPHER_KEY_SIZE 32 + int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv, enum cipher_mode c_mode, enum encrypt_mode e_mode); int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out); @@ -199,4 +201,9 @@ int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, */ int DCRYPTO_equals(const void *a, const void *b, size_t len); +/* + * Key ladder related functions. + */ +int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2); + #endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */ diff --git a/chip/g/dcrypto/key_ladder.c b/chip/g/dcrypto/key_ladder.c new file mode 100644 index 0000000000..d58b961f53 --- /dev/null +++ b/chip/g/dcrypto/key_ladder.c @@ -0,0 +1,110 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "dcrypto.h" +#include "internal.h" +#include "endian.h" +#include "registers.h" + +void DCRYPTO_ladder_init(void) +{ + /* Do not reset keyladder engine here, as before. + * + * Should not be needed and if it is, it is indicative + * of sync error between this and sha engine usage. + * Reset will make this flow work, but will have broken + * the other pending sha flow. + * Hence leave as is and observe the error. + * + * TODO: hw sha engine usage and keyladder usage cannot + * interleave and should share a semaphore. + */ +} + +int DCRYPTO_ladder_step(uint32_t cert) +{ + uint32_t itop; + + GREG32(KEYMGR, SHA_ITOP) = 0; /* clear status */ + + GREG32(KEYMGR, SHA_USE_CERT_INDEX) = + (cert << GC_KEYMGR_SHA_USE_CERT_INDEX_LSB) | + GC_KEYMGR_SHA_USE_CERT_ENABLE_MASK; + + GREG32(KEYMGR, SHA_CFG_EN) = + GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK; + GREG32(KEYMGR, SHA_TRIG) = + GC_KEYMGR_SHA_TRIG_TRIG_GO_MASK; + + do { + itop = GREG32(KEYMGR, SHA_ITOP); + } while (!itop); + + GREG32(KEYMGR, SHA_ITOP) = 0; /* clear status */ + + return !!GREG32(KEYMGR, HKEY_ERR_FLAGS); +} + +static int compute_certs(const uint32_t *certs, size_t num_certs) +{ + int i; + + for (i = 0; i < num_certs; i++) { + if (DCRYPTO_ladder_step(certs[i])) + return 0; + } + + return 1; +} + +#define KEYMGR_CERT_0 0 +#define KEYMGR_CERT_3 3 +#define KEYMGR_CERT_4 4 +#define KEYMGR_CERT_5 5 +#define KEYMGR_CERT_7 7 +#define KEYMGR_CERT_15 15 +#define KEYMGR_CERT_20 20 +#define KEYMGR_CERT_25 25 +#define KEYMGR_CERT_26 26 + +static const uint32_t FRK2_CERTS_PREFIX[] = { + KEYMGR_CERT_0, + KEYMGR_CERT_3, + KEYMGR_CERT_4, + KEYMGR_CERT_5, + KEYMGR_CERT_7, + KEYMGR_CERT_15, + KEYMGR_CERT_20, +}; + +static const uint32_t FRK2_CERTS_POSTFIX[] = { + KEYMGR_CERT_26, +}; + +#define MAX_MAJOR_FW_VERSION 254 + +int DCRYPTO_ladder_compute_frk2(size_t fw_version, uint8_t *frk2) +{ + int i; + + if (fw_version > MAX_MAJOR_FW_VERSION) + return 0; + + DCRYPTO_ladder_init(); + + if (!compute_certs(FRK2_CERTS_PREFIX, ARRAY_SIZE(FRK2_CERTS_PREFIX))) + return 0; + + for (i = 0; i < MAX_MAJOR_FW_VERSION - fw_version; i++) { + if (DCRYPTO_ladder_step(KEYMGR_CERT_25)) + return 0; + } + + if (!compute_certs(FRK2_CERTS_POSTFIX, ARRAY_SIZE(FRK2_CERTS_POSTFIX))) + return 0; + + memcpy(frk2, (void *) GREG32_ADDR(KEYMGR, HKEY_FRR0), + AES256_BLOCK_CIPHER_KEY_SIZE); + return 1; +} -- cgit v1.2.1