xref: /aosp_15_r20/external/tink/go/mac/subtle/cmac_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package subtle_test
18
19import (
20	"encoding/hex"
21	"encoding/json"
22	"os"
23	"path/filepath"
24	"testing"
25
26	"github.com/google/tink/go/mac/subtle"
27	"github.com/google/tink/go/subtle/random"
28)
29
30var (
31	// Test vectors from RFC 4493.
32	keyRFC4493, _  = hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c")
33	dataRFC4493, _ = hex.DecodeString("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710")
34	expected       = map[int]string{
35		0:  "bb1d6929e95937287fa37d129b756746",
36		16: "070a16b46b4d4144f79bdd9dd04a287c",
37		40: "dfa66747de9ae63030ca32611497c827",
38		64: "51f0bebf7e3b9d92fc49741779363cfe",
39	}
40)
41
42type testdata struct {
43	Algorithm        string
44	GeneratorVersion string
45	NumberOfTests    uint32
46	TestGroups       []*testgroup
47}
48
49type testgroup struct {
50	KeySize uint32
51	TagSize uint32
52	Type    string
53	Tests   []*testcase
54}
55
56type testcase struct {
57	Comment string
58	Key     string
59	Msg     string
60	Result  string
61	Tag     string
62	TcID    uint32
63}
64
65func TestVectorsWycheproof(t *testing.T) {
66	srcDir, ok := os.LookupEnv("TEST_SRCDIR")
67	if !ok {
68		t.Skip("TEST_SRCDIR not set")
69	}
70	f, err := os.Open(filepath.Join(srcDir, "wycheproof/testvectors/aes_cmac_test.json"))
71	if err != nil {
72		t.Fatalf("cannot open file: %s", err)
73	}
74	parser := json.NewDecoder(f)
75	data := new(testdata)
76	if err := parser.Decode(data); err != nil {
77		t.Fatalf("cannot decode test data: %s", err)
78	}
79
80	for _, g := range data.TestGroups {
81		for _, tc := range g.Tests {
82			key, err := hex.DecodeString(tc.Key)
83			if err != nil || uint32(len(key))*8 != g.KeySize {
84				t.Errorf("Could not decode key for test case %d (%s): %v", tc.TcID, tc.Comment, err)
85				continue
86			}
87			msg, err := hex.DecodeString(tc.Msg)
88			if err != nil {
89				t.Errorf("Could not decode message for test case %d (%s): %v", tc.TcID, tc.Comment, err)
90				continue
91			}
92			tag, err := hex.DecodeString(tc.Tag)
93			if err != nil {
94				t.Errorf("Could not decode expected tag for test case %d (%s): %v", tc.TcID, tc.Comment, err)
95				continue
96			}
97			if g.TagSize%8 != 0 {
98				t.Errorf("Requested tag size for test case %d (%s) is not a multiple of 8, but %d", tc.TcID, tc.Comment, g.TagSize)
99				continue
100			}
101			aes, err := subtle.NewAESCMAC(key, g.TagSize/8)
102			valid := tc.Result == "valid"
103			if valid && err != nil {
104				t.Errorf("Could not create subtle.CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err)
105				continue
106			}
107			if !valid && err != nil {
108				continue
109			}
110			res, err := aes.ComputeMAC(msg)
111			if valid && err != nil {
112				t.Errorf("Could not compute AES-CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err)
113				continue
114			}
115			if valid && hex.EncodeToString(res) != tc.Tag {
116				t.Errorf("Compute AES-CMAC and expected for test case %d (%s) do not match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag)
117			}
118			if !valid && hex.EncodeToString(res) == tc.Tag && err == nil {
119				t.Errorf("Compute AES-CMAC and invalid expected for test case %d (%s) match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag)
120			}
121			err = aes.VerifyMAC(tag, msg)
122			if valid && err != nil {
123				t.Errorf("Could not verify MAC for test case %d (%s): %v", tc.TcID, tc.Comment, err)
124			}
125			if !valid && err == nil {
126				t.Errorf("Verified invalid MAC for test case %d (%s)", tc.TcID, tc.Comment)
127			}
128		}
129	}
130}
131
132func TestCMACBasic(t *testing.T) {
133	a, err := subtle.NewAESCMAC(keyRFC4493, 16)
134	if err != nil {
135		t.Errorf("Could not create subtle.CMAC object: %v", err)
136	}
137	for l, e := range expected {
138		output, err := a.ComputeMAC(dataRFC4493[:l])
139		if err != nil {
140			t.Errorf("Error computing AES-CMAC: %v", err)
141		}
142		if hex.EncodeToString(output) != e {
143			t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e)
144		}
145		exp, err := hex.DecodeString(e)
146		if err != nil {
147			t.Errorf("Could not decode expected string %q: %v", e, err)
148		}
149		err = a.VerifyMAC(exp, dataRFC4493[:l])
150		if err != nil {
151			t.Errorf("Verification of test vector failed. Test Vector %q, Verification %v", e, err)
152		}
153	}
154}
155
156func TestNewCMACWithInvalidInput(t *testing.T) {
157	// key too short
158	_, err := subtle.NewAESCMAC(random.GetRandomBytes(1), 16)
159	if err == nil {
160		t.Errorf("expect an error when key is too short")
161	}
162	// tag too short
163	_, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 9)
164	if err == nil {
165		t.Errorf("expect an error when tag size is too small")
166	}
167	// tag too big
168	_, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 17)
169	if err == nil {
170		t.Errorf("expect an error when tag size is too big")
171	}
172}
173
174func TestCMACComputeVerifyWithNilInput(t *testing.T) {
175	cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16)
176	if err != nil {
177		t.Errorf("unexpected error when creating new CMAC")
178	}
179	tag, err := cipher.ComputeMAC(nil)
180	if err != nil {
181		t.Errorf("cipher.ComputeMAC(nil) failed: %v", err)
182	}
183	if err := cipher.VerifyMAC(tag, nil); err != nil {
184		t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err)
185	}
186}
187
188func TestCMACVerifyMACWithInvalidInput(t *testing.T) {
189	cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16)
190	if err != nil {
191		t.Errorf("unexpected error when creating new CMAC")
192	}
193	if err := cipher.VerifyMAC(nil, []byte{1}); err == nil {
194		t.Errorf("expect an error when mac is nil")
195	}
196	if err := cipher.VerifyMAC([]byte{1}, nil); err == nil {
197		t.Errorf("expect an error when data is nil")
198	}
199	if err := cipher.VerifyMAC(nil, nil); err == nil {
200		t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly")
201	}
202}
203
204func TestCMACModification(t *testing.T) {
205	a, err := subtle.NewAESCMAC(keyRFC4493, 16)
206	if err != nil {
207		t.Errorf("Could not create subtle.CMAC object: %v", err)
208	}
209	for l, e := range expected {
210		exp, err := hex.DecodeString(e)
211		if err != nil {
212			t.Errorf("Could not decode expected string %q: %v", e, err)
213		}
214		for i := 0; i < len(exp); i++ {
215			for j := 0; j < 8; j++ {
216				notExpected := make([]byte, 16)
217				copy(notExpected, exp)
218				notExpected[i] ^= 1 << uint8(j)
219				err = a.VerifyMAC(notExpected, dataRFC4493[:l])
220				if err == nil {
221					t.Errorf("Verification of modified test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected))
222				}
223			}
224		}
225	}
226}
227
228func TestCMACTruncation(t *testing.T) {
229	a, err := subtle.NewAESCMAC(keyRFC4493, 16)
230	if err != nil {
231		t.Errorf("Could not create subtle.CMAC object: %v", err)
232	}
233	for l, e := range expected {
234		exp, err := hex.DecodeString(e)
235		if err != nil {
236			t.Errorf("Could not decode expected string %q: %v", e, err)
237		}
238		for i := 1; i < len(exp); i++ {
239			notExpected := exp[:i]
240			err = a.VerifyMAC(notExpected, dataRFC4493[:l])
241			if err == nil {
242				t.Errorf("Verification of truncated test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected))
243			}
244		}
245	}
246}
247
248func TestCMACSmallerTagSize(t *testing.T) {
249	for i := 10; i <= 16; i++ {
250		a, err := subtle.NewAESCMAC(keyRFC4493, uint32(i))
251		if err != nil {
252			t.Errorf("Could not create subtle.CMAC object: %v", err)
253		}
254		for l, e := range expected {
255			exp, err := hex.DecodeString(e)
256			if err != nil {
257				t.Errorf("Could not decode expected string %q: %v", e, err)
258			}
259			err = a.VerifyMAC(exp[:i], dataRFC4493[:l])
260			if err != nil {
261				t.Errorf("Verification of smaller tag test vector did fail. Test Vector %q, Verification: %v", hex.EncodeToString(exp[:i]), err)
262			}
263		}
264	}
265}
266