Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Add ACVP test framework for ML-DSA #2068

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crypto/dilithium/ml_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ int ml_dsa_44_sign_internal(const uint8_t *private_key /* IN */,
size_t message_len /* IN */,
const uint8_t *pre /* IN */,
size_t pre_len /* IN */,
uint8_t *rnd /* IN */) {
const uint8_t *rnd /* IN */) {
ml_dsa_params params;
ml_dsa_44_params_init(&params);
return crypto_sign_signature_internal(&params, sig, sig_len, message, message_len,
Expand Down Expand Up @@ -126,7 +126,7 @@ int ml_dsa_65_sign_internal(const uint8_t *private_key /* IN */,
size_t message_len /* IN */,
const uint8_t *pre /* IN */,
size_t pre_len /* IN */,
uint8_t *rnd /* IN */) {
const uint8_t *rnd /* IN */) {
ml_dsa_params params;
ml_dsa_65_params_init(&params);
return crypto_sign_signature_internal(&params, sig, sig_len, message, message_len,
Expand Down Expand Up @@ -194,7 +194,7 @@ int ml_dsa_87_sign_internal(const uint8_t *private_key /* IN */,
size_t message_len /* IN */,
const uint8_t *pre /* IN */,
size_t pre_len /* IN */,
uint8_t *rnd /* IN */) {
const uint8_t *rnd /* IN */) {
ml_dsa_params params;
ml_dsa_87_params_init(&params);
return crypto_sign_signature_internal(&params, sig, sig_len, message, message_len,
Expand Down
6 changes: 3 additions & 3 deletions crypto/dilithium/ml_dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ OPENSSL_EXPORT int ml_dsa_44_sign_internal(const uint8_t *private_key,
uint8_t *sig, size_t *sig_len,
const uint8_t *message, size_t message_len,
const uint8_t *pre, size_t pre_len,
uint8_t *rnd);
const uint8_t *rnd);

OPENSSL_EXPORT int ml_dsa_44_verify(const uint8_t *public_key,
const uint8_t *sig, size_t sig_len,
Expand Down Expand Up @@ -74,7 +74,7 @@ OPENSSL_EXPORT int ml_dsa_65_sign_internal(const uint8_t *private_key,
uint8_t *sig, size_t *sig_len,
const uint8_t *message, size_t message_len,
const uint8_t *pre, size_t pre_len,
uint8_t *rnd);
const uint8_t *rnd);

OPENSSL_EXPORT int ml_dsa_65_verify(const uint8_t *public_key,
const uint8_t *sig, size_t sig_len,
Expand Down Expand Up @@ -102,7 +102,7 @@ OPENSSL_EXPORT int ml_dsa_87_sign_internal(const uint8_t *private_key,
uint8_t *sig, size_t *sig_len,
const uint8_t *message, size_t message_len,
const uint8_t *pre, size_t pre_len,
uint8_t *rnd);
const uint8_t *rnd);

OPENSSL_EXPORT int ml_dsa_87_verify(const uint8_t *public_key,
const uint8_t *sig, size_t sig_len,
Expand Down
2 changes: 1 addition & 1 deletion crypto/dilithium/p_pqdsa_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ struct PQDSATestVector {
uint8_t *sig, size_t *sig_len,
const uint8_t *message, size_t message_len,
const uint8_t *pre, size_t pre_len,
uint8_t *rnd);
const uint8_t *rnd);

int (*verify)(const uint8_t *public_key,
const uint8_t *sig, size_t sig_len,
Expand Down
13 changes: 10 additions & 3 deletions crypto/dilithium/pqcrystals_dilithium_ref_common/params.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef PARAMS_H
#define PARAMS_H

#if defined(__cplusplus)
extern "C" {
#endif

// The only defined parameters are those that don't depend
// on the parameter set. All other parameters are specified
// in ml_dsa_params structure that is unique for each parameter
Expand Down Expand Up @@ -45,8 +49,11 @@ typedef struct {
#define DILITHIUM_POLY_UNIFORM_ETA_NBLOCKS_MAX ((227 + SHAKE256_RATE - 1)/SHAKE256_RATE)
#define DILITHIUM_POLYZ_PACKEDBYTES_MAX (576)

void ml_dsa_44_params_init(ml_dsa_params *params);
void ml_dsa_65_params_init(ml_dsa_params *params);
void ml_dsa_87_params_init(ml_dsa_params *params);
OPENSSL_EXPORT void ml_dsa_44_params_init(ml_dsa_params *params);
OPENSSL_EXPORT void ml_dsa_65_params_init(ml_dsa_params *params);
OPENSSL_EXPORT void ml_dsa_87_params_init(ml_dsa_params *params);

#if defined(__cplusplus)
}
#endif
#endif
218 changes: 218 additions & 0 deletions util/fipstools/acvp/acvptool/subprocess/ml_dsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

package subprocess

import (
"encoding/json"
"fmt"
"strings"
)

type mlDsa struct{}

func (*mlDsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
var vs struct {
Mode string `json:"mode"`
TestGroups json.RawMessage `json:"testGroups"`
}

if err := json.Unmarshal(vectorSet, &vs); err != nil {
return nil, err
}

switch {
case strings.EqualFold(vs.Mode, "keyGen"):
return processMlDsaKeyGen(vs.TestGroups, m)
case strings.EqualFold(vs.Mode, "sigGen"):
return processMlDsaSigGen(vs.TestGroups, m)
case strings.EqualFold(vs.Mode, "sigVer"):
return processMlDsaSigVer(vs.TestGroups, m)
}

return nil, fmt.Errorf("unknown ML-DSA mode: %v", vs.Mode)
}

type mlDsaKeyGenTestGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Tests []struct {
ID uint64 `json:"tcId"`
SEED hexEncodedByteString `json:"seed"`
}
}

type mlDsaKeyGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []mlDsaKeyGenTestCaseResponse `json:"tests"`
}

type mlDsaKeyGenTestCaseResponse struct {
ID uint64 `json:"tcId"`
PK hexEncodedByteString `json:"pk"`
SK hexEncodedByteString `json:"sk"`
}

func processMlDsaKeyGen(vectors json.RawMessage, m Transactable) (interface{}, error) {
var groups []mlDsaKeyGenTestGroup

if err := json.Unmarshal(vectors, &groups); err != nil {
return nil, err
}

var responses []mlDsaKeyGenTestGroupResponse

for _, group := range groups {
if !strings.EqualFold(group.Type, "AFT") {
return nil, fmt.Errorf("unsupported keyGen test type: %v", group.Type)
}

response := mlDsaKeyGenTestGroupResponse{
ID: group.ID,
}

for _, test := range group.Tests {
results, err := m.Transact("ML-DSA/"+group.ParameterSet+"/keyGen", 2, test.SEED)
if err != nil {
return nil, err
}

pk := results[0]
sk := results[1]

response.Tests = append(response.Tests, mlDsaKeyGenTestCaseResponse{
ID: test.ID,
PK: pk,
SK: sk,
})
}

responses = append(responses, response)
}

return responses, nil
}

type mlDsaSigGenTestGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Deterministic bool `json:"deterministic"`
Tests []struct {
ID uint64 `json:"tcId"`
Message hexEncodedByteString `json:"message"`
SK hexEncodedByteString `json:"sk"`
RND hexEncodedByteString `json:"rnd"`
}
}

type mlDsaSigGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []mlDsaSigGenTestCaseResponse `json:"tests"`
}

type mlDsaSigGenTestCaseResponse struct {
ID uint64 `json:"tcId"`
Signature hexEncodedByteString `json:"signature"`
}

func processMlDsaSigGen(vectors json.RawMessage, m Transactable) (interface{}, error) {
var groups []mlDsaSigGenTestGroup

if err := json.Unmarshal(vectors, &groups); err != nil {
return nil, err
}

var responses []mlDsaSigGenTestGroupResponse

for _, group := range groups {
if !strings.EqualFold(group.Type, "AFT") {
return nil, fmt.Errorf("unsupported sigGen test type: %v", group.Type)
}

response := mlDsaSigGenTestGroupResponse{
ID: group.ID,
}

for _, test := range group.Tests {
results, err := m.Transact("ML-DSA/"+group.ParameterSet+"/sigGen", 1, test.SK, test.Message, test.RND)
if err != nil {
return nil, err
}

signature := results[0]

response.Tests = append(response.Tests, mlDsaSigGenTestCaseResponse{
ID: test.ID,
Signature: signature,
})
}

responses = append(responses, response)
}
return responses, nil
}

type mlDsaSigVerTestGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ParameterSet string `json:"parameterSet"`
PK hexEncodedByteString `json:"pk"`
Tests []struct {
ID uint64 `json:"tcId"`
Message hexEncodedByteString `json:"message"`
Signature hexEncodedByteString `json:"signature"`
}
}

type mlDsaSigVerTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []mlDsaSigVerTestCaseResponse `json:"tests"`
}

type mlDsaSigVerTestCaseResponse struct {
ID uint64 `json:"tcId"`
TestPassed *bool `json:"testPassed"`
}

func processMlDsaSigVer(vectors json.RawMessage, m Transactable) (interface{}, error) {
var groups []mlDsaSigVerTestGroup

if err := json.Unmarshal(vectors, &groups); err != nil {
return nil, err
}

var responses []mlDsaSigVerTestGroupResponse

for _, group := range groups {
if !strings.EqualFold(group.Type, "AFT") {
return nil, fmt.Errorf("unsupported sigVer test type: %v", group.Type)
}

response := mlDsaSigVerTestGroupResponse{
ID: group.ID,
}

for _, test := range group.Tests {
results, err := m.Transact("ML-DSA/"+group.ParameterSet+"/sigVer", 1, test.Signature, group.PK, test.Message)
if err != nil {
return nil, err
}

var passed *bool
if len(results[0]) == 1 {
val := results[0][0] == 1
passed = &val
}

response.Tests = append(response.Tests, mlDsaSigVerTestCaseResponse{
ID: test.ID,
TestPassed: passed,
})
}

responses = append(responses, response)
}
return responses, nil
}
1 change: 1 addition & 0 deletions util/fipstools/acvp/acvptool/subprocess/subprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess
"PBKDF": &pbkdf{},
"ML-KEM": &mlKem{},
"EDDSA": &eddsa{},
"ML-DSA": &mlDsa{},
}
m.primitives["ECDSA"] = &ecdsa{"ECDSA", map[string]bool{"P-224": true, "P-256": true, "P-384": true, "P-521": true}, m.primitives}

Expand Down
Binary file not shown.
3 changes: 2 additions & 1 deletion util/fipstools/acvp/acvptool/test/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@
{"Wrapper": "modulewrapper", "In": "vectors/ML-KEM.bz2", "Out": "expected/ML-KEM.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/EDDSA.bz2", "Out": "expected/EDDSA.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/EDDSA-KeyGen.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/EDDSA-SigGen.bz2"}
{"Wrapper": "modulewrapper", "In": "vectors/EDDSA-SigGen.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ML-DSA.bz2", "Out": "expected/ML-DSA.bz2"}
]
Binary file not shown.
Loading
Loading