Skip to content

Commit 0c94c5f

Browse files
cpugopherbot
authored andcommitted
crypto/internal/fips140test: add counter KDF ACVP tests
Adds ACVP test coverage for the SP 800-108r1 KDF counter mode algorithm based on the NIST spec: https://pages.nist.gov/ACVP/draft-celi-acvp-kbkdf.html The implementation in our FIPS module fixes some parameters, requiring tailoring of the advertised capability to match. Notably: * We only support macModes CMAC-AES-128, -192, and -256 * We only support supportedLengths 256 (matching the [32]byte output from CounterKDF.DeriveKey) * We only support fixedDataOrder "before fixed data" * We only support counterLength 16 No acvp_test.config.json update accompanies this support because the ACVP tests for this algorithm aren't amenable to fixed data testing. Updates #69642 Change-Id: I9e02d6c8cb6e209ac8e4c9fba926fffbad916098 Reviewed-on: https://go-review.googlesource.com/c/go/+/639776 Reviewed-by: Filippo Valsorda <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> Auto-Submit: Filippo Valsorda <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 0bc57a3 commit 0c94c5f

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/crypto/internal/fips140test/acvp_capabilities.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,7 @@
6767
{"algorithm":"TLS-v1.3","mode":"KDF","revision":"RFC8446","hmacAlg":["SHA2-256","SHA2-384"],"runningMode":["DHE","PSK","PSK-DHE"]},
6868
{"algorithm":"kdf-components","mode":"ssh","revision":"1.0","hashAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512"],"cipher":["AES-128","AES-192","AES-256"]},
6969

70-
{"algorithm":"KAS-ECC-SSC","revision":"Sp800-56Ar3","scheme":{"ephemeralUnified":{"kasRole":["initiator","responder"]},"staticUnified":{"kasRole":["initiator","responder"]}},"domainParameterGenerationMethods":["P-224","P-256","P-384","P-521"]}
70+
{"algorithm":"KAS-ECC-SSC","revision":"Sp800-56Ar3","scheme":{"ephemeralUnified":{"kasRole":["initiator","responder"]},"staticUnified":{"kasRole":["initiator","responder"]}},"domainParameterGenerationMethods":["P-224","P-256","P-384","P-521"]},
71+
72+
{"algorithm":"KDF","revision":"1.0","capabilities":[{"kdfMode":"counter","macMode":["CMAC-AES128","CMAC-AES192","CMAC-AES256"],"supportedLengths":[256],"fixedDataOrder":["before fixed data"],"counterLength":[16]}]}
7173
]

src/crypto/internal/fips140test/acvp_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ var (
129129
// https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ssc-ecc.html#section-7.3
130130
// HMAC DRBG and CTR DRBG algorithm capabilities:
131131
// https://pages.nist.gov/ACVP/draft-vassilev-acvp-drbg.html#section-7.2
132+
// KDF-Counter algorithm capabilities:
133+
// https://pages.nist.gov/ACVP/draft-celi-acvp-kbkdf.html#section-7.3
132134
//go:embed acvp_capabilities.json
133135
capabilitiesJson []byte
134136

@@ -265,6 +267,8 @@ var (
265267

266268
"ctrDRBG/AES-256": cmdCtrDrbgAft(),
267269
"ctrDRBG-reseed/AES-256": cmdCtrDrbgReseedAft(),
270+
271+
"KDF-counter": cmdKdfCounterAft(),
268272
}
269273
)
270274

@@ -1579,6 +1583,57 @@ func require48Bytes(input []byte) (*[48]byte, error) {
15791583
return (*[48]byte)(input), nil
15801584
}
15811585

1586+
func cmdKdfCounterAft() command {
1587+
return command{
1588+
requiredArgs: 5, // Number output bytes, PRF name, counter location string, key, number of counter bits
1589+
handler: func(args [][]byte) ([][]byte, error) {
1590+
outputBytes := binary.LittleEndian.Uint32(args[0])
1591+
prf := args[1]
1592+
counterLocation := args[2]
1593+
key := args[3]
1594+
counterBits := binary.LittleEndian.Uint32(args[4])
1595+
1596+
if outputBytes != 32 {
1597+
return nil, fmt.Errorf("KDF received unsupported output length %d bytes", outputBytes)
1598+
}
1599+
if !bytes.Equal(prf, []byte("CMAC-AES128")) && !bytes.Equal(prf, []byte("CMAC-AES192")) && !bytes.Equal(prf, []byte("CMAC-AES256")) {
1600+
return nil, fmt.Errorf("KDF received unsupported PRF %q", string(prf))
1601+
}
1602+
if !bytes.Equal(counterLocation, []byte("before fixed data")) {
1603+
return nil, fmt.Errorf("KDF received unsupported counter location %q", string(counterLocation))
1604+
}
1605+
// The spec doesn't describe the "deferred" property for a KDF counterMode test case.
1606+
// BoringSSL's acvptool sends an empty key when deferred=true, but with the capabilities
1607+
// we register all test cases ahve deferred=false and provide a key from the populated
1608+
// keyIn property.
1609+
if len(key) == 0 {
1610+
return nil, errors.New("deferred test cases are not supported")
1611+
}
1612+
if counterBits != 16 {
1613+
return nil, fmt.Errorf("KDF received unsupported counter length %d", counterBits)
1614+
}
1615+
1616+
block, err := aes.New(key)
1617+
if err != nil {
1618+
return nil, fmt.Errorf("failed to create cipher: %v", err)
1619+
}
1620+
kdf := gcm.NewCounterKDF(block)
1621+
1622+
var label byte
1623+
var context [12]byte
1624+
rand.Reader.Read(context[:])
1625+
1626+
result := kdf.DeriveKey(label, context)
1627+
1628+
fixedData := make([]byte, 1+1+12) // 1 byte label, 1 null byte, 12 bytes context.
1629+
fixedData[0] = label
1630+
copy(fixedData[2:], context[:])
1631+
1632+
return [][]byte{key, fixedData, result[:]}, nil
1633+
},
1634+
}
1635+
}
1636+
15821637
func TestACVP(t *testing.T) {
15831638
testenv.SkipIfShortAndSlow(t)
15841639

0 commit comments

Comments
 (0)