Skip to content

Commit

Permalink
ACVP ML-KEM testing
Browse files Browse the repository at this point in the history
  • Loading branch information
skmcgrail committed Sep 9, 2024
1 parent 16ca6e7 commit 08aab54
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 4 deletions.
194 changes: 194 additions & 0 deletions util/fipstools/acvp/acvptool/subprocess/ml_kem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// 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 mlKem struct{}

func (*mlKem) 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 processMlKemKeyGen(vs.TestGroups, m)
case strings.EqualFold(vs.Mode, "encapDecap"):
return processMlKemEncapDecap(vs.TestGroups, m)
}

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

type mlKemKeyGenTestGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Tests []struct {
ID uint64 `json:"tcId"`
D hexEncodedByteString `json:"d"`
Z hexEncodedByteString `json:"z"`
}
}

type mlKemKeyGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []mlKemKeyGenTestCaseResponse `json:"tests"`
}

type mlKemKeyGenTestCaseResponse struct {
ID uint64 `json:"tcId"`
EK hexEncodedByteString `json:"ek"`
DK hexEncodedByteString `json:"dk"`
}

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

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

var responses []mlKemKeyGenTestGroupResponse

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

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

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

ek := results[0]
dk := results[1]

response.Tests = append(response.Tests, mlKemKeyGenTestCaseResponse{
ID: test.ID,
EK: ek,
DK: dk,
})
}

responses = append(responses, response)
}

return responses, nil
}

type mlKemEncapDecapTestGroup struct {
ID uint64 `json:"tgId"`
Type string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Function string `json:"function"`
DK hexEncodedByteString `json:"dk"`
Tests []struct {
ID uint64 `json:"tcId"`
EK hexEncodedByteString `json:"ek"`
M hexEncodedByteString `json:"m"`
C hexEncodedByteString `json:"c"`
}
}

type mlKemEncDecapTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []mlKemEncDecapTestCaseResponse `json:"tests"`
}

type mlKemEncDecapTestCaseResponse struct {
ID uint64 `json:"tcId"`
C hexEncodedByteString `json:"c,omitempty"`
K hexEncodedByteString `json:"k,omitempty"`
}

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

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

var responses []mlKemEncDecapTestGroupResponse

for _, group := range groups {
if (strings.EqualFold(group.Function, "encapsulation") && !strings.EqualFold(group.Type, "AFT")) ||
(strings.EqualFold(group.Function, "decapsulation") && !strings.EqualFold(group.Type, "VAL")) {
return nil, fmt.Errorf("unsupported encapDecap function and test group type pair: (%v, %v)", group.Function, group.Type)
}

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

for _, test := range group.Tests {
var (
err error
testResponse mlKemEncDecapTestCaseResponse
)

switch {
case strings.EqualFold(group.Function, "encapsulation"):
testResponse, err = processMlKemEncapTestCase(test.ID, group.ParameterSet, test.EK, test.M, m)
case strings.EqualFold(group.Function, "decapsulation"):
testResponse, err = processMlKemDecapTestCase(test.ID, group.ParameterSet, group.DK, test.C, m)
default:
return nil, fmt.Errorf("unknown encDecap function: %v", group.Function)
}
if err != nil {
return nil, err
}

response.Tests = append(response.Tests, testResponse)
}

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

func processMlKemEncapTestCase(id uint64, algorithm string, ek []byte, m []byte, t Transactable) (mlKemEncDecapTestCaseResponse, error) {
results, err := t.Transact("ML-KEM/"+algorithm+"/encap", 2, ek, m)
if err != nil {
return mlKemEncDecapTestCaseResponse{}, err
}

c := results[0]
k := results[1]

return mlKemEncDecapTestCaseResponse{
ID: id,
C: c,
K: k,
}, nil
}

func processMlKemDecapTestCase(id uint64, algorithm string, dk []byte, c []byte, t Transactable) (mlKemEncDecapTestCaseResponse, error) {
results, err := t.Transact("ML-KEM/"+algorithm+"/decap", 1, dk, c)
if err != nil {
return mlKemEncDecapTestCaseResponse{}, err
}

k := results[0]

return mlKemEncDecapTestCaseResponse{
ID: id,
K: k,
}, 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 @@ -153,6 +153,7 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess
"KAS-ECC-SSC": &kas{},
"KAS-FFC-SSC": &kasDH{},
"PBKDF": &pbkdf{},
"ML-KEM": &mlKem{},
}
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 @@ -31,5 +31,6 @@
{"Wrapper": "modulewrapper", "In": "vectors/TLS-1.2-KDF.bz2", "Out": "expected/TLS-1.2-KDF.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/PBKDF.bz2", "Out": "expected/PBKDF.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/KDA-HKDF.bz2", "Out": "expected/KDA-HKDF.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/KDA-OneStep.bz2", "Out": "expected/KDA-OneStep.bz2"}
{"Wrapper": "modulewrapper", "In": "vectors/KDA-OneStep.bz2", "Out": "expected/KDA-OneStep.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ML-KEM.bz2", "Out": "expected/ML-KEM.bz2"}
]
Binary file not shown.
Loading

0 comments on commit 08aab54

Please sign in to comment.