// Copyright 2015 The Vanadium 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 !go1.6,!android,linux,amd64,cgo,!noopenssl openssl,cgo

// The purpose of this file is to improve performance, as demonstrated by
// benchmarks when linked against openssl-1.0.1f (with further improvements in
// openssl-1.0.2, at the time this comment was written).
//   go test -bench ECDSA v.io/v23/security
//
// With Go 1.6, the Go standard library will have performance on-par with
// OpenSSL for amd64 (see https://go-review.googlesource.com/#/c/8968/).
// Prior to that however, using OpenSSL (via cgo) provides a significant
// performance improvement.
//
// By default (without an explicit build tag), this is disabled for darwin
// since OpenSSL has been marked deprecated on OS X since version 10.7.  The
// last openssl release on OS X was version 0.9.8 and compiling this file will
// show these deprecation warnings.  Those sensitive to performance are
// encouraged to move to Go 1.6.
//
// Currently, this file is disabled for linux/arm as a temporary hack.  In
// practice, linux/arm binaries are often cross-compiled on a linux/amd64 host.
// The author of this comment hadn't changed the vanadium devtools to download
// and build a cross-compiled OpenSSL library at the time this comment was
// written.
//
// TODO(ashankar): Figure out how to remove the "amd64" tag hack.

package security

// #cgo pkg-config: libcrypto
// #include <openssl/bn.h>
// #include <openssl/ec.h>
// #include <openssl/ecdsa.h>
// #include <openssl/err.h>
// #include <openssl/objects.h>
// #include <openssl/opensslv.h>
// #include <openssl/x509.h>
//
// void openssl_init_locks();
// EC_KEY* openssl_d2i_EC_PUBKEY(const unsigned char** data, long len, unsigned long* e);
// EC_KEY* openssl_d2i_ECPrivateKey(const unsigned char** data, long len, unsigned long* e);
// ECDSA_SIG* openssl_ECDSA_do_sign(const unsigned char* data, int len, EC_KEY* key, unsigned long *e);
import "C"

import (
	"crypto/ecdsa"
	"crypto/x509"
	"fmt"
	"math/big"
	"runtime"
	"sync"
	"unsafe"

	"v.io/v23/verror"
)

var (
	errOpenSSL          = verror.Register(pkgPath+".errOpenSSL", verror.NoRetry, "{1:}{2:} OpenSSL error ({3}): {4} in {5}:{6}")
	errUnsupportedCurve = verror.Register(pkgPath+".errUnsupportedCurve", verror.NoRetry, "{1:}{2:} elliptic curve {3} is not supported")
	opensslLocks        []sync.RWMutex
)

func init() {
	C.ERR_load_crypto_strings()
	opensslLocks = make([]sync.RWMutex, C.CRYPTO_num_locks())
	C.openssl_init_locks()
}

//export openssl_lock
func openssl_lock(mode, n C.int) {
	l := &opensslLocks[int(n)]
	if (mode & C.CRYPTO_LOCK) == 0 {
		if (mode & C.CRYPTO_READ) == 0 {
			l.Unlock()
		} else {
			l.RUnlock()
		}
	} else {
		if (mode & C.CRYPTO_READ) == 0 {
			l.Lock()
		} else {
			l.RLock()
		}
	}
}

type opensslECPublicKey struct {
	k   *C.EC_KEY
	h   Hash
	der []byte
}

func (k *opensslECPublicKey) MarshalBinary() ([]byte, error) {
	cpy := make([]byte, len(k.der))
	copy(cpy, k.der)
	return cpy, nil
}
func (k *opensslECPublicKey) String() string { return publicKeyString(k) }
func (k *opensslECPublicKey) hash() Hash     { return k.h }
func (k *opensslECPublicKey) verify(digest []byte, signature *Signature) bool {
	sig := C.ECDSA_SIG_new()
	sig.r = C.BN_bin2bn(uchar(signature.R), C.int(len(signature.R)), sig.r)
	sig.s = C.BN_bin2bn(uchar(signature.S), C.int(len(signature.S)), sig.s)
	status := C.ECDSA_do_verify(uchar(digest), C.int(len(digest)), sig, k.k)
	C.ECDSA_SIG_free(sig)
	return status == 1
}

func newOpenSSLPublicKey(golang *ecdsa.PublicKey) (PublicKey, error) {
	der, err := x509.MarshalPKIXPublicKey(golang)
	if err != nil {
		return nil, err
	}
	return unmarshalPublicKeyImpl(der)
}

type opensslSigner struct {
	k *C.EC_KEY
}

func (k *opensslSigner) sign(data []byte) (r, s *big.Int, err error) {
	var errno C.ulong
	sig := C.openssl_ECDSA_do_sign(uchar(data), C.int(len(data)), k.k, &errno)
	if sig == nil {
		return nil, nil, opensslMakeError(errno)
	}
	var (
		rlen = (int(C.BN_num_bits(sig.r)) + 7) / 8
		slen = (int(C.BN_num_bits(sig.s)) + 7) / 8
		buf  []byte
	)
	if rlen > slen {
		buf = make([]byte, rlen)
	} else {
		buf = make([]byte, slen)
	}
	r = big.NewInt(0).SetBytes(buf[0:int(C.BN_bn2bin(sig.r, uchar(buf)))])
	s = big.NewInt(0).SetBytes(buf[0:int(C.BN_bn2bin(sig.s, uchar(buf)))])
	C.ECDSA_SIG_free(sig)
	return r, s, nil
}

func newOpenSSLSigner(golang *ecdsa.PrivateKey) (Signer, error) {
	der, err := x509.MarshalECPrivateKey(golang)
	if err != nil {
		return nil, err
	}
	pubkey, err := newOpenSSLPublicKey(&golang.PublicKey)
	if err != nil {
		return nil, err
	}
	var errno C.ulong
	in := uchar(der)
	k := C.openssl_d2i_ECPrivateKey(&in, C.long(len(der)), &errno)
	if k == nil {
		return nil, opensslMakeError(errno)
	}
	impl := &opensslSigner{k}
	runtime.SetFinalizer(impl, func(k *opensslSigner) { C.EC_KEY_free(k.k) })
	return &ecdsaSigner{
		sign: func(data []byte) (r, s *big.Int, err error) {
			return impl.sign(data)
		},
		pubkey: pubkey,
		impl:   impl,
	}, nil
}

func opensslMakeError(errno C.ulong) error {
	return verror.New(errOpenSSL, nil, errno, C.GoString(C.ERR_func_error_string(errno)), C.GoString(C.ERR_lib_error_string(errno)), C.GoString(C.ERR_reason_error_string(errno)))
}

func uchar(b []byte) *C.uchar {
	if len(b) == 0 {
		return nil
	}
	return (*C.uchar)(unsafe.Pointer(&b[0]))
}

func openssl_version() string {
	return fmt.Sprintf("%v (CFLAGS:%v)", C.GoString(C.SSLeay_version(C.SSLEAY_VERSION)), C.GoString(C.SSLeay_version(C.SSLEAY_CFLAGS)))
}

func openssl_hash_for_key(k *C.EC_KEY) (Hash, error) {
	switch nid := C.EC_GROUP_get_curve_name(C.EC_KEY_get0_group(k)); nid {
	case C.NID_secp224r1, C.NID_X9_62_prime256v1:
		return SHA256Hash, nil
	case C.NID_secp384r1:
		return SHA384Hash, nil
	case C.NID_secp521r1:
		return SHA512Hash, nil
	default:
		var h Hash
		return h, verror.New(errUnsupportedCurve, nil, C.GoString(C.OBJ_nid2sn(C.int(nid))))
	}
}

func newInMemoryECDSASignerImpl(key *ecdsa.PrivateKey) (Signer, error) {
	return newOpenSSLSigner(key)
}

func newECDSAPublicKeyImpl(key *ecdsa.PublicKey) PublicKey {
	if key, err := newOpenSSLPublicKey(key); err == nil {
		return key
	}
	return newGoStdlibPublicKey(key)
}

func unmarshalPublicKeyImpl(der []byte) (PublicKey, error) {
	var errno C.ulong
	in := uchar(der)
	k := C.openssl_d2i_EC_PUBKEY(&in, C.long(len(der)), &errno)
	if k == nil {
		return nil, opensslMakeError(errno)
	}
	h, err := openssl_hash_for_key(k)
	if err != nil {
		return nil, err
	}
	dercpy := make([]byte, len(der))
	copy(dercpy, der)
	ret := &opensslECPublicKey{k, h, dercpy}
	runtime.SetFinalizer(ret, func(k *opensslECPublicKey) { C.EC_KEY_free(k.k) })
	return ret, nil
}
