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 <fabio.utzig@nordicsemi.no>
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h
index dc221f9..9936c92 100644
--- a/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h
+++ b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h
@@ -96,10 +96,12 @@
* @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 1dfb92d..ec8c394 100644
--- a/ext/tinycrypt/lib/source/ctr_mode.c
+++ b/ext/tinycrypt/lib/source/ctr_mode.c
@@ -35,18 +35,21 @@
#include <tinycrypt/utils.h>
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 @@
/* 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 @@
}
}
/* 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 daf3787..f323856 100644
--- a/ext/tinycrypt/tests/test_ctr_mode.c
+++ b/ext/tinycrypt/tests/test_ctr_mode.c
@@ -81,30 +81,42 @@
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 @@
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;
}