xref: /aosp_15_r20/external/tink/go/prf/aes_cmac_prf_key_manager_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 prf_test
18
19import (
20	"encoding/hex"
21	"fmt"
22	"testing"
23
24	"google.golang.org/protobuf/proto"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/prf"
27	"github.com/google/tink/go/prf/subtle"
28	"github.com/google/tink/go/subtle/random"
29	"github.com/google/tink/go/testutil"
30	cmacpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto"
31	commonpb "github.com/google/tink/go/proto/common_go_proto"
32	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
33)
34
35func TestGetPrimitiveCMACBasic(t *testing.T) {
36	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
37	if err != nil {
38		t.Errorf("AES CMAC PRF key manager not found: %s", err)
39	}
40	testKeys := genValidCMACKeys()
41	for i := 0; i < len(testKeys); i++ {
42		serializedKey, _ := proto.Marshal(testKeys[i])
43		p, err := km.Primitive(serializedKey)
44		if err != nil {
45			t.Errorf("unexpected error in test case %d: %s", i, err)
46		}
47		if err := validateCMACPrimitive(p, testKeys[i]); err != nil {
48			t.Errorf("%s", err)
49		}
50	}
51}
52
53func TestGetPrimitiveCMACWithInvalidInput(t *testing.T) {
54	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
55	if err != nil {
56		t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err)
57	}
58	// invalid key
59	testKeys := genInvalidCMACKeys()
60	for i := 0; i < len(testKeys); i++ {
61		serializedKey, _ := proto.Marshal(testKeys[i])
62		if _, err := km.Primitive(serializedKey); err == nil {
63			t.Errorf("expect an error in test case %d", i)
64		}
65	}
66	if _, err := km.Primitive(nil); err == nil {
67		t.Errorf("expect an error when input is nil")
68	}
69	// empty input
70	if _, err := km.Primitive([]byte{}); err == nil {
71		t.Errorf("expect an error when input is empty")
72	}
73}
74
75func TestNewKeyCMACMultipleTimes(t *testing.T) {
76	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
77	if err != nil {
78		t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err)
79	}
80	serializedFormat, _ := proto.Marshal(testutil.NewAESCMACPRFKeyFormat())
81	keys := make(map[string]bool)
82	nTest := 26
83	for i := 0; i < nTest; i++ {
84		key, _ := km.NewKey(serializedFormat)
85		serializedKey, _ := proto.Marshal(key)
86		keys[string(serializedKey)] = true
87
88		keyData, _ := km.NewKeyData(serializedFormat)
89		serializedKey = keyData.Value
90		keys[string(serializedKey)] = true
91	}
92	if len(keys) != nTest*2 {
93		t.Errorf("key is repeated")
94	}
95}
96
97func TestNewKeyCMACBasic(t *testing.T) {
98	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
99	if err != nil {
100		t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err)
101	}
102	testFormats := genValidCMACKeyFormats()
103	for i := 0; i < len(testFormats); i++ {
104		serializedFormat, _ := proto.Marshal(testFormats[i])
105		key, err := km.NewKey(serializedFormat)
106		if err != nil {
107			t.Errorf("unexpected error in test case %d: %s", i, err)
108		}
109		if err := validateCMACKey(testFormats[i], key.(*cmacpb.AesCmacPrfKey)); err != nil {
110			t.Errorf("%s", err)
111		}
112	}
113}
114
115func TestNewKeyCMACWithInvalidInput(t *testing.T) {
116	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
117	if err != nil {
118		t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err)
119	}
120	// invalid key formats
121	testFormats := genInvalidCMACKeyFormats()
122	for i := 0; i < len(testFormats); i++ {
123		serializedFormat, err := proto.Marshal(testFormats[i])
124		if err != nil {
125			fmt.Println("Error!")
126		}
127		if _, err := km.NewKey(serializedFormat); err == nil {
128			t.Errorf("expect an error in test case %d: %s", i, err)
129		}
130	}
131	if _, err := km.NewKey(nil); err == nil {
132		t.Errorf("expect an error when input is nil")
133	}
134	// empty input
135	if _, err := km.NewKey([]byte{}); err == nil {
136		t.Errorf("expect an error when input is empty")
137	}
138}
139
140func TestNewKeyDataCMACBasic(t *testing.T) {
141	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
142	if err != nil {
143		t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err)
144	}
145	testFormats := genValidCMACKeyFormats()
146	for i := 0; i < len(testFormats); i++ {
147		serializedFormat, _ := proto.Marshal(testFormats[i])
148		keyData, err := km.NewKeyData(serializedFormat)
149		if err != nil {
150			t.Errorf("unexpected error in test case %d: %s", i, err)
151		}
152		if keyData.TypeUrl != testutil.AESCMACPRFTypeURL {
153			t.Errorf("incorrect type url in test case %d", i)
154		}
155		if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC {
156			t.Errorf("incorrect key material type in test case %d", i)
157		}
158		key := new(cmacpb.AesCmacPrfKey)
159		if err := proto.Unmarshal(keyData.Value, key); err != nil {
160			t.Errorf("invalid key value")
161		}
162		if err := validateCMACKey(testFormats[i], key); err != nil {
163			t.Errorf("invalid key")
164		}
165	}
166}
167
168func TestNewKeyDataCMACWithInvalidInput(t *testing.T) {
169	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
170	if err != nil {
171		t.Errorf("AES CMAC PRF key manager not found: %s", err)
172	}
173	// invalid key formats
174	testFormats := genInvalidCMACKeyFormats()
175	for i := 0; i < len(testFormats); i++ {
176		serializedFormat, _ := proto.Marshal(testFormats[i])
177		if _, err := km.NewKeyData(serializedFormat); err == nil {
178			t.Errorf("expect an error in test case %d", i)
179		}
180	}
181	// nil input
182	if _, err := km.NewKeyData(nil); err == nil {
183		t.Errorf("expect an error when input is nil")
184	}
185}
186
187func TestCMACDoesSupport(t *testing.T) {
188	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
189	if err != nil {
190		t.Errorf("AES CMAC PRF key manager not found: %s", err)
191	}
192	if !km.DoesSupport(testutil.AESCMACPRFTypeURL) {
193		t.Errorf("AESCMACPRFKeyManager must support %s", testutil.AESCMACPRFTypeURL)
194	}
195	if km.DoesSupport("some bad type") {
196		t.Errorf("AESCMACPRFKeyManager must support only %s", testutil.AESCMACPRFTypeURL)
197	}
198}
199
200func TestCMACTypeURL(t *testing.T) {
201	km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL)
202	if err != nil {
203		t.Errorf("AES CMAC PRF key manager not found: %s", err)
204	}
205	if km.TypeURL() != testutil.AESCMACPRFTypeURL {
206		t.Errorf("incorrect GetKeyType()")
207	}
208}
209
210func genInvalidCMACKeys() []proto.Message {
211	badVersionKey := testutil.NewAESCMACPRFKey()
212	badVersionKey.Version++
213	shortKey := testutil.NewAESCMACPRFKey()
214	shortKey.KeyValue = []byte{1, 1}
215	return []proto.Message{
216		// not a AESCMACPRFKey
217		testutil.NewHMACParams(commonpb.HashType_SHA256, 32),
218		// bad version
219		badVersionKey,
220		// key too short
221		shortKey,
222	}
223}
224
225func genInvalidCMACKeyFormats() []proto.Message {
226	shortKeyFormat := testutil.NewAESCMACPRFKeyFormat()
227	shortKeyFormat.KeySize = 1
228	return []proto.Message{
229		// not a AESCMACPRFKeyFormat
230		testutil.NewHMACParams(commonpb.HashType_SHA256, 32),
231		// key too short
232		shortKeyFormat,
233	}
234}
235
236func genValidCMACKeyFormats() []*cmacpb.AesCmacPrfKeyFormat {
237	return []*cmacpb.AesCmacPrfKeyFormat{
238		testutil.NewAESCMACPRFKeyFormat(),
239	}
240}
241
242func genValidCMACKeys() []*cmacpb.AesCmacPrfKey {
243	return []*cmacpb.AesCmacPrfKey{
244		testutil.NewAESCMACPRFKey(),
245	}
246}
247
248// Checks whether the given CMACPRFKey matches the given key AESCMACPRFKeyFormat
249func validateCMACKey(format *cmacpb.AesCmacPrfKeyFormat, key *cmacpb.AesCmacPrfKey) error {
250	if format.KeySize != uint32(len(key.KeyValue)) {
251		return fmt.Errorf("key format and generated key do not match")
252	}
253	p, err := subtle.NewAESCMACPRF(key.KeyValue)
254	if err != nil {
255		return fmt.Errorf("cannot create primitive from key: %s", err)
256	}
257	return validateCMACPrimitive(p, key)
258}
259
260// validateCMACPrimitive checks whether the given primitive matches the given AESCMACPRFKey
261func validateCMACPrimitive(p interface{}, key *cmacpb.AesCmacPrfKey) error {
262	cmacPrimitive := p.(prf.PRF)
263	prfPrimitive, err := subtle.NewAESCMACPRF(key.KeyValue)
264	if err != nil {
265		return fmt.Errorf("Could not create AES CMAC PRF with key material %q: %s", hex.EncodeToString(key.KeyValue), err)
266	}
267	data := random.GetRandomBytes(20)
268	res, err := cmacPrimitive.ComputePRF(data, 16)
269	if err != nil {
270		return fmt.Errorf("prf computation failed: %s", err)
271	}
272	if len(res) != 16 {
273		return fmt.Errorf("prf computation did not produce 16 byte output")
274	}
275	res2, err := prfPrimitive.ComputePRF(data, 16)
276	if err != nil {
277		return fmt.Errorf("prf computation failed: %s", err)
278	}
279	if len(res2) != 16 {
280		return fmt.Errorf("prf computation did not produce 16 byte output")
281	}
282	if hex.EncodeToString(res) != hex.EncodeToString(res2) {
283		return fmt.Errorf("prf computation did not produce the same output for the same key and input")
284	}
285	return nil
286}
287