xref: /aosp_15_r20/external/tink/go/streamingaead/subtle/aes_gcm_hkdf_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	"testing"
22
23	"github.com/google/tink/go/streamingaead/subtle"
24)
25
26func TestAESGCMHKDFEncryptDecrypt(t *testing.T) {
27	testCases := []struct {
28		name               string
29		keySizeInBytes     int
30		segmentSize        int
31		firstSegmentOffset int
32		plaintextSize      int
33		chunkSize          int
34	}{
35		{
36			name:               "small-1",
37			keySizeInBytes:     16,
38			segmentSize:        256,
39			firstSegmentOffset: 0,
40			plaintextSize:      20,
41			chunkSize:          64,
42		},
43		{
44			name:               "small-2",
45			keySizeInBytes:     16,
46			segmentSize:        512,
47			firstSegmentOffset: 0,
48			plaintextSize:      400,
49			chunkSize:          64,
50		},
51		{
52			name:               "small-offset-1",
53			keySizeInBytes:     16,
54			segmentSize:        256,
55			firstSegmentOffset: 8,
56			plaintextSize:      20,
57			chunkSize:          64,
58		},
59		{
60			name:               "small-offset-2",
61			keySizeInBytes:     16,
62			segmentSize:        512,
63			firstSegmentOffset: 8,
64			plaintextSize:      400,
65			chunkSize:          64,
66		},
67		{
68			name:               "empty-1",
69			keySizeInBytes:     16,
70			segmentSize:        256,
71			firstSegmentOffset: 0,
72			plaintextSize:      0,
73			chunkSize:          128,
74		},
75		{
76			name:               "empty-2",
77			keySizeInBytes:     16,
78			segmentSize:        256,
79			firstSegmentOffset: 8,
80			plaintextSize:      0,
81			chunkSize:          128,
82		},
83		{
84			name:               "medium-1",
85			keySizeInBytes:     16,
86			segmentSize:        256,
87			firstSegmentOffset: 0,
88			plaintextSize:      1024,
89			chunkSize:          128,
90		},
91		{
92			name:               "medium-2",
93			keySizeInBytes:     16,
94			segmentSize:        512,
95			firstSegmentOffset: 0,
96			plaintextSize:      3086,
97			chunkSize:          128,
98		},
99		{
100			name:               "medium-3",
101			keySizeInBytes:     32,
102			segmentSize:        1024,
103			firstSegmentOffset: 0,
104			plaintextSize:      12345,
105			chunkSize:          128,
106		},
107		{
108			name:               "large-chunks-1",
109			keySizeInBytes:     16,
110			segmentSize:        256,
111			firstSegmentOffset: 0,
112			plaintextSize:      1024,
113			chunkSize:          4096,
114		},
115		{
116			name:               "large-chunks-2",
117			keySizeInBytes:     16,
118			segmentSize:        512,
119			firstSegmentOffset: 0,
120			plaintextSize:      5086,
121			chunkSize:          4096,
122		},
123		{
124			name:               "large-chunks-3",
125			keySizeInBytes:     32,
126			segmentSize:        1024,
127			firstSegmentOffset: 0,
128			plaintextSize:      12345,
129			chunkSize:          5000,
130		},
131		{
132			name:               "medium-offset-1",
133			keySizeInBytes:     16,
134			segmentSize:        256,
135			firstSegmentOffset: 8,
136			plaintextSize:      1024,
137			chunkSize:          64,
138		},
139		{
140			name:               "medium-offset-2",
141			keySizeInBytes:     16,
142			segmentSize:        512,
143			firstSegmentOffset: 20,
144			plaintextSize:      3086,
145			chunkSize:          256,
146		},
147		{
148			name:               "medium-offset-3",
149			keySizeInBytes:     32,
150			segmentSize:        1024,
151			firstSegmentOffset: 10,
152			plaintextSize:      12345,
153			chunkSize:          5000,
154		},
155		{
156			name:               "last-segment-full-1",
157			keySizeInBytes:     16,
158			segmentSize:        256,
159			firstSegmentOffset: 0,
160			plaintextSize:      216,
161			chunkSize:          64,
162		},
163		{
164			name:               "last-segment-full-2",
165			keySizeInBytes:     16,
166			segmentSize:        256,
167			firstSegmentOffset: 16,
168			plaintextSize:      200,
169			chunkSize:          256,
170		},
171		{
172			name:               "last-segment-full-3",
173			keySizeInBytes:     16,
174			segmentSize:        256,
175			firstSegmentOffset: 16,
176			plaintextSize:      440,
177			chunkSize:          1024,
178		},
179		{
180			name:               "single-byte-1",
181			keySizeInBytes:     16,
182			segmentSize:        256,
183			firstSegmentOffset: 0,
184			plaintextSize:      1024,
185			chunkSize:          1,
186		},
187		{
188			name:               "single-byte-2",
189			keySizeInBytes:     32,
190			segmentSize:        512,
191			firstSegmentOffset: 0,
192			plaintextSize:      5086,
193			chunkSize:          1,
194		},
195	}
196	for _, tc := range testCases {
197		t.Run(tc.name, func(t *testing.T) {
198			cipher, err := subtle.NewAESGCMHKDF(ikm, "SHA256", tc.keySizeInBytes, tc.segmentSize, tc.firstSegmentOffset)
199			if err != nil {
200				t.Errorf("Cannot create a cipher: %v", err)
201			}
202
203			pt, ct, err := encrypt(cipher, aad, tc.plaintextSize)
204			if err != nil {
205				t.Error(err)
206			}
207
208			if err := decrypt(cipher, aad, pt, ct, tc.chunkSize); err != nil {
209				t.Error(err)
210			}
211		})
212	}
213}
214
215func TestAESGCMHKDFModifiedCiphertext(t *testing.T) {
216	ikm, err := hex.DecodeString("000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff")
217	if err != nil {
218		t.Fatal(err)
219	}
220	aad, err := hex.DecodeString("aabbccddeeff")
221	if err != nil {
222		t.Fatal(err)
223	}
224
225	const (
226		keySizeInBytes     = 16
227		segmentSize        = 256
228		firstSegmentOffset = 8
229		plaintextSize      = 1024
230		chunkSize          = 128
231	)
232
233	cipher, err := subtle.NewAESGCMHKDF(ikm, "SHA256", keySizeInBytes, segmentSize, firstSegmentOffset)
234	if err != nil {
235		t.Errorf("Cannot create a cipher: %v", err)
236	}
237
238	pt, ct, err := encrypt(cipher, aad, plaintextSize)
239	if err != nil {
240		t.Error(err)
241	}
242
243	t.Run("truncate ciphertext", func(t *testing.T) {
244		for i := 0; i < len(ct); i += 8 {
245			if err := decrypt(cipher, aad, pt, ct[:i], chunkSize); err == nil {
246				t.Errorf("expected error")
247			}
248		}
249	})
250	t.Run("append to ciphertext", func(t *testing.T) {
251		sizes := []int{1, segmentSize - len(ct)%segmentSize, segmentSize}
252		for _, size := range sizes {
253			ct2 := append(ct, make([]byte, size)...)
254			if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil {
255				t.Errorf("expected error")
256			}
257		}
258	})
259	t.Run("flip bits", func(t *testing.T) {
260		for i := range ct {
261			ct2 := make([]byte, len(ct))
262			copy(ct2, ct)
263			ct2[i] ^= byte(1)
264			if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil {
265				t.Errorf("expected error")
266			}
267		}
268	})
269	t.Run("delete segments", func(t *testing.T) {
270		for i := 0; i < len(ct)/segmentSize+1; i++ {
271			start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i)
272			if start > len(ct) {
273				break
274			}
275			if end > len(ct) {
276				end = len(ct)
277			}
278			ct2 := append(ct[:start], ct[end:]...)
279			if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil {
280				t.Errorf("expected error")
281			}
282		}
283	})
284	t.Run("duplicate segments", func(t *testing.T) {
285		for i := 0; i < len(ct)/segmentSize+1; i++ {
286			start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i)
287			if start > len(ct) {
288				break
289			}
290			if end > len(ct) {
291				end = len(ct)
292			}
293			ct2 := append(ct[:end], ct[start:]...)
294			if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil {
295				t.Errorf("expected error")
296			}
297		}
298	})
299	t.Run("modify aad", func(t *testing.T) {
300		for i := range aad {
301			aad2 := make([]byte, len(aad))
302			copy(aad2, aad)
303			aad2[i] ^= byte(1)
304			if err := decrypt(cipher, aad2, pt, ct, chunkSize); err == nil {
305				t.Errorf("expected error")
306			}
307		}
308	})
309}
310