From 7d2e4fbf5ba0c27f5d84bfa321bd857dbd7c33ff Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Sun, 22 Jan 2017 21:25:42 -0800 Subject: g: common: introduce generic crypto API On boards based on the g chip cryptographic functions come from hardware, they should be implemented in chip/g as opposed to a particular board. The common modules (like nvmem) should be using some generic API, which hopefully will be implemented by other chips, or could be replaced by a purely software implementation where crypto hardware support is not available. Crypto API definition is being added in include/ and the g chip implementation (a wrapper around dcrypto functions) is being added in chip/g. test/nvmem_vars.h needed to be edited to avoid conflict with . BRANCH=none BUG=chrome-os-partner:62260 TEST=make buildall -j still passes. Booting reef with the new image works fine too. Change-Id: Ifef281215f89239966882ecbe3e90c8351b9b91a Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/431313 Reviewed-by: Randall Spangler Reviewed-by: Nagendra Modadugu --- board/cr50/board.c | 15 ------------- chip/g/build.mk | 2 ++ chip/g/crypto_api.c | 31 +++++++++++++++++++++++++++ chip/g/dcrypto/dcrypto.h | 3 +++ common/nvmem.c | 29 +++++++++++++------------ include/crypto_api.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ include/nvmem.h | 13 ++---------- test/nvmem.c | 11 ++++++---- test/nvmem_vars.c | 2 -- 9 files changed, 116 insertions(+), 45 deletions(-) create mode 100644 chip/g/crypto_api.c create mode 100644 include/crypto_api.h diff --git a/board/cr50/board.c b/board/cr50/board.c index b7ce1704c7..c1e35eabd9 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -652,21 +652,6 @@ int is_ec_rst_asserted(void) return GREAD(RBOX, ASSERT_EC_RST); } -void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, - uint8_t *p_sha, int sha_len) -{ - uint8_t sha1_digest[SHA_DIGEST_SIZE]; - /* - * Taking advantage of the built in dcrypto engine to generate - * a CRC-like value that can be used to validate contents of an - * NvMem partition. Only using the lower 4 bytes of the sha1 hash. - */ - DCRYPTO_SHA1_hash((uint8_t *)p_buf, - num_bytes, - sha1_digest); - memcpy(p_sha, sha1_digest, sha_len); -} - static int device_state_changed(enum device_type device, enum device_state state) { diff --git a/chip/g/build.mk b/chip/g/build.mk index 8d226275f3..f52efee865 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -28,6 +28,8 @@ chip-y += uart.o chip-y += uartn.o endif +chip-$(CONFIG_DCRYPTO)+= crypto_api.o + chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o chip-$(CONFIG_DCRYPTO)+= dcrypto/app_cipher.o chip-$(CONFIG_DCRYPTO)+= dcrypto/app_key.o diff --git a/chip/g/crypto_api.c b/chip/g/crypto_api.c new file mode 100644 index 0000000000..a3854eba8c --- /dev/null +++ b/chip/g/crypto_api.c @@ -0,0 +1,31 @@ +/* + * Copyright 2017 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 "crypto_api.h" +#include "dcrypto.h" + +void app_compute_hash(uint8_t *p_buf, size_t num_bytes, + uint8_t *p_hash, size_t hash_len) +{ + uint8_t sha1_digest[SHA_DIGEST_SIZE]; + + /* + * Use the built in dcrypto engine to generate the sha1 hash of the + * buffer. + */ + DCRYPTO_SHA1_hash((uint8_t *)p_buf, num_bytes, sha1_digest); + + memcpy(p_hash, sha1_digest, MIN(hash_len, sizeof(sha1_digest))); + + if (hash_len > sizeof(sha1_digest)) + memset(p_hash + sizeof(sha1_digest), 0, + hash_len - sizeof(sha1_digest)); +} + +int app_cipher(const void *salt, void *out, const void *in, size_t size) +{ + return DCRYPTO_app_cipher(salt, out, in, size); +} diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h index 3f018d48e4..58f45ddcc9 100644 --- a/chip/g/dcrypto/dcrypto.h +++ b/chip/g/dcrypto/dcrypto.h @@ -15,6 +15,8 @@ #include "internal.h" +#include "crypto_api.h" + #include #include "cryptoc/hmac.h" @@ -219,6 +221,7 @@ void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx); /* Number of bytes in the salt object. */ #define DCRYPTO_CIPHER_SALT_SIZE 16 +BUILD_ASSERT(DCRYPTO_CIPHER_SALT_SIZE == CIPHER_SALT_SIZE); /* * Encrypt/decrypt a flat blob. diff --git a/common/nvmem.c b/common/nvmem.c index 3358ad5b3a..3251ed8e94 100644 --- a/common/nvmem.c +++ b/common/nvmem.c @@ -48,6 +48,18 @@ static int nvmem_error_state; /* Flag to track if an Nv write/move is not completed */ static int nvmem_write_error; +/* + * Given the nvmem tag address calculate the sha value of the nvmem buffer and + * save it in the provided space. The caller is expected to provide enough + * space to store CIPHER_SALT_SIZE bytes. + */ +static void nvmem_compute_sha(struct nvmem_tag *tag, void *sha_buf) +{ + app_compute_hash(&tag->generation, + NVMEM_PARTITION_SIZE - NVMEM_SHA_SIZE, + sha_buf, sizeof(tag->sha)); +} + static int nvmem_save(uint8_t tag_generation, size_t partition) { struct nvmem_tag *tag; @@ -67,11 +79,7 @@ static int nvmem_save(uint8_t tag_generation, size_t partition) tag->generation = tag_generation; /* Calculate sha of the whole thing. */ - nvmem_compute_sha(&tag->generation, - NVMEM_PARTITION_SIZE - - offsetof(struct nvmem_tag, generation), - tag->sha, - sizeof(tag->sha)); + nvmem_compute_sha(tag, tag->sha); /* Write partition */ if (flash_physical_write(nvmem_offset, @@ -90,9 +98,7 @@ static int nvmem_partition_sha_match(int index) struct nvmem_partition *p_part; p_part = (struct nvmem_partition *)nvmem_base_addr[index]; - nvmem_compute_sha(&p_part->tag.generation, - (NVMEM_PARTITION_SIZE - NVMEM_SHA_SIZE), - sha_comp, sizeof(sha_comp)); + nvmem_compute_sha(&p_part->tag, sha_comp); /* Check if computed value matches stored value. */ return !memcmp(p_part->tag.sha, sha_comp, NVMEM_SHA_SIZE); @@ -342,11 +348,8 @@ int nvmem_setup(uint8_t starting_generation) /* Commit function will increment generation number */ p_part->tag.generation = starting_generation + part - 1; /* Compute sha for the partition */ - nvmem_compute_sha(&cache.base_ptr[NVMEM_SHA_SIZE], - NVMEM_PARTITION_SIZE - - NVMEM_SHA_SIZE, - p_part->tag.sha, - NVMEM_SHA_SIZE); + nvmem_compute_sha(&p_part->tag, p_part->tag.sha); + /* Partition is now ready, write it to flash. */ ret = nvmem_commit(); if (ret != EC_SUCCESS) diff --git a/include/crypto_api.h b/include/crypto_api.h new file mode 100644 index 0000000000..2628e2bd7b --- /dev/null +++ b/include/crypto_api.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 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 __INCLUDE_CRYPTO_API_H +#define __INCLUDE_CRYPTO_API_H + +#include "util.h" + +/** + * Calculate hash of an arbitrary data + * + * Up to SHA_DIGEST_SIZE byte hash can be generated, if hash_len is + * longer - it is padded with zeros. + * + * @param p_buf: pointer to beginning of data + * @param num_bytes: length of data in bytes + * @param p_hash: pointer to where computed hash will be stored + * @param hash_len: length in bytes to use from sha computation. If this + * value exceeds SHA1 size (20 bytes), the rest of the + * hash is filled up with zeros. + */ +void app_compute_hash(uint8_t *p_buf, size_t num_bytes, + uint8_t *p_hash, size_t hash_len); + +#define CIPHER_SALT_SIZE 16 + +/* + * Encrypt/decrypt a flat blob. + * + * Encrypt or decrypt the input buffer, and write the correspondingly + * ciphered output to out. The number of bytes produced is equal to + * the number of input bytes. + * + * This API is expected to be applied to a single contiguous region. WARNING: + * Presently calling this function more than once with "in" pointing to + * logically different buffers will result in using the same IV value + * internally and as such reduce encryption efficiency. + * + * @param salt pointer to a unique value to be associated with this blob, + * used for derivation of the proper IV, the size of this value + * is as defined by CIPHER_SALT_SIZE above. + * WARNING: a given salt/"in" pair must be unique (it is an ERROR + * to use a given salt with more than one unique buffer). For an + * example, a good salt would be a digest of the plaintext input. + * @param out Destination pointer where to write plaintext / ciphertext. + * @param in Source pointer where to read ciphertext / plaintext. + * @param len Number of bytes to read from in / write to out. + * @return non-zero on success, and zero otherwise. + */ +int app_cipher(const void *salt, void *out, const void *in, size_t size); + +#endif /* __INCLUDE_CRYPTO_API_H */ diff --git a/include/nvmem.h b/include/nvmem.h index 9bbf851a75..536548fc4c 100644 --- a/include/nvmem.h +++ b/include/nvmem.h @@ -6,6 +6,8 @@ #ifndef __CROS_EC_NVMEM_UTILS_H #define __CROS_EC_NVMEM_UTILS_H +#include "crypto_api.h" + /* * In order to provide maximum robustness for NvMem operations, the NvMem space * is divided into two equal sized partitions. A partition contains a tag @@ -166,17 +168,6 @@ int nvmem_commit(void); */ int nvmem_setup(uint8_t generation); -/** - * Compute sha1 (lower 4 bytes or equivalent checksum) for NvMem tag - * - * @param p_buf: pointer to beginning of data - * @param num_bytes: length of data in bytes - * @param p_sha: pointer to where computed sha will be stored - * @param sha_len: length in bytes to use from sha computation - */ -void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha, - int sha_len); - /* * Temporarily stopping NVMEM commits could be beneficial. One use case is * when TPM operations need to be sped up. diff --git a/test/nvmem.c b/test/nvmem.c index 5ed33f3445..3366f8e862 100644 --- a/test/nvmem.c +++ b/test/nvmem.c @@ -30,8 +30,8 @@ static uint8_t read_buffer[NVMEM_PARTITION_SIZE]; static int flash_write_fail; static int lock_test_started; -void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha, - int sha_bytes) +void app_compute_hash(uint8_t *p_buf, size_t num_bytes, + uint8_t *p_hash, size_t hash_bytes) { uint32_t crc; uint32_t *p_data; @@ -46,8 +46,11 @@ void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha, crc32_hash32(*p_data++); crc = crc32_result(); - p_data = (uint32_t *)p_sha; - *p_data = crc; + for (n = 0; n < hash_bytes; n += sizeof(crc)) { + size_t copy_bytes = MIN(sizeof(crc), hash_bytes - n); + + memcpy(p_hash + n, &crc, copy_bytes); + } } /* Used to allow/prevent Flash erase/write operations */ diff --git a/test/nvmem_vars.c b/test/nvmem_vars.c index 56b96ef054..5e31d6a2aa 100644 --- a/test/nvmem_vars.c +++ b/test/nvmem_vars.c @@ -5,8 +5,6 @@ * Test of the key=val variable implementation (set, get, delete, etc). */ -#include - #include "common.h" #include "compile_time_macros.h" #include "nvmem.h" -- cgit v1.2.1