// Code generated by cmd/cgo; DO NOT EDIT.

//line /builddir/build/BUILD/go-go-1.11.6-5-openssl-fips/src/crypto/internal/boring/ecdsa.go:1:1
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux
// +build !android
// +build !no_openssl
// +build !cmd_go_bootstrap
// +build !msan

package boring

// #include "goboringcrypto.h"
import _ "unsafe"
import (
	"crypto"
	"encoding/asn1"
	"errors"
	"math/big"
	"runtime"
	"unsafe"
)

type ecdsaSignature struct {
	R, S *big.Int
}

type PrivateKeyECDSA struct {
	key *_Ctype_struct_ec_key_st
}

func (k *PrivateKeyECDSA) finalize() {
	func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(k.key)
}

type PublicKeyECDSA struct {
	key *_Ctype_struct_ec_key_st
}

func (k *PublicKeyECDSA) finalize() {
	func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(k.key)
}

var errUnknownCurve = errors.New("boringcrypto: unknown elliptic curve")
var errUnsupportedCurve = errors.New("boringcrypto: unsupported elliptic curve")

func curveNID(curve string) (_Ctype_int, error) {
	switch curve {
	case "P-224":
		return 0, errUnsupportedCurve
	case "P-256":
		return (_Ciconst_GO_NID_X9_62_prime256v1), nil
	case "P-384":
		return (_Ciconst_GO_NID_secp384r1), nil
	case "P-521":
		return (_Ciconst_GO_NID_secp521r1), nil
	}
	return 0, errUnknownCurve
}

func NewPublicKeyECDSA(curve string, X, Y *big.Int) (*PublicKeyECDSA, error) {
	key, err := newECKey(curve, X, Y)
	if err != nil {
		return nil, err
	}
	k := &PublicKeyECDSA{key}
	// Note: Because of the finalizer, any time k.key is passed to cgo,
	// that call must be followed by a call to runtime.KeepAlive(k),
	// to make sure k is not collected (and finalized) before the cgo
	// call returns.
	runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize)
	return k, nil
}

func newECKey(curve string, X, Y *big.Int) (*_Ctype_struct_ec_key_st, error) {
	nid, err := curveNID(curve)
	if err != nil {
		return nil, err
	}
	key := (_Cfunc__goboringcrypto_EC_KEY_new_by_curve_name)(nid)
	if key == nil {
		return nil, fail("EC_KEY_new_by_curve_name")
	}
	group := func(_cgo0 *_Ctype_struct_ec_key_st) *_Ctype_struct_ec_group_st {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_KEY_get0_group)(_cgo0);}(key)
	pt := func(_cgo0 *_Ctype_struct_ec_group_st) *_Ctype_struct_ec_point_st {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_POINT_new)(_cgo0);}(group)
	if pt == nil {
		func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(key)
		return nil, fail("EC_POINT_new")
	}
	bx := bigToBN(X)
	by := bigToBN(Y)
	ok := bx != nil && by != nil && func(_cgo0 *_Ctype_struct_ec_group_st, _cgo1 *_Ctype_struct_ec_point_st, _cgo2 *_Ctype_struct_bignum_st, _cgo3 *_Ctype_struct_bignum_st, _cgo4 *_Ctype_struct_bignum_ctx) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo1);	_cgoCheckPointer(_cgo2);	_cgoCheckPointer(_cgo3);	return (_Cfunc__goboringcrypto_EC_POINT_set_affine_coordinates_GFp)(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4);}(group, pt, bx, by, nil) != 0 &&
		func(_cgo0 *_Ctype_struct_ec_key_st, _cgo1 *_Ctype_struct_ec_point_st) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo1);	return (_Cfunc__goboringcrypto_EC_KEY_set_public_key)(_cgo0, _cgo1);}(key, pt) != 0
	if bx != nil {
		func(_cgo0 *_Ctype_struct_bignum_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_BN_free)(_cgo0);}(bx)
	}
	if by != nil {
		func(_cgo0 *_Ctype_struct_bignum_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_BN_free)(_cgo0);}(by)
	}
	func(_cgo0 *_Ctype_struct_ec_point_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_POINT_free)(_cgo0);}(pt)
	if !ok {
		func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(key)
		return nil, fail("EC_POINT_set_affine_coordinates_GFp")
	}
	return key, nil
}

func NewPrivateKeyECDSA(curve string, X, Y *big.Int, D *big.Int) (*PrivateKeyECDSA, error) {
	key, err := newECKey(curve, X, Y)
	if err != nil {
		return nil, err
	}
	bd := bigToBN(D)
	ok := bd != nil && func(_cgo0 *_Ctype_struct_ec_key_st, _cgo1 *_Ctype_struct_bignum_st) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo1);	return (_Cfunc__goboringcrypto_EC_KEY_set_private_key)(_cgo0, _cgo1);}(key, bd) != 0
	if bd != nil {
		func(_cgo0 *_Ctype_struct_bignum_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_BN_free)(_cgo0);}(bd)
	}
	if !ok {
		func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(key)
		return nil, fail("EC_KEY_set_private_key")
	}
	k := &PrivateKeyECDSA{key}
	// Note: Because of the finalizer, any time k.key is passed to cgo,
	// that call must be followed by a call to runtime.KeepAlive(k),
	// to make sure k is not collected (and finalized) before the cgo
	// call returns.
	runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize)
	return k, nil
}

func SignECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) (r, s *big.Int, err error) {
	// We could use ECDSA_do_sign instead but would need to convert
	// the resulting BIGNUMs to *big.Int form. If we're going to do a
	// conversion, converting the ASN.1 form is more convenient and
	// likely not much more expensive.
	sig, err := SignMarshalECDSA(priv, hash, h)
	if err != nil {
		return nil, nil, err
	}
	var esig ecdsaSignature
	if _, err := asn1.Unmarshal(sig, &esig); err != nil {
		return nil, nil, err
	}
	return esig.R, esig.S, nil
}

func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) ([]byte, error) {
	size := func(_cgo0 *_Ctype_struct_ec_key_st) _Ctype_size_t {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_ECDSA_size)(_cgo0);}(priv.key)
	sig := make([]byte, size)
	md := cryptoHashToMD(h)
	if md == nil {
		panic("boring: invalid hash")
	}
	var sigLen _Ctype_size_t
	if func(_cgo0 *_Ctype_struct_env_md_st, _cgo1 *_Ctype_uint8_t, _cgo2 _Ctype_size_t, _cgo3 *_Ctype_uint8_t, _cgo4 *_Ctype_size_t, _cgo5 *_Ctype_struct_ec_key_st) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo5);	return (_Cfunc__goboringcrypto_ECDSA_sign)(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4, _cgo5);}(md, base(hash), _Ctype_size_t(len(hash)), (*_Ctype_uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 {
		return nil, fail("ECDSA_sign")
	}
	runtime.KeepAlive(priv)
	return sig[:sigLen], nil
}

func VerifyECDSA(pub *PublicKeyECDSA, msg []byte, r, s *big.Int, h crypto.Hash) bool {
	// We could use ECDSA_do_verify instead but would need to convert
	// r and s to BIGNUM form. If we're going to do a conversion, marshaling
	// to ASN.1 is more convenient and likely not much more expensive.
	sig, err := asn1.Marshal(ecdsaSignature{r, s})
	if err != nil {
		return false
	}
	md := cryptoHashToMD(h)
	if md == nil {
		panic("boring: invalid hash")
	}
	ok := func(_cgo0 *_Ctype_struct_env_md_st, _cgo1 *_Ctype_uint8_t, _cgo2 _Ctype_size_t, _cgo3 *_Ctype_uint8_t, _cgo4 _Ctype_size_t, _cgo5 *_Ctype_struct_ec_key_st) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo5);	return (_Cfunc__goboringcrypto_ECDSA_verify)(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4, _cgo5);}(md, base(msg), _Ctype_size_t(len(msg)), (*_Ctype_uint8_t)(unsafe.Pointer(&sig[0])), _Ctype_size_t(len(sig)), pub.key) > 0
	runtime.KeepAlive(pub)
	return ok
}

func GenerateKeyECDSA(curve string) (X, Y, D *big.Int, err error) {
	nid, err := curveNID(curve)
	if err != nil {
		return nil, nil, nil, err
	}
	key := (_Cfunc__goboringcrypto_EC_KEY_new_by_curve_name)(nid)
	if key == nil {
		return nil, nil, nil, fail("EC_KEY_new_by_curve_name")
	}
	defer func(_cgo0 *_Ctype_struct_ec_key_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_EC_KEY_free)(_cgo0);}(key)
	if func(_cgo0 *_Ctype_struct_ec_key_st) _Ctype_int {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_KEY_generate_key)(_cgo0);}(key) == 0 {
		return nil, nil, nil, fail("EC_KEY_generate_key")
	}
	group := func(_cgo0 *_Ctype_struct_ec_key_st) *_Ctype_struct_ec_group_st {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_KEY_get0_group)(_cgo0);}(key)
	pt := func(_cgo0 *_Ctype_struct_ec_key_st) *_Ctype_struct_ec_point_st {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_KEY_get0_public_key)(_cgo0);}(key)
	bd := func(_cgo0 *_Ctype_struct_ec_key_st) *_Ctype_struct_bignum_st {;	_cgoCheckPointer(_cgo0);	return (_Cfunc__goboringcrypto_EC_KEY_get0_private_key)(_cgo0);}(key)
	if pt == nil || bd == nil {
		return nil, nil, nil, fail("EC_KEY_get0_private_key")
	}
	bx := (_Cfunc__goboringcrypto_BN_new)()
	if bx == nil {
		return nil, nil, nil, fail("BN_new")
	}
	defer func(_cgo0 *_Ctype_struct_bignum_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_BN_free)(_cgo0);}(bx)
	by := (_Cfunc__goboringcrypto_BN_new)()
	if by == nil {
		return nil, nil, nil, fail("BN_new")
	}
	defer func(_cgo0 *_Ctype_struct_bignum_st) {;	_cgoCheckPointer(_cgo0);	(_Cfunc__goboringcrypto_BN_free)(_cgo0);}(by)
	if func(_cgo0 *_Ctype_struct_ec_group_st, _cgo1 *_Ctype_struct_ec_point_st, _cgo2 *_Ctype_struct_bignum_st, _cgo3 *_Ctype_struct_bignum_st, _cgo4 *_Ctype_struct_bignum_ctx) _Ctype_int {;	_cgoCheckPointer(_cgo0);	_cgoCheckPointer(_cgo1);	_cgoCheckPointer(_cgo2);	_cgoCheckPointer(_cgo3);	return (_Cfunc__goboringcrypto_EC_POINT_get_affine_coordinates_GFp)(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4);}(group, pt, bx, by, nil) == 0 {
		return nil, nil, nil, fail("EC_POINT_get_affine_coordinates_GFp")
	}
	return bnToBig(bx), bnToBig(by), bnToBig(bd), nil
}
