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

//import "fmt"
import "github.com/milagro-crypto/amcl/version3/go/amcl"

const RFS int = int(MODBYTES) * FFLEN

const RSA_HASH_TYPE int = amcl.SHA256

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

func New_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_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 == amcl.SHA256 {
		H := amcl.NewHASH256()
		if A != nil {
			H.Process_array(A)
		}
		if n >= 0 {
			H.Process_num(int32(n))
		}
		R = H.Hash()
	}
	if sha == amcl.SHA384 {
		H := amcl.NewHASH384()
		if A != nil {
			H.Process_array(A)
		}
		if n >= 0 {
			H.Process_num(int32(n))
		}
		R = H.Hash()
	}
	if sha == amcl.SHA512 {
		H := amcl.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 *amcl.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 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 RSA_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 == amcl.SHA256 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA256ID[j]
			i++
		}
	}
	if hlen == amcl.SHA384 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA384ID[j]
			i++
		}
	}
	if hlen == amcl.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 *amcl.RAND, p []byte) []byte {
	olen := RFS - 1
	mlen := len(m)
	var f [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()
	}
	MGF1(sha, SEED, olen-seedlen, DBMASK)

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

	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 := 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 := 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) < RFS {
		d := RFS - len(f)
		for i := 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]
	}

	MGF1(sha, DBMASK, seedlen, SEED)
	for i := 0; i < seedlen; i++ {
		SEED[i] ^= f[i+1]
	}
	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)
}
