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

/* RSA API high-level functions  */

package main

//import "fmt"

const RSA_RFS int=int(MODBYTES)*FFLEN
const RSA_SHA256 int=32
const RSA_SHA384 int=48
const RSA_SHA512 int=64

const RSA_HASH_TYPE int=RSA_SHA256


type rsa_private_key struct {
	p,q,dp,dq,c *FF
}

func New_rsa_private_key(n int) *rsa_private_key {
	SK:=new(rsa_private_key)
	SK.p=NewFFint(n)
	SK.q=NewFFint(n)
	SK.dp=NewFFint(n)
	SK.dq=NewFFint(n)
	SK.c=NewFFint(n)
	return SK
}

type rsa_public_key struct {
	e int
	n *FF
}

func New_rsa_public_key(m int) *rsa_public_key{
	PK:=new(rsa_public_key)
	PK.e=0
	PK.n=NewFFint(m)
	return PK
}

func hashit(sha int,A []byte,n int) []byte {
	var R []byte
	if sha==RSA_SHA256 {
		H:=NewHASH256()
		if A!=nil {H.Process_array(A)}
		if n>=0 {H.Process_num(int32(n))}
		R=H.Hash()
	}
	if sha==RSA_SHA384 {
		H:=NewHASH384()
		if A!=nil {H.Process_array(A)}
		if n>=0 {H.Process_num(int32(n))}
		R=H.Hash()
	}
	if sha==RSA_SHA512 {
		H:=NewHASH512()
		if A!=nil {H.Process_array(A)}
		if n>=0 {H.Process_num(int32(n))}
		R=H.Hash()
	}
	return R
}

func RSA_KEY_PAIR(rng *RAND,e int,PRIV *rsa_private_key,PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */
	n:=PUB.n.getlen()/2
	t:=NewFFint(n)
	p1:=NewFFint(n)
	q1:=NewFFint(n)

	for true {
		PRIV.p.random(rng)
		for PRIV.p.lastbits(2)!=3 {PRIV.p.inc(1)}	
		for !prime(PRIV.p,rng) {
			PRIV.p.inc(4)
		}
			
		p1.copy(PRIV.p)
		p1.dec(1)

		if p1.cfactor(e) {continue}
		break;
	}

	for true {
		PRIV.q.random(rng);
		for PRIV.q.lastbits(2)!=3 {PRIV.q.inc(1)}
		for !prime(PRIV.q,rng) {
			PRIV.q.inc(4)
		}
			
		q1.copy(PRIV.q);
		q1.dec(1);

		if q1.cfactor(e) {continue}

		break;
	}
	
	PUB.n=ff_mul(PRIV.p,PRIV.q);
	PUB.e=e;

	t.copy(p1)
	t.shr()
	PRIV.dp.set(e)
	PRIV.dp.invmodp(t)
	if PRIV.dp.parity()==0 {PRIV.dp.add(t)}
	PRIV.dp.norm();

	t.copy(q1)
	t.shr()
	PRIV.dq.set(e)
	PRIV.dq.invmodp(t)
	if PRIV.dq.parity()==0 {PRIV.dq.add(t)}
	PRIV.dq.norm()

	PRIV.c.copy(PRIV.p)
	PRIV.c.invmodp(PRIV.q)

}

/* Mask Generation Function */

func RSA_MGF1(sha int,Z []byte,olen int,K []byte) {
	hlen:=sha

	var k int=0
	for i:=0;i<len(K);i++ {K[i]=0}

	cthreshold:=olen/hlen 
	if olen%hlen!=0 {cthreshold++}
	for counter:=0;counter<cthreshold;counter++ {
		B:=hashit(sha,Z,counter)

		if (k+hlen>olen) {
			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
		} else {
			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
		}
	}	
}

/* SHAXXX identifier strings */
var SHA256ID= [...]byte {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}
var SHA384ID= [...]byte {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
var SHA512ID= [...]byte {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};

func PKCS15(sha int,m []byte,w []byte) bool {
	olen:=FF_BITS/8
	hlen:=sha
	idlen:=19

	if olen<idlen+hlen+10 {return false}
	H:=hashit(sha,m,-1)

	for i:=0;i<len(w);i++ {w[i]=0}
	i:=0
	w[i]=0; i++
	w[i]=1; i++
	for j:=0;j<olen-idlen-hlen-3;j++ {w[i]=0xff; i++}
	w[i]=0; i++

	if hlen==RSA_SHA256 {
		for j:=0;j<idlen;j++ {w[i]=SHA256ID[j]; i++}
	}
	if hlen==RSA_SHA384 {
		for j:=0;j<idlen;j++ {w[i]=SHA384ID[j]; i++}
	}
	if hlen==RSA_SHA512 {
		for j:=0;j<idlen;j++ {w[i]=SHA512ID[j]; i++}
	}
	for j:=0;j<hlen;j++ {w[i]=H[j]; i++}

	return true
}


/* OAEP Message Encoding for Encryption */
func RSA_OAEP_ENCODE(sha int,m []byte,rng *RAND,p []byte) []byte { 
	olen:=RSA_RFS-1
	mlen:=len(m)
	var f [RSA_RFS]byte

	hlen:=sha

	SEED:=make([]byte,hlen);

	seedlen:=hlen
	if (mlen>olen-hlen-seedlen-1) {return nil} 

	DBMASK:=make([]byte,olen-seedlen)

	h:=hashit(sha,p,-1);

	for i:=0;i<hlen;i++ {f[i]=h[i]}

	slen:=olen-mlen-hlen-seedlen-1      

	for i:=0;i<slen;i++ {f[hlen+i]=0}
	f[hlen+slen]=1
	for i:=0;i<mlen;i++ {f[hlen+slen+1+i]=m[i]}

	for i:=0;i<seedlen;i++ {SEED[i]=rng.GetByte()}
	RSA_MGF1(sha,SEED,olen-seedlen,DBMASK)

	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}

	RSA_MGF1(sha,DBMASK,seedlen,f[:])

	for i:=0;i<seedlen;i++ {f[i]^=SEED[i]}

	for i:=0;i<olen-seedlen;i++ {f[i+seedlen]=DBMASK[i]}

	/* pad to length RFS */
	d:=1
	for i:=RSA_RFS-1;i>=d;i-- {
		f[i]=f[i-d]
	}
	for i:=d-1;i>=0;i-- {
		f[i]=0
	}
	return f[:]
}

/* OAEP Message Decoding for Decryption */
func RSA_OAEP_DECODE(sha int,p []byte,f []byte) [] byte {
	olen:=RSA_RFS-1

	hlen:=sha
	SEED:=make([]byte,hlen)
	seedlen:=hlen;
	CHASH:=make([]byte,hlen)
	
	if olen<seedlen+hlen+1 {return nil}
	DBMASK:=make([]byte,olen-seedlen)
	for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}

	if len(f)<RSA_RFS {
		d:=RSA_RFS-len(f)
		for i:=RSA_RFS-1;i>=d;i-- {
			f[i]=f[i-d]
		}
		for i:=d-1;i>=0;i-- {
			f[i]=0
		}
	}

	h:=hashit(sha,p,-1)
	for i:=0;i<hlen;i++ {CHASH[i]=h[i]}

	x:=f[0]

	for i:=seedlen;i<olen;i++ {
		DBMASK[i-seedlen]=f[i+1]
	}

	RSA_MGF1(sha,DBMASK,seedlen,SEED)
	for i:=0;i<seedlen;i++ {SEED[i]^=f[i+1]}
	RSA_MGF1(sha,SEED,olen-seedlen,f)
	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}

	comp:=true
	for i:=0;i<hlen;i++ {
		if CHASH[i]!=DBMASK[i] {comp=false}
	}

	for i:=0;i<olen-seedlen-hlen;i++ {
		DBMASK[i]=DBMASK[i+hlen]
	}

	for i:=0;i<hlen;i++ {
		SEED[i]=0; CHASH[i]=0
	}
		
	var k int
	for k=0;;k++ {
		if k>=olen-seedlen-hlen {return nil}
		if DBMASK[k]!=0 {break}
	}

	t:=DBMASK[k]
	if (!comp || x!=0 || t!=0x01) {
		for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}
		return nil
	}

	var r = make([]byte,olen-seedlen-hlen-k-1)

	for i:=0;i<olen-seedlen-hlen-k-1;i++ {
		r[i]=DBMASK[i+k+1]
	}
	
	for i:=0;i<olen-seedlen;i++  {DBMASK[i]=0}

	return r
}

/* destroy the Private Key structure */
func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) {
	PRIV.p.zero();
	PRIV.q.zero();
	PRIV.dp.zero();
	PRIV.dq.zero();
	PRIV.c.zero();
}

/* RSA encryption with the public key */
func RSA_ENCRYPT(PUB *rsa_public_key,F []byte,G []byte) {
	n:=PUB.n.getlen()
	f:=NewFFint(n)

	ff_fromBytes(f,F)
	f.power(PUB.e,PUB.n)
	f.toBytes(G)
}

/* RSA decryption with the private key */
func RSA_DECRYPT(PRIV *rsa_private_key,G []byte,F []byte) {
	n:=PRIV.p.getlen()
	g:=NewFFint(2*n)

	ff_fromBytes(g,G);
	jp:=g.dmod(PRIV.p)
	jq:=g.dmod(PRIV.q)

	jp.skpow(PRIV.dp,PRIV.p)
	jq.skpow(PRIV.dq,PRIV.q)

	g.zero()
	g.dscopy(jp)
	jp.mod(PRIV.q)
	if ff_comp(jp,jq)>0 {jq.add(PRIV.q)}
	jq.sub(jp)
	jq.norm()

	t:=ff_mul(PRIV.c,jq)
	jq=t.dmod(PRIV.q)

	t=ff_mul(jq,PRIV.p)
	g.add(t)
	g.norm()

	g.toBytes(F)
}

