#include <stdio.h>
#include <crypto.h>
#include <asn1.h>
#include <jkl.h>
#include <CdsaMem.h>
char	testkey1[] =  { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 
			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 
			0x0b, 0x0b };
char	testkey2[] =  "Jefe";
char	testkey3[] =  { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa };
char	testkey4[] =  { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
			0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
			0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 };
char 	testkey5[] =  { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
			0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
			0x0c, 0x0c };
char	testkey6[] =  { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };

char	testkey7[] =  { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };

char	testdata1[] = "Hi There";
char	testdata2[] = "what do ya want for nothing?";
char	testdata3[] = { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
			0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
			0xdd, 0xdd, 0xdd, 0xdd, 0xdd };

char	testdata4[] = { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 
			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 
			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 
			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 
			0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 
			0xcd, 0xcd, 0xcd, 0xcd, 0xcd };
char	testdata5[] = "Test With Truncation";
char	testdata6[] = "Test Using Larger Than Block-Size Key - Hash Key First";
char	testdata7[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data";
char	digest1[] = "0xb617318655057264e28bc0b6fb378c8ef146be00";
char	digest2[] = "0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79";
char	digest3[] = "0x125d7342b9ac11cd91a39af48aa17b4f63f175d3";
char	digest4[] = "0x4c9007f4026250c6bc8414f9bf50c86c2d7235da";
char	digest5[] = "0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04";
char	digest6[] = "0xaa4ae5e15272d00e95705637ce8a3b55ed402112";
char	digest7[] = "0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91";
int	tk1len = 20;
int 	td1len = 8;
int	tk2len = 4;
int	td2len = 28;
int	tk3len = 20;
int	td3len = 50;
int	tk4len = 25;
int	td4len = 50;
int	tk5len = 20;
int	td5len = 20;
int	tk6len = 80;
int	td6len = 54;
int	tk7len = 80;
int	td7len = 73;

static CSSM_MEMORY_FUNCS memoryFuncs = { CR_CSSM_Malloc, CR_CSSM_Free, 
                                         CR_CSSM_Realloc, CR_CSSM_Calloc, 
                                         NULL };
struct HMACtest {
  unsigned char	key[1024];
  uint32	keyLen;
  unsigned char	data[2048];
  uint32 dataLen;
  char expected[BUFSIZ];
};

#define HMAC_TESTS	7

main(int argc, char *argv[]) 
{

  struct	HMACtest	TestData[HMAC_TESTS];
  struct	HMACtest	*tp;
  int x, c;

  JKL_InitializeCSSM(memoryFuncs);
  tp = &TestData[0];
  tp->dataLen = td1len;
  tp->keyLen = tk1len;
  memcpy(tp->data, testdata1, td1len);
  memcpy(tp->key, testkey1, tk1len);
  memcpy(tp->expected, digest1, strlen(digest1));
  tp = &TestData[1];
  tp->dataLen = td2len;
  tp->keyLen = tk2len;
  memcpy(tp->data, testdata2, td2len);
  memcpy(tp->key, testkey2, tk2len);
  memcpy(tp->expected, digest2, strlen(digest2));
  tp = &TestData[2];
  tp->dataLen = td3len;
  tp->keyLen = tk3len;
  memcpy(tp->data, testdata3, td3len);
  memcpy(tp->key, testkey3, tk3len);
  memcpy(tp->expected, digest3, strlen(digest3));
  tp = &TestData[3];
  tp->dataLen = td4len;
  tp->keyLen = tk4len;
  memcpy(tp->data, testdata4, td4len);
  memcpy(tp->key, testkey4, tk4len);
  memcpy(tp->expected, digest4, strlen(digest4));
  tp = &TestData[4];
  tp->dataLen = td5len;
  tp->keyLen = tk5len;
  memcpy(tp->data, testdata5, td5len);
  memcpy(tp->key, testkey5, tk5len);
  memcpy(tp->expected, digest5, strlen(digest5));
  tp = &TestData[5];
  tp->dataLen = td6len;
  tp->keyLen = tk6len;
  memcpy(tp->data, testdata6, td6len);
  memcpy(tp->key, testkey6, tk6len);
  memcpy(tp->expected, digest6, strlen(digest6));
  tp = &TestData[6];
  tp->dataLen = td7len;
  tp->keyLen = tk7len;
  memcpy(tp->data, testdata7, td7len);
  memcpy(tp->key, testkey7, tk7len);
  memcpy(tp->expected, digest7, strlen(digest7));

  for(x = 0; x < HMAC_TESTS; x++) {
    buffer_t	keybuf;
    buffer_t	databuf;
    buffer_t	digestbuf;

    keybuf.clear();
    databuf.clear();
    digestbuf.clear();
    keybuf.append(TestData[x].key, TestData[x].keyLen);
    databuf.append(TestData[x].data, TestData[x].dataLen);
    CR_HMACWithSHA1(databuf, keybuf, digestbuf);
    printf("Digest #%d = 0x", x);
    for(c = 0; c < digestbuf.data_len; c++) {
      printf("%02x", digestbuf.data[c]);
    }
    printf("\n");
    printf("Expect #%d = %s\n", x, TestData[x].expected);
  }
}
