util/fipstools/acvp/acvptool/subprocess/kda_onestep.go (140 lines of code) (raw):

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC package subprocess import ( "bytes" "encoding/json" "fmt" "strings" ) // Processes Vectors defined by https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-kdf-onestep.html type kdaOneStepMode struct{} func (k *kdaOneStepMode) ProcessKDA(vectorSet []byte, m Transactable) (interface{}, error) { var parsed kdaOneStepTestVectorSet if err := json.Unmarshal(vectorSet, &parsed); err != nil { return nil, err } var respGroups []kdaOneStepTestGroupResponse for _, group := range parsed.Groups { group := group groupResp := kdaOneStepTestGroupResponse{ID: group.ID} // determine the test type var isValidationTest bool switch group.Type { case "VAL": isValidationTest = true case "AFT": isValidationTest = false default: return nil, fmt.Errorf("unknown test type %q", group.Type) } // get the number of bytes to output and the auxillary function we're using outBytes, auxFunctionName, auxFuncType, err := group.Configuration.extract() if err != nil { return nil, err } for _, test := range group.Tests { test := test testResp := kdaOneStepTestCaseResponse{ID: test.ID} info := test.fixedInfoBytes() var args [][]byte args = append(args, test.KDFParameter.Z) if auxFuncType == hmacAuxFunction { args = append(args, test.KDFParameter.Salt) } args = append(args, info) args = append(args, uint32le(outBytes)) resp, err := m.Transact("KDA/OneStep/"+auxFunctionName, 1, args...) if err != nil { return nil, fmt.Errorf("KDA_OneStep operation failed: %s", err) } if isValidationTest { passed := bytes.Equal(test.DerivedKeyMaterial, resp[0]) testResp.Passed = &passed } else { testResp.DerivedKeyMaterial = resp[0] } groupResp.Tests = append(groupResp.Tests, testResp) } respGroups = append(respGroups, groupResp) } return respGroups, nil } type kdaOneStepTestVectorSet struct { Groups []kdaOneStepTestGroup `json:"testGroups"` } type kdaOneStepTestGroup struct { ID uint64 `json:"tgId"` Type string `json:"testType"` Configuration kdaOneStepConfiguration `json:"kdfConfiguration"` Tests []kdaOneStepTest `json:"tests"` } type kdaOneStepConfiguration struct { Type string `json:"kdfType"` SaltMethod string `json:"saltMethod"` FixedInfoPattern string `json:"fixedInfoPattern"` FixedInfoEncoding string `json:"fixedInfoEncoding"` AuxFunction string `json:"auxFunction"` L uint32 `json:"l"` } func (k *kdaOneStepConfiguration) extract() (outLen uint32, auxFunction string, auxFuncType auxFunctionType, err error) { if k.Type != "oneStep" { return 0, "", unknownAuxFunction, fmt.Errorf("unexpected kdfType: %v", k.Type) } auxFuncType.setFromString(k.AuxFunction) if auxFuncType == unknownAuxFunction { return 0, "", unknownAuxFunction, fmt.Errorf("unknown auxillary function: %v", k.AuxFunction) } if k.FixedInfoPattern != "uPartyInfo||vPartyInfo" || k.FixedInfoEncoding != "concatenation" { return 0, "", unknownAuxFunction, fmt.Errorf("unsupported FixedInfo construction, pattern(%v) with encoding(%v)", k.FixedInfoPattern, k.FixedInfoEncoding) } return k.L / 8, k.AuxFunction, auxFuncType, nil } type kdaOneStepTest struct { ID uint64 `json:"tcId"` KDFParameter struct { Type string `json:"kdfType"` Salt hexEncodedByteString `json:"salt,omitempty"` Z hexEncodedByteString `json:"z"` } `json:"kdfParameter"` FixedInfoPartyU kdaOneStepFixedInfoParty `json:"fixedInfoPartyU"` FixedInfoPartyV kdaOneStepFixedInfoParty `json:"fixedInfoPartyV"` DerivedKeyMaterial hexEncodedByteString `json:"dkm,omitempty"` } func (k *kdaOneStepTest) fixedInfoBytes() []byte { uBytes := k.FixedInfoPartyU.concatenatedBytes() vBytes := k.FixedInfoPartyV.concatenatedBytes() v := make([]byte, 0, len(uBytes)+len(vBytes)) v = append(v, uBytes...) v = append(v, vBytes...) return v } type kdaOneStepFixedInfoParty struct { PartyID hexEncodedByteString `json:"partyId"` EphemeralData hexEncodedByteString `json:"ephemeralData"` } func (k *kdaOneStepFixedInfoParty) concatenatedBytes() []byte { v := make([]byte, 0, len(k.PartyID)+len(k.EphemeralData)) v = append(v, k.PartyID...) v = append(v, k.EphemeralData...) return v } type kdaOneStepTestGroupResponse struct { ID uint64 `json:"tgId"` Tests []kdaOneStepTestCaseResponse `json:"tests"` } type kdaOneStepTestCaseResponse struct { ID uint64 `json:"tcId"` Passed *bool `json:"testPassed,omitempty"` DerivedKeyMaterial hexEncodedByteString `json:"dkm,omitempty"` } type auxFunctionType uint func (a *auxFunctionType) setFromString(v string) { if strings.HasPrefix(v, "HMAC-") { *a = hmacAuxFunction } else if strings.HasPrefix(v, "SHA-") || strings.HasPrefix(v, "SHA2-") || strings.HasPrefix(v, "SHA3-") { *a = digestAuxFunction } else { *a = unknownAuxFunction } } const ( unknownAuxFunction auxFunctionType = iota digestAuxFunction hmacAuxFunction )