Skip to content

Commit

Permalink
Wire-up ACVP Testing for SHA3 Signatures with RSA (#1805)
Browse files Browse the repository at this point in the history
### Description of changes: 
Enables ACVP testing of SHA3 signatures with RSA for PKCS#1.5 signatures
and PSS signatures.

### How are new algorithms added to `kPKCS1SigPrefixes`?
This is my outline of how I generated the prefixes for additional
algorithms:

For each algorithm:
1. Generate an arbitrary digest using the digest algorithm
```
$ echo -n "" | openssl sha3-256
SHA3-256(stdin)= a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
```

2. Make a file with the ASN.1 definition and content, being sure to set
`id` to the correct algorithm OID name, and `digest` to the arbitrary
digest from step 1.
```
$ cat > ~/encoding.txt <<EOF
asn1 = SEQUENCE:info

[info]
alg = SEQUENCE:alg
digest = FORMAT:HEX,OCT:a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

[alg]
id = OID:SHA3-256
param = NULL

EOF
```

3. Generate the output DER using the definition defined in step 4
```
$ openssl asn1parse -genconf ~/encoding.txt -out ~/encoding.der
```

4. Output the DER encoding in hex format suitable for C
```
$ xxd -i < ~/encoding.der
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20, 0xa7, 0xff, 0xc6, 0xf8, 0xbf,
0x1e, 0xd7, 0x66, 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, 0xf5,
0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, 0x82, 0xd8, 0x0a, 0x4b, 0x80,
0xf8, 0x43, 0x4a
```

5. Finally, strip out off the bytes from the end that are the digest
hash produced in step 1 and used in step 2. This is your final prefix
bytes to use with `kPKCS1SigPrefixes`.
```
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20
```

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
  • Loading branch information
skmcgrail authored Sep 3, 2024
1 parent 173bd09 commit 3571a86
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 114 deletions.
28 changes: 28 additions & 0 deletions crypto/fipsmodule/rsa/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,34 @@ static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = {
{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20},
},
{
NID_sha3_224,
28,
19,
{0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1c},
},
{
NID_sha3_256,
32,
19,
{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20},
},
{
NID_sha3_384,
48,
19,
{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30},
},
{
NID_sha3_512,
64,
19,
{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40},
},
{
NID_undef, 0, 0, {0},
},
Expand Down
96 changes: 37 additions & 59 deletions util/fipstools/acvp/acvptool/subprocess/rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
package subprocess

import (
"encoding/hex"
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -49,12 +49,12 @@ type rsaKeyGenTestGroupResponse struct {
}

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 hexEncodedByteString `json:"e"`
P hexEncodedByteString `json:"p"`
Q hexEncodedByteString `json:"q"`
N hexEncodedByteString `json:"n"`
D hexEncodedByteString `json:"d"`
}

type rsaSigGenTestVectorSet struct {
Expand All @@ -71,40 +71,40 @@ type rsaSigGenGroup struct {
}

type rsaSigGenTest struct {
ID uint64 `json:"tcId"`
MessageHex string `json:"message"`
ID uint64 `json:"tcId"`
Message hexEncodedByteString `json:"message"`
}

type rsaSigGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
N string `json:"n"`
E string `json:"e"`
N hexEncodedByteString `json:"n"`
E hexEncodedByteString `json:"e"`
Tests []rsaSigGenTestResponse `json:"tests"`
}

type rsaSigGenTestResponse struct {
ID uint64 `json:"tcId"`
Sig string `json:"signature"`
ID uint64 `json:"tcId"`
Sig hexEncodedByteString `json:"signature"`
}

type rsaSigVerTestVectorSet struct {
Groups []rsaSigVerGroup `json:"testGroups"`
}

type rsaSigVerGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
SigType string `json:"sigType"`
Hash string `json:"hashAlg"`
N string `json:"n"`
E string `json:"e"`
Tests []rsaSigVerTest `json:"tests"`
ID uint64 `json:"tgId"`
Type string `json:"testType"`
SigType string `json:"sigType"`
Hash string `json:"hashAlg"`
N hexEncodedByteString `json:"n"`
E hexEncodedByteString `json:"e"`
Tests []rsaSigVerTest `json:"tests"`
}

type rsaSigVerTest struct {
ID uint64 `json:"tcId"`
MessageHex string `json:"message"`
SignatureHex string `json:"signature"`
ID uint64 `json:"tcId"`
Message hexEncodedByteString `json:"message"`
Signature hexEncodedByteString `json:"signature"`
}

type rsaSigVerTestGroupResponse struct {
Expand Down Expand Up @@ -145,11 +145,11 @@ func processKeyGen(vectorSet []byte, m Transactable) (interface{}, error) {

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]),
E: results[0],
P: results[1],
Q: results[2],
N: results[3],
D: results[4],
})
}

Expand Down Expand Up @@ -186,12 +186,7 @@ func processSigGen(vectorSet []byte, m Transactable) (interface{}, error) {
for _, test := range group.Tests {
test := test

msg, err := hex.DecodeString(test.MessageHex)
if err != nil {
return nil, fmt.Errorf("test case %d/%d contains invalid hex: %s", group.ID, test.ID, err)
}

results, err := m.Transact(operation, 3, uint32le(group.ModulusBits), msg)
results, err := m.Transact(operation, 3, uint32le(group.ModulusBits), test.Message)
if err != nil {
return nil, err
}
Expand All @@ -201,23 +196,23 @@ func processSigGen(vectorSet []byte, m Transactable) (interface{}, error) {
sig := results[2]

if len(response.N) == 0 {
response.N = hex.EncodeToString(n)
response.E = hex.EncodeToString(e)
} else if response.N != hex.EncodeToString(n) {
response.N = n
response.E = e
} else if !bytes.Equal(response.N, n) {
return nil, fmt.Errorf("module wrapper returned different RSA keys for the same SigGen configuration")
}

// Ask the subprocess to verify the generated signature for this test case.
ver_results, ver_err := m.Transact(ver_operation, 1, n, e, msg, sig)
ver_results, ver_err := m.Transact(ver_operation, 1, n, e, test.Message, sig)
if ver_err != nil {
return nil, ver_err
}
if len(ver_results[0]) != 1 || ver_results[0][0] != 1 {
return nil, fmt.Errorf("module wrapper returned RSA Sig cannot be verified for test case %d/%d.", group.ID, test.ID)
return nil, fmt.Errorf("module wrapper returned RSA Sig cannot be verified for test case %d/%d", group.ID, test.ID)
}
response.Tests = append(response.Tests, rsaSigGenTestResponse{
ID: test.ID,
Sig: hex.EncodeToString(sig),
Sig: sig,
})
}

Expand All @@ -244,15 +239,6 @@ func processSigVer(vectorSet []byte, m Transactable) (interface{}, error) {
return nil, fmt.Errorf("RSA SigVer test group has type %q, but only 'generation' tests (%q) are supported", group.Type, expectedType)
}

n, err := hex.DecodeString(group.N)
if err != nil {
return nil, fmt.Errorf("test group %d contains invalid hex: %s", group.ID, err)
}
e, err := hex.DecodeString(group.E)
if err != nil {
return nil, fmt.Errorf("test group %d contains invalid hex: %s", group.ID, err)
}

response := rsaSigVerTestGroupResponse{
ID: group.ID,
}
Expand All @@ -261,16 +247,8 @@ func processSigVer(vectorSet []byte, m Transactable) (interface{}, error) {

for _, test := range group.Tests {
test := test
msg, err := hex.DecodeString(test.MessageHex)
if err != nil {
return nil, fmt.Errorf("test case %d/%d contains invalid hex: %s", group.ID, test.ID, err)
}
sig, err := hex.DecodeString(test.SignatureHex)
if err != nil {
return nil, fmt.Errorf("test case %d/%d contains invalid hex: %s", group.ID, test.ID, err)
}

results, err := m.Transact(operation, 1, n, e, msg, sig)
results, err := m.Transact(operation, 1, group.N, group.E, test.Message, test.Signature)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -303,6 +281,6 @@ func (r *rsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
case "sigVer":
return processSigVer(vectorSet, m)
default:
return nil, fmt.Errorf("Unknown RSA mode %q", parsed.Mode)
return nil, fmt.Errorf("unknown RSA mode %q", parsed.Mode)
}
}
Binary file modified util/fipstools/acvp/acvptool/test/expected/RSA.bz2
Binary file not shown.
Binary file modified util/fipstools/acvp/acvptool/test/vectors/RSA-SigGen.bz2
Binary file not shown.
Binary file modified util/fipstools/acvp/acvptool/test/vectors/RSA.bz2
Binary file not shown.
Loading

0 comments on commit 3571a86

Please sign in to comment.