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

//line /builddir/build/BUILD/go-go-1.12.8-2-openssl-fips/src/crypto/internal/boring/hmac.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"
	"hash"
	"runtime"
	"unsafe"
)

// hashToMD converts a hash.Hash implementation from this package
// to a BoringCrypto *C.GO_EVP_MD.
func hashToMD(h hash.Hash) * /*line :24:29*/_Ctype_struct_env_md_st /*line :24:40*/ {
	switch h.(type) {
	case *sha1Hash:
		return ( /*line :27:10*/_Cfunc__goboringcrypto_EVP_sha1 /*line :27:35*/)()
	case *sha224Hash:
		return ( /*line :29:10*/_Cfunc__goboringcrypto_EVP_sha224 /*line :29:37*/)()
	case *sha256Hash:
		return ( /*line :31:10*/_Cfunc__goboringcrypto_EVP_sha256 /*line :31:37*/)()
	case *sha384Hash:
		return ( /*line :33:10*/_Cfunc__goboringcrypto_EVP_sha384 /*line :33:37*/)()
	case *sha512Hash:
		return ( /*line :35:10*/_Cfunc__goboringcrypto_EVP_sha512 /*line :35:37*/)()
	}
	return nil
}

// cryptoHashToMD converts a crypto.Hash
// to a BoringCrypto *C.GO_EVP_MD.
func cryptoHashToMD(ch crypto.Hash) * /*line :42:38*/_Ctype_struct_env_md_st /*line :42:49*/ {
	switch ch {
	case crypto.MD5:
		return ( /*line :45:10*/_Cfunc__goboringcrypto_EVP_md5 /*line :45:34*/)()
	case crypto.MD5SHA1:
		return ( /*line :47:10*/_Cfunc__goboringcrypto_EVP_md5_sha1 /*line :47:39*/)()
	case crypto.SHA1:
		return ( /*line :49:10*/_Cfunc__goboringcrypto_EVP_sha1 /*line :49:35*/)()
	case crypto.SHA224:
		return ( /*line :51:10*/_Cfunc__goboringcrypto_EVP_sha224 /*line :51:37*/)()
	case crypto.SHA256:
		return ( /*line :53:10*/_Cfunc__goboringcrypto_EVP_sha256 /*line :53:37*/)()
	case crypto.SHA384:
		return ( /*line :55:10*/_Cfunc__goboringcrypto_EVP_sha384 /*line :55:37*/)()
	case crypto.SHA512:
		return ( /*line :57:10*/_Cfunc__goboringcrypto_EVP_sha512 /*line :57:37*/)()
	}
	return nil
}

// NewHMAC returns a new HMAC using BoringCrypto.
// The function h must return a hash implemented by
// BoringCrypto (for example, h could be boring.NewSHA256).
// If h is not recognized, NewHMAC returns nil.
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash {
	ch := h()
	md := hashToMD(ch)
	if md == nil {
		return nil
	}

	var hkey []byte
	if key != nil && len(key) > 0 {
		// Note: Could hash down long keys here using EVP_Digest.
		hkey = make([]byte, len(key))
		copy(hkey, key)
	} else {
		// This is supported in BoringSSL/Standard lib and as such
		// we must support it here. When using HMAC with a null key
		// HMAC_Init will try and reuse the key from the ctx. This is
		// not the bahavior previously implemented, so as a workaround
		// we pass an "empty" key.
		hkey = make([]byte, ( /*line :84:23*/_Ciconst_EVP_MAX_MD_SIZE /*line :84:39*/))
	}
	hmac := &boringHMAC{
		md:        md,
		size:      ch.Size(),
		blockSize: ch.BlockSize(),
		key:       hkey,
		ctx:       ( /*line :91:14*/_Cfunc__goboringcrypto_HMAC_CTX_new /*line :91:43*/)(),
	}
	hmac.Reset()
	return hmac
}

type boringHMAC struct {
	md          * /*line :98:15*/_Ctype_struct_env_md_st /*line :98:26*/
	ctx         * /*line :99:15*/_Ctype_struct_hmac_ctx_st /*line :99:28*/
	ctx2        * /*line :100:15*/_Ctype_struct_hmac_ctx_st /*line :100:28*/
	size        int
	blockSize   int
	key         []byte
	sum         []byte
	needCleanup bool
}

func (h *boringHMAC) Reset() {
	if !h.needCleanup {
		h.needCleanup = true
		// Note: Because of the finalizer, any time h.ctx is passed to cgo,
		// that call must be followed by a call to runtime.KeepAlive(h),
		// to make sure h is not collected (and finalized) before the cgo
		// call returns.
		runtime.SetFinalizer(h, (*boringHMAC).finalize)
	}
	func() { _cgo0 := /*line :117:35*/h.ctx; _cgoCheckPointer(_cgo0); _Cfunc__goboringcrypto_HMAC_CTX_reset(_cgo0); }()

	if func() _Ctype_int{ _cgo0 := /*line :119:36*/h.ctx; _cgo1 := /*line :119:43*/unsafe.Pointer(base(h.key)); var _cgo2 _Ctype_int = _Ctype_int(len(h.key)); _cgo3 := /*line :119:91*/h.md; var _cgo4 *_Ctype_struct_engine_st = /*line :119:97*/nil; _cgoCheckPointer(_cgo0); _cgoCheckPointer(_cgo1); _cgoCheckPointer(_cgo3); return _Cfunc__goboringcrypto_HMAC_Init_ex(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }() == 0 {
		panic("boringcrypto: HMAC_Init failed")
	}
	if int(func() _Ctype_size_t{ _cgo0 := /*line :122:37*/h.ctx; _cgoCheckPointer(_cgo0); return _Cfunc__goboringcrypto_HMAC_size(_cgo0); }()) != h.size {
		println("boringcrypto: HMAC size:", func() _Ctype_size_t{ _cgo0 := /*line :123:67*/h.ctx; _cgoCheckPointer(_cgo0); return _Cfunc__goboringcrypto_HMAC_size(_cgo0); }(), "!=", h.size)
		panic("boringcrypto: HMAC size mismatch")
	}
	runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure.
	h.sum = nil
}

func (h *boringHMAC) finalize() {
	func() { _cgo0 := /*line :131:34*/h.ctx; _cgoCheckPointer(_cgo0); _Cfunc__goboringcrypto_HMAC_CTX_free(_cgo0); }()
}

func (h *boringHMAC) Write(p []byte) (int, error) {
	if len(p) > 0 {
		func() _Ctype_int{ _cgo0 := /*line :136:33*/h.ctx; var _cgo1 *_Ctype_uint8_t = /*line :136:40*/(*_Ctype_uint8_t)(unsafe.Pointer(&p[0])); var _cgo2 _Ctype_size_t = _Ctype_size_t(len(p)); _cgoCheckPointer(_cgo0); return _Cfunc__goboringcrypto_HMAC_Update(_cgo0, _cgo1, _cgo2); }()
	}
	runtime.KeepAlive(h)
	return len(p), nil
}

func (h *boringHMAC) Size() int {
	return h.size
}

func (h *boringHMAC) BlockSize() int {
	return h.blockSize
}

func (h *boringHMAC) Sum(in []byte) []byte {
	if h.sum == nil {
		size := h.Size()
		h.sum = make([]byte, size)
	}
	// Make copy of context because Go hash.Hash mandates
	// that Sum has no effect on the underlying stream.
	// In particular it is OK to Sum, then Write more, then Sum again,
	// and the second Sum acts as if the first didn't happen.
	h.ctx2 = ( /*line :159:11*/_Cfunc__goboringcrypto_HMAC_CTX_new /*line :159:40*/)()
	if func() _Ctype_int{ _cgo0 := /*line :160:40*/h.ctx2; _cgo1 := /*line :160:48*/h.ctx; _cgoCheckPointer(_cgo0); _cgoCheckPointer(_cgo1); return _Cfunc__goboringcrypto_HMAC_CTX_copy_ex(_cgo0, _cgo1); }() == 0 {
		panic("boringcrypto: HMAC_CTX_copy_ex failed")
	}
	func() _Ctype_int{ _cgo0 := /*line :163:31*/h.ctx2; var _cgo1 *_Ctype_uint8_t = /*line :163:39*/(*_Ctype_uint8_t)(unsafe.Pointer(&h.sum[0])); var _cgo2 *_Ctype_uint = /*line :163:80*/nil; _cgoCheckPointer(_cgo0); return _Cfunc__goboringcrypto_HMAC_Final(_cgo0, _cgo1, _cgo2); }()
	func() { _cgo0 := /*line :164:34*/h.ctx2; _cgoCheckPointer(_cgo0); _Cfunc__goboringcrypto_HMAC_CTX_free(_cgo0); }()
	return append(in, h.sum...)
}
