mirror of
https://github.com/golang/go
synced 2024-11-22 15:44:53 -07:00
crypto/internal/fips/aes/gcm: add GCMForTLS12 and GCMForTLS13
For #69536 Change-Id: I2d7b6e7b9932d0f0f582a5ab0bb871395dc2a1e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/626675 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
parent
b86f770bec
commit
79c0041daf
@ -5,8 +5,11 @@
|
||||
package gcm
|
||||
|
||||
import (
|
||||
"crypto/internal/fips/aes"
|
||||
"crypto/internal/fips/alias"
|
||||
"crypto/internal/fips/drbg"
|
||||
"internal/byteorder"
|
||||
"math"
|
||||
)
|
||||
|
||||
// SealWithRandomNonce encrypts plaintext to out, and writes a random nonce to
|
||||
@ -36,3 +39,98 @@ func SealWithRandomNonce(g *GCM, nonce, out, plaintext, additionalData []byte) {
|
||||
drbg.Read(nonce)
|
||||
seal(out, g, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
// NewGCMForTLS12 returns a new AEAD that works like GCM, but enforces the
|
||||
// construction of nonces as specified in RFC 5288, Section 3 and RFC 9325,
|
||||
// Section 7.2.1.
|
||||
//
|
||||
// This complies with FIPS 140-3 IG C.H Resolution 1.a.
|
||||
func NewGCMForTLS12(cipher *aes.Block) (*GCMForTLS12, error) {
|
||||
g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GCMForTLS12{g: *g}, nil
|
||||
}
|
||||
|
||||
type GCMForTLS12 struct {
|
||||
g GCM
|
||||
next uint64
|
||||
}
|
||||
|
||||
func (g *GCMForTLS12) NonceSize() int { return gcmStandardNonceSize }
|
||||
|
||||
func (g *GCMForTLS12) Overhead() int { return gcmTagSize }
|
||||
|
||||
func (g *GCMForTLS12) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
if len(nonce) != gcmStandardNonceSize {
|
||||
panic("crypto/cipher: incorrect nonce length given to GCM")
|
||||
}
|
||||
|
||||
counter := byteorder.BeUint64(nonce[len(nonce)-8:])
|
||||
|
||||
// Ensure the counter is monotonically increasing.
|
||||
if counter == math.MaxUint64 {
|
||||
panic("crypto/cipher: counter wrapped")
|
||||
}
|
||||
if counter < g.next {
|
||||
panic("crypto/cipher: counter decreased")
|
||||
}
|
||||
g.next = counter + 1
|
||||
|
||||
return g.g.Seal(dst, nonce, plaintext, data)
|
||||
}
|
||||
|
||||
func (g *GCMForTLS12) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
return g.g.Open(dst, nonce, ciphertext, data)
|
||||
}
|
||||
|
||||
// NewGCMForTLS13 returns a new AEAD that works like GCM, but enforces the
|
||||
// construction of nonces as specified in RFC 8446, Section 5.3.
|
||||
func NewGCMForTLS13(cipher *aes.Block) (*GCMForTLS13, error) {
|
||||
g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GCMForTLS13{g: *g}, nil
|
||||
}
|
||||
|
||||
type GCMForTLS13 struct {
|
||||
g GCM
|
||||
ready bool
|
||||
mask uint64
|
||||
next uint64
|
||||
}
|
||||
|
||||
func (g *GCMForTLS13) NonceSize() int { return gcmStandardNonceSize }
|
||||
|
||||
func (g *GCMForTLS13) Overhead() int { return gcmTagSize }
|
||||
|
||||
func (g *GCMForTLS13) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
if len(nonce) != gcmStandardNonceSize {
|
||||
panic("crypto/cipher: incorrect nonce length given to GCM")
|
||||
}
|
||||
|
||||
counter := byteorder.BeUint64(nonce[len(nonce)-8:])
|
||||
if !g.ready {
|
||||
// In the first call, the counter is zero, so we learn the XOR mask.
|
||||
g.ready = true
|
||||
g.mask = counter
|
||||
}
|
||||
counter ^= g.mask
|
||||
|
||||
// Ensure the counter is monotonically increasing.
|
||||
if counter == math.MaxUint64 {
|
||||
panic("crypto/cipher: counter wrapped")
|
||||
}
|
||||
if counter < g.next {
|
||||
panic("crypto/cipher: counter decreased")
|
||||
}
|
||||
g.next = counter + 1
|
||||
|
||||
return g.g.Seal(dst, nonce, plaintext, data)
|
||||
}
|
||||
|
||||
func (g *GCMForTLS13) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
return g.g.Open(dst, nonce, ciphertext, data)
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"crypto/des"
|
||||
"crypto/hmac"
|
||||
"crypto/internal/boring"
|
||||
fipsaes "crypto/internal/fips/aes"
|
||||
"crypto/internal/fips/aes/gcm"
|
||||
"crypto/rc4"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
@ -521,7 +523,7 @@ func aeadAESGCM(key, noncePrefix []byte) aead {
|
||||
aead, err = boring.NewGCMTLS(aes)
|
||||
} else {
|
||||
boring.Unreachable()
|
||||
aead, err = cipher.NewGCM(aes)
|
||||
aead, err = gcm.NewGCMForTLS12(aes.(*fipsaes.Block))
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -555,7 +557,7 @@ func aeadAESGCMTLS13(key, nonceMask []byte) aead {
|
||||
aead, err = boring.NewGCMTLS13(aes)
|
||||
} else {
|
||||
boring.Unreachable()
|
||||
aead, err = cipher.NewGCM(aes)
|
||||
aead, err = gcm.NewGCMForTLS13(aes.(*fipsaes.Block))
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
Loading…
Reference in New Issue
Block a user