1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:07:59 -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:
Filippo Valsorda 2024-11-08 19:56:50 +01:00 committed by Gopher Robot
parent b86f770bec
commit 79c0041daf
2 changed files with 102 additions and 2 deletions

View File

@ -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)
}

View File

@ -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)