acvp: support RSA key generation tests.

Change-Id: I40bbf6d10fcfd1e0fb506bef44f4cd6e9d2daac5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43644
Reviewed-by: David Benjamin <davidben@google.com>
chromium-5359
Adam Langley 4 years ago committed by Adam Langley
parent 80e3f957e4
commit 2e22d1b3cb
  1. 115
      util/fipstools/acvp/acvptool/subprocess/rsa.go
  2. 1
      util/fipstools/acvp/acvptool/subprocess/subprocess.go
  3. 52
      util/fipstools/acvp/modulewrapper/modulewrapper.cc

@ -0,0 +1,115 @@
// Copyright (c) 2020, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package subprocess
import (
"encoding/hex"
"encoding/json"
"fmt"
)
// See https://usnistgov.github.io/ACVP/draft-celi-acvp-rsa.html#section-7.4
// although, at the time of writing, that spec doesn't match what the NIST demo
// server actually produces. This code matches the server.
type rsaTestVectorSet struct {
Mode string `json:"mode"`
}
type rsaKeyGenTestVectorSet struct {
Groups []rsaKeyGenGroup `json:"testGroups"`
}
type rsaKeyGenGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ModulusBits uint32 `json:"modulo"`
Tests []rsaKeyGenTest `json:"tests"`
}
type rsaKeyGenTest struct {
ID uint64 `json:"tcId"`
}
type rsaKeyGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []rsaKeyGenTestResponse `json:"tests"`
}
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"`
}
func processKeyGen(vectorSet []byte, m Transactable) (interface{}, error) {
var parsed rsaKeyGenTestVectorSet
if err := json.Unmarshal(vectorSet, &parsed); err != nil {
return nil, err
}
var ret []rsaKeyGenTestGroupResponse
for _, group := range parsed.Groups {
// GDT means "Generated data test", i.e. "please generate an RSA key".
const expectedType = "GDT"
if group.Type != expectedType {
return nil, fmt.Errorf("RSA KeyGen test group has type %q, but only generation tests (%q) are supported", group.Type, expectedType)
}
response := rsaKeyGenTestGroupResponse{
ID: group.ID,
}
for _, test := range group.Tests {
results, err := m.Transact("RSA/keyGen", 5, uint32le(group.ModulusBits))
if err != nil {
return nil, err
}
response.Tests = append(response.Tests, rsaKeyGenTestResponse{
ID: test.ID,
E: hex.EncodeToString(results[0]),
P: hex.EncodeToString(results[1]),
Q: hex.EncodeToString(results[2]),
N: hex.EncodeToString(results[3]),
D: hex.EncodeToString(results[4]),
})
}
ret = append(ret, response)
}
return ret, nil
}
type rsa struct{}
func (*rsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
var parsed rsaTestVectorSet
if err := json.Unmarshal(vectorSet, &parsed); err != nil {
return nil, err
}
switch parsed.Mode {
case "keyGen":
return processKeyGen(vectorSet, m)
default:
return nil, fmt.Errorf("Unknown RSA mode %q", parsed.Mode)
}
}

@ -94,6 +94,7 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess
"hmacDRBG": &drbg{"hmacDRBG", map[string]bool{"SHA-1": true, "SHA2-224": true, "SHA2-256": true, "SHA2-384": true, "SHA2-512": true}},
"KDF": &kdfPrimitive{},
"CMAC-AES": &keyedMACPrimitive{"CMAC-AES"},
"RSA": &rsa{},
}
m.primitives["ECDSA"] = &ecdsa{"ECDSA", map[string]bool{"P-224": true, "P-256": true, "P-384": true, "P-521": true}, m.primitives}

@ -34,6 +34,7 @@
#include <openssl/ecdsa.h>
#include <openssl/hmac.h>
#include <openssl/obj.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/span.h>
@ -395,6 +396,34 @@ static bool GetConfig(const Span<const uint8_t> args[]) {
]
}]
},
{
"algorithm": "RSA",
"mode": "keyGen",
"revision": "FIPS186-4",
"infoGeneratedByServer": true,
"pubExpMode": "fixed",
"fixedPubExp": "010001",
"keyFormat": "standard",
"capabilities": [{
"randPQ": "B.3.3",
"properties": [{
"modulo": 2048,
"primeTest": [
"tblC2"
]
},{
"modulo": 3072,
"primeTest": [
"tblC2"
]
},{
"modulo": 4096,
"primeTest": [
"tblC2"
]
}]
}]
},
{
"algorithm": "CMAC-AES",
"revision": "1.0",
@ -1003,6 +1032,28 @@ static bool CMAC_AES(const Span<const uint8_t> args[]) {
return WriteReply(STDOUT_FILENO, Span<const uint8_t>(mac, mac_len));
}
static bool RSAKeyGen(const Span<const uint8_t> args[]) {
uint32_t bits;
if (args[0].size() != sizeof(bits)) {
return false;
}
memcpy(&bits, args[0].data(), sizeof(bits));
bssl::UniquePtr<RSA> key(RSA_new());
if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
fprintf(stderr, "RSA_generate_key_fips failed for modulus length %u.\n",
bits);
return false;
}
const BIGNUM *n, *e, *d, *p, *q;
RSA_get0_key(key.get(), &n, &e, &d);
RSA_get0_factors(key.get(), &p, &q);
return WriteReply(STDOUT_FILENO, BIGNUMBytes(e), BIGNUMBytes(p),
BIGNUMBytes(q), BIGNUMBytes(n), BIGNUMBytes(d));
}
static constexpr struct {
const char name[kMaxNameLength + 1];
uint8_t expected_args;
@ -1043,6 +1094,7 @@ static constexpr struct {
{"ECDSA/sigGen", 4, ECDSASigGen},
{"ECDSA/sigVer", 7, ECDSASigVer},
{"CMAC-AES", 3, CMAC_AES},
{"RSA/keyGen", 1, RSAKeyGen},
};
int main() {

Loading…
Cancel
Save