util/fipstools: ACVP RSA keyFormat=crt keyGen

Support ACVP testing of RSA capabilities where the keyGen keyFormat is
crt.

This requires the modulewrapper return more results than it would
otherwise, so the new command "RSA/keyGen/crt" is used to differentiate
from "RSA/keyGen", the pre-existing command that assumes standard
keyFormat.

See https://pages.nist.gov/ACVP/draft-celi-acvp-rsa.html#section-7.3 for
more information.

Change-Id: I97cfd81e5849d38a388062d30c8c695ea9246669
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/87747
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/util/fipstools/acvp/ACVP.md b/util/fipstools/acvp/ACVP.md
index 49be6a7..66e4535 100644
--- a/util/fipstools/acvp/ACVP.md
+++ b/util/fipstools/acvp/ACVP.md
@@ -99,6 +99,7 @@
 | KDF-counter          | Number output bytes, PRF name, counter location string, key (or empty), number of counter bits | key, counter, derived key |
 | KDF-feedback | Number output bytes, PRF name, counter location string, key (or empty), number of counter bits | key, counter, derived key |
 | RSA/keyGen           | Modulus bit-size | e, p, q, n, d |
+| RSA/keyGen/crt       | Modulus bit-size | e, p, q, n, d, dmp1, dmq1, iqmp |
 | RSA/sigGen/&lt;HASH&gt;/pkcs1v1.5 | Modulus bit-size, message | n, e, signature |
 | RSA/sigGen/&lt;HASH&gt;/pss       | Modulus bit-size, message | n, e, signature |
 | RSA/sigVer/&lt;HASH&gt;/pkcs1v1.5 | n, e, message, signature | Single-byte validity flag |
diff --git a/util/fipstools/acvp/acvptool/subprocess/rsa.go b/util/fipstools/acvp/acvptool/subprocess/rsa.go
index 57461b4..20eef07 100644
--- a/util/fipstools/acvp/acvptool/subprocess/rsa.go
+++ b/util/fipstools/acvp/acvptool/subprocess/rsa.go
@@ -36,6 +36,7 @@
 	ID          uint64          `json:"tgId"`
 	Type        string          `json:"testType"`
 	ModulusBits uint32          `json:"modulo"`
+	KeyFormat   string          `json:"keyFormat"`
 	Tests       []rsaKeyGenTest `json:"tests"`
 }
 
@@ -49,12 +50,15 @@
 }
 
 type rsaKeyGenTestResponse struct {
-	ID uint64 `json:"tcId"`
-	E  string `json:"e"`
-	P  string `json:"p"`
-	Q  string `json:"q"`
-	N  string `json:"n"`
-	D  string `json:"d"`
+	ID   uint64 `json:"tcId"`
+	E    string `json:"e"`
+	P    string `json:"p"`
+	Q    string `json:"q"`
+	N    string `json:"n"`
+	D    string `json:"d"`
+	Dmp1 string `json:"dmp1,omitempty"`
+	Dmq1 string `json:"dmq1,omitempty"`
+	Iqmp string `json:"iqmp,omitempty"`
 }
 
 type rsaSigGenTestVectorSet struct {
@@ -134,22 +138,41 @@
 			return nil, fmt.Errorf("RSA KeyGen test group has type %q, but only generation tests (%q) are supported", group.Type, expectedType)
 		}
 
+		if group.KeyFormat != "standard" && group.KeyFormat != "crt" {
+			return nil, fmt.Errorf("RSA KeyGen test group has keyFormat %q, but only standard and crt are supported", group.KeyFormat)
+		}
+
 		response := rsaKeyGenTestGroupResponse{
 			ID: group.ID,
 		}
 
 		for _, test := range group.Tests {
 			test := test
+			cmd := "RSA/keyGen"
+			expectedResults := 5
 
-			m.TransactAsync("RSA/keyGen", 5, [][]byte{uint32le(group.ModulusBits)}, func(result [][]byte) error {
-				response.Tests = append(response.Tests, rsaKeyGenTestResponse{
+			if group.KeyFormat == "crt" {
+				cmd = cmd + "/crt"
+				expectedResults = 8
+			}
+
+			m.TransactAsync(cmd, expectedResults, [][]byte{uint32le(group.ModulusBits)}, func(result [][]byte) error {
+				keyGenResponse := rsaKeyGenTestResponse{
 					ID: test.ID,
 					E:  hex.EncodeToString(result[0]),
 					P:  hex.EncodeToString(result[1]),
 					Q:  hex.EncodeToString(result[2]),
 					N:  hex.EncodeToString(result[3]),
 					D:  hex.EncodeToString(result[4]),
-				})
+				}
+
+				if group.KeyFormat == "crt" {
+					keyGenResponse.Dmp1 = hex.EncodeToString(result[5])
+					keyGenResponse.Dmq1 = hex.EncodeToString(result[6])
+					keyGenResponse.Iqmp = hex.EncodeToString(result[7])
+				}
+
+				response.Tests = append(response.Tests, keyGenResponse)
 				return nil
 			})
 		}