diff options
-rw-r--r-- | board/cr50/build.mk | 4 | ||||
-rw-r--r-- | board/cr50/dcrypto/aes.c | 119 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto.h | 33 | ||||
-rw-r--r-- | board/cr50/dcrypto/internal.h | 20 | ||||
-rw-r--r-- | board/cr50/tpm2/aes.c | 252 | ||||
-rw-r--r-- | board/cr50/tpm2/stubs.c | 115 | ||||
-rw-r--r-- | chip/g/registers.h | 4 |
7 files changed, 433 insertions, 114 deletions
diff --git a/board/cr50/build.mk b/board/cr50/build.mk index f2e547fba9..7cdc079bde 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -22,12 +22,16 @@ else all: hex # The simulator components have their own subdirectory +CFLAGS += -I$(realpath $(BDIR)/dcrypto) CFLAGS += -I$(realpath $(BDIR)/tpm2) +dirs-y += $(BDIR)/dcrypto dirs-y += $(BDIR)/tpm2 # Objects that we need to build board-y = board.o +board-y += dcrypto/aes.o board-y += tpm2/NVMem.o +board-y += tpm2/aes.o board-y += tpm2/platform.o board-y += tpm2/stubs.o diff --git a/board/cr50/dcrypto/aes.c b/board/cr50/dcrypto/aes.c new file mode 100644 index 0000000000..86e31fcca4 --- /dev/null +++ b/board/cr50/dcrypto/aes.c @@ -0,0 +1,119 @@ +/* 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 set_control_register( + unsigned mode, unsigned key_size, unsigned encrypt) +{ + GWRITE_FIELD(KEYMGR, AES_CTRL, RESET, CTRL_NO_SOFT_RESET); + GWRITE_FIELD(KEYMGR, AES_CTRL, KEYSIZE, key_size); + GWRITE_FIELD(KEYMGR, AES_CTRL, CIPHER_MODE, mode); + GWRITE_FIELD(KEYMGR, AES_CTRL, ENC_MODE, encrypt); + GWRITE_FIELD(KEYMGR, AES_CTRL, CTR_ENDIAN, CTRL_CTR_BIG_ENDIAN); + GWRITE_FIELD(KEYMGR, AES_CTRL, ENABLE, CTRL_ENABLE); +} + +static int wait_read_data(volatile uint32_t *addr) +{ + int empty; + int count = 20; /* Wait these many ~cycles. */ + + do { + empty = REG32(addr); + count--; + } while (count && empty); + + return empty ? 0 : 1; +} + +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 i; + const uint32_t *p; + uint32_t key_mode; + + switch (key_len) { + case 128: + key_mode = 0; + break; + case 192: + key_mode = 1; + break; + case 256: + key_mode = 2; + break; + default: + /* Invalid key length specified. */ + return 0; + } + set_control_register(c_mode, key_mode, e_mode); + + /* Initialize hardware with AES key */ + p = (uint32_t *) key; + for (i = 0; i < (key_len >> 5); i++) + GR_KEYMGR_AES_KEY(i) = p[i]; + /* Trigger key expansion. */ + GREG32(KEYMGR, AES_KEY_START) = 1; + + /* Wait for key expansion. */ + if (!wait_read_data(GREG32_ADDR(KEYMGR, AES_KEY_START))) { + /* Should not happen. */ + return 0; + } + + /* Initialize IV for modes that require it. */ + if (iv) { + p = (uint32_t *) iv; + for (i = 0; i < 4; i++) + GR_KEYMGR_AES_CTR(i) = p[i]; + } + return 1; +} + +int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out) +{ + int i; + uint32_t *outw; + const uint32_t *inw = (const uint32_t *) in; + + /* Write plaintext. */ + for (i = 0; i < 4; i++) + GREG32(KEYMGR, AES_WFIFO_DATA) = inw[i]; + + /* Wait for the result. */ + if (!wait_read_data(GREG32_ADDR(KEYMGR, AES_RFIFO_EMPTY))) { + /* Should not happen, ciphertext not ready. */ + return 0; + } + + /* Read ciphertext. */ + outw = (uint32_t *) out; + for (i = 0; i < 4; i++) + outw[i] = GREG32(KEYMGR, AES_RFIFO_DATA); + return 1; +} + +void DCRYPTO_aes_write_iv(const uint8_t *iv) +{ + int i; + const uint32_t *p = (const uint32_t *) iv; + + for (i = 0; i < 4; i++) + GR_KEYMGR_AES_CTR(i) = p[i]; +} + +void DCRYPTO_aes_read_iv(uint8_t *iv) +{ + int i; + uint32_t *p = (uint32_t *) iv; + + for (i = 0; i < 4; i++) + p[i] = GR_KEYMGR_AES_CTR(i); +} diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h new file mode 100644 index 0000000000..9add80cce0 --- /dev/null +++ b/board/cr50/dcrypto/dcrypto.h @@ -0,0 +1,33 @@ +/* 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. + */ + +/* + * Crypto wrapper library for CR50. + */ +#ifndef EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ +#define EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ + +#include <inttypes.h> + +enum cipher_mode { + CIPHER_MODE_ECB = 0, + CIPHER_MODE_CTR = 1, + CIPHER_MODE_CBC = 2, + CIPHER_MODE_GCM = 3 +}; + +enum encrypt_mode { + DECRYPT_MODE = 0, + ENCRYPT_MODE = 1 +}; + +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); + +void DCRYPTO_aes_write_iv(const uint8_t *iv); +void DCRYPTO_aes_read_iv(uint8_t *iv); + +#endif /* ! EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ */ diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h new file mode 100644 index 0000000000..11f5c9a35d --- /dev/null +++ b/board/cr50/dcrypto/internal.h @@ -0,0 +1,20 @@ +/* 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. + */ + +/* + * Crypto wrapper library for CR50. + */ +#ifndef EC_BOARD_CR50_DCRYPTO_INTERNAL_H_ +#define EC_BOARD_CR50_DCRYPTO_INTERNAL_H_ + +#include "registers.h" +#include <inttypes.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 + +#endif /* ! EC_BOARD_CR50_DCRYPTO_INTERNAL_H_ */ diff --git a/board/cr50/tpm2/aes.c b/board/cr50/tpm2/aes.c new file mode 100644 index 0000000000..e8ef12bcf7 --- /dev/null +++ b/board/cr50/tpm2/aes.c @@ -0,0 +1,252 @@ +/* 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 "dcrypto.h" + +#include <assert.h> +#include <string.h> + +static CRYPT_RESULT _cpri__AESBlock( + uint8_t *out, uint32_t len, uint8_t *in); + + +CRYPT_RESULT _cpri__AESDecryptCBC( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint8_t *iv, + uint32_t len, uint8_t *in) +{ + CRYPT_RESULT result; + + if (len == 0) + return CRYPT_SUCCESS; + assert(key != NULL && iv != NULL && in != NULL && out != NULL); + assert(len <= INT32_MAX); + if (!DCRYPTO_aes_init(key, num_bits, iv, CIPHER_MODE_CBC, DECRYPT_MODE)) + return CRYPT_PARAMETER; + + result = _cpri__AESBlock(out, len, in); + if (result != CRYPT_SUCCESS) + return result; + + DCRYPTO_aes_read_iv(iv); + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESDecryptCFB(uint8_t *out, uint32_t num_bits, + uint8_t *key, uint8_t *iv, uint32_t len, + uint8_t *in) +{ + uint8_t *ivp = NULL; + int i; + int32_t slen; + + if (len == 0) + return CRYPT_SUCCESS; + + assert(key != NULL && iv != NULL && out != NULL && in != NULL); + assert(len <= INT32_MAX); + slen = (int32_t) len; + /* Initialize AES hardware. */ + if (!DCRYPTO_aes_init(key, num_bits, iv, CIPHER_MODE_CTR, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + + for (; slen > 0; slen -= 16) { + uint8_t tmpin[16]; + uint8_t tmpout[16]; + const uint8_t *inp; + uint8_t *outp; + + if (slen < 16) { + memcpy(tmpin, in, slen); + inp = tmpin; + outp = tmpout; + } else { + inp = in; + outp = out; + } + DCRYPTO_aes_block(inp, outp); + if (outp != out) + memcpy(out, outp, slen); + + ivp = iv; + for (i = (slen < 16) ? slen : 16; i > 0; i--) { + *ivp++ = *in++; + out++; + } + DCRYPTO_aes_write_iv(iv); + } + /* If the inner loop (i loop) was smaller than 16, then slen + * would have been smaller than 16 and it is now negative + * If it is negative, then it indicates how may fill bytes + * are needed to pad out the IV for the next round. */ + for (; slen < 0; slen++) + *ivp++ = 0; + + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESDecryptECB( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint32_t len, + uint8_t *in) +{ + assert(key != NULL); + /* Initialize AES hardware. */ + if (!DCRYPTO_aes_init(key, num_bits, NULL, + CIPHER_MODE_ECB, DECRYPT_MODE)) + return CRYPT_PARAMETER; + return _cpri__AESBlock(out, len, in); +} + +static CRYPT_RESULT _cpri__AESBlock( + uint8_t *out, uint32_t len, uint8_t *in) +{ + int32_t slen; + + assert(out != NULL && in != NULL && len > 0 && len <= INT32_MAX); + slen = (int32_t) len; + if ((slen % 16) != 0) + return CRYPT_PARAMETER; + + for (; slen > 0; slen -= 16) { + DCRYPTO_aes_block(in, out); + in = &in[16]; + out = &out[16]; + } + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESEncryptCBC( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint8_t *iv, + uint32_t len, uint8_t *in) +{ + CRYPT_RESULT result; + + assert(key != NULL && iv != NULL); + if (!DCRYPTO_aes_init(key, num_bits, iv, CIPHER_MODE_CBC, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + + result = _cpri__AESBlock(out, len, in); + if (result != CRYPT_SUCCESS) + return result; + + DCRYPTO_aes_read_iv(iv); + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESEncryptCFB( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint8_t *iv, + uint32_t len, uint8_t *in) +{ + uint8_t *ivp = NULL; + int32_t slen; + int i; + + if (len == 0) + return CRYPT_SUCCESS; + + assert(out != NULL && key != NULL && iv != NULL && in != NULL); + assert(len <= INT32_MAX); + slen = (int32_t) len; + if (!DCRYPTO_aes_init(key, num_bits, iv, CIPHER_MODE_CTR, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + + for (; slen > 0; slen -= 16) { + DCRYPTO_aes_block(in, out); + ivp = iv; + for (i = slen < 16 ? slen : 16; i > 0; i--) { + *ivp++ = *out++; + in++; + } + DCRYPTO_aes_write_iv(iv); + } + /* If the inner loop (i loop) was smaller than 16, then slen + * would have been smaller than 16 and it is now negative. If + * it is negative, then it indicates how many bytes are needed + * to pad out the IV for the next round. */ + for (; slen < 0; slen++) + *ivp++ = 0; + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESEncryptCTR( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint8_t *iv, + uint32_t len, uint8_t *in) +{ + int32_t slen; + + if (len == 0) + return CRYPT_SUCCESS; + + assert(out != NULL && key != NULL && iv != NULL && in != NULL); + assert(len <= INT32_MAX); + slen = (int32_t) len; + /* Initialize AES hardware. */ + if (!DCRYPTO_aes_init(key, num_bits, iv, + CIPHER_MODE_CTR, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + + for (; slen > 0; slen -= 16) { + uint8_t tmpin[16]; + uint8_t tmpout[16]; + uint8_t *inp; + uint8_t *outp; + + if (slen < 16) { + memcpy(tmpin, in, slen); + inp = tmpin; + outp = tmpout; + } else { + inp = in; + outp = out; + } + DCRYPTO_aes_block(inp, outp); + if (outp != out) + memcpy(out, outp, (slen < 16) ? slen : 16); + + in += 16; + out += 16; + } + return CRYPT_SUCCESS; +} + +CRYPT_RESULT _cpri__AESEncryptECB( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint32_t len, + uint8_t *in) +{ + assert(key != NULL); + /* Initialize AES hardware. */ + if (!DCRYPTO_aes_init(key, num_bits, NULL, + CIPHER_MODE_ECB, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + return _cpri__AESBlock(out, len, in); +} + +CRYPT_RESULT _cpri__AESEncryptOFB( + uint8_t *out, uint32_t num_bits, uint8_t *key, uint8_t *iv, + uint32_t len, uint8_t *in) +{ + uint8_t *ivp; + int32_t slen; + int i; + + if (len == 0) + return CRYPT_SUCCESS; + + assert(out != NULL && key != NULL && iv != NULL && in != NULL); + assert(len <= INT32_MAX); + slen = (int32_t) len; + /* Initialize AES hardware. */ + if (!DCRYPTO_aes_init(key, num_bits, NULL, + CIPHER_MODE_ECB, ENCRYPT_MODE)) + return CRYPT_PARAMETER; + + for (; slen > 0; slen -= 16) { + DCRYPTO_aes_block(iv, iv); + ivp = iv; + for (i = (slen < 16) ? slen : 16; i > 0; i--) + *out++ = (*ivp++ ^ *in++); + } + return CRYPT_SUCCESS; +} diff --git a/board/cr50/tpm2/stubs.c b/board/cr50/tpm2/stubs.c index 7b6a3a8faf..b723c529b9 100644 --- a/board/cr50/tpm2/stubs.c +++ b/board/cr50/tpm2/stubs.c @@ -4,120 +4,7 @@ */ #include "Global.h" -#include "_TPM_Init_fp.h" -#include "CryptoEngine.h" - - -CRYPT_RESULT _cpri__AESDecryptCBC( - BYTE * dOut, // OUT: the decrypted data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. The size of this - // buffer is 16 byte - UINT32 dInSize, // IN: data size - BYTE * dIn) // IN: data buffer -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESDecryptCFB( - BYTE * dOut, // OUT: the decrypted data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. - UINT32 dInSize, // IN: data size - BYTE * dIn) // IN: data buffer -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESDecryptECB( - BYTE * dOut, // OUT: the clear text data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - UINT32 dInSize, // IN: data size - BYTE * dIn // IN: cipher text buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESEncryptCBC( - BYTE * dOut, // OUT: - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. - UINT32 dInSize, // IN: data size (is required to be a multiple - // of 16 bytes) - BYTE * dIn // IN: data buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESEncryptCFB( - BYTE * dOut, // OUT: the encrypted - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. - UINT32 dInSize, // IN: data size - BYTE * dIn // IN: data buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESEncryptCTR( - BYTE * dOut, // OUT: the encrypted data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. - UINT32 dInSize, // IN: data size - BYTE * dIn // IN: data buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESEncryptECB( - BYTE * dOut, // OUT: encrypted data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - UINT32 dInSize, // IN: data size - BYTE * dIn // IN: clear text buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} - -CRYPT_RESULT _cpri__AESEncryptOFB( - BYTE * dOut, // OUT: the encrypted/decrypted data - UINT32 keySizeInBits, // IN: key size in bit - BYTE * key, // IN: key buffer. The size of this buffer in - // bytes is (keySizeInBits + 7) / 8 - BYTE * iv, // IN/OUT: IV for decryption. The size of this - // buffer is 16 byte - UINT32 dInSize, // IN: data size - BYTE * dIn // IN: data buffer - ) -{ - ecprintf("%s called\n", __func__); - return CRYPT_FAIL; -} +#include "CryptoEngine.h" CRYPT_RESULT _cpri__C_2_2_KeyExchange( TPMS_ECC_POINT * outZ1, // OUT: a computed point diff --git a/chip/g/registers.h b/chip/g/registers.h index 501079fcb4..88e0a6aa7b 100644 --- a/chip/g/registers.h +++ b/chip/g/registers.h @@ -329,6 +329,10 @@ static inline int x_timehs_addr(unsigned int module, unsigned int timer, #define GR_XO_OSC_SETHOLD REG32(GC_XO0_BASE_ADDR + GC_XO_OSC_SETHOLD_OFFSET) #define GR_XO_OSC_CLRHOLD REG32(GC_XO0_BASE_ADDR + GC_XO_OSC_CLRHOLD_OFFSET) +/* 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)) + /* USB device controller */ #define GR_USB_REG(off) REG32(GC_USB0_BASE_ADDR + (off)) #define GR_USB_GAHBCFG GR_USB_REG(GC_USB_GAHBCFG_OFFSET) |