xref: /aosp_15_r20/external/tink/go/streamingaead/aes_ctr_hmac_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 streamingaead_test
18
19import (
20	"bytes"
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/streamingaead/subtle"
27	"github.com/google/tink/go/testutil"
28	ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto"
29	commonpb "github.com/google/tink/go/proto/common_go_proto"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33var aesCTRHMACKeySizes = []uint32{16, 32}
34
35func TestAESCTRHMACGetPrimitiveBasic(t *testing.T) {
36	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
37	if err != nil {
38		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
39	}
40	for _, keySize := range aesCTRHMACKeySizes {
41		key := testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096)
42		serializedKey, err := proto.Marshal(key)
43		if err != nil {
44			t.Errorf("failed to marshal key: %s", err)
45		}
46		p, err := keyManager.Primitive(serializedKey)
47		if err != nil {
48			t.Errorf("unexpected error: %s", err)
49		}
50		if err := validateAESCTRHMACPrimitive(p, key); err != nil {
51			t.Errorf("%s", err)
52		}
53	}
54}
55
56func TestAESCTRHMACGetPrimitiveWithInvalidInput(t *testing.T) {
57	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
58	if err != nil {
59		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
60	}
61
62	testKeys := genInvalidAESCTRHMACKeys()
63	for i := 0; i < len(testKeys); i++ {
64		serializedKey, err := proto.Marshal(testKeys[i])
65		if err != nil {
66			t.Errorf("failed to marshal key: %s", err)
67		}
68		if _, err := keyManager.Primitive(serializedKey); err == nil {
69			t.Errorf("expect an error in test case %d", i)
70		}
71	}
72
73	if _, err := keyManager.Primitive(nil); err == nil {
74		t.Errorf("expect an error when input is nil")
75	}
76	if _, err := keyManager.Primitive([]byte{}); err == nil {
77		t.Errorf("expect an error when input is empty")
78	}
79}
80
81func TestAESCTRHMACNewKeyMultipleTimes(t *testing.T) {
82	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
83	if err != nil {
84		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
85	}
86	format := testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096)
87	serializedFormat, err := proto.Marshal(format)
88	if err != nil {
89		t.Errorf("failed to marshal key: %s", err)
90	}
91	keys := make(map[string]struct{})
92	n := 26
93	for i := 0; i < n; i++ {
94		key, _ := keyManager.NewKey(serializedFormat)
95		serializedKey, err := proto.Marshal(key)
96		if err != nil {
97			t.Errorf("failed to marshal key: %s", err)
98		}
99		keys[string(serializedKey)] = struct{}{}
100
101		keyData, _ := keyManager.NewKeyData(serializedFormat)
102		serializedKey = keyData.Value
103		keys[string(serializedKey)] = struct{}{}
104	}
105	if len(keys) != n*2 {
106		t.Errorf("key is repeated")
107	}
108}
109
110func TestAESCTRHMACNewKeyBasic(t *testing.T) {
111	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
112	if err != nil {
113		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
114	}
115	for _, keySize := range aesCTRHMACKeySizes {
116		format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096)
117		serializedFormat, err := proto.Marshal(format)
118		if err != nil {
119			t.Errorf("failed to marshal key: %s", err)
120		}
121		m, err := keyManager.NewKey(serializedFormat)
122		if err != nil {
123			t.Errorf("unexpected error: %s", err)
124		}
125		key := m.(*ctrhmacpb.AesCtrHmacStreamingKey)
126		if err := validateAESCTRHMACKey(key, format); err != nil {
127			t.Errorf("%s", err)
128		}
129	}
130}
131
132func TestAESCTRHMACNewKeyWithInvalidInput(t *testing.T) {
133	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
134	if err != nil {
135		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
136	}
137	// bad format
138	badFormats := genInvalidAESCTRHMACKeyFormats()
139	for i := 0; i < len(badFormats); i++ {
140		serializedFormat, err := proto.Marshal(badFormats[i])
141		if err != nil {
142			t.Errorf("failed to marshal key: %s", err)
143		}
144		if _, err := keyManager.NewKey(serializedFormat); err == nil {
145			t.Errorf("expect an error in test case %d", i)
146		}
147	}
148	// nil
149	if _, err := keyManager.NewKey(nil); err == nil {
150		t.Errorf("expect an error when input is nil")
151	}
152	// empty array
153	if _, err := keyManager.NewKey([]byte{}); err == nil {
154		t.Errorf("expect an error when input is empty")
155	}
156}
157
158func TestAESCTRHMACNewKeyDataBasic(t *testing.T) {
159	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
160	if err != nil {
161		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
162	}
163	for _, keySize := range aesCTRHMACKeySizes {
164		format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096)
165		serializedFormat, err := proto.Marshal(format)
166		if err != nil {
167			t.Errorf("failed to marshal key: %s", err)
168		}
169		keyData, err := keyManager.NewKeyData(serializedFormat)
170		if err != nil {
171			t.Errorf("unexpected error: %s", err)
172		}
173		if keyData.TypeUrl != testutil.AESCTRHMACTypeURL {
174			t.Errorf("incorrect type url")
175		}
176		if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC {
177			t.Errorf("incorrect key material type")
178		}
179		key := new(ctrhmacpb.AesCtrHmacStreamingKey)
180		if err := proto.Unmarshal(keyData.Value, key); err != nil {
181			t.Errorf("incorrect key value")
182		}
183		if err := validateAESCTRHMACKey(key, format); err != nil {
184			t.Errorf("%s", err)
185		}
186	}
187}
188
189func TestAESCTRHMACNewKeyDataWithInvalidInput(t *testing.T) {
190	km, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
191	if err != nil {
192		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
193	}
194	badFormats := genInvalidAESCTRHMACKeyFormats()
195	for i := 0; i < len(badFormats); i++ {
196		serializedFormat, err := proto.Marshal(badFormats[i])
197		if err != nil {
198			t.Errorf("failed to marshal key: %s", err)
199		}
200		if _, err := km.NewKeyData(serializedFormat); err == nil {
201			t.Errorf("expect an error in test case %d", i)
202		}
203	}
204	// nil input
205	if _, err := km.NewKeyData(nil); err == nil {
206		t.Errorf("expect an error when input is nil")
207	}
208	// empty input
209	if _, err := km.NewKeyData([]byte{}); err == nil {
210		t.Errorf("expect an error when input is empty")
211	}
212}
213
214func TestAESCTRHMACDoesSupport(t *testing.T) {
215	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
216	if err != nil {
217		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
218	}
219	if !keyManager.DoesSupport(testutil.AESCTRHMACTypeURL) {
220		t.Errorf("AESCTRHMACKeyManager must support %s", testutil.AESCTRHMACTypeURL)
221	}
222	if keyManager.DoesSupport("some bad type") {
223		t.Errorf("AESCTRHMACKeyManager must support only %s", testutil.AESCTRHMACTypeURL)
224	}
225}
226
227func TestAESCTRHMACTypeURL(t *testing.T) {
228	keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL)
229	if err != nil {
230		t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err)
231	}
232	if keyManager.TypeURL() != testutil.AESCTRHMACTypeURL {
233		t.Errorf("incorrect key type")
234	}
235}
236
237func genInvalidAESCTRHMACKeys() []proto.Message {
238	return []proto.Message{
239		// not a AESCTRHMACKey
240		testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096),
241
242		// bad key size
243		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096),
244		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096),
245		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096),
246
247		// bad version
248		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion+1, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096),
249
250		// bad ciphertext_segment_size
251		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 2147483648),
252
253		// bad hmac params hash type
254		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA224, 16, 4096),
255		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA384, 16, 4096),
256
257		// bad hkdf hash type
258		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA224, 16, commonpb.HashType_SHA256, 16, 4096),
259		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA384, 16, commonpb.HashType_SHA256, 16, 4096),
260	}
261}
262
263func genInvalidAESCTRHMACKeyFormats() []proto.Message {
264	return []proto.Message{
265		// not AESCTRHMACKeyFormat
266		testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096),
267
268		// invalid key size
269		testutil.NewAESCTRHMACKeyFormat(17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096),
270		testutil.NewAESCTRHMACKeyFormat(16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096),
271		testutil.NewAESCTRHMACKeyFormat(33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096),
272	}
273}
274
275func validateAESCTRHMACKey(key *ctrhmacpb.AesCtrHmacStreamingKey, format *ctrhmacpb.AesCtrHmacStreamingKeyFormat) error {
276	if uint32(len(key.KeyValue)) != format.KeySize {
277		return fmt.Errorf("incorrect key size")
278	}
279	if key.Version != testutil.AESCTRHMACKeyVersion {
280		return fmt.Errorf("incorrect key version")
281	}
282	if key.Params.CiphertextSegmentSize != format.Params.CiphertextSegmentSize {
283		return fmt.Errorf("incorrect ciphertext segment size")
284	}
285	if key.Params.DerivedKeySize != format.Params.DerivedKeySize {
286		return fmt.Errorf("incorrect derived key size")
287	}
288	if key.Params.HkdfHashType != format.Params.HkdfHashType {
289		return fmt.Errorf("incorrect HKDF hash type")
290	}
291	// try to encrypt and decrypt
292	p, err := subtle.NewAESCTRHMAC(
293		key.KeyValue,
294		key.Params.HkdfHashType.String(),
295		int(key.Params.DerivedKeySize),
296		key.Params.HmacParams.Hash.String(),
297		int(key.Params.HmacParams.TagSize),
298		int(key.Params.CiphertextSegmentSize),
299		0,
300	)
301	if err != nil {
302		return fmt.Errorf("invalid key")
303	}
304	return validateAESCTRHMACPrimitive(p, key)
305}
306
307func validateAESCTRHMACPrimitive(p interface{}, key *ctrhmacpb.AesCtrHmacStreamingKey) error {
308	cipher := p.(*subtle.AESCTRHMAC)
309	if !bytes.Equal(cipher.MainKey, key.KeyValue) {
310		return fmt.Errorf("main key and primitive don't match")
311	}
312	return encryptDecrypt(cipher, cipher, 32, 32)
313}
314