xref: /aosp_15_r20/external/tink/go/hybrid/internal/hpke/encrypt_decrypt_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2022 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 hpke
18
19import (
20	"bytes"
21	"math/rand"
22	"testing"
23
24	"github.com/google/tink/go/subtle/random"
25	"github.com/google/tink/go/subtle"
26	pb "github.com/google/tink/go/proto/hpke_go_proto"
27)
28
29func TestNewEncryptDecryptUnknownKEM(t *testing.T) {
30	params := validParams(t)
31	params.Kem = pb.HpkeKem_KEM_UNKNOWN
32	pubKey, privKey := pubPrivKeys(t, params)
33
34	if _, err := NewEncrypt(pubKey); err == nil {
35		t.Error("NewEncrypt(unknown KEM): got success, want err")
36	}
37	if _, err := NewDecrypt(privKey); err == nil {
38		t.Error("NewDecrypt(unknown KEM): got success, want err")
39	}
40}
41
42func TestNewEncryptDecryptUnknownKDF(t *testing.T) {
43	params := validParams(t)
44	params.Kdf = pb.HpkeKdf_KDF_UNKNOWN
45	pubKey, privKey := pubPrivKeys(t, params)
46
47	if _, err := NewEncrypt(pubKey); err == nil {
48		t.Error("NewEncrypt(unknown KDF): got success, want err")
49	}
50	if _, err := NewDecrypt(privKey); err == nil {
51		t.Error("NewDecrypt(unknown KDF): got success, want err")
52	}
53}
54
55func TestNewEncryptDecryptUnknownAEAD(t *testing.T) {
56	params := validParams(t)
57	params.Aead = pb.HpkeAead_AEAD_UNKNOWN
58	pubKey, privKey := pubPrivKeys(t, params)
59
60	if _, err := NewEncrypt(pubKey); err == nil {
61		t.Error("NewEncrypt(unknown AEAD): got success, want err")
62	}
63	if _, err := NewDecrypt(privKey); err == nil {
64		t.Error("NewDecrypt(unknown AEAD): got success, want err")
65	}
66}
67
68func TestNewEncryptDecryptMissingParams(t *testing.T) {
69	pubKey, privKey := pubPrivKeys(t, nil)
70
71	if _, err := NewEncrypt(pubKey); err == nil {
72		t.Error("NewEncrypt(missing params): got success, want err")
73	}
74	if _, err := NewDecrypt(privKey); err == nil {
75		t.Error("NewDecrypt(missing params): got success, want err")
76	}
77}
78
79func TestNewEncryptMissingPubKeyBytes(t *testing.T) {
80	pubKey, _ := pubPrivKeys(t, validParams(t))
81	pubKey.PublicKey = nil
82	if _, err := NewEncrypt(pubKey); err == nil {
83		t.Error("NewEncrypt(nil pub key): got success, want err")
84	}
85	pubKey.PublicKey = []byte{}
86	if _, err := NewEncrypt(pubKey); err == nil {
87		t.Error("NewEncrypt(zero-length pub key): got success, want err")
88	}
89}
90
91func TestNewDecryptMissingPrivKeyBytes(t *testing.T) {
92	_, privKey := pubPrivKeys(t, validParams(t))
93	privKey.PrivateKey = nil
94	if _, err := NewDecrypt(privKey); err == nil {
95		t.Error("NewDecrypt(nil priv key): got success, want err")
96	}
97	privKey.PrivateKey = []byte{}
98	if _, err := NewDecrypt(privKey); err == nil {
99		t.Error("NewDecrypt(zero-length priv key): got success, want err")
100	}
101}
102
103func TestEncryptDecrypt(t *testing.T) {
104	aeadIDs := []pb.HpkeAead{pb.HpkeAead_AES_128_GCM, pb.HpkeAead_AES_256_GCM, pb.HpkeAead_CHACHA20_POLY1305}
105	for _, aeadID := range aeadIDs {
106		params := &pb.HpkeParams{
107			Kem:  pb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
108			Kdf:  pb.HpkeKdf_HKDF_SHA256,
109			Aead: aeadID,
110		}
111		pubKey, privKey := pubPrivKeys(t, params)
112
113		enc, err := NewEncrypt(pubKey)
114		if err != nil {
115			t.Fatalf("NewEncrypt: err %q", err)
116		}
117		dec, err := NewDecrypt(privKey)
118		if err != nil {
119			t.Fatalf("NewDecrypt: err %q", err)
120		}
121
122		wantPT := random.GetRandomBytes(200)
123		ctxInfo := random.GetRandomBytes(100)
124		ct, err := enc.Encrypt(wantPT, ctxInfo)
125		if err != nil {
126			t.Fatalf("Encrypt: err %q", err)
127		}
128		gotPT, err := dec.Decrypt(ct, ctxInfo)
129		if err != nil {
130			t.Fatalf("Decrypt: err %q", err)
131		}
132		if !bytes.Equal(gotPT, wantPT) {
133			t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT)
134		}
135	}
136}
137
138func TestDecryptModifiedCiphertextOrContextInfo(t *testing.T) {
139	pubKey, privKey := pubPrivKeys(t, validParams(t))
140	enc, err := NewEncrypt(pubKey)
141	if err != nil {
142		t.Fatalf("NewEncrypt: err %q", err)
143	}
144	dec, err := NewDecrypt(privKey)
145	if err != nil {
146		t.Fatalf("NewDecrypt: err %q", err)
147	}
148
149	wantPT := random.GetRandomBytes(200)
150	ctxInfo := random.GetRandomBytes(100)
151	ct, err := enc.Encrypt(wantPT, ctxInfo)
152	if err != nil {
153		t.Fatalf("Encrypt: err %q", err)
154	}
155	gotPT, err := dec.Decrypt(ct, ctxInfo)
156	if err != nil {
157		t.Fatalf("Decrypt: err %q", err)
158	}
159	if !bytes.Equal(gotPT, wantPT) {
160		t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT)
161	}
162
163	tests := []struct {
164		name    string
165		ct      []byte
166		ctxInfo []byte
167	}{
168		{"extended ct", append(ct, []byte("hi there")...), ctxInfo},
169		{"flip byte ct", flipRandByte(t, ct), ctxInfo},
170		{"short ct", ct[:len(ct)-5], ctxInfo},
171		{"empty ct", []byte{}, ctxInfo},
172		{"extended ctxInfo", ct, append(ctxInfo, []byte("hi there")...)},
173		{"flip byte ctxInfo", ct, flipRandByte(t, ctxInfo)},
174		{"short ctxInfo", ct, ctxInfo[:len(ctxInfo)-5]},
175		{"empty ctxInfo", ct, []byte{}},
176	}
177
178	for _, test := range tests {
179		t.Run(test.name, func(t *testing.T) {
180			if _, err := dec.Decrypt(test.ct, test.ctxInfo); err == nil {
181				t.Error("Decrypt: got success, want err")
182			}
183		})
184	}
185}
186
187func TestEncryptDecryptEmptyContextInfo(t *testing.T) {
188	pubKey, privKey := pubPrivKeys(t, validParams(t))
189	enc, err := NewEncrypt(pubKey)
190	if err != nil {
191		t.Fatalf("NewEncrypt: err %q", err)
192	}
193	dec, err := NewDecrypt(privKey)
194	if err != nil {
195		t.Fatalf("NewDecrypt: err %q", err)
196	}
197
198	wantPT := random.GetRandomBytes(200)
199	ctxInfo := []byte{}
200	ct, err := enc.Encrypt(wantPT, ctxInfo)
201	if err != nil {
202		t.Fatalf("Encrypt: err %q", err)
203	}
204	gotPT, err := dec.Decrypt(ct, ctxInfo)
205	if err != nil {
206		t.Fatalf("Decrypt: err %q", err)
207	}
208	if !bytes.Equal(gotPT, wantPT) {
209		t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT)
210	}
211}
212
213// TestDecryptEncapsulatedKeyWithFlippedMSB checks that ciphertexts with its
214// encapsulated key MSB flipped fails to decrypt. See details at b/213886185.
215func TestDecryptEncapsulatedKeyWithFlippedMSB(t *testing.T) {
216	pubKey, privKey := pubPrivKeys(t, validParams(t))
217	enc, err := NewEncrypt(pubKey)
218	if err != nil {
219		t.Fatalf("NewEncrypt: err %q", err)
220	}
221	dec, err := NewDecrypt(privKey)
222	if err != nil {
223		t.Fatalf("NewDecrypt: err %q", err)
224	}
225
226	wantPT := random.GetRandomBytes(200)
227	ctxInfo := random.GetRandomBytes(100)
228	ct, err := enc.Encrypt(wantPT, ctxInfo)
229	if err != nil {
230		t.Fatalf("Encrypt: err %q", err)
231	}
232	gotPT, err := dec.Decrypt(ct, ctxInfo)
233	if err != nil {
234		t.Fatalf("Decrypt: err %q", err)
235	}
236	if !bytes.Equal(gotPT, wantPT) {
237		t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT)
238	}
239
240	// Flip the MSB of the encapsulated key, which is the first 32 bytes of ct.
241	ct[31] = ct[31] ^ 128
242	if _, err := dec.Decrypt(ct, ctxInfo); err == nil {
243		t.Error("Decrypt with encapsulated key MSB flipped: got success, want err")
244	}
245}
246
247func validParams(t *testing.T) *pb.HpkeParams {
248	t.Helper()
249	return &pb.HpkeParams{
250		Kem:  pb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
251		Kdf:  pb.HpkeKdf_HKDF_SHA256,
252		Aead: pb.HpkeAead_AES_256_GCM,
253	}
254}
255
256func pubPrivKeys(t *testing.T, params *pb.HpkeParams) (*pb.HpkePublicKey, *pb.HpkePrivateKey) {
257	t.Helper()
258
259	priv, err := subtle.GeneratePrivateKeyX25519()
260	if err != nil {
261		t.Fatalf("GeneratePrivateKeyX25519: err %q", err)
262	}
263	pub, err := subtle.PublicFromPrivateX25519(priv)
264	if err != nil {
265		t.Fatalf("PublicFromPrivateX25519: err %q", err)
266	}
267
268	pubKey := &pb.HpkePublicKey{
269		Version:   0,
270		Params:    params,
271		PublicKey: pub,
272	}
273	privKey := &pb.HpkePrivateKey{
274		Version:    0,
275		PublicKey:  pubKey,
276		PrivateKey: priv,
277	}
278	return pubKey, privKey
279}
280
281func flipRandByte(t *testing.T, b []byte) []byte {
282	t.Helper()
283	ret := make([]byte, len(b))
284	copy(ret, b)
285	randByte := rand.Intn(len(b))
286	ret[randByte] = ret[randByte] ^ 255
287	return ret
288}
289