summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-01-22 21:25:42 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-01-25 22:12:28 -0800
commit7d2e4fbf5ba0c27f5d84bfa321bd857dbd7c33ff (patch)
tree6a8626fd1f271cf2bfaffc4d9e81a20ad20254e5
parent09fca7bddbc4785c5f0d5f4590cdf9d09b3d5471 (diff)
downloadchrome-ec-7d2e4fbf5ba0c27f5d84bfa321bd857dbd7c33ff.tar.gz
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 <string.h>. 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 <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/431313 Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Nagendra Modadugu <ngm@google.com>
-rw-r--r--board/cr50/board.c15
-rw-r--r--chip/g/build.mk2
-rw-r--r--chip/g/crypto_api.c31
-rw-r--r--chip/g/dcrypto/dcrypto.h3
-rw-r--r--common/nvmem.c29
-rw-r--r--include/crypto_api.h55
-rw-r--r--include/nvmem.h13
-rw-r--r--test/nvmem.c11
-rw-r--r--test/nvmem_vars.c2
9 files changed, 116 insertions, 45 deletions
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 <stddef.h>
#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 <string.h>
-
#include "common.h"
#include "compile_time_macros.h"
#include "nvmem.h"