From 0f409b0589213d2daab027bf4ee418d9b744591f Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Fri, 6 Nov 2020 15:12:21 -0300 Subject: [PATCH] ext: tinycrypt: update ctr mode to stream Add an offset parameter to mode ctr so it can be properly used as a streaming cipher, like required by the flash encryption algorithm. Signed-off-by: Fabio Utzig --- .../include/bootutil/crypto/aes_ctr.h | 26 ++----------------- .../lib/include/tinycrypt/ctr_mode.h | 4 ++- ext/tinycrypt/lib/source/ctr_mode.c | 12 ++++++--- ext/tinycrypt/tests/test_ctr_mode.c | 18 ++++++++++--- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index b2ba7a4e..8422f451 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -96,31 +96,9 @@ static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const static int _bootutil_aes_ctr_crypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *in, uint32_t inlen, uint32_t blk_off, uint8_t *out) { - uint8_t buf[16]; - uint32_t buflen; int rc; - if (blk_off == 0) { - rc = tc_ctr_mode(out, inlen, in, inlen, counter, ctx); - if (rc != TC_CRYPTO_SUCCESS) { - return -1; - } - } else if (blk_off < 16) { - buflen = ((inlen + blk_off <= 16) ? inlen : (16 - blk_off)); - inlen -= buflen; - memcpy(&buf[blk_off], &in[0], buflen); - rc = tc_ctr_mode(buf, 16, buf, 16, counter, ctx); - if (rc != TC_CRYPTO_SUCCESS) { - return -1; - } - memcpy(&out[0], &buf[blk_off], buflen); - memset(&buf[0], 0, 16); - if (inlen > 0) { - rc = tc_ctr_mode(&out[buflen], inlen, &in[buflen], inlen, counter, ctx); - } - if (rc != TC_CRYPTO_SUCCESS) { - return -1; - } - } else { + rc = tc_ctr_mode(out, inlen, in, inlen, counter, &blk_off, ctx); + if (rc != TC_CRYPTO_SUCCESS) { return -1; } return 0; diff --git a/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h index dc221f9e..9936c925 100644 --- a/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h +++ b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h @@ -96,10 +96,12 @@ extern "C" { * @param in IN -- data to encrypt (or decrypt) * @param inlen IN -- length of input data in bytes * @param ctr IN/OUT -- the current counter value + * @param blk_off IN/OUT -- the offset in the block * @param sched IN -- an initialized AES key schedule */ int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched); + unsigned int inlen, uint8_t *ctr, uint32_t *blk_off, + const TCAesKeySched_t sched); #ifdef __cplusplus } diff --git a/ext/tinycrypt/lib/source/ctr_mode.c b/ext/tinycrypt/lib/source/ctr_mode.c index 1dfb92df..ec8c394d 100644 --- a/ext/tinycrypt/lib/source/ctr_mode.c +++ b/ext/tinycrypt/lib/source/ctr_mode.c @@ -35,18 +35,21 @@ #include int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) + unsigned int inlen, uint8_t *ctr, uint32_t *blk_off, + const TCAesKeySched_t sched) { uint8_t buffer[TC_AES_BLOCK_SIZE]; uint8_t nonce[TC_AES_BLOCK_SIZE]; unsigned int block_num; unsigned int i; + uint32_t n; /* input sanity check: */ if (out == (uint8_t *) 0 || in == (uint8_t *) 0 || ctr == (uint8_t *) 0 || + blk_off == (uint32_t *) 0 || sched == (TCAesKeySched_t) 0 || inlen == 0 || outlen == 0 || @@ -60,8 +63,9 @@ int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, /* select the last 4 bytes of the nonce to be incremented */ block_num = (nonce[12] << 24) | (nonce[13] << 16) | (nonce[14] << 8) | (nonce[15]); + n = *blk_off; for (i = 0; i < inlen; ++i) { - if ((i % (TC_AES_BLOCK_SIZE)) == 0) { + if (n == 0) { /* encrypt data using the current nonce */ if (tc_aes_encrypt(buffer, nonce, sched)) { block_num++; @@ -74,8 +78,10 @@ int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, } } /* update the output */ - *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++; + *out++ = buffer[n] ^ *in++; + n = (n + 1) % TC_AES_BLOCK_SIZE; } + *blk_off = n; /* update the counter */ ctr[12] = nonce[12]; ctr[13] = nonce[13]; diff --git a/ext/tinycrypt/tests/test_ctr_mode.c b/ext/tinycrypt/tests/test_ctr_mode.c index daf37878..f323856f 100644 --- a/ext/tinycrypt/tests/test_ctr_mode.c +++ b/ext/tinycrypt/tests/test_ctr_mode.c @@ -81,30 +81,42 @@ unsigned int test_1_and_2(void) uint8_t out[80]; uint8_t decrypted[64]; unsigned int result = TC_PASS; + uint32_t off = 0; TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n"); (void)tc_aes128_set_encrypt_key(&sched, key); (void)memcpy(out, ctr, sizeof(ctr)); if (tc_ctr_mode(&out[TC_AES_BLOCK_SIZE], sizeof(plaintext), plaintext, - sizeof(plaintext), ctr, &sched) == 0) { + sizeof(plaintext), ctr, &off, &sched) == 0) { TC_ERROR("CTR test #1 (encryption SP 800-38a tests) failed in %s.\n", __func__); result = TC_FAIL; goto exitTest1; } + if (off != 0) { + TC_ERROR("CTR test #1 invalid block offset (%u).\n", off); + result = TC_FAIL; + goto exitTest1; + } result = check_result(1, ciphertext, sizeof(out), out, sizeof(out)); TC_END_RESULT(result); TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n"); (void) memcpy(ctr, out, sizeof(ctr)); + off = 0; if (tc_ctr_mode(decrypted, sizeof(decrypted), &out[TC_AES_BLOCK_SIZE], - sizeof(decrypted), ctr, &sched) == 0) { + sizeof(decrypted), ctr, &off, &sched) == 0) { TC_ERROR("CTR test #2 (decryption SP 800-38a tests) failed in %s.\n", __func__); result = TC_FAIL; goto exitTest1; } + if (off != 0) { + TC_ERROR("CTR test #2 invalid block offset (%u).\n", off); + result = TC_FAIL; + goto exitTest1; + } result = check_result(2, plaintext, sizeof(plaintext), decrypted, sizeof(plaintext)); @@ -126,7 +138,7 @@ int main(void) TC_PRINT("Performing CTR tests:\n"); result = test_1_and_2(); if (result == TC_FAIL) { /* terminate test */ - TC_ERROR("CBC test #1 failed.\n"); + TC_ERROR("CTR test #1 failed.\n"); goto exitTest; }