mirror of
https://github.com/golang/go
synced 2024-11-26 02:57:57 -07:00
[dev.boringcrypto] crypto/hmac: use BoringCrypto
Change-Id: Id4019d601c615b4835b0337d82be3d508292810e Reviewed-on: https://go-review.googlesource.com/55475 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
parent
96d6718e4f
commit
74e33c43e9
@ -22,6 +22,7 @@ timing side-channels:
|
||||
package hmac
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
)
|
||||
@ -65,6 +66,13 @@ func (h *hmac) Reset() {
|
||||
|
||||
// New returns a new HMAC hash using the given hash.Hash type and key.
|
||||
func New(h func() hash.Hash, key []byte) hash.Hash {
|
||||
if boring.Enabled {
|
||||
hm := boring.NewHMAC(h, key)
|
||||
if hm != nil {
|
||||
return hm
|
||||
}
|
||||
// BoringCrypto did not recognize h, so fall through to standard Go code.
|
||||
}
|
||||
hm := new(hmac)
|
||||
hm.outer = h()
|
||||
hm.inner = h()
|
||||
|
137
src/crypto/internal/boring/hmac.go
Normal file
137
src/crypto/internal/boring/hmac.go
Normal file
@ -0,0 +1,137 @@
|
||||
// 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,amd64
|
||||
// +build !cmd_go_bootstrap
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"hash"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// hashToMD converts a hash.Hash implementation from this package
|
||||
// to a BoringCrypto *C.GO_EVP_MD.
|
||||
func hashToMD(h hash.Hash) *C.GO_EVP_MD {
|
||||
switch h.(type) {
|
||||
case *sha1Hash:
|
||||
return C._goboringcrypto_EVP_sha1()
|
||||
case *sha224Hash:
|
||||
return C._goboringcrypto_EVP_sha224()
|
||||
case *sha256Hash:
|
||||
return C._goboringcrypto_EVP_sha256()
|
||||
case *sha384Hash:
|
||||
return C._goboringcrypto_EVP_sha384()
|
||||
case *sha512Hash:
|
||||
return C._goboringcrypto_EVP_sha512()
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// Note: Could hash down long keys here using EVP_Digest.
|
||||
hkey := make([]byte, len(key))
|
||||
copy(hkey, key)
|
||||
hmac := &boringHMAC{
|
||||
md: md,
|
||||
size: ch.Size(),
|
||||
blockSize: ch.BlockSize(),
|
||||
key: hkey,
|
||||
}
|
||||
hmac.Reset()
|
||||
return hmac
|
||||
}
|
||||
|
||||
type boringHMAC struct {
|
||||
md *C.GO_EVP_MD
|
||||
ctx C.GO_HMAC_CTX
|
||||
size int
|
||||
blockSize int
|
||||
key []byte
|
||||
sum []byte
|
||||
needCleanup bool
|
||||
}
|
||||
|
||||
func (h *boringHMAC) Reset() {
|
||||
if h.needCleanup {
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
|
||||
} else {
|
||||
h.needCleanup = true
|
||||
runtime.SetFinalizer(h, (*boringHMAC).finalize)
|
||||
}
|
||||
C._goboringcrypto_HMAC_CTX_init(&h.ctx)
|
||||
|
||||
if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(&h.key[0]), C.int(len(h.key)), h.md) == 0 {
|
||||
panic("boringcrypto: HMAC_Init failed")
|
||||
}
|
||||
if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size {
|
||||
println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size)
|
||||
panic("boringcrypto: HMAC size mismatch")
|
||||
}
|
||||
h.sum = nil
|
||||
}
|
||||
|
||||
func (h *boringHMAC) finalize() {
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
|
||||
}
|
||||
|
||||
var badSum = make([]byte, 1)
|
||||
|
||||
func (h *boringHMAC) Write(p []byte) (int, error) {
|
||||
if h.sum != nil {
|
||||
h.sum = badSum
|
||||
} else if len(p) > 0 {
|
||||
C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
|
||||
}
|
||||
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)
|
||||
C._goboringcrypto_HMAC_Final(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil)
|
||||
|
||||
// Clean up and disable finalizer since most of the time
|
||||
// there is no Reset coming. If we do get a Reset, we will
|
||||
// re-enable the finalizer. We have a saved copy of the key.
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
|
||||
h.needCleanup = false
|
||||
runtime.SetFinalizer(h, nil)
|
||||
} else if &h.sum[0] == &badSum[0] {
|
||||
// crypto/tls's tls10.MAC method calls Write after Sum,
|
||||
// in an attempt to do more-like-constant-time checksums
|
||||
// during TLS 1.0 SHA1-based MACs. We can't support that,
|
||||
// so we ignore the Write in that case above, but we also
|
||||
// poison h.sum so that future Sum calls panic, to avoid
|
||||
// returning the pre-Write checksum.
|
||||
// We expect no code actually does Sum, Write, Sum.
|
||||
// Under FIPS restrictions, crypto/tls would not use
|
||||
// any SHA1-based MACs anyway.
|
||||
panic("boringcrypto: hmac used with Sum, Write, Sum")
|
||||
}
|
||||
return append(in, h.sum...)
|
||||
}
|
@ -29,3 +29,5 @@ func NewSHA224() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA256() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA384() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA512() hash.Hash { panic("boringcrypto: not available") }
|
||||
|
||||
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: not available") }
|
||||
|
Loading…
Reference in New Issue
Block a user