#include "CommonCMACSPI.h"
#include "CommonCryptorPriv.h"
#include <corecrypto/ccaes.h>
#include "ccdebug.h"
const uint8_t const_Rb[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
};
static void leftshift_onebit(uint8_t *input, uint8_t *output)
{
int i;
uint8_t overflow = 0;
for ( i=15; i>=0; i-- ) {
output[i] = input[i] << 1;
output[i] |= overflow;
overflow = (input[i] & 0x80)?1:0;
}
return;
}
static void xor_128(const uint8_t *a, const uint8_t *b, uint8_t *out)
{
int i;
for (i=0;i<16; i++) out[i] = a[i] ^ b[i];
}
static void ccGenAESSubKey(const struct ccmode_ecb *aesmode, ccecb_ctx *ctx, void *key1, void *key2)
{
uint8_t L[16];
uint8_t Z[16];
uint8_t tmp[16];
memset(Z, 0, 16);
aesmode->ecb(ctx, 1, Z, L);
if ( (L[0] & 0x80) == 0 ) {
leftshift_onebit(L, key1);
} else {
leftshift_onebit(L, tmp);
xor_128(tmp,const_Rb, key1);
}
if ( (((uint8_t *)key1)[0] & 0x80) == 0 ) {
leftshift_onebit(key1, key2);
} else {
leftshift_onebit(key1, tmp);
xor_128(tmp,const_Rb, key2);
}
return;
}
static void ccAESCMacPadding (const uint8_t *lastb, uint8_t *pad, int length)
{
int j;
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 CCAESCmac(const void *key,
const uint8_t *data,
size_t dataLength,
void *macOut)
{
uint8_t X[16],Y[16], M_last[16], padded[16];
uint8_t K1[16], K2[16];
int flag;
size_t n;
const struct ccmode_ecb *aesmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCEncrypt).ecb;
ccecb_ctx_decl(aesmode->size, ctx);
CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
aesmode->init(aesmode, ctx, 16, key);
aesmode->ecb(ctx, 1, Y, X);
ccGenAESSubKey(aesmode, ctx, K1, K2);
n = (dataLength+15) / 16;
if ( 0 == n ) {
n = 1;
flag = 0;
} else {
if ( (dataLength%16) == 0 ) flag = 1;
else flag = 0;
}
if ( flag ) {
xor_128(&data[16*(n-1)],K1,M_last);
} else {
ccAESCMacPadding(&data[16*(n-1)],padded,dataLength%16);
xor_128(padded,K2,M_last);
}
memset(X, 0, 16);
for (size_t i=0; i<n-1; i++ ) {
xor_128(X,&data[16*i],Y);
aesmode->ecb(ctx, 1, Y, X);
}
xor_128(X,M_last,Y);
aesmode->ecb(ctx, 1, Y, X);
memcpy(macOut, X, 16);
}