Newer
Older
AESLearning / aes_cmac.c
@Takayuki Kurosawa Takayuki Kurosawa on 17 Mar 2015 2 KB maintainance release
/* SensorBoard Secure Library
 *  Subject: AES-CMAC implementation from  IETF RFC 4493
 *    (http://tools.ietf.org/html/rfc4493)
 *  Copyright (C) 2015, T.Kurosawa
 */
#include <string.h>

#include "aes_cmac.h"
#include "aes128.h"

static uint mac[4]; //aes_datalen_i];
static uint  K1[4]; //aes_datalen_i];
static uint  K2[4]; //aes_datalen_i];

static const uint const_Zero[] =
  {0x00000000, 0x00000000, 0x00000000, 0x00000000 };

static const uint8 const_Rb[] = 
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 };

/// operators
static void ShiftCopy(uint *to, uint *from)
{
  int i, carry = 0;
  for (i = aes_datalen_i-1; i>= 0; i--) {
    to[i] = from[i] << 1 | carry;
    carry = (from[i] & (1<<31))? 1: 0;
  }
}

static void Xor(uint *a, const uint *b)
{
  int i;
  for (i = 0; i< aes_datalen_i; i++) {
    a[i] ^= b[i];
  }
}

static int Ceil(int a, int b)
{
  return (a/b)+(((a % b)!=0)?1:0);
}

static void padding(uint *P, int len)
{
  int i;
  uint8 *p = (uint8 *)P;

  len %= aes_datalen;
  p[len] = 0x80;
  for (i = len+1; i< aes_datalen; i++) {
    p[i] = 0x00;
  }
}


/// sub function
void Generate_Subkey(uint8 *key)
{
  uint L[aes_datalen_i];

  memcpy(L, const_Zero, sizeof(L));
  AES128_crypt(L, key);

  ShiftCopy(K1, L);
  if ((L[0] & (1<<31)) != 0) Xor(K1, (uint *)const_Rb);

  ShiftCopy(K2, K1);
  if ((K1[0] & (1<<31)) != 0) Xor(K2, (uint *)const_Rb);
}

/// exported function
uint *AES_cmac(uint8 *K, uint *M, int len)
{
  uint M_last[aes_datalen_i];
  int n = Ceil(len, aes_datalen);
  int i, flag;

  Generate_Subkey(K);

  if (len == 0)
    flag = 0;
  else 
    flag = ((len % aes_datalen) == 0)? 1: 0;

  if (flag) {
    memcpy(M_last, M+(n-1)*aes_datalen_i, aes_datalen);
    Xor(M_last, K1);
  } else {
    memcpy(M_last, M+(n-1)*aes_datalen_i, (len % aes_datalen));
    padding(M_last, len);
    Xor(M_last, K2);
  }
  memcpy(mac, const_Zero, sizeof(mac));
  for (i = 0; i< n-1; i++) {
    Xor(mac, M+i*4);
    AES128_crypt(mac, K);
  }
  Xor(mac, M_last);
  AES128_crypt(mac, K);
  return mac;
}

// O.M.A.J.I.N.A.I.
// vi:expandtab:foldmethod=syntax sw=2 ts=2