blob: a722ac9a135c432d1beabc9f7cda123cc79b8333 [file] [log] [blame]
Adam Langleyfb0c05c2020-07-01 13:23:55 -07001// Copyright (c) 2020, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15package subprocess
16
17import (
Adam Langleyfb0c05c2020-07-01 13:23:55 -070018 "encoding/hex"
19 "encoding/json"
20 "fmt"
21)
22
23// The following structures reflect the JSON of CMAC-AES tests. See
Adam Langleyf0e5ea22021-05-10 13:04:58 -070024// https://pages.nist.gov/ACVP/draft-fussell-acvp-mac.html#name-test-vectors
Adam Langleyfb0c05c2020-07-01 13:23:55 -070025
26type keyedMACTestVectorSet struct {
27 Groups []keyedMACTestGroup `json:"testGroups"`
28}
29
30type keyedMACTestGroup struct {
31 ID uint64 `json:"tgId"`
32 Type string `json:"testType"`
33 Direction string `json:"direction"`
34 MsgBits uint32 `json:"msgLen"`
35 KeyBits uint32 `json:"keyLen"`
36 MACBits uint32 `json:"macLen"`
37 Tests []struct {
38 ID uint64 `json:"tcId"`
39 KeyHex string `json:"key"`
40 MsgHex string `json:"message"`
41 MACHex string `json:"mac"`
42 }
43}
44
45type keyedMACTestGroupResponse struct {
46 ID uint64 `json:"tgId"`
47 Tests []keyedMACTestResponse `json:"tests"`
48}
49
50type keyedMACTestResponse struct {
51 ID uint64 `json:"tcId"`
52 MACHex string `json:"mac,omitempty"`
53 Passed *bool `json:"testPassed,omitempty"`
54}
55
56type keyedMACPrimitive struct {
57 algo string
58}
59
David Benjamin77b6f252023-05-02 10:14:11 -040060func (k *keyedMACPrimitive) Process(vectorSet []byte, m Transactable) (any, error) {
Adam Langleyfb0c05c2020-07-01 13:23:55 -070061 var vs keyedMACTestVectorSet
62 if err := json.Unmarshal(vectorSet, &vs); err != nil {
63 return nil, err
64 }
65
66 var respGroups []keyedMACTestGroupResponse
67 for _, group := range vs.Groups {
68 respGroup := keyedMACTestGroupResponse{ID: group.ID}
69
70 if group.KeyBits%8 != 0 {
71 return nil, fmt.Errorf("%d bit key in test group %d: fractional bytes not supported", group.KeyBits, group.ID)
72 }
73 if group.MsgBits%8 != 0 {
74 return nil, fmt.Errorf("%d bit message in test group %d: fractional bytes not supported", group.KeyBits, group.ID)
75 }
76 if group.MACBits%8 != 0 {
77 return nil, fmt.Errorf("%d bit MAC in test group %d: fractional bytes not supported", group.KeyBits, group.ID)
78 }
79
80 var generate bool
81 switch group.Direction {
82 case "gen":
83 generate = true
84 case "ver":
85 generate = false
86 default:
87 return nil, fmt.Errorf("unknown test direction %q in test group %d", group.Direction, group.ID)
88 }
89
90 outputBytes := uint32le(group.MACBits / 8)
91
92 for _, test := range group.Tests {
93 respTest := keyedMACTestResponse{ID: test.ID}
94
95 // Validate input.
96 if keyBits := uint32(len(test.KeyHex)) * 4; keyBits != group.KeyBits {
97 return nil, fmt.Errorf("test case %d/%d contains key of length %d bits, but expected %d-bit value", group.ID, test.ID, keyBits, group.KeyBits)
98 }
99 if msgBits := uint32(len(test.MsgHex)) * 4; msgBits != group.MsgBits {
100 return nil, fmt.Errorf("test case %d/%d contains message of length %d bits, but expected %d-bit value", group.ID, test.ID, msgBits, group.MsgBits)
101 }
102
103 if generate {
104 if len(test.MACHex) != 0 {
105 return nil, fmt.Errorf("test case %d/%d contains MAC but should not", group.ID, test.ID)
106 }
107 } else {
108 if macBits := uint32(len(test.MACHex)) * 4; macBits != group.MACBits {
109 return nil, fmt.Errorf("test case %d/%d contains MAC of length %d bits, but expected %d-bit value", group.ID, test.ID, macBits, group.MACBits)
110 }
111 }
112
113 // Set up Transact parameters.
114 key, err := hex.DecodeString(test.KeyHex)
115 if err != nil {
116 return nil, fmt.Errorf("failed to decode KeyHex in test case %d/%d: %v", group.ID, test.ID, err)
117 }
118
119 msg, err := hex.DecodeString(test.MsgHex)
120 if err != nil {
121 return nil, fmt.Errorf("failed to decode MsgHex in test case %d/%d: %v", group.ID, test.ID, err)
122 }
123
Adam Langleyfb0c05c2020-07-01 13:23:55 -0700124 if generate {
Adam Langley4a196cc2021-01-27 16:32:59 -0800125 result, err := m.Transact(k.algo, 1, outputBytes, key, msg)
126 if err != nil {
127 return nil, fmt.Errorf("wrapper %s operation failed: %s", k.algo, err)
128 }
129
130 calculatedMAC := result[0]
131 if len(calculatedMAC) != int(group.MACBits/8) {
132 return nil, fmt.Errorf("%s operation returned incorrect length value", k.algo)
133 }
134
Adam Langleyfb0c05c2020-07-01 13:23:55 -0700135 respTest.MACHex = hex.EncodeToString(calculatedMAC)
136 } else {
137 expectedMAC, err := hex.DecodeString(test.MACHex)
138 if err != nil {
139 return nil, fmt.Errorf("failed to decode MACHex in test case %d/%d: %v", group.ID, test.ID, err)
140 }
Adam Langley4a196cc2021-01-27 16:32:59 -0800141 if 8*len(expectedMAC) != int(group.MACBits) {
142 return nil, fmt.Errorf("MACHex in test case %d/%d is %x, but should be %d bits", group.ID, test.ID, expectedMAC, group.MACBits)
143 }
144
145 result, err := m.Transact(k.algo+"/verify", 1, key, msg, expectedMAC)
146 if err != nil {
147 return nil, fmt.Errorf("wrapper %s operation failed: %s", k.algo, err)
148 }
149
150 if len(result[0]) != 1 || (result[0][0]&0xfe) != 0 {
151 return nil, fmt.Errorf("wrapper %s returned invalid success flag: %x", k.algo, result[0])
152 }
153
154 ok := result[0][0] == 1
Adam Langleyfb0c05c2020-07-01 13:23:55 -0700155 respTest.Passed = &ok
156 }
157
158 respGroup.Tests = append(respGroup.Tests, respTest)
159 }
160
161 respGroups = append(respGroups, respGroup)
162 }
163
164 return respGroups, nil
165}