util/fipstools: add ACVP KTS-IFC crt support Previously the FIPS acvptool KTS subprocess support required keyGenerationMethods=rsakpg1-basic, citing a requirement for fixed public exponents. This commit extends support to include rsakpg1-crt, another fixed public exponent form that provides the keypair in Chinese Remainder Theorem (CRT) format. This requires the acvptool to provide the modulewrapper different arguments for the responder role than it would otherwise (sending dmp1, dmq1, iqmp and no d), so the new command "KTS-IFC/$DIGEST/responder/crt" is used to differentiate from "KTS-IFC/$DIGEST/responder", the pre-existing command that assumes basic keyFormat. See https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ifc.html for more information Change-Id: Ia02d1fe58f03fbe92f3d18752f33260f78518111 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/88387 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/util/fipstools/acvp/ACVP.md b/util/fipstools/acvp/ACVP.md index 66e4535..3374e37 100644 --- a/util/fipstools/acvp/ACVP.md +++ b/util/fipstools/acvp/ACVP.md
@@ -149,6 +149,7 @@ | SSHKDF/<HASH>/server | K, H, SessionID, cipher algorithm | server IV key, server encryption key, server integrity key | | KTS-IFC/<HASH>/initiator | output length bytes, serverN bytes, serverE bytes | generated ciphertext (iutC), derived keying material (dkm) | | KTS-IFC/<HASH>/responder | iutN bytes, iutE bytes, iutP bytes, iutQ bytes, iutD bytes, ciphertext (serverC) bytes | derived keying material (dkm) | +| KTS-IFC/<HASH>/responder/crt | iutN bytes, iutE bytes, iutP bytes, iutQ bytes, iutDmp1 bytes, iutDmq1 bytes, iutIqmp bytes, ciphertext (serverC) bytes | derived keying material (dkm) | | OneStepNoCounter/<HASH> | key, info, salt, output length bytes | derived key | ¹ The iterated tests would result in excessive numbers of round trips if the module wrapper handled only basic operations. Thus some ACVP logic is pushed down for these tests so that the inner loop can be handled locally. Either read the NIST documentation ([block-ciphers](https://pages.nist.gov/ACVP/draft-celi-acvp-symmetric.html#name-monte-carlo-tests-for-block) [hashes](https://pages.nist.gov/ACVP/draft-celi-acvp-sha.html#name-monte-carlo-tests-for-sha-1)) to understand the iteration count and return values or, probably more fruitfully, see how these functions are handled in the `modulewrapper` directory.
diff --git a/util/fipstools/acvp/acvptool/subprocess/kts.go b/util/fipstools/acvp/acvptool/subprocess/kts.go index a483914..e8145df 100644 --- a/util/fipstools/acvp/acvptool/subprocess/kts.go +++ b/util/fipstools/acvp/acvptool/subprocess/kts.go
@@ -53,11 +53,14 @@ ServerE string `json:"serverE,omitempty"` ServerC string `json:"serverC,omitempty"` - IutN string `json:"iutN,omitempty"` - IutE string `json:"iutE,omitempty"` - IutP string `json:"iutP,omitempty"` - IutQ string `json:"iutQ,omitempty"` - IutD string `json:"iutD,omitempty"` + IutN string `json:"iutN,omitempty"` + IutE string `json:"iutE,omitempty"` + IutP string `json:"iutP,omitempty"` + IutQ string `json:"iutQ,omitempty"` + IutD string `json:"iutD,omitempty"` + IutDmp1 string `json:"iutDmp1,omitempty"` + IutDmq1 string `json:"iutDmq1,omitempty"` + IutIqmp string `json:"iutIqmp,omitempty"` } type ktsTestGroupResponse struct { @@ -100,8 +103,9 @@ return nil, fmt.Errorf("unsupported scheme %q in test group %d", group.Scheme, group.ID) } - if group.KeyGen != "rsakpg1-basic" { - return nil, fmt.Errorf("unsupported key generation method %q in test group %d - only fixed public exponent (rsakpg1-basic) is supported", group.KeyGen, group.ID) + if group.KeyGen != "rsakpg1-basic" && group.KeyGen != "rsakpg1-crt" { + return nil, fmt.Errorf( + "unsupported key generation method %q in test group %d - only fixed public exponent (rsakpg1-basic or rsakpg1-crt) are supported", group.KeyGen, group.ID) } if group.OutputBits%8 != 0 { @@ -121,7 +125,7 @@ case "initiator": err = k.processInitiator(m, &testResponses, group.KTSConf.HashAlg, group.OutputBits, test) case "responder": - err = k.processResponder(m, &testResponses, group.KTSConf.HashAlg, test) + err = k.processResponder(m, &testResponses, group.KTSConf.HashAlg, group.KeyGen, test) default: err = fmt.Errorf("unknown role %q", group.Role) } @@ -172,7 +176,7 @@ return nil } -func (k *kts) processResponder(m Transactable, responses *[]ktsTestResponse, hashAlg string, test ktsTest) error { +func (k *kts) processResponder(m Transactable, responses *[]ktsTestResponse, hashAlg string, keyGen string, test ktsTest) error { nBytes, err := hex.DecodeString(test.IutN) if err != nil { return fmt.Errorf("invalid IutN: %v", err) @@ -193,18 +197,39 @@ return fmt.Errorf("invalid IutQ: %v", err) } - dBytes, err := hex.DecodeString(test.IutD) - if err != nil { - return fmt.Errorf("invalid IutD: %v", err) - } - cBytes, err := hex.DecodeString(test.ServerC) if err != nil { return fmt.Errorf("invalid ServerC: %v", err) } cmd := fmt.Sprintf("KTS-IFC/%s/responder", hashAlg) - args := [][]byte{nBytes, eBytes, pBytes, qBytes, dBytes, cBytes} + var args [][]byte + + if keyGen == "rsakpg1-basic" { + dBytes, err := hex.DecodeString(test.IutD) + if err != nil { + return fmt.Errorf("invalid IutD: %v", err) + } + args = [][]byte{nBytes, eBytes, pBytes, qBytes, dBytes, cBytes} + } else { + dmp1Bytes, err := hex.DecodeString(test.IutDmp1) + if err != nil { + return fmt.Errorf("invalid IutDmp1: %v", err) + } + + dmq1Bytes, err := hex.DecodeString(test.IutDmq1) + if err != nil { + return fmt.Errorf("invalid IutDmq1: %v", err) + } + + iqmpBytes, err := hex.DecodeString(test.IutIqmp) + if err != nil { + return fmt.Errorf("invalid IutIqmp: %v", err) + } + + cmd = cmd + "/crt" + args = [][]byte{nBytes, eBytes, pBytes, qBytes, dmp1Bytes, dmq1Bytes, iqmpBytes, cBytes} + } m.TransactAsync(cmd, 1, args, func(result [][]byte) error { *responses = append(*responses,