Implement AES-CMAC.

This commit is contained in:
Stephen Heumann 2024-04-14 22:16:04 -05:00
parent 191a27af86
commit 60e4998d16
5 changed files with 303 additions and 4 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2017,2023 Stephen Heumann
Copyright (c) 2017,2023,2024 Stephen Heumann
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@ -3,8 +3,8 @@ CFLAGS = -O255 -w255
LIBRARIES = lib65816crypto lib65816hash
PROGRAMS = aescbctest aesctrtest aestest aescrypt rc4test sha1sum sha1test \
sha256sum sha256test md5sum md5test md4sum md4test hmactest
PROGRAMS = aescbctest aesctrtest aestest aescrypt rc4test cmactest sha1sum \
sha1test sha256sum sha256test md5sum md5test md4sum md4test hmactest
.PHONY: default
default: $(LIBRARIES) $(PROGRAMS)
@ -14,6 +14,8 @@ pagealign.root: pagealign.asm
mv pagealign.ROOT pagealign.root
# Encryption/decryption algorithms
aescmac.a: aescmac.c aes.h
$(CC) $(CFLAGS) -c $<
aesmodes.a: aesmodes.c aes.h
$(CC) $(CFLAGS) -c $<
aes.a: aes.asm aes.macros
@ -42,7 +44,7 @@ md4.a: md4.cc md4.h md4.asm md4.macros hmacimpl.h
md4.B: md4.a
# Libraries
lib65816crypto: aesmodes.a aes.a rc4.a rc4.B
lib65816crypto: aescmac.a aesmodes.a aes.a rc4.a rc4.B
rm -f $@
iix makelib -P $@ $(patsubst %,+%,$^)
lib65816hash: sha1.a sha1.B sha256.a sha256.B md5.a md5.B md4.a md4.B
@ -62,6 +64,9 @@ aescrypt.a: aescrypt.c aes.h
rc4test.a: rc4test.c rc4.h
$(CC) $(CFLAGS) -c $<
cmactest.a: cmactest.c aes.h
$(CC) $(CFLAGS) -c $<
sha1sum.a: sha1sum.c sha1.h cksumcommon.h
$(CC) $(CFLAGS) -c $<
sha1test.a: sha1test.c sha1.h
@ -97,6 +102,9 @@ aescrypt: aescrypt.a pagealign.root lib65816crypto
rc4test: rc4test.a lib65816crypto
$(CC) $(CFLAGS) $< -L. -llib65816crypto -o $@
cmactest: cmactest.a lib65816crypto
$(CC) $(CFLAGS) pagealign.root $< -L. -llib65816crypto -o $@
sha1sum: sha1sum.a lib65816hash
$(CC) $(CFLAGS) $< -L. -llib65816hash -o $@
sha1test: sha1test.a lib65816hash

23
aes.h
View File

@ -21,6 +21,12 @@ struct aes_context {
unsigned char reserved2[16*13];
};
struct aes_cmac_context {
struct aes_context ctx;
unsigned char k1[16];
unsigned char k2[16];
};
/*
* The context structure must be in bank 0, preferably page-aligned.
* Note that a 256-byte (one page) context structure is sufficient for
@ -90,3 +96,20 @@ void aes_ctr_process(struct aes_context *context,
unsigned char *out,
unsigned long nblocks,
const unsigned char *counter);
/*
* Initialize a context for AES-CMAC computation with a specified key.
* This must be called before any calling aes_cmac_compute.
*/
void aes_cmac_init(struct aes_cmac_context *context,
const unsigned char key[16]);
/*
* Compute the AES-CMAC of a message as a single operation.
* The result will be in context->ctx.data.
* The context can be reused for multiple aes_cmac_compute operations.
*/
void aes_cmac_compute(struct aes_cmac_context *context,
const unsigned char *message,
unsigned long message_length);

176
aescmac.c Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2024 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma noroot
#pragma lint -1
#pragma optimize -1
#include <string.h>
#include <stddef.h>
#include "aes.h"
extern void AES_ENCRYPT(void);
static asm void aes_cmac_subkey_compute_step(struct aes_cmac_context *ctx) {
tdc
tay
phb
plx
pla
pld
sta 1,s
phx
plb
sep #0x20
asl 15
rol 14
rol 13
rol 12
rol 11
rol 10
rol 9
rol 8
rol 7
rol 6
rol 5
rol 4
rol 3
rol 2
rol 1
rol 0
bcc done
lda 15
eor #0x87
sta 15
done: rep #0x20
tya
tcd
rtl
}
/*
* Initialize a context for AES-CMAC computation with a specified key.
* This must be called before any calling aes_cmac_compute.
*/
void aes_cmac_init(struct aes_cmac_context *context,
const unsigned char key[16])
{
memcpy(context->ctx.key, key, 16);
aes128_expandkey(&context->ctx);
memset(context->ctx.data, 0, 16);
aes_encrypt(&context->ctx);
aes_cmac_subkey_compute_step(context);
memcpy(context->k1, context->ctx.data, 16);
aes_cmac_subkey_compute_step(context);
memcpy(context->k2, context->ctx.data, 16);
}
/*
* Compute the AES-CMAC of a message as a single operation.
* The result will be in context->ctx.data.
* The context can be reused for multiple aes_cmac_compute operations.
*/
void aes_cmac_compute(struct aes_cmac_context *context,
const unsigned char *message,
unsigned long message_length)
{
unsigned i;
memset(&context->ctx.data, 0, 16);
while (message_length > 16) {
asm {
lda [message]
eor [context]
sta [context]
ldy #2
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
iny
iny
lda [message],y
eor [context],y
sta [context],y
phd
lda context
tcd
jsl AES_ENCRYPT
pld
}
message_length -= 16;
message += 16;
}
if (message_length == 16) {
for (i = 0; i < 16; i++) {
context->ctx.data[i] ^= message[i] ^ context->k1[i];
}
} else {
for (i = 0; i < 16; i++) {
if (i < message_length) {
context->ctx.data[i] ^= message[i] ^ context->k2[i];
} else if (i == message_length) {
context->ctx.data[i] ^= 0x80 ^ context->k2[i];
} else {
context->ctx.data[i] ^= context->k2[i];
}
}
}
asm {
phd
lda context
tcd
jsl AES_ENCRYPT
pld
}
}

92
cmactest.c Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2024 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "aes.h"
/* AES-CMAC test vectors from RFC 4493 */
unsigned char K[16] = {
0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,
0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c
};
unsigned char K1[16] = {
0xfb,0xee,0xd6,0x18,0x35,0x71,0x33,0x66,
0x7c,0x85,0xe0,0x8f,0x72,0x36,0xa8,0xde
};
unsigned char K2[16] = {
0xf7,0xdd,0xac,0x30,0x6a,0xe2,0x66,0xcc,
0xf9,0x0b,0xc1,0x1e,0xe4,0x6d,0x51,0x3b
};
unsigned char ex2[16] = {
0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a
};
unsigned char ex3[40] = {
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
};
unsigned char ex4[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
};
void print_hexbytes(char *prefix, unsigned char *data, unsigned int n) {
int i;
printf("%s", prefix);
for (i = 0; i < n; i++) {
printf("%02x ", data[i]);
}
printf("\n");
}
int main(void) {
struct aes_cmac_context *ctx;
aes_cmac_init(ctx, K);
if (memcmp(ctx->k1, K1, 16) != 0)
print_hexbytes("wrong K1: got ", ctx->k1, 16);
if (memcmp(ctx->k2, K2, 16) != 0)
print_hexbytes("wrong K2: got ", ctx->k2, 16);
aes_cmac_compute(ctx, "", 0);
print_hexbytes("Example 1 AES-CMAC: ", ctx->ctx.data, 16);
aes_cmac_compute(ctx, ex2, sizeof(ex2));
print_hexbytes("Example 2 AES-CMAC: ", ctx->ctx.data, 16);
aes_cmac_compute(ctx, ex3, sizeof(ex3));
print_hexbytes("Example 3 AES-CMAC: ", ctx->ctx.data, 16);
aes_cmac_compute(ctx, ex4, sizeof(ex4));
print_hexbytes("Example 4 AES-CMAC: ", ctx->ctx.data, 16);
}