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>
This commit is contained in:
parent
d3838989d2
commit
0f409b0589
|
@ -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)
|
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;
|
int rc;
|
||||||
if (blk_off == 0) {
|
rc = tc_ctr_mode(out, inlen, in, inlen, counter, &blk_off, ctx);
|
||||||
rc = tc_ctr_mode(out, inlen, in, inlen, counter, ctx);
|
if (rc != TC_CRYPTO_SUCCESS) {
|
||||||
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 {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -96,10 +96,12 @@ extern "C" {
|
||||||
* @param in IN -- data to encrypt (or decrypt)
|
* @param in IN -- data to encrypt (or decrypt)
|
||||||
* @param inlen IN -- length of input data in bytes
|
* @param inlen IN -- length of input data in bytes
|
||||||
* @param ctr IN/OUT -- the current counter value
|
* @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
|
* @param sched IN -- an initialized AES key schedule
|
||||||
*/
|
*/
|
||||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,18 +35,21 @@
|
||||||
#include <tinycrypt/utils.h>
|
#include <tinycrypt/utils.h>
|
||||||
|
|
||||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
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 buffer[TC_AES_BLOCK_SIZE];
|
||||||
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
||||||
unsigned int block_num;
|
unsigned int block_num;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
uint32_t n;
|
||||||
|
|
||||||
/* input sanity check: */
|
/* input sanity check: */
|
||||||
if (out == (uint8_t *) 0 ||
|
if (out == (uint8_t *) 0 ||
|
||||||
in == (uint8_t *) 0 ||
|
in == (uint8_t *) 0 ||
|
||||||
ctr == (uint8_t *) 0 ||
|
ctr == (uint8_t *) 0 ||
|
||||||
|
blk_off == (uint32_t *) 0 ||
|
||||||
sched == (TCAesKeySched_t) 0 ||
|
sched == (TCAesKeySched_t) 0 ||
|
||||||
inlen == 0 ||
|
inlen == 0 ||
|
||||||
outlen == 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 */
|
/* select the last 4 bytes of the nonce to be incremented */
|
||||||
block_num = (nonce[12] << 24) | (nonce[13] << 16) |
|
block_num = (nonce[12] << 24) | (nonce[13] << 16) |
|
||||||
(nonce[14] << 8) | (nonce[15]);
|
(nonce[14] << 8) | (nonce[15]);
|
||||||
|
n = *blk_off;
|
||||||
for (i = 0; i < inlen; ++i) {
|
for (i = 0; i < inlen; ++i) {
|
||||||
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
|
if (n == 0) {
|
||||||
/* encrypt data using the current nonce */
|
/* encrypt data using the current nonce */
|
||||||
if (tc_aes_encrypt(buffer, nonce, sched)) {
|
if (tc_aes_encrypt(buffer, nonce, sched)) {
|
||||||
block_num++;
|
block_num++;
|
||||||
|
@ -74,8 +78,10 @@ int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* update the output */
|
/* 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 */
|
/* update the counter */
|
||||||
ctr[12] = nonce[12]; ctr[13] = nonce[13];
|
ctr[12] = nonce[12]; ctr[13] = nonce[13];
|
||||||
|
|
|
@ -81,30 +81,42 @@ unsigned int test_1_and_2(void)
|
||||||
uint8_t out[80];
|
uint8_t out[80];
|
||||||
uint8_t decrypted[64];
|
uint8_t decrypted[64];
|
||||||
unsigned int result = TC_PASS;
|
unsigned int result = TC_PASS;
|
||||||
|
uint32_t off = 0;
|
||||||
|
|
||||||
TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n");
|
TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n");
|
||||||
(void)tc_aes128_set_encrypt_key(&sched, key);
|
(void)tc_aes128_set_encrypt_key(&sched, key);
|
||||||
|
|
||||||
(void)memcpy(out, ctr, sizeof(ctr));
|
(void)memcpy(out, ctr, sizeof(ctr));
|
||||||
if (tc_ctr_mode(&out[TC_AES_BLOCK_SIZE], sizeof(plaintext), plaintext,
|
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__);
|
TC_ERROR("CTR test #1 (encryption SP 800-38a tests) failed in %s.\n", __func__);
|
||||||
result = TC_FAIL;
|
result = TC_FAIL;
|
||||||
goto exitTest1;
|
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));
|
result = check_result(1, ciphertext, sizeof(out), out, sizeof(out));
|
||||||
TC_END_RESULT(result);
|
TC_END_RESULT(result);
|
||||||
|
|
||||||
TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n");
|
TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n");
|
||||||
(void) memcpy(ctr, out, sizeof(ctr));
|
(void) memcpy(ctr, out, sizeof(ctr));
|
||||||
|
off = 0;
|
||||||
if (tc_ctr_mode(decrypted, sizeof(decrypted), &out[TC_AES_BLOCK_SIZE],
|
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__);
|
TC_ERROR("CTR test #2 (decryption SP 800-38a tests) failed in %s.\n", __func__);
|
||||||
result = TC_FAIL;
|
result = TC_FAIL;
|
||||||
goto exitTest1;
|
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),
|
result = check_result(2, plaintext, sizeof(plaintext),
|
||||||
decrypted, sizeof(plaintext));
|
decrypted, sizeof(plaintext));
|
||||||
|
|
||||||
|
@ -126,7 +138,7 @@ int main(void)
|
||||||
TC_PRINT("Performing CTR tests:\n");
|
TC_PRINT("Performing CTR tests:\n");
|
||||||
result = test_1_and_2();
|
result = test_1_and_2();
|
||||||
if (result == TC_FAIL) { /* terminate test */
|
if (result == TC_FAIL) { /* terminate test */
|
||||||
TC_ERROR("CBC test #1 failed.\n");
|
TC_ERROR("CTR test #1 failed.\n");
|
||||||
goto exitTest;
|
goto exitTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue