diff --git a/chip/g/build.mk b/chip/g/build.mk index f5df5069d4..8d226275f3 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -29,6 +29,7 @@ chip-y += uartn.o endif chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o +chip-$(CONFIG_DCRYPTO)+= dcrypto/app_cipher.o chip-$(CONFIG_DCRYPTO)+= dcrypto/app_key.o chip-$(CONFIG_DCRYPTO)+= dcrypto/bn.o chip-$(CONFIG_DCRYPTO)+= dcrypto/bn_hw.o diff --git a/chip/g/dcrypto/app_cipher.c b/chip/g/dcrypto/app_cipher.c new file mode 100644 index 0000000000..9b45ad7515 --- /dev/null +++ b/chip/g/dcrypto/app_cipher.c @@ -0,0 +1,106 @@ +/* + * 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 "common.h" + +#include "console.h" +#include "dcrypto.h" +#include "flash.h" +#include "hooks.h" +#include "shared_mem.h" +#include "task.h" +#include "timer.h" + + +int DCRYPTO_app_cipher(const void *salt, void *out, const void *in, size_t len) +{ + struct APPKEY_CTX ctx; + uint32_t iv[4]; + + memcpy(iv, salt, sizeof(iv)); + if (!DCRYPTO_appkey_init(NVMEM, &ctx)) + return 0; + + if (!DCRYPTO_aes_ctr(out, ctx.key, 128, (uint8_t *) iv, in, len)) + return 0; + + DCRYPTO_appkey_finish(&ctx); + return 1; +} + +/* + * Let's use some odd size to make sure unaligned buffers are handled + * properly. + */ +#define TEST_BLOB_SIZE 16387 + +static uint8_t result; +static void run_cipher_cmd(void) +{ + int rv; + char *p; + uint8_t sha[SHA_DIGEST_SIZE]; + uint8_t sha_after[SHA_DIGEST_SIZE]; + int match; + uint32_t tstamp; + + rv = shared_mem_acquire(TEST_BLOB_SIZE, (char **)&p); + + if (rv != EC_SUCCESS) { + result = rv; + return; + } + + ccprintf("original data %.16h\n", p); + + DCRYPTO_SHA1_hash((uint8_t *)p, TEST_BLOB_SIZE, sha); + + tstamp = get_time().val; + rv = DCRYPTO_app_cipher(&sha, p, p, TEST_BLOB_SIZE); + tstamp = get_time().val - tstamp; + ccprintf("rv 0x%02x, out data %.16h, time %d us\n", + rv, p, tstamp); + + if (rv == 1) { + tstamp = get_time().val; + rv = DCRYPTO_app_cipher(&sha, p, p, TEST_BLOB_SIZE); + tstamp = get_time().val - tstamp; + ccprintf("rv 0x%02x, orig. data %.16h, time %d us\n", + rv, p, tstamp); + } + + DCRYPTO_SHA1_hash((uint8_t *)p, TEST_BLOB_SIZE, sha_after); + + match = !memcmp(sha, sha_after, sizeof(sha)); + ccprintf("sha1 before and after %smatch!\n", + match ? "" : "MIS"); + + shared_mem_release(p); + + if ((rv == 1) && match) + result = EC_SUCCESS; + else + result = EC_ERROR_UNKNOWN; + + task_set_event(TASK_ID_CONSOLE, TASK_EVENT_CUSTOM(1), 0); +} +DECLARE_DEFERRED(run_cipher_cmd); + +static int cmd_cipher(int argc, char **argv) +{ + uint32_t events; + + hook_call_deferred(&run_cipher_cmd_data, 0); + + /* Should be done much sooner than in 1 second. */ + events = task_wait_event_mask(TASK_EVENT_CUSTOM(1), 1 * SECOND); + if (!(events & TASK_EVENT_CUSTOM(1))) { + ccprintf("Timed out, you might want to reboot...\n"); + return EC_ERROR_TIMEOUT; + } + + return result; +} +DECLARE_SAFE_CONSOLE_COMMAND(cipher, cmd_cipher, NULL, NULL); diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h index 3b80f6e6b8..3f018d48e4 100644 --- a/chip/g/dcrypto/dcrypto.h +++ b/chip/g/dcrypto/dcrypto.h @@ -217,4 +217,30 @@ struct APPKEY_CTX { int DCRYPTO_appkey_init(enum dcrypto_appid id, struct APPKEY_CTX *ctx); void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx); +/* Number of bytes in the salt object. */ +#define DCRYPTO_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. Upcoming changes are + * expected to make proper use of blob_iv. + * + * @param salt pointer to a unique value to be associated with this blob, + * used for derivation of the proper IV, the size of the value + * is as defined by DCRYPTO_CIPHER_SALT_SIZE above. + * @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 DCRYPTO_app_cipher(const void *salt, void *out, const void *in, size_t len); + #endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */