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

var ECDH = {

	INVALID_PUBLIC_KEY:-2,
	ERROR:-3,
	INVALID:-4,
	EFS:ROM.MODBYTES,
	EGS:ROM.MODBYTES,
	EAS:16,
	EBS:16,

	/* Convert Integer to n-byte array */
	inttobytes: function(n,len)
	{
		var i;
		var b=[];

		for (i=0;i<len;i++) b[i]=0;
		i=len;
		while (n>0 && i>0)
		{
			i--;
			b[i]=(n&0xff);
			n=Math.floor(n/256);
		}
		return b;
	},

	bytestostring: function(b)
	{
		var s="";
		var len=b.length;
		var ch;

		for (var i=0;i<len;i++)
		{
			ch=b[i];
			s+=((ch>>>4)&15).toString(16);
			s+=(ch&15).toString(16);

		}
		return s;
	},

	stringtobytes: function(s)
	{
		var b=[];
		for (var i=0;i<s.length;i++)
			b.push(s.charCodeAt(i));
		return b;
	},


	KDF1: function(Z,olen)
	{
/* NOTE: the parameter olen is the length of the output K in bytes */
		var H=new HASH();
		var i,hlen=32;
		var K=[];

		var B=[];
		var counter,cthreshold,k=0;

		for (i=0;i<K.length;i++) K[i]=0;  // redundant?

		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;

		for (counter=0;counter<cthreshold;counter++)
		{
			H.process_array(Z); if (counter>0) H.process_num(counter);
			B=H.hash();
			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
			else for (i=0;i<hlen;i++) K[k++]=B[i];
		}
		return K;
	},

	KDF2: function(Z,P,olen)
	{
/* NOTE: the parameter olen is the length of the output k in bytes */
		var H=new HASH();
		var i,hlen=32;
		var K=[];

		var B=[];
		var counter,cthreshold,k=0;

		for (i=0;i<K.length;i++) K[i]=0;  // redundant?

		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;

		for (counter=1;counter<=cthreshold;counter++)
		{
			H.process_array(Z); H.process_num(counter); H.process_array(P);
			B=H.hash();
			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
			else for (i=0;i<hlen;i++) K[k++]=B[i];
		}
		return K;
	},

/* Password based Key Derivation Function */
/* Input password p, salt s, and repeat count */
/* Output key of length olen */

	PBKDF2: function(Pass,Salt,rep,olen)
	{
		var i,j,k,d,opt;
		d=Math.floor(olen/32); if (olen%32!==0) d++;
		var F=new Array(this.EFS);
		var U=[];
		var S=[];

		var K=[];
		opt=0;

		for (i=1;i<=d;i++)
		{
			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
			var N=this.inttobytes(i,4);
			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
			this.HMAC(S,Pass,F);
			for (j=0;j<this.EFS;j++) U[j]=F[j];
			for (j=2;j<=rep;j++)
			{
				this.HMAC(U,Pass,U);
				for (k=0;k<this.EFS;k++) F[k]^=U[k];
			}
			for (j=0;j<this.EFS;j++) K[opt++]=F[j];
		}
		var key=[];
		for (i=0;i<olen;i++) key[i]=K[i];
		return key;
	},

	HMAC: function(M,K,tag)
	{
	/* Input is from an octet m        *
	* olen is requested output length in bytes. k is the key  *
	* The output is the calculated tag */
		var i,b;
		var B=[];
		var K0=new Array(64);
		var olen=tag.length;

		b=K0.length;
		if (olen<4 || olen>32) return 0;

		for (i=0;i<b;i++) K0[i]=0;

		var H=new HASH();

		if (K.length > b)
		{
			H.process_array(K); B=H.hash();
			for (i=0;i<32;i++) K0[i]=B[i];
		}
		else
			for (i=0;i<K.length;i++) K0[i]=K[i];

		for (i=0;i<b;i++) K0[i]^=0x36;
		H.process_array(K0); H.process_array(M); B=H.hash();

		for (i=0;i<b;i++) K0[i]^=0x6a;
		H.process_array(K0); H.process_array(B); B=H.hash();

		for (i=0;i<olen;i++) tag[i]=B[i];

		return 1;
	},

/* AES encryption/decryption */

	AES_CBC_IV0_ENCRYPT: function(K,M)
	{ /* AES CBC encryption, with Null IV and key K */
	/* Input is from an octet string M, output is to an octet string C */
	/* Input is padded as necessary to make up a full final block */
		var a=new AES();
		var fin;
		var i,j,ipt,opt;
		var buff=[];
		/*var clen=16+(Math.floor(M.length/16))*16;*/

		var C=[];
		var padlen;

		a.init(ROM.CBC,K,null);

		ipt=opt=0;
		fin=false;
		for(;;)
		{
			for (i=0;i<16;i++)
			{
				if (ipt<M.length) buff[i]=M[ipt++];
				else {fin=true; break;}
			}
			if (fin) break;
			a.encrypt(buff);
			for (i=0;i<16;i++)
				C[opt++]=buff[i];
		}

/* last block, filled up to i-th index */

		padlen=16-i;
		for (j=i;j<16;j++) buff[j]=padlen;
		a.encrypt(buff);
		for (i=0;i<16;i++)
			C[opt++]=buff[i];
		a.end();
		return C;
	},

	AES_CBC_IV0_DECRYPT: function(K,C)
	{ /* padding is removed */
		var a=new AES();
		var i,ipt,opt,ch;
		var buff=[];
		var MM=[];
		var fin,bad;
		var padlen;
		ipt=opt=0;

		a.init(ROM.CBC,K,null);

		if (C.length===0) return [];
		ch=C[ipt++];

		fin=false;

		for(;;)
		{
			for (i=0;i<16;i++)
			{
				buff[i]=ch;
				if (ipt>=C.length) {fin=true; break;}
				else ch=C[ipt++];
			}
			a.decrypt(buff);
			if (fin) break;
			for (i=0;i<16;i++)
				MM[opt++]=buff[i];
		}

		a.end();
		bad=false;
		padlen=buff[15];
		if (i!=15 || padlen<1 || padlen>16) bad=true;
		if (padlen>=2 && padlen<=16)
			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;

		if (!bad) for (i=0;i<16-padlen;i++)
					MM[opt++]=buff[i];

		var M=[];
		if (bad) return M;

		for (i=0;i<opt;i++) M[i]=MM[i];
		return M;
	},

	KEY_PAIR_GENERATE: function(RNG,S,W)
	{
		var r,gx,gy,s;
		var G,WP;
		var res=0;
		var T=[];
		G=new ECP(0);

		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);

		if (ROM.CURVETYPE!=ROM.MOMTGOMERY)
		{
			gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
			G.setxy(gx,gy);
		}
		else G.setx(gx);

		r=new BIG(0); r.rcopy(ROM.CURVE_Order);

		if (RNG===null)
		{
			s=BIG.fromBytes(S);
		}
		else
		{
			s=BIG.randomnum(r,RNG);

			s.toBytes(T);
			for (var i=0;i<this.EGS;i++) S[i]=T[i];
		}

		WP=G.mul(s);
		WP.toBytes(W);

		return res;
	},

	PUBLIC_KEY_VALIDATE: function(full,W)
	{
		var r;
		var WP=ECP.fromBytes(W);
		var res=0;

		r=new BIG(0); r.rcopy(ROM.CURVE_Order);

		if (WP.is_infinity()) res=this.INVALID_PUBLIC_KEY;

		if (res===0 && full)
		{
			WP=WP.mul(r);
			if (!WP.is_infinity()) res=this.INVALID_PUBLIC_KEY;
		}
		return res;
	},

	ECPSVDP_DH: function(S,WD,Z)
	{
		var r,s;
		var W;
		var res=0;
		var T=[];

		s=BIG.fromBytes(S);

		W=ECP.fromBytes(WD);
		if (W.is_infinity()) res=this.ERROR;

		if (res===0)
		{
			r=new BIG(0); r.rcopy(ROM.CURVE_Order);
			s.mod(r);
			W=W.mul(s);
			if (W.is_infinity()) res=this.ERROR;
			else
			{
				W.getX().toBytes(T);
				for (var i=0;i<this.EFS;i++) Z[i]=T[i];
			}
		}
		return res;
	},

	ECPSP_DSA: function(RNG,S,F,C,D)
	{
		var T=[];
		var i,gx,gy,r,s,f,c,d,u,vx;
		var G,V;

		var H=new HASH();
		H.process_array(F);
		var B=H.hash();

		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);

		G=new ECP(0);
		G.setxy(gx,gy);
		r=new BIG(0); r.rcopy(ROM.CURVE_Order);

		s=BIG.fromBytes(S);
		f=BIG.fromBytes(B);

		c=new BIG(0);
		d=new BIG(0);
		V=new ECP();

		do {
			u=BIG.randomnum(r,RNG);

			V.copy(G);
			V=V.mul(u);
			vx=V.getX();
			c.copy(vx);
			c.mod(r);
			if (c.iszilch()) continue;
			u.invmodp(r);
			d=BIG.modmul(s,c,r);
			d.add(f);
			d=BIG.modmul(u,d,r);
		} while (d.iszilch());

		c.toBytes(T);
		for (i=0;i<this.EFS;i++) C[i]=T[i];
		d.toBytes(T);
		for (i=0;i<this.EFS;i++) D[i]=T[i];
		return 0;
	},

	ECPVP_DSA: function(W,F,C,D)
	{
		var B=[];
		var r,gx,gy,f,c,d,h2;
		var res=0;
		var G,WP,P;

		var H=new HASH();
		H.process_array(F);
		B=H.hash();

		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);

		G=new ECP(0);
		G.setxy(gx,gy);
		r=new BIG(0); r.rcopy(ROM.CURVE_Order);

		c=BIG.fromBytes(C);
		d=BIG.fromBytes(D);
		f=BIG.fromBytes(B);

		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0)
            res=this.INVALID;

		if (res===0)
		{
			d.invmodp(r);
			f=BIG.modmul(f,d,r);
			h2=BIG.modmul(c,d,r);

			WP=ECP.fromBytes(W);
			if (WP.is_infinity()) res=this.ERROR;
			else
			{
				P=new ECP();
				P.copy(WP);
				P=P.mul2(h2,G,f);
				if (P.is_infinity()) res=this.INVALID;
				else
				{
					d=P.getX();
					d.mod(r);
					if (BIG.comp(d,c)!==0) res=this.INVALID;
				}
			}
		}

		return res;
	},

	ECIES_ENCRYPT: function(P1,P2,RNG,W,M,V,T)
	{
		var i;

		var Z=[];
		var VZ=[];
		var K1=[];
		var K2=[];
		var U=[];
		var C=[];

		if (this.KEY_PAIR_GENERATE(RNG,U,V)!==0) return C;
		if (this.ECPSVDP_DH(U,W,Z)!==0) return C;

		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];


		var K=this.KDF2(VZ,P1,EFS);

		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];}

		C=this.AES_CBC_IV0_ENCRYPT(K1,M);

		var L2=this.inttobytes(P2.length,8);

		var AC=[];
		for (i=0;i<C.length;i++) AC[i]=C[i];
		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];

		this.HMAC(AC,K2,T);

		return C;
	},

	ECIES_DECRYPT: function(P1,P2,V,C,T,U)
	{

		var i;

		var Z=[];
		var VZ=[];
		var K1=[];
		var K2=[];
		var TAG=new Array(T.length);
		var M=[];

		if (this.ECPSVDP_DH(U,V,Z)!==0) return M;

		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];

		var K=this.KDF2(VZ,P1,this.EFS);

		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];}

		M=this.AES_CBC_IV0_DECRYPT(K1,C);

		if (M.length===0) return M;

		var L2=this.inttobytes(P2.length,8);

		var AC=[];

		for (i=0;i<C.length;i++) AC[i]=C[i];
		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];

		this.HMAC(AC,K2,TAG);

		var same=true;
		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
		if (!same) return [];

		return M;
	}
};
