From cfadee23bb8aa02bacdb9c8e5a254fa4ed7f6c96 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 2 Jul 2017 18:25:43 -0500 Subject: [PATCH] Add implementation and test for AES CTR mode. --- aes.h | 15 +++++ aesctrtest.c | 126 +++++++++++++++++++++++++++++++++++++++++ aescbc.c => aesmodes.c | 109 +++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 aesctrtest.c rename aescbc.c => aesmodes.c (69%) diff --git a/aes.h b/aes.h index be16826..3843546 100644 --- a/aes.h +++ b/aes.h @@ -75,3 +75,18 @@ void aes_cbc_decrypt(struct aes_context *context, unsigned char *out, unsigned long nblocks, const unsigned char *iv); + +/* + * Process data using AES-128, AES-192, or AES-256 in CTR mode. + * This either encrypts or decrypts data, depending on whether + * in contains plaintext or ciphertext. + * The key must have been specified via aes{128,192,256}_expandkey(). + * nblocks gives the number of 16-byte blocks to be processed. + * counter will be interpreted as a 128-bit big-endian integer, + * and incremented for each block processed. + */ +void aes_ctr_process(struct aes_context *context, + const unsigned char *in, + unsigned char *out, + unsigned long nblocks, + const unsigned char *counter); diff --git a/aesctrtest.c b/aesctrtest.c new file mode 100644 index 0000000..81b2a71 --- /dev/null +++ b/aesctrtest.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include "aes.h" + +unsigned char initial_counter[16] = { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +}; + +unsigned char counter[16]; + +unsigned char key128[16] = { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c +}; + +unsigned char key192[24] = { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b +}; + +unsigned char key256[32] = { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 +}; + +unsigned char plaintext[64] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 +}; + +unsigned char output[64]; +unsigned char output2[64]; + +#define BUFSIZE 64000 + +static void printhex(char *str, unsigned char *buf, unsigned int count) { + unsigned int i; + + if (str) + printf("%s\n", str); + + for (i = 0; i < count; i++) { + printf("%02x", buf[i]); + if (i && (i & 0x0F) == 0x0F) + printf("\n"); + } +} + +int main(void) { + struct aes_context **context_hndl; + struct aes_context *context; + unsigned char *inbuf, *outbuf; + unsigned long tick_count; + long double bytes_per_sec; + + context_hndl = (struct aes_context **)NewHandle(sizeof(struct aes_context), + userid(), attrFixed|attrPage|attrBank|attrNoCross, 0x000000); + if (toolerror()) + return 0; + context = *context_hndl; + + memcpy(context->key, key128, 16); + aes128_expandkey(context); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, plaintext, output, 4, counter); + printhex("AES-128 ciphertext:", output, 64); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, output, output2, 4, counter); + printhex("Decrypted plaintext:", output2, 64); + + + memcpy(context->key, key192, 24); + aes192_expandkey(context); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, plaintext, output, 4, counter); + printhex("AES-192 ciphertext:", output, 64); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, output, output2, 4, counter); + printhex("Decrypted plaintext:", output2, 64); + + + memcpy(context->key, key256, 32); + aes256_expandkey(context); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, plaintext, output, 4, counter); + printhex("AES-256 ciphertext:", output, 64); + + memcpy(counter, initial_counter, 16); + aes_ctr_process(context, output, output2, 4, counter); + printhex("Decrypted plaintext:", output2, 64); + + /* Timing tests */ + inbuf = calloc(BUFSIZE, 1); + outbuf = malloc(BUFSIZE); + if (inbuf == NULL || outbuf == NULL) + return -1; + + memcpy(context->key, key128, 16); + aes128_expandkey(context); + memcpy(counter, initial_counter, 16); + + tick_count = GetTick(); + aes_ctr_process(context, inbuf, outbuf, BUFSIZE / 16, counter); + tick_count = GetTick() - tick_count; + bytes_per_sec = (long double)BUFSIZE * 60 / tick_count; + printf("AES-128 CTR encryption/decryption: %lf bytes/sec\n", bytes_per_sec); +} diff --git a/aescbc.c b/aesmodes.c similarity index 69% rename from aescbc.c rename to aesmodes.c index 74e7425..4c95ce5 100644 --- a/aescbc.c +++ b/aesmodes.c @@ -281,3 +281,112 @@ void aes_cbc_decrypt(struct aes_context *context, out += 16; } } + +/* + * Process data using AES-128, AES-192, or AES-256 in CTR mode. + * This either encrypts or decrypts data, depending on whether + * in contains plaintext or ciphertext. + * The key must have been specified via aes{128,192,256}_expandkey(). + * nblocks gives the number of 16-byte blocks to be processed. + * counter will be interpreted as a 128-bit big-endian integer, + * and incremented for each block processed. + */ +void aes_ctr_process(struct aes_context *context, + const unsigned char *in, + unsigned char *out, + unsigned long nblocks, + const unsigned char *counter) +{ + while (nblocks-- > 0) { + asm { + lda [counter] + sta [context] + ldy #2 + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + iny + iny + lda [counter],y + sta [context],y + + phd + lda context + tcd + jsl AES_ENCRYPT + pld + + lda [context] + eor [in] + sta [out] + ldy #2 + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + iny + iny + lda [context],y + eor [in],y + sta [out],y + + ldy #14 +incloop: lda [counter],y + xba + inc a + xba + sta [counter],y + bne incdone + dey + dey + bpl incloop +incdone: + } + in += 16; + out += 16; + } +} +