// Copyright 2020 Google LLC
//
// Licensed 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.
//
////////////////////////////////////////////////////////////////////////////////

package subtle

import (
	"bytes"
	"crypto/elliptic"
	"crypto/rand"
	"errors"
	"fmt"
	"math/big"
)

// ECPublicKey represents a elliptic curve public key.
type ECPublicKey struct {
	elliptic.Curve
	Point ECPoint
}

// ECPrivateKey represents a elliptic curve private key.
type ECPrivateKey struct {
	PublicKey ECPublicKey
	D         *big.Int
}

// GetECPrivateKey converts a stored private key to ECPrivateKey.
func GetECPrivateKey(c elliptic.Curve, b []byte) *ECPrivateKey {
	d := new(big.Int)
	d.SetBytes(b)

	x, y := c.Params().ScalarBaseMult(b)
	pub := ECPublicKey{
		Curve: c,
		Point: ECPoint{
			X: x,
			Y: y,
		},
	}
	return &ECPrivateKey{
		PublicKey: pub,
		D:         d,
	}

}

// ECPoint represents a point on the elliptic curve.
type ECPoint struct {
	X, Y *big.Int
}

func (p *ECPrivateKey) getParams() *elliptic.CurveParams {
	return p.PublicKey.Curve.Params()
}

func getModulus(c elliptic.Curve) *big.Int {
	return c.Params().P
}

func fieldSizeInBits(c elliptic.Curve) int {
	t := big.NewInt(1)
	r := t.Sub(getModulus(c), t)
	return r.BitLen()
}

func fieldSizeInBytes(c elliptic.Curve) int {
	return (fieldSizeInBits(c) + 7) / 8
}

func encodingSizeInBytes(c elliptic.Curve, p string) (int, error) {
	cSize := fieldSizeInBytes(c)
	switch p {
	case "UNCOMPRESSED":
		return 2*cSize + 1, nil
	case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED":
		return 2 * cSize, nil
	case "COMPRESSED":
		return cSize + 1, nil
	}
	return 0, fmt.Errorf("invalid point format :%s", p)

}

// PointEncode encodes a point into the format specified.
func PointEncode(c elliptic.Curve, pFormat string, pt ECPoint) ([]byte, error) {
	if !c.IsOnCurve(pt.X, pt.Y) {
		return nil, errors.New("curve check failed")
	}
	cSize := fieldSizeInBytes(c)
	y := pt.Y.Bytes()
	x := pt.X.Bytes()
	switch pFormat {
	case "UNCOMPRESSED":
		encoded := make([]byte, 2*cSize+1)
		copy(encoded[1+2*cSize-len(y):], y)
		copy(encoded[1+cSize-len(x):], x)
		encoded[0] = 4
		return encoded, nil
	case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED":
		encoded := make([]byte, 2*cSize)
		if len(x) > cSize {
			x = bytes.Replace(x, []byte("\x00"), []byte{}, -1)
		}
		if len(y) > cSize {
			y = bytes.Replace(y, []byte("\x00"), []byte{}, -1)
		}
		copy(encoded[2*cSize-len(y):], y)
		copy(encoded[cSize-len(x):], x)
		return encoded, nil
	case "COMPRESSED":
		encoded := make([]byte, cSize+1)
		copy(encoded[1+cSize-len(x):], x)
		encoded[0] = 2
		if pt.Y.Bit(0) > 0 {
			encoded[0] = 3
		}
		return encoded, nil
	}
	return nil, errors.New("invalid point format")

}

// PointDecode decodes a encoded point to return an ECPoint
func PointDecode(c elliptic.Curve, pFormat string, e []byte) (*ECPoint, error) {
	cSize := fieldSizeInBytes(c)
	x, y := new(big.Int), new(big.Int)
	switch pFormat {
	case "UNCOMPRESSED":
		if len(e) != (2*cSize + 1) {
			return nil, errors.New("invalid point size")
		}
		if e[0] != 4 {
			return nil, errors.New("invalid point format")
		}
		x.SetBytes(e[1 : cSize+1])
		y.SetBytes(e[cSize+1:])
		if !c.IsOnCurve(x, y) {
			return nil, errors.New("invalid point")
		}
		return &ECPoint{
			X: x,
			Y: y,
		}, nil
	case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED":
		if len(e) != 2*cSize {
			return nil, errors.New("invalid point size")
		}
		x.SetBytes(e[:cSize])
		y.SetBytes(e[cSize:])
		if !c.IsOnCurve(x, y) {
			return nil, errors.New("invalid point")
		}
		return &ECPoint{
			X: x,
			Y: y,
		}, nil
	case "COMPRESSED":
		if len(e) != cSize+1 {
			return nil, errors.New("compressed point has wrong length")
		}
		lsb := false
		if e[0] == 2 {
			lsb = false
		} else if e[0] == 3 {
			lsb = true
		} else {
			return nil, errors.New("invalid format")
		}
		x := new(big.Int)
		x.SetBytes(e[1:])
		if (x.Sign() == -1) || (x.Cmp(c.Params().P) != -1) {
			return nil, errors.New("x is out of range")
		}
		y := getY(x, lsb, c)
		return &ECPoint{
			X: x,
			Y: y,
		}, nil
	}
	return nil, fmt.Errorf("invalid format: %s", pFormat)
}

func getY(x *big.Int, lsb bool, c elliptic.Curve) *big.Int {
	// y² = x³ - 3x + b
	x3 := new(big.Int).Mul(x, x)
	x3.Mul(x3, x)

	threeX := new(big.Int).Lsh(x, 1)
	threeX.Add(threeX, x)
	b := c.Params().B
	p := c.Params().P

	x3.Sub(x3, threeX)
	x3.Add(x3, b)
	x3.ModSqrt(x3, p)
	e := uint(1)
	if lsb {
		e = 0
	}
	if e == x3.Bit(0) {
		x3 := x3.Sub(p, x3)
		x3.Mod(x3, p)
	}
	return x3
}

func validatePublicPoint(pub *ECPoint, priv *ECPrivateKey) error {
	if priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) {
		return nil
	}
	return errors.New("invalid public key")
}

// ComputeSharedSecret is used to compute a shared secret using given private key and peer public key.
func ComputeSharedSecret(pub *ECPoint, priv *ECPrivateKey) ([]byte, error) {
	if err := validatePublicPoint(pub, priv); err != nil {
		return nil, err
	}

	x, y := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes())

	if x == nil {
		return nil, errors.New("shared key compute error")
	}
	// check if x,y are on the curve
	if err := validatePublicPoint(&ECPoint{X: x, Y: y}, priv); err != nil {
		return nil, errors.New("invalid shared key")
	}

	sharedSecret := make([]byte, maxSharedKeyLength(priv.PublicKey))
	return x.FillBytes(sharedSecret), nil
}

func maxSharedKeyLength(pub ECPublicKey) int {
	return (pub.Curve.Params().BitSize + 7) / 8
}

// GenerateECDHKeyPair will create a new private key for a given curve.
func GenerateECDHKeyPair(c elliptic.Curve) (*ECPrivateKey, error) {
	p, x, y, err := elliptic.GenerateKey(c, rand.Reader)
	if err != nil {
		return nil, err
	}
	return &ECPrivateKey{
		PublicKey: ECPublicKey{
			Curve: c,
			Point: ECPoint{
				X: x,
				Y: y,
			},
		},
		D: new(big.Int).SetBytes(p),
	}, nil

}

// GetCurve returns the elliptic.Curve for a given standard curve name.
func GetCurve(c string) (elliptic.Curve, error) {
	switch c {
	case "secp224r1", "NIST_P224", "P-224":
		return elliptic.P224(), nil
	case "secp256r1", "NIST_P256", "P-256", "EllipticCurveType_NIST_P256":
		return elliptic.P256(), nil
	case "secp384r1", "NIST_P384", "P-384", "EllipticCurveType_NIST_P384":
		return elliptic.P384(), nil
	case "secp521r1", "NIST_P521", "P-521", "EllipticCurveType_NIST_P521":
		return elliptic.P521(), nil
	default:
		return nil, errors.New("unsupported curve")
	}
}
