]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/internal/fips/aes/gcm: add SealWithRandomNonce
authorFilippo Valsorda <filippo@golang.org>
Sun, 3 Nov 2024 21:30:43 +0000 (22:30 +0100)
committerGopher Robot <gobot@golang.org>
Tue, 19 Nov 2024 00:32:04 +0000 (00:32 +0000)
We don't expose it as an AEAD yet because the logic for that is complex
due to overlap issues. For #69981 we will make a cipher.AEAD wrapper
outside the FIPS module, but maybe a v2 interface will make it easier,
and then we'll be able to use this method more directly.

Updates #69981
For #69536

Change-Id: Id88191c01443b0dec89ff0d6c4a6289f519369d1
Reviewed-on: https://go-review.googlesource.com/c/go/+/624916
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/crypto/internal/fips/aes/gcm/ctrkdf_test.go
src/crypto/internal/fips/aes/gcm/gcm_nonces.go [new file with mode: 0644]

index 2dcd9c7f647c3730880fc4545d5836ad01a667fa..9ed46c3b0baa50923d246be58b53fc29269c81f7 100644 (file)
@@ -9,6 +9,7 @@ import (
        "crypto/internal/cryptotest"
        "crypto/internal/fips/aes"
        "crypto/internal/fips/aes/gcm"
+       "crypto/internal/fips/drbg"
        "crypto/internal/fips/sha3"
        "encoding/hex"
        "testing"
@@ -31,6 +32,30 @@ func TestAllocations(t *testing.T) {
        }
 }
 
+func TestXAES(t *testing.T) {
+       key := bytes.Repeat([]byte{0x01}, 32)
+       plaintext := []byte("XAES-256-GCM")
+       additionalData := []byte("c2sp.org/XAES-256-GCM")
+
+       nonce := make([]byte, 24)
+       ciphertext := make([]byte, len(plaintext)+16)
+
+       drbg.Read(nonce[:12])
+       c, _ := aes.New(key)
+       k := gcm.NewCounterKDF(c).DeriveKey(0x58, [12]byte(nonce))
+       a, _ := aes.New(k[:])
+       g, _ := gcm.New(a, 12, 16)
+       gcm.SealWithRandomNonce(g, nonce[12:], ciphertext, plaintext, additionalData)
+
+       got, err := xaesOpen(nil, key, nonce, ciphertext, additionalData)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if !bytes.Equal(plaintext, got) {
+               t.Errorf("plaintext and got are not equal")
+       }
+}
+
 // ACVP tests consider fixed data part of the output, not part of the input, and
 // all the pre-generated vectors at
 // https://github.com/usnistgov/ACVP-Server/blob/3a7333f6/gen-val/json-files/KDF-1.0/expectedResults.json
diff --git a/src/crypto/internal/fips/aes/gcm/gcm_nonces.go b/src/crypto/internal/fips/aes/gcm/gcm_nonces.go
new file mode 100644 (file)
index 0000000..3dc02ac
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2024 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.
+
+package gcm
+
+import (
+       "crypto/internal/fips/alias"
+       "crypto/internal/fips/drbg"
+)
+
+// SealWithRandomNonce encrypts plaintext to out, and writes a random nonce to
+// nonce. nonce must be 12 bytes, and out must be 16 bytes longer than plaintext.
+// out and plaintext may overlap exactly or not at all. additionalData and out
+// must not overlap.
+//
+// This complies with FIPS 140-3 IG C.H Resolution 2.
+//
+// Note that this is NOT a [cipher.AEAD].Seal method.
+func SealWithRandomNonce(g *GCM, nonce, out, plaintext, additionalData []byte) {
+       if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize {
+               panic("crypto/cipher: message too large for GCM")
+       }
+       if len(nonce) != gcmStandardNonceSize {
+               panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce")
+       }
+       if len(out) != len(plaintext)+gcmTagSize {
+               panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce")
+       }
+       if alias.InexactOverlap(out, plaintext) {
+               panic("crypto/cipher: invalid buffer overlap of output and input")
+       }
+       if alias.AnyOverlap(out, additionalData) {
+               panic("crypto/cipher: invalid buffer overlap of output and additional data")
+       }
+       drbg.Read(nonce)
+       seal(out, g, nonce, plaintext, additionalData)
+}