/*************************************************************** * * Broadcom Corp. Confidential * Copyright 2011 Broadcom Corp. All Rights Reserved. * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * File: aes-cmac.c * Description: aes-cmac reference implementation. this implementation * is lifted from RFC-4493 and modified to work with particular aes * implementation that I had. This used only for testing of signatures * and not intended for production since it is very slow. * * Created: Mon November 15 2010. * * * ****************************************************************/ #include "ministd.h" #include "aes.h" /* constants */ unsigned char const_Zero[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; unsigned char const_Rb[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x87}; void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) { int i; for (i=0;i<16; i++) { out[i] = a[i] ^ b[i]; } } void leftshift_onebit(unsigned char *input,unsigned char *output) { int i; unsigned char overflow = 0; for ( i=15; i>=0; i-- ) { output[i] = input[i] << 1; output[i] |= overflow; overflow = (input[i] & 0x80)?1:0; } return; } void generate_subkey(aes_ctx_t *ctx, unsigned char *K1, unsigned char *K2) { unsigned char L[16]; unsigned char tmp[16]; aes_encrypt(ctx,const_Zero,L); if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */ leftshift_onebit(L,K1); } else { /* Else K1 = ( L << 1 ) (+) Rb */ leftshift_onebit(L,tmp); xor_128(tmp,const_Rb,K1); } if ( (K1[0] & 0x80) == 0 ) { leftshift_onebit(K1,K2); } else { leftshift_onebit(K1,tmp); xor_128(tmp,const_Rb,K2); } return; } void padding ( unsigned char *lastb, unsigned char *pad, int length ) { int j; /* original last block */ for ( j=0; j<16; j++ ) { if ( j < length ) { pad[j] = lastb[j]; } else if ( j == length ) { pad[j] = 0x80; } else { pad[j] = 0x00; } } } void aes_cmac ( aes_ctx_t *ctx, unsigned char *input, int length, unsigned char *mac ) { unsigned char X[16],Y[16], M_last[16], padded[16]; unsigned char K1[16], K2[16]; int n, i, flag; generate_subkey(ctx, K1,K2); n = (length+15) / 16; /* n is number of rounds */ if ( n == 0 ) { n = 1; flag = 0; } else { if ( (length%16) == 0 ) { /* last block is a complete block */ flag = 1; } else { /* last block is not complete block */ flag = 0; } } if ( flag ) { /* last block is complete block */ xor_128(&input[16*(n-1)],K1,M_last); } else { padding(&input[16*(n-1)],padded,length%16); xor_128(padded,K2,M_last); } for ( i=0; i<16; i++ ) X[i] = 0; for ( i=0; i