xref: /aosp_15_r20/external/tink/go/aead/aead_key_templates_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2018 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 aead_test
18
19import (
20	"bytes"
21	"fmt"
22	"testing"
23
24	"github.com/google/tink/go/aead"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/internal/tinkerror/tinkerrortest"
27	"github.com/google/tink/go/keyset"
28	"github.com/google/tink/go/mac"
29	"github.com/google/tink/go/testing/fakekms"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33func TestKeyTemplates(t *testing.T) {
34	var testCases = []struct {
35		name     string
36		template *tinkpb.KeyTemplate
37	}{
38		{
39			name:     "AES128_GCM",
40			template: aead.AES128GCMKeyTemplate(),
41		}, {
42			name:     "AES256_GCM",
43			template: aead.AES256GCMKeyTemplate(),
44		}, {
45			name:     "AES256_GCM_NO_PREFIX",
46			template: aead.AES256GCMNoPrefixKeyTemplate(),
47		}, {
48			name:     "AES128_GCM_SIV",
49			template: aead.AES128GCMSIVKeyTemplate(),
50		}, {
51			name:     "AES256_GCM_SIV",
52			template: aead.AES256GCMSIVKeyTemplate(),
53		}, {
54			name:     "AES256_GCM_SIV_NO_PREFIX",
55			template: aead.AES256GCMSIVNoPrefixKeyTemplate(),
56		}, {
57			name:     "AES128_CTR_HMAC_SHA256",
58			template: aead.AES128CTRHMACSHA256KeyTemplate(),
59		}, {
60			name:     "AES256_CTR_HMAC_SHA256",
61			template: aead.AES256CTRHMACSHA256KeyTemplate(),
62		}, {
63			name:     "CHACHA20_POLY1305",
64			template: aead.ChaCha20Poly1305KeyTemplate(),
65		}, {
66			name:     "XCHACHA20_POLY1305",
67			template: aead.XChaCha20Poly1305KeyTemplate(),
68		},
69	}
70	for _, tc := range testCases {
71		t.Run(tc.name, func(t *testing.T) {
72			if err := testEncryptDecrypt(tc.template); err != nil {
73				t.Errorf("%v", err)
74			}
75		})
76	}
77}
78
79func TestKMSEnvelopeAEADKeyTemplate(t *testing.T) {
80	fakeKmsClient, err := fakekms.NewClient("fake-kms://")
81	if err != nil {
82		t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err)
83	}
84	registry.RegisterKMSClient(fakeKmsClient)
85
86	fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE"
87	newKeyURI, err := fakekms.NewKeyURI()
88	if err != nil {
89		t.Fatalf("fakekms.NewKeyURI() failed: %v", err)
90	}
91	fixedKeyTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate())
92	if err != nil {
93		t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err)
94	}
95	newKeyTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(newKeyURI, aead.AES128GCMKeyTemplate())
96	if err != nil {
97		t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err)
98	}
99
100	var testCases = []struct {
101		name     string
102		template *tinkpb.KeyTemplate
103	}{
104		{
105			name:     "Fixed Fake KMS Envelope AEAD Key with AES128_GCM",
106			template: fixedKeyTemplate,
107		}, {
108			name:     "New Fake KMS Envelope AEAD Key with AES128_GCM",
109			template: newKeyTemplate,
110		},
111	}
112	for _, tc := range testCases {
113		t.Run(tc.name, func(t *testing.T) {
114			if tc.template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW {
115				t.Errorf("KMS envelope template %s does not use RAW prefix, found '%s'", tc.name, tc.template.GetOutputPrefixType())
116			}
117			if err := testEncryptDecrypt(tc.template); err != nil {
118				t.Errorf("%v", err)
119			}
120		})
121	}
122}
123
124// Tests that two KMSEnvelopeAEAD keys that use the same KEK and DEK template
125// should be able to decrypt each other's ciphertexts.
126func TestKMSEnvelopeAEADKeyTemplateMultipleKeysSameKEK(t *testing.T) {
127	fakeKmsClient, err := fakekms.NewClient("fake-kms://")
128	if err != nil {
129		t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err)
130	}
131	registry.RegisterKMSClient(fakeKmsClient)
132
133	fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE"
134	template1, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate())
135	if err != nil {
136		t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err)
137	}
138	template2, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate())
139	if err != nil {
140		t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err)
141	}
142
143	handle1, err := keyset.NewHandle(template1)
144	if err != nil {
145		t.Fatalf("keyset.NewHandle(template1) failed: %v", err)
146	}
147	aead1, err := aead.New(handle1)
148	if err != nil {
149		t.Fatalf("aead.New(handle) failed: %v", err)
150	}
151
152	handle2, err := keyset.NewHandle(template2)
153	if err != nil {
154		t.Fatalf("keyset.NewHandle(template2) failed: %v", err)
155	}
156	aead2, err := aead.New(handle2)
157	if err != nil {
158		t.Fatalf("aead.New(handle) failed: %v", err)
159	}
160
161	plaintext := []byte("some data to encrypt")
162	aad := []byte("extra data to authenticate")
163
164	ciphertext, err := aead1.Encrypt(plaintext, aad)
165	if err != nil {
166		t.Fatalf("encryption failed, error: %v", err)
167	}
168	decrypted, err := aead2.Decrypt(ciphertext, aad)
169	if err != nil {
170		t.Fatalf("decryption failed, error: %v", err)
171	}
172	if !bytes.Equal(plaintext, decrypted) {
173		t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext)
174	}
175}
176
177// Testing deprecated function, ignoring GoDeprecated.
178func TestCreateKMSEnvelopeAEADKeyTemplateCompatibleWithKMSEnevelopeAEADKeyTemplate(t *testing.T) {
179	fakeKmsClient, err := fakekms.NewClient("fake-kms://")
180	if err != nil {
181		t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err)
182	}
183	registry.RegisterKMSClient(fakeKmsClient)
184
185	fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE"
186	template1, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate())
187	if err != nil {
188		t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err)
189	}
190	template2 := aead.KMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate())
191
192	handle1, err := keyset.NewHandle(template1)
193	if err != nil {
194		t.Fatalf("keyset.NewHandle(template1) failed: %v", err)
195	}
196	aead1, err := aead.New(handle1)
197	if err != nil {
198		t.Fatalf("aead.New(handle) failed: %v", err)
199	}
200
201	handle2, err := keyset.NewHandle(template2)
202	if err != nil {
203		t.Fatalf("keyset.NewHandle(template2) failed: %v", err)
204	}
205	aead2, err := aead.New(handle2)
206	if err != nil {
207		t.Fatalf("aead.New(handle) failed: %v", err)
208	}
209
210	plaintext := []byte("some data to encrypt")
211	aad := []byte("extra data to authenticate")
212
213	ciphertext, err := aead1.Encrypt(plaintext, aad)
214	if err != nil {
215		t.Fatalf("encryption failed, error: %v", err)
216	}
217	decrypted, err := aead2.Decrypt(ciphertext, aad)
218	if err != nil {
219		t.Fatalf("decryption failed, error: %v", err)
220	}
221	if !bytes.Equal(plaintext, decrypted) {
222		t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext)
223	}
224}
225
226// Testing deprecated function, ignoring GoDeprecated.
227func TestKMSEnvelopeAEADKeyTemplateFails(t *testing.T) {
228	keyURI, err := fakekms.NewKeyURI()
229	if err != nil {
230		t.Fatalf("fakekms.NewKeyURI() err = %v", err)
231	}
232	invalidTemplate := &tinkpb.KeyTemplate{
233		// String fields cannot contain invalid UTF-8 characters.
234		TypeUrl: "\xff",
235	}
236	var template *tinkpb.KeyTemplate
237	err = tinkerrortest.RecoverFromFail(func() {
238		template = aead.KMSEnvelopeAEADKeyTemplate(keyURI, invalidTemplate)
239	})
240	if err == nil {
241		t.Errorf("aead.KMSEnvelopAEADKeyTemplate() err = nil, want non-nil")
242	}
243	t.Logf("template: %+v", template)
244}
245
246func TestCreateKMSEnvelopeAEADKeyTemplateFails(t *testing.T) {
247	keyURI, err := fakekms.NewKeyURI()
248	if err != nil {
249		t.Fatalf("fakekms.NewKeyURI() err = %v", err)
250	}
251	invalidTemplate := &tinkpb.KeyTemplate{
252		// String fields cannot contain invalid UTF-8 characters.
253		TypeUrl: "\xff",
254	}
255	if _, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, invalidTemplate); err == nil {
256		t.Errorf("aead.CreateKMSEnvelopAEADKeyTemplate(keyURI, invalidTemplate) err = nil, want non-nil")
257	}
258}
259
260func TestCreateKMSEnvelopeAEADKeyTemplateWithUnsupportedTemplateFails(t *testing.T) {
261	keyURI, err := fakekms.NewKeyURI()
262	if err != nil {
263		t.Fatalf("fakekms.NewKeyURI() err = %v", err)
264	}
265	unsupportedTemplate := mac.HMACSHA256Tag128KeyTemplate()
266	if _, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, unsupportedTemplate); err == nil {
267		t.Errorf("aead.CreateKMSEnvelopAEADKeyTemplate(keyURI, unsupportedTemplate) err = nil, want non-nil")
268	}
269}
270
271func testEncryptDecrypt(template *tinkpb.KeyTemplate) error {
272	handle, err := keyset.NewHandle(template)
273	if err != nil {
274		return fmt.Errorf("keyset.NewHandle(template) failed: %v", err)
275	}
276	primitive, err := aead.New(handle)
277	if err != nil {
278		return fmt.Errorf("aead.New(handle) failed: %v", err)
279	}
280
281	var testInputs = []struct {
282		plaintext []byte
283		aad1      []byte
284		aad2      []byte
285	}{
286		{
287			plaintext: []byte("some data to encrypt"),
288			aad1:      []byte("extra data to authenticate"),
289			aad2:      []byte("extra data to authenticate"),
290		}, {
291			plaintext: []byte("some data to encrypt"),
292			aad1:      []byte(""),
293			aad2:      []byte(""),
294		}, {
295			plaintext: []byte("some data to encrypt"),
296			aad1:      nil,
297			aad2:      nil,
298		}, {
299			plaintext: []byte(""),
300			aad1:      nil,
301			aad2:      nil,
302		}, {
303			plaintext: nil,
304			aad1:      []byte("extra data to authenticate"),
305			aad2:      []byte("extra data to authenticate"),
306		}, {
307			plaintext: nil,
308			aad1:      []byte(""),
309			aad2:      []byte(""),
310		}, {
311			plaintext: nil,
312			aad1:      nil,
313			aad2:      nil,
314		}, {
315			plaintext: []byte("some data to encrypt"),
316			aad1:      []byte(""),
317			aad2:      nil,
318		}, {
319			plaintext: []byte("some data to encrypt"),
320			aad1:      nil,
321			aad2:      []byte(""),
322		},
323	}
324	for _, ti := range testInputs {
325		ciphertext, err := primitive.Encrypt(ti.plaintext, ti.aad1)
326		if err != nil {
327			return fmt.Errorf("encryption failed, error: %v", err)
328		}
329		decrypted, err := primitive.Decrypt(ciphertext, ti.aad2)
330		if err != nil {
331			return fmt.Errorf("decryption failed, error: %v", err)
332		}
333		if !bytes.Equal(ti.plaintext, decrypted) {
334			return fmt.Errorf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, ti.plaintext)
335		}
336	}
337	return nil
338}
339