xref: /aosp_15_r20/external/tink/go/aead/subtle/aes_gcm_siv_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	"bytes"
21	"encoding/hex"
22	"fmt"
23	"testing"
24
25	"github.com/google/tink/go/aead/subtle"
26	"github.com/google/tink/go/subtle/random"
27	"github.com/google/tink/go/testutil"
28)
29
30func TestAESGCMSIVRejectsInvalidKeyLength(t *testing.T) {
31	invalidKeySizes := []uint32{4, 8, 12, 15, 17, 24, 30, 31, 33, 64, 128}
32
33	for _, keySize := range invalidKeySizes {
34		key := random.GetRandomBytes(keySize)
35
36		if _, err := subtle.NewAESGCMSIV(key); err == nil {
37			t.Errorf("expected error with invalid key-size %d", keySize)
38		}
39	}
40}
41
42func TestAESGCMSIVRandomNonceProducesDifferentCiphertexts(t *testing.T) {
43	nSample := 1 << 17
44	key := random.GetRandomBytes(16)
45	pt := []byte{}
46	ad := []byte{}
47	a, _ := subtle.NewAESGCMSIV(key)
48	ctSet := make(map[string]bool)
49
50	for i := 0; i < nSample; i++ {
51		ct, _ := a.Encrypt(pt, ad)
52		ctHex := hex.EncodeToString(ct)
53
54		if _, existed := ctSet[ctHex]; existed {
55			t.Errorf("nonce is repeated after %d samples", i)
56		}
57		ctSet[ctHex] = true
58	}
59}
60
61func TestAESGCMSIVModifyCiphertext(t *testing.T) {
62	ad := random.GetRandomBytes(33)
63	key := random.GetRandomBytes(16)
64	pt := random.GetRandomBytes(32)
65	a, _ := subtle.NewAESGCMSIV(key)
66	ct, _ := a.Encrypt(pt, ad)
67	// flipping bits
68	for i := 0; i < len(ct); i++ {
69		tmp := ct[i]
70		for j := 0; j < 8; j++ {
71			ct[i] ^= 1 << uint8(j)
72			if _, err := a.Decrypt(ct, ad); err == nil {
73				t.Errorf("expect an error when flipping bit of ciphertext: byte %d, bit %d", i, j)
74			}
75			ct[i] = tmp
76		}
77	}
78	// truncated ciphertext
79	for i := 1; i < len(ct); i++ {
80		if _, err := a.Decrypt(ct[:i], ad); err == nil {
81			t.Errorf("expect an error ciphertext is truncated until byte %d", i)
82		}
83	}
84	// modify associated data
85	for i := 0; i < len(ad); i++ {
86		tmp := ad[i]
87		for j := 0; j < 8; j++ {
88			ad[i] ^= 1 << uint8(j)
89			if _, err := a.Decrypt(ct, ad); err == nil {
90				t.Errorf("expect an error when flipping bit of ad: byte %d, bit %d", i, j)
91			}
92			ad[i] = tmp
93		}
94	}
95}
96
97func TestAESGCMSIVWycheproofCases(t *testing.T) {
98	testutil.SkipTestIfTestSrcDirIsNotSet(t)
99	suite := new(AEADSuite)
100	if err := testutil.PopulateSuite(suite, "aes_gcm_siv_test.json"); err != nil {
101		t.Fatalf("failed populating suite: %s", err)
102	}
103	for _, group := range suite.TestGroups {
104		for _, test := range group.Tests {
105			caseName := fmt.Sprintf("%s-%s(%d):Case-%d", suite.Algorithm, group.Type, group.KeySize, test.CaseID)
106			t.Run("DecryptOnly/"+caseName, func(t *testing.T) { runWycheproofDecryptOnly(t, test) })
107			t.Run("EncryptDecrypt/"+caseName, func(t *testing.T) { runWycheproofEncryptDecrypt(t, test) })
108		}
109	}
110}
111
112func runWycheproofDecryptOnly(t *testing.T, testCase *AEADCase) {
113	aead, err := subtle.NewAESGCMSIV(testCase.Key)
114	if err != nil {
115		t.Fatalf("cannot create aead, error: %v", err)
116	}
117
118	var combinedCt []byte
119	combinedCt = append(combinedCt, testCase.Iv...)
120	combinedCt = append(combinedCt, testCase.Ct...)
121	combinedCt = append(combinedCt, testCase.Tag...)
122	decrypted, err := aead.Decrypt(combinedCt, testCase.Aad)
123	switch testCase.Result {
124	case "valid":
125		if err != nil {
126			t.Errorf("unexpected error in test-case: %v", err)
127		} else if !bytes.Equal(decrypted, testCase.Msg) {
128			t.Errorf(
129				"incorrect decryption: actual: %s; expected %s",
130				hex.EncodeToString(decrypted), hex.EncodeToString(testCase.Msg))
131		}
132	case "invalid":
133		if err == nil && bytes.Equal(testCase.Ct, decrypted) {
134			t.Error("successfully decrypted invalid test-case")
135		}
136	default:
137		t.Errorf("unknown test-case result: %s", testCase.Result)
138	}
139}
140
141func runWycheproofEncryptDecrypt(t *testing.T, testCase *AEADCase) {
142	aead, err := subtle.NewAESGCMSIV(testCase.Key)
143	if err != nil {
144		t.Fatalf("cannot create aead, error: %v", err)
145	}
146
147	ct, err := aead.Encrypt(testCase.Msg, testCase.Aad)
148	if err != nil {
149		if testCase.Result != "invalid" {
150			t.Errorf("unexpected error in test-case: %v", err)
151		}
152		return
153	}
154
155	decrypted, err := aead.Decrypt(ct, testCase.Aad)
156	switch testCase.Result {
157	case "valid":
158		if err != nil {
159			t.Errorf("unexpected error in test-case: %v", err)
160		} else if !bytes.Equal(decrypted, testCase.Msg) {
161			t.Errorf(
162				"incorrect decryption: actual: %s; expected %s",
163				hex.EncodeToString(decrypted), hex.EncodeToString(testCase.Msg))
164		}
165	case "invalid":
166		if err == nil && bytes.Equal(ct, decrypted) {
167			t.Error("successfully decrypted invalid test-case")
168		}
169	default:
170		t.Errorf("unknown test-case result: %s", testCase.Result)
171	}
172}
173