/*
	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
 */

var GCM = function() {
	this.table=new Array(128);
	for (var i=0;i<128;i++)
		this.table[i]=new Array(4);  /* 2k bytes */
	this.stateX=[];
	this.Y_0=[];
	this.counter=0;
	this.lenA=[];
	this.lenC=[];
	this.status=0;
	this.a=new AES();
};

GCM.prototype={

	precompute: function(H)
	{
		var i,j,c;
		var b=[];

		for (i=j=0;i<4;i++,j+=4) 
		{
			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
			this.table[0][i]=GCM.pack(b);
		}
		for (i=1;i<128;i++)
		{
			c=0;
			for (j=0;j<4;j++) 
			{
				this.table[i][j]=c|(this.table[i-1][j])>>>1; 
				c=this.table[i-1][j]<<31;
			}
			if (c!==0) this.table[i][0]^=0xE1000000; /* irreducible polynomial */
		}
	},

	gf2mul: function()
	{ /* gf2m mul - Z=H*X mod 2^128 */
		var i,j,m,k;
		var P=[];
		var c;
		var b=[];

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

	wrap: function()
	{ /* Finish off GHASH */
		var i,j;
		var F=[];
		var L=[];
		var b=[];

/* convert lengths from bytes to bits */
		F[0]=(this.lenA[0]<<3)|(this.lenA[1]&0xE0000000)>>>29;
		F[1]=this.lenA[1]<<3;
		F[2]=(this.lenC[0]<<3)|(this.lenC[1]&0xE0000000)>>>29;
		F[3]=this.lenC[1]<<3;
		for (i=j=0;i<4;i++,j+=4)
		{
			b=GCM.unpack(F[i]);
			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
		}
		for (i=0;i<16;i++) this.stateX[i]^=L[i];
		this.gf2mul();
	},

/* Initialize GCM mode */
	init: function(nk,key,niv,iv)
	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
		var i;
		var H=[];
		var b=[];

		for (i=0;i<16;i++) {H[i]=0; this.stateX[i]=0;}

		this.a.init(ROM.ECB,nk,key,iv);
		this.a.ecb_encrypt(H);     /* E(K,0) */
		this.precompute(H);
	
		this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
		if (niv==12)
		{
			for (i=0;i<12;i++) this.a.f[i]=iv[i];
			b=GCM.unpack(1);
			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3];  /* initialise IV */
			for (i=0;i<16;i++) this.Y_0[i]=this.a.f[i];
		}
		else
		{
			this.status=ROM.GCM_ACCEPTING_CIPHER;
			this.ghash(iv,niv); /* GHASH(H,0,IV) */
			this.wrap();
			for (i=0;i<16;i++) {this.a.f[i]=this.stateX[i];this.Y_0[i]=this.a.f[i];this.stateX[i]=0;}
			this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
		}
		this.status=ROM.GCM_ACCEPTING_HEADER;
	},

/* Add Header data - included but not encrypted */
	add_header: function(header,len)
	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
		var i,j=0;
		if (this.status!=ROM.GCM_ACCEPTING_HEADER) return false;

		while (j<len)
		{
			for (i=0;i<16 && j<len;i++)
			{
				this.stateX[i]^=header[j++];
				this.lenA[1]++; this.lenA[1]|=0; if (this.lenA[1]===0) this.lenA[0]++;
			}
			this.gf2mul();
		}
		if (len%16!==0) this.status=ROM.GCM_ACCEPTING_CIPHER;
		return true;
	},

	ghash: function(plain,len)
	{
		var i,j=0;

		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return false;
		
		while (j<len)
		{
			for (i=0;i<16 && j<len;i++)
			{
				this.stateX[i]^=plain[j++];
				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
			}
			this.gf2mul();
		}
		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
		return true;
	},

/* Add Plaintext - included and encrypted */
	add_plain: function(plain,len)
	{
		var i,j=0;
		var B=[];
		var b=[];
		var cipher=[];

		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return cipher;
		
		while (j<len)
		{

			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
			this.counter=GCM.pack(b);
			this.counter++;
			b=GCM.unpack(this.counter);
			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
			for (i=0;i<16;i++) B[i]=this.a.f[i];
			this.a.ecb_encrypt(B);        /* encrypt it  */
		
			for (i=0;i<16 && j<len;i++)
			{
				cipher[j]=(plain[j]^B[i]);
				this.stateX[i]^=cipher[j++];
				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
			}
			this.gf2mul();
		}
		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
		return cipher;
	},

/* Add Ciphertext - decrypts to plaintext */
	add_cipher: function(cipher,len)
	{
		var i,j=0;
		var B=[];
		var b=[];
		var plain=[];

		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return plain;
	
		while (j<len)
		{
			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
			this.counter=GCM.pack(b);
			this.counter++;
			b=GCM.unpack(this.counter);
			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
			for (i=0;i<16;i++) B[i]=this.a.f[i];
			this.a.ecb_encrypt(B);        /* encrypt it  */
			for (i=0;i<16 && j<len;i++)
			{
				var oc=cipher[j];
				plain[j]=(cipher[j]^B[i]);
				this.stateX[i]^=oc; j++;
				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
			}
			this.gf2mul();
		}
		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
		return plain;
	},

/* Finish and extract Tag */
	finish: function(extract)
	{ /* Finish off GHASH and extract tag (MAC) */
		var i;
		var tag=[];

		this.wrap();
/* extract tag */
		if (extract)
		{
			this.a.ecb_encrypt(this.Y_0);        /* E(K,Y0) */
			for (i=0;i<16;i++) this.Y_0[i]^=this.stateX[i];
			for (i=0;i<16;i++) {tag[i]=this.Y_0[i];this.Y_0[i]=this.stateX[i]=0;}
		}
		this.status=ROM.GCM_FINISHED;
		this.a.end();
		return tag;
	}

};

GCM.pack= function(b)
{ /* pack 4 bytes into a 32-bit Word */
		return (((b[0])&0xff)<<24)|((b[1]&0xff)<<16)|((b[2]&0xff)<<8)|(b[3]&0xff);
};

GCM.unpack=function(a)
{ /* unpack bytes from a word */
	var b=[];
	b[3]=(a&0xff);
	b[2]=((a>>>8)&0xff);
	b[1]=((a>>>16)&0xff);
	b[0]=((a>>>24)&0xff);
	return b;
};

GCM.hex2bytes=function(s) 
{
	var len = s.length;
	var data = [];
	for (var i = 0; i < len; i += 2) 
		data[i / 2] = parseInt(s.substr(i,2),16);

	return data;
};
