/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

/*
 * Implementation of the AES-GCM Encryption/Authentication
 *
 * Some restrictions..
 * 1. Only for use with AES
 * 2. Returned tag is always 128-bits. Truncate at your own risk.
 * 3. The order of function calls must follow some rules
 *
 * Typical sequence of calls..
 * 1. call GCM_init
 * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
 * 3. call GCM_add_header one last time with any length of header
 * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
 * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
 * 6. call GCM_finish to extract the tag.
 *
 * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
 */
/* SU=m, m is Stack Usage */

#include <stdlib.h>
#include <string.h>
#include "arch.h"
#include "amcl.h"

#define NB 4
#define MR_TOBYTE(x) ((uchar)((x)))

static unsign32 pack(const uchar *b)
{
    /* pack bytes into a 32-bit Word */
    return ((unsign32)b[0]<<24)|((unsign32)b[1]<<16)|((unsign32)b[2]<<8)|(unsign32)b[3];
}

static void unpack(unsign32 a,uchar *b)
{
    /* unpack bytes from a word */
    b[3]=MR_TOBYTE(a);
    b[2]=MR_TOBYTE(a>>8);
    b[1]=MR_TOBYTE(a>>16);
    b[0]=MR_TOBYTE(a>>24);
}

static void precompute(gcm *g,uchar *H)
{
    /* precompute small 2k bytes gf2m table of x^n.H */
    int i,j;
    unsign32 *last,*next,b;

    for (i=j=0; i<NB; i++,j+=4) g->table[0][i]=pack((uchar *)&H[j]);

    for (i=1; i<128; i++)
    {
        next=g->table[i];
        last=g->table[i-1];
        b=0;
        for (j=0; j<NB; j++)
        {
            next[j]=b|(last[j])>>1;
            b=last[j]<<31;
        }
        if (b) next[0]^=0xE1000000; /* irreducible polynomial */
    }
}

/* SU= 32 */
static void gf2mul(gcm *g)
{
    /* gf2m mul - Z=H*X mod 2^128 */
    int i,j,m,k;
    unsign32 P[4];
    unsign32 b;

    P[0]=P[1]=P[2]=P[3]=0;
    j=8;
    m=0;
    for (i=0; i<128; i++)
    {
        b=(unsign32)(g->stateX[m]>>(--j))&1;
        b=~b+1;
        for (k=0; k<NB; k++) P[k]^=(g->table[i][k]&b);
        if (j==0)
        {
            j=8;
            m++;
            if (m==16) break;
        }
    }
    for (i=j=0; i<NB; i++,j+=4) unpack(P[i],(uchar *)&g->stateX[j]);
}

/* SU= 32 */
static void GCM_wrap(gcm *g)
{
    /* Finish off GHASH */
    int i,j;
    unsign32 F[4];
    uchar L[16];

    /* convert lengths from bytes to bits */
    F[0]=(g->lenA[0]<<3)|(g->lenA[1]&0xE0000000)>>29;
    F[1]=g->lenA[1]<<3;
    F[2]=(g->lenC[0]<<3)|(g->lenC[1]&0xE0000000)>>29;
    F[3]=g->lenC[1]<<3;
    for (i=j=0; i<NB; i++,j+=4) unpack(F[i],(uchar *)&L[j]);

    for (i=0; i<16; i++) g->stateX[i]^=L[i];
    gf2mul(g);
}

static int GCM_ghash(gcm *g,char *plain,int len)
{
    int i,j=0;
    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;

    while (j<len)
    {
        for (i=0; i<16 && j<len; i++)
        {
            g->stateX[i]^=plain[j++];
            g->lenC[1]++;
            if (g->lenC[1]==0) g->lenC[0]++;
        }
        gf2mul(g);
    }
    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
    return 1;
}

/* SU= 48 */
/* Initialize GCM mode */
void GCM_init(gcm* g,int nk,char *key,int niv,char *iv)
{
    /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
    int i;
    uchar H[16];
    for (i=0; i<16; i++)
    {
        H[i]=0;
        g->stateX[i]=0;
    }

    AES_init(&(g->a),ECB,nk,key,iv);
    AES_ecb_encrypt(&(g->a),H);     /* E(K,0) */
    precompute(g,H);

    g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
    if (niv==12)
    {
        for (i=0; i<12; i++) g->a.f[i]=iv[i];
        unpack((unsign32)1,(uchar *)&(g->a.f[12]));  /* initialise IV */
        for (i=0; i<16; i++) g->Y_0[i]=g->a.f[i];
    }
    else
    {
        g->status=GCM_ACCEPTING_CIPHER;
        GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */
        GCM_wrap(g);
        for (i=0; i<16; i++)
        {
            g->a.f[i]=g->stateX[i];
            g->Y_0[i]=g->a.f[i];
            g->stateX[i]=0;
        }
        g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
    }
    g->status=GCM_ACCEPTING_HEADER;
}

/* SU= 24 */
/* Add Header data - included but not encrypted */
int GCM_add_header(gcm* g,char *header,int len)
{
    /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
    int i,j=0;
    if (g->status!=GCM_ACCEPTING_HEADER) return 0;

    while (j<len)
    {
        for (i=0; i<16 && j<len; i++)
        {
            g->stateX[i]^=header[j++];
            g->lenA[1]++;
            if (g->lenA[1]==0) g->lenA[0]++;
        }
        gf2mul(g);
    }
    if (len%16!=0) g->status=GCM_ACCEPTING_CIPHER;
    return 1;
}

/* SU= 48 */
/* Add Plaintext - included and encrypted */
int GCM_add_plain(gcm *g,char *cipher,char *plain,int len)
{
    /* Add plaintext to extract ciphertext, len is length of plaintext.  */
    int i,j=0;
    unsign32 counter;
    uchar B[16];
    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;

    while (j<len)
    {
        counter=pack((uchar *)&(g->a.f[12]));
        counter++;
        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
        for (i=0; i<16; i++) B[i]=g->a.f[i];
        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */

        for (i=0; i<16 && j<len; i++)
        {
            cipher[j]=plain[j]^B[i];
            g->stateX[i]^=cipher[j++];
            g->lenC[1]++;
            if (g->lenC[1]==0) g->lenC[0]++;
        }
        gf2mul(g);
    }
    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
    return 1;
}

/* SU= 48 */
/* Add Ciphertext - decrypts to plaintext */
int GCM_add_cipher(gcm *g,char *plain,char *cipher,int len)
{
    /* Add ciphertext to extract plaintext, len is length of ciphertext. */
    int i,j=0;
    unsign32 counter;
    char oc;
    uchar B[16];
    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;

    while (j<len)
    {
        counter=pack((uchar *)&(g->a.f[12]));
        counter++;
        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
        for (i=0; i<16; i++) B[i]=g->a.f[i];
        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
        for (i=0; i<16 && j<len; i++)
        {
            oc=cipher[j];
            plain[j]=cipher[j]^B[i];
            g->stateX[i]^=oc;
            j++;
            g->lenC[1]++;
            if (g->lenC[1]==0) g->lenC[0]++;
        }
        gf2mul(g);
    }
    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
    return 1;
}

/* SU= 16 */
/* Finish and extract Tag */
void GCM_finish(gcm *g,char *tag)
{
    /* Finish off GHASH and extract tag (MAC) */
    int i;

    GCM_wrap(g);

    /* extract tag */
    if (tag!=NULL)
    {
        AES_ecb_encrypt(&(g->a),g->Y_0);        /* E(K,Y0) */
        for (i=0; i<16; i++) g->Y_0[i]^=g->stateX[i];
        for (i=0; i<16; i++)
        {
            tag[i]=g->Y_0[i];
            g->Y_0[i]=g->stateX[i]=0;
        }
    }
    g->status=GCM_FINISHED;
    AES_end(&(g->a));
}


// Compile with
// gcc -O2 gcm.c aes.c -o gcm.exe
/* SU= 16
*/

/* static void hex2bytes(char *hex,char *bin) */
/* { */
/* 	int i; */
/* 	char v; */
/* 	int len=strlen(hex); */
/* 	for (i = 0; i < len/2; i++) { */
/*         char c = hex[2*i]; */
/*         if (c >= '0' && c <= '9') { */
/*             v = c - '0'; */
/*         } else if (c >= 'A' && c <= 'F') { */
/*             v = c - 'A' + 10; */
/*         } else if (c >= 'a' && c <= 'f') { */
/*             v = c - 'a' + 10; */
/*         } else { */
/*             v = 0; */
/*         } */
/*         v <<= 4; */
/*         c = hex[2*i + 1]; */
/*         if (c >= '0' && c <= '9') { */
/*             v += c - '0'; */
/*         } else if (c >= 'A' && c <= 'F') { */
/*             v += c - 'A' + 10; */
/*         } else if (c >= 'a' && c <= 'f') { */
/*             v += c - 'a' + 10; */
/*         } else { */
/*             v = 0; */
/*         } */
/*         bin[i] = v; */
/*     } */
/* } */

/*
int main()
{
	int i;

//	char* KT="feffe9928665731c6d6a8f9467308308";
//	char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
//	char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
//	char* NT="cafebabefacedbaddecaf888";
// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
//	char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
// Tag should be 619cc5aefffe0bfa462af43c1699d050

  char* KT="6dfb5dc68af6ae2f3242e9184f100918";
  char* MT="47809d16c2c6ec685962c90e53fe1bba";
  char* HT="dd0fa6e494031139d71ee45f00d56fa4";
  char* NT="37d36f5c54d53479d4745dd1";


	int len=strlen(MT)/2;
	int lenH=strlen(HT)/2;
	int lenK=strlen(KT)/2;
	int lenIV=strlen(NT)/2;

	char T[16];   // Tag
	char K[16];   // AES Key
	char H[64];   // Header - to be included in Authentication, but not encrypted
	char N[100];   // IV - Initialisation vector
	char M[100];  // Plaintext to be encrypted/authenticated
	char C[100];  // Ciphertext
	char P[100];  // Recovered Plaintext

	gcm g;

    hex2bytes(MT, M);
    hex2bytes(HT, H);
    hex2bytes(NT, N);
	hex2bytes(KT, K);

	printf("lenK= %d\n",lenK);

 	printf("Plaintext=\n");
	for (i=0;i<len;i++) printf("%02x",(unsigned char)M[i]);
	printf("\n");

	GCM_init(&g,16,K,lenIV,N);
	GCM_add_header(&g,H,lenH);
	GCM_add_plain(&g,C,M,len);
	GCM_finish(&g,T);

	printf("Ciphertext=\n");
	for (i=0;i<len;i++) printf("%02x",(unsigned char)C[i]);
	printf("\n");

	printf("Tag=\n");
	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
	printf("\n");

	GCM_init(&g,16,K,lenIV,N);
	GCM_add_header(&g,H,lenH);
	GCM_add_cipher(&g,P,C,len);
	GCM_finish(&g,T);

 	printf("Plaintext=\n");
	for (i=0;i<len;i++) printf("%02x",(unsigned char)P[i]);
	printf("\n");

	printf("Tag=\n");
	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
	printf("\n");
}

*/
