mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/internal/fips140test: add hmac DRBG ACVP tests
Adds ACVP test coverage for the hmacDRBG algorithm based on the NIST spec: https://pages.nist.gov/ACVP/draft-vassilev-acvp-drbg.html#section-7.2 The HMAC DRBG algorithm in our fips module is a minimal implementation tailored for use for generating ECDSA nonces and so lives in crypto/internal/fips140/ecdsa. In order to be testable by crypto/internal/fips140test this changeset exports a ecdsa.TestingOnlyNewDrbg() constructor to support the ACVP use-case. All FIPS-compatible SHA2 and SHA3 digests are tested. The ACVP capability registration is customized to match the limited capabilities of our ecdsa-focused impl. Most notably: * reseedImplemented is false - we expect this impl to be invoked only once or twice per instantiation and do not support explicit reseeding. * predResistanceEnabled is false - this requires reseeding. * Per mode: * derFuncEnabled is always false - this is only used by ctrDRBG. * additionalInputLen is 0 for all modes - this is only used with preResistanceEnabled. The other capability values are chosen based on Table 4: https://pages.nist.gov/ACVP/draft-vassilev-acvp-drbg.html#section-7.4 Updates #69642 Change-Id: Ia58979d691f912e2ed739a05efb719f580fbbf89 Reviewed-on: https://go-review.googlesource.com/c/go/+/639775 Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
parent
7255b94920
commit
19e923182e
4 changed files with 72 additions and 3 deletions
|
|
@ -116,6 +116,15 @@ func newDRBG[H fips140.Hash](hash func() H, entropy, nonce []byte, s personaliza
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestingOnlyNewDRBG creates an SP 800-90A Rev. 1 HMAC_DRBG with a plain
|
||||||
|
// personalization string.
|
||||||
|
//
|
||||||
|
// This should only be used for ACVP testing. hmacDRBG is not intended to be
|
||||||
|
// used directly.
|
||||||
|
func TestingOnlyNewDRBG(hash func() fips140.Hash, entropy, nonce []byte, s []byte) *hmacDRBG {
|
||||||
|
return newDRBG(hash, entropy, nonce, plainPersonalizationString(s))
|
||||||
|
}
|
||||||
|
|
||||||
func pad000(h *hmac.HMAC, writtenSoFar int) {
|
func pad000(h *hmac.HMAC, writtenSoFar int) {
|
||||||
blockSize := h.BlockSize()
|
blockSize := h.BlockSize()
|
||||||
if rem := writtenSoFar % blockSize; rem != 0 {
|
if rem := writtenSoFar % blockSize; rem != 0 {
|
||||||
|
|
|
||||||
|
|
@ -26,5 +26,16 @@
|
||||||
{"algorithm":"PBKDF","capabilities":[{"iterationCount":[{"min":1,"max":10000,"increment":1}],"keyLen":[{"min":112,"max":4096,"increment":8}],"passwordLen":[{"min":8,"max":64,"increment":1}],"saltLen":[{"min":128,"max":512,"increment":8}],"hmacAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512","SHA2-512/224","SHA2-512/256","SHA3-224","SHA3-256","SHA3-384","SHA3-512"]}],"revision":"1.0"},
|
{"algorithm":"PBKDF","capabilities":[{"iterationCount":[{"min":1,"max":10000,"increment":1}],"keyLen":[{"min":112,"max":4096,"increment":8}],"passwordLen":[{"min":8,"max":64,"increment":1}],"saltLen":[{"min":128,"max":512,"increment":8}],"hmacAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512","SHA2-512/224","SHA2-512/256","SHA3-224","SHA3-256","SHA3-384","SHA3-512"]}],"revision":"1.0"},
|
||||||
|
|
||||||
{"algorithm":"ML-KEM","mode":"keyGen","revision":"FIPS203","parameterSets":["ML-KEM-768","ML-KEM-1024"]},
|
{"algorithm":"ML-KEM","mode":"keyGen","revision":"FIPS203","parameterSets":["ML-KEM-768","ML-KEM-1024"]},
|
||||||
{"algorithm":"ML-KEM","mode":"encapDecap","revision":"FIPS203","parameterSets":["ML-KEM-768","ML-KEM-1024"],"functions":["encapsulation","decapsulation"]}
|
{"algorithm":"ML-KEM","mode":"encapDecap","revision":"FIPS203","parameterSets":["ML-KEM-768","ML-KEM-1024"],"functions":["encapsulation","decapsulation"]},
|
||||||
|
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-224","derFuncEnabled":false,"entropyInputLen":[192],"nonceLen":[96],"persoStringLen":[192],"additionalInputLen":[0],"returnedBitsLen":224}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-256","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":256}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-384","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":384}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-512","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":512}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-512/224","derFuncEnabled":false,"entropyInputLen":[192],"nonceLen":[96],"persoStringLen":[192],"additionalInputLen":[0],"returnedBitsLen":224}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA2-512/256","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":256}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA3-224","derFuncEnabled":false,"entropyInputLen":[192],"nonceLen":[96],"persoStringLen":[192],"additionalInputLen":[0],"returnedBitsLen":224}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA3-256","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":256}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA3-384","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":384}]},
|
||||||
|
{"algorithm":"hmacDRBG","revision":"1.0","predResistanceEnabled":[false],"reseedImplemented":false,"capabilities":[{"mode":"SHA3-512","derFuncEnabled":false,"entropyInputLen":[256],"nonceLen":[128],"persoStringLen":[256],"additionalInputLen":[0],"returnedBitsLen":512}]}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,7 @@
|
||||||
|
|
||||||
{"Wrapper": "go", "In": "vectors/PBKDF.bz2", "Out": "expected/PBKDF.bz2"},
|
{"Wrapper": "go", "In": "vectors/PBKDF.bz2", "Out": "expected/PBKDF.bz2"},
|
||||||
|
|
||||||
{"Wrapper": "go", "In": "vectors/ML-KEM.bz2", "Out": "expected/ML-KEM.bz2"}
|
{"Wrapper": "go", "In": "vectors/ML-KEM.bz2", "Out": "expected/ML-KEM.bz2"},
|
||||||
|
|
||||||
|
{"Wrapper": "go", "In": "vectors/hmacDRBG.bz2", "Out": "expected/hmacDRBG.bz2"}
|
||||||
]
|
]
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/internal/cryptotest"
|
"crypto/internal/cryptotest"
|
||||||
"crypto/internal/fips140"
|
"crypto/internal/fips140"
|
||||||
|
"crypto/internal/fips140/ecdsa"
|
||||||
"crypto/internal/fips140/hmac"
|
"crypto/internal/fips140/hmac"
|
||||||
"crypto/internal/fips140/mlkem"
|
"crypto/internal/fips140/mlkem"
|
||||||
"crypto/internal/fips140/pbkdf2"
|
"crypto/internal/fips140/pbkdf2"
|
||||||
|
|
@ -78,6 +79,8 @@ var (
|
||||||
// https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html#section-7.3
|
// https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html#section-7.3
|
||||||
// ML-KEM algorithm capabilities:
|
// ML-KEM algorithm capabilities:
|
||||||
// https://pages.nist.gov/ACVP/draft-celi-acvp-ml-kem.html#section-7.3
|
// https://pages.nist.gov/ACVP/draft-celi-acvp-ml-kem.html#section-7.3
|
||||||
|
// HMAC DRBG algorithm capabilities:
|
||||||
|
// https://pages.nist.gov/ACVP/draft-vassilev-acvp-drbg.html#section-7.2
|
||||||
//go:embed acvp_capabilities.json
|
//go:embed acvp_capabilities.json
|
||||||
capabilitiesJson []byte
|
capabilitiesJson []byte
|
||||||
|
|
||||||
|
|
@ -128,6 +131,17 @@ var (
|
||||||
"ML-KEM-1024/keyGen": cmdMlKem1024KeyGenAft(),
|
"ML-KEM-1024/keyGen": cmdMlKem1024KeyGenAft(),
|
||||||
"ML-KEM-1024/encap": cmdMlKem1024EncapAft(),
|
"ML-KEM-1024/encap": cmdMlKem1024EncapAft(),
|
||||||
"ML-KEM-1024/decap": cmdMlKem1024DecapAft(),
|
"ML-KEM-1024/decap": cmdMlKem1024DecapAft(),
|
||||||
|
|
||||||
|
"hmacDRBG/SHA2-224": cmdHmacDrbgAft(func() fips140.Hash { return sha256.New224() }),
|
||||||
|
"hmacDRBG/SHA2-256": cmdHmacDrbgAft(func() fips140.Hash { return sha256.New() }),
|
||||||
|
"hmacDRBG/SHA2-384": cmdHmacDrbgAft(func() fips140.Hash { return sha512.New384() }),
|
||||||
|
"hmacDRBG/SHA2-512": cmdHmacDrbgAft(func() fips140.Hash { return sha512.New() }),
|
||||||
|
"hmacDRBG/SHA2-512/224": cmdHmacDrbgAft(func() fips140.Hash { return sha512.New512_224() }),
|
||||||
|
"hmacDRBG/SHA2-512/256": cmdHmacDrbgAft(func() fips140.Hash { return sha512.New512_256() }),
|
||||||
|
"hmacDRBG/SHA3-224": cmdHmacDrbgAft(func() fips140.Hash { return sha3.New224() }),
|
||||||
|
"hmacDRBG/SHA3-256": cmdHmacDrbgAft(func() fips140.Hash { return sha3.New256() }),
|
||||||
|
"hmacDRBG/SHA3-384": cmdHmacDrbgAft(func() fips140.Hash { return sha3.New384() }),
|
||||||
|
"hmacDRBG/SHA3-512": cmdHmacDrbgAft(func() fips140.Hash { return sha3.New512() }),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -538,12 +552,45 @@ func cmdMlKem1024DecapAft() command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmdHmacDrbgAft(h func() fips140.Hash) command {
|
||||||
|
return command{
|
||||||
|
requiredArgs: 6, // Output length, entropy, personalization, ad1, ad2, nonce
|
||||||
|
handler: func(args [][]byte) ([][]byte, error) {
|
||||||
|
outLen := binary.LittleEndian.Uint32(args[0])
|
||||||
|
entropy := args[1]
|
||||||
|
personalization := args[2]
|
||||||
|
ad1 := args[3]
|
||||||
|
ad2 := args[4]
|
||||||
|
nonce := args[5]
|
||||||
|
|
||||||
|
// Our capabilities describe no additional data support.
|
||||||
|
if len(ad1) != 0 || len(ad2) != 0 {
|
||||||
|
return nil, errors.New("additional data not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our capabilities describe no prediction resistance (requires reseed) and no reseed.
|
||||||
|
// So the test procedure is:
|
||||||
|
// * Instantiate DRBG
|
||||||
|
// * Generate but don't output
|
||||||
|
// * Generate output
|
||||||
|
// * Uninstantiate
|
||||||
|
// See Table 7 in draft-vassilev-acvp-drbg
|
||||||
|
out := make([]byte, outLen)
|
||||||
|
drbg := ecdsa.TestingOnlyNewDRBG(h, entropy, nonce, personalization)
|
||||||
|
drbg.Generate(out)
|
||||||
|
drbg.Generate(out)
|
||||||
|
|
||||||
|
return [][]byte{out}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestACVP(t *testing.T) {
|
func TestACVP(t *testing.T) {
|
||||||
testenv.SkipIfShortAndSlow(t)
|
testenv.SkipIfShortAndSlow(t)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
bsslModule = "boringssl.googlesource.com/boringssl.git"
|
bsslModule = "boringssl.googlesource.com/boringssl.git"
|
||||||
bsslVersion = "v0.0.0-20241218033850-ca3146c56300"
|
bsslVersion = "v0.0.0-20250108043213-d3f61eeacbf7"
|
||||||
goAcvpModule = "github.com/cpu/go-acvp"
|
goAcvpModule = "github.com/cpu/go-acvp"
|
||||||
goAcvpVersion = "v0.0.0-20250102201911-6839fc40f9f8"
|
goAcvpVersion = "v0.0.0-20250102201911-6839fc40f9f8"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue