xref: /aosp_15_r20/external/tink/go/hybrid/hpke_private_key_manager_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 hybrid
18
19import (
20	"bytes"
21	"testing"
22
23	"github.com/google/go-cmp/cmp"
24	"google.golang.org/protobuf/proto"
25	"google.golang.org/protobuf/testing/protocmp"
26	"github.com/google/tink/go/core/registry"
27	"github.com/google/tink/go/hybrid/internal/hpke"
28	"github.com/google/tink/go/subtle/random"
29	hpkepb "github.com/google/tink/go/proto/hpke_go_proto"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33func TestPrivateKeyManagerPrimitiveRejectsInvalidKeyVersion(t *testing.T) {
34	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
35	if err != nil {
36		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
37	}
38	params := &hpkepb.HpkeParams{
39		Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
40		Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
41		Aead: hpkepb.HpkeAead_AES_256_GCM,
42	}
43	_, privKey := pubPrivKeys(t, params)
44	privKey.Version = 1
45	serializedPrivKey, err := proto.Marshal(privKey)
46	if err != nil {
47		t.Fatal(err)
48	}
49	if _, err := km.Primitive(serializedPrivKey); err == nil {
50		t.Error("Primitive() err = nil, want error")
51	}
52}
53
54func TestPrivateKeyManagerPrimitiveRejectsInvalidParams(t *testing.T) {
55	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
56	if err != nil {
57		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
58	}
59
60	tests := []struct {
61		name   string
62		params *hpkepb.HpkeParams
63	}{
64		{"kem", &hpkepb.HpkeParams{
65			Kem:  hpkepb.HpkeKem_KEM_UNKNOWN,
66			Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
67			Aead: hpkepb.HpkeAead_AES_256_GCM,
68		}},
69		{"kdf", &hpkepb.HpkeParams{
70			Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
71			Kdf:  hpkepb.HpkeKdf_KDF_UNKNOWN,
72			Aead: hpkepb.HpkeAead_AES_256_GCM,
73		}},
74		{"aead", &hpkepb.HpkeParams{
75			Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
76			Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
77			Aead: hpkepb.HpkeAead_AEAD_UNKNOWN,
78		}},
79	}
80
81	for _, test := range tests {
82		t.Run(test.name, func(t *testing.T) {
83			_, serializedPrivKey := serializedPubPrivKeys(t, test.params)
84			if _, err := km.Primitive(serializedPrivKey); err == nil {
85				t.Error("Primitive() err = nil, want error")
86			}
87		})
88	}
89}
90
91func TestPrivateKeyManagerPrimitiveRejectsMissingParams(t *testing.T) {
92	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
93	if err != nil {
94		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
95	}
96	_, serializedPrivKey := serializedPubPrivKeys(t, nil)
97	if _, err := km.Primitive(serializedPrivKey); err == nil {
98		t.Error("Primitive() err = nil, want error")
99	}
100}
101
102func TestPrivateKeyManagerPrimitiveRejectsNilKey(t *testing.T) {
103	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
104	if err != nil {
105		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
106	}
107	if _, err := km.Primitive(nil); err == nil {
108		t.Error("Primitive() err = nil, want error")
109	}
110}
111
112func TestPrivateKeyManagerPrimitiveEncryptDecrypt(t *testing.T) {
113	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
114	if err != nil {
115		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
116	}
117	pt := random.GetRandomBytes(200)
118	ctxInfo := random.GetRandomBytes(100)
119
120	for _, aeadID := range hpkeAEADs {
121		params := &hpkepb.HpkeParams{
122			Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
123			Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
124			Aead: aeadID,
125		}
126		pubKey, privKey := pubPrivKeys(t, params)
127		serializedPrivKey, err := proto.Marshal(privKey)
128		if err != nil {
129			t.Fatal(err)
130		}
131
132		enc, err := hpke.NewEncrypt(pubKey)
133		if err != nil {
134			t.Fatalf("hpke.NewEncrypt() err = %v, want nil", err)
135		}
136		d, err := km.Primitive(serializedPrivKey)
137		if err != nil {
138			t.Fatalf("Primitive() err = %v, want nil", err)
139		}
140		dec, ok := d.(*hpke.Decrypt)
141		if !ok {
142			t.Fatal("primitive is not Decrypt")
143		}
144
145		ct, err := enc.Encrypt(pt, ctxInfo)
146		if err != nil {
147			t.Fatalf("Encrypt() err = %v, want nil", err)
148		}
149		gotPT, err := dec.Decrypt(ct, ctxInfo)
150		if err != nil {
151			t.Fatalf("Decrypt() err = %v, want nil", err)
152		}
153		if want := pt; !bytes.Equal(gotPT, want) {
154			t.Errorf("Decrypt() = %x, want %x", gotPT, want)
155		}
156	}
157}
158
159func TestPrivateKeyManagerNewKeyRejectsNilKeyFormat(t *testing.T) {
160	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
161	if err != nil {
162		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
163	}
164	if _, err := km.NewKey(nil); err == nil {
165		t.Error("NewKey() err = nil, want error")
166	}
167}
168
169func TestPrivateKeyManagerNewKeyRejectsInvalidKeyFormat(t *testing.T) {
170	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
171	if err != nil {
172		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
173	}
174	serializedKeyFormatUnknownKEM, err := proto.Marshal(
175		&hpkepb.HpkeParams{
176			Kem:  hpkepb.HpkeKem_KEM_UNKNOWN,
177			Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
178			Aead: hpkepb.HpkeAead_AES_256_GCM,
179		})
180	if err != nil {
181		t.Fatal(err)
182	}
183	serializedKeyFormatUnknownKDF, err := proto.Marshal(
184		&hpkepb.HpkeParams{
185			Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
186			Kdf:  hpkepb.HpkeKdf_KDF_UNKNOWN,
187			Aead: hpkepb.HpkeAead_AES_256_GCM,
188		})
189	if err != nil {
190		t.Fatal(err)
191	}
192	serializedKeyFormatUnknownAEAD, err := proto.Marshal(
193		&hpkepb.HpkeParams{
194			Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
195			Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
196			Aead: hpkepb.HpkeAead_AEAD_UNKNOWN,
197		})
198	if err != nil {
199		t.Fatal(err)
200	}
201
202	tests := []struct {
203		name      string
204		keyFormat []byte
205	}{
206		{"kem", serializedKeyFormatUnknownKEM},
207		{"kdf", serializedKeyFormatUnknownKDF},
208		{"aead", serializedKeyFormatUnknownAEAD},
209	}
210
211	for _, test := range tests {
212		t.Run(test.name, func(t *testing.T) {
213			if _, err := km.NewKey(test.keyFormat); err == nil {
214				t.Error("NewKey() err = nil, want error")
215			}
216		})
217	}
218}
219
220func TestPrivateKeyManagerNewKeyEncryptDecrypt(t *testing.T) {
221	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
222	if err != nil {
223		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
224	}
225
226	wantPT := random.GetRandomBytes(200)
227	ctxInfo := random.GetRandomBytes(100)
228
229	for _, aeadID := range hpkeAEADs {
230		keyFormat := &hpkepb.HpkeKeyFormat{
231			Params: &hpkepb.HpkeParams{
232				Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
233				Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
234				Aead: aeadID,
235			},
236		}
237		serializedKeyFormat, err := proto.Marshal(keyFormat)
238		if err != nil {
239			t.Fatal(err)
240		}
241
242		privKeyProto, err := km.NewKey(serializedKeyFormat)
243		if err != nil {
244			t.Fatalf("NewKey() err = %v, want nil", err)
245		}
246		privKey, ok := privKeyProto.(*hpkepb.HpkePrivateKey)
247		if !ok {
248			t.Fatal("primitive is not HpkePrivateKey")
249		}
250		if privKey.GetVersion() != 0 {
251			t.Errorf("private key version = %d, want %d", privKey.GetVersion(), 0)
252		}
253		if len(privKey.GetPrivateKey()) == 0 {
254			t.Error("private key is missing")
255		}
256
257		pubKey := privKey.GetPublicKey()
258		if pubKey.GetVersion() != 0 {
259			t.Errorf("public key version = %d, want %d", pubKey.GetVersion(), 0)
260		}
261		if !cmp.Equal(pubKey.GetParams(), keyFormat.GetParams(), protocmp.Transform()) {
262			t.Errorf("key params = %v, want %v", pubKey.GetParams(), keyFormat.GetParams())
263		}
264		if len(pubKey.GetPublicKey()) == 0 {
265			t.Error("public key is missing")
266		}
267
268		enc, err := hpke.NewEncrypt(pubKey)
269		if err != nil {
270			t.Fatalf("hpke.NewEncrypt() err = %v, want nil", err)
271		}
272		serializedPrivKey, err := proto.Marshal(privKeyProto)
273		if err != nil {
274			t.Fatal(err)
275		}
276		d, err := km.Primitive(serializedPrivKey)
277		if err != nil {
278			t.Fatalf("Primitive() err = %v, want nil", err)
279		}
280		dec, ok := d.(*hpke.Decrypt)
281		if !ok {
282			t.Fatal("primitive is not Decrypt")
283		}
284
285		ct, err := enc.Encrypt(wantPT, ctxInfo)
286		if err != nil {
287			t.Fatalf("Encrypt() err = %v, want nil", err)
288		}
289		gotPT, err := dec.Decrypt(ct, ctxInfo)
290		if err != nil {
291			t.Fatalf("Decrypt() err = %v, want nil", err)
292		}
293		if !bytes.Equal(gotPT, wantPT) {
294			t.Errorf("Decrypt() = %x, want %x", gotPT, wantPT)
295		}
296	}
297}
298
299func TestPrivateKeyManagerNewKeyDataRejectsNilKeyFormat(t *testing.T) {
300	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
301	if err != nil {
302		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
303	}
304	if _, err := km.NewKeyData(nil); err == nil {
305		t.Error("NewKey() err = nil, want error")
306	}
307}
308
309func TestPrivateKeyManagerNewKeyData(t *testing.T) {
310	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
311	if err != nil {
312		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
313	}
314
315	for _, aeadID := range hpkeAEADs {
316		keyFormat := &hpkepb.HpkeKeyFormat{
317			Params: &hpkepb.HpkeParams{
318				Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
319				Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
320				Aead: aeadID,
321			},
322		}
323		serializedKeyFormat, err := proto.Marshal(keyFormat)
324		if err != nil {
325			t.Fatal(err)
326		}
327
328		keyData, err := km.NewKeyData(serializedKeyFormat)
329		if err != nil {
330			t.Fatalf("NewKeyData() err = %v, want nil", err)
331		}
332		if got, want := keyData.GetTypeUrl(), hpkePrivateKeyTypeURL; got != want {
333			t.Errorf("type URL = %q, want %q", got, want)
334		}
335		if got, want := keyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE; got != want {
336			t.Errorf("key material type = %d, want %d", got, want)
337		}
338
339		privKey := new(hpkepb.HpkePrivateKey)
340		if err := proto.Unmarshal(keyData.GetValue(), privKey); err != nil {
341			t.Fatalf("Unmarshal err = %v, want nil", err)
342		}
343		if privKey.GetVersion() != 0 {
344			t.Errorf("private key version = %d, want %d", privKey.GetVersion(), 0)
345		}
346		if len(privKey.GetPrivateKey()) == 0 {
347			t.Error("private key is missing")
348		}
349
350		pubKey := privKey.GetPublicKey()
351		if pubKey.GetVersion() != 0 {
352			t.Errorf("public key version = %d, want %d", pubKey.GetVersion(), 0)
353		}
354		if !cmp.Equal(pubKey.GetParams(), keyFormat.GetParams(), protocmp.Transform()) {
355			t.Errorf("key params = %v, want %v", pubKey.GetParams(), keyFormat.GetParams())
356		}
357		if len(pubKey.GetPublicKey()) == 0 {
358			t.Error("public key is missing")
359		}
360	}
361}
362
363func TestPrivateKeyManagerPublicKeyDataAcceptsNilKey(t *testing.T) {
364	k, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
365	if err != nil {
366		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
367	}
368	km, ok := k.(registry.PrivateKeyManager)
369	if !ok {
370		t.Errorf("primitive is not PrivateKeyManager")
371	}
372	if _, err := km.PublicKeyData(nil); err != nil {
373		t.Errorf("PublicKeyData() err = %v, want nil", err)
374	}
375}
376
377func TestPrivateKeyManagerPublicKeyData(t *testing.T) {
378	k, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
379	if err != nil {
380		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
381	}
382	km, ok := k.(registry.PrivateKeyManager)
383	if !ok {
384		t.Errorf("primitive is not PrivateKeyManager")
385	}
386
387	params := &hpkepb.HpkeParams{
388		Kem:  hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256,
389		Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
390		Aead: hpkepb.HpkeAead_AES_256_GCM,
391	}
392	_, privKey := pubPrivKeys(t, params)
393	serializedPrivKey, err := proto.Marshal(privKey)
394	if err != nil {
395		t.Fatal(err)
396	}
397	wantPubKey := privKey.GetPublicKey()
398	serializedPubKey, err := proto.Marshal(wantPubKey)
399	if err != nil {
400		t.Fatal(err)
401	}
402
403	pubKey, err := km.PublicKeyData(serializedPrivKey)
404	if err != nil {
405		t.Fatalf("PublicKeyData() err = %v, want nil", err)
406	}
407	if got, want := pubKey.GetTypeUrl(), hpkePublicKeyTypeURL; got != want {
408		t.Errorf("type URL = %q, want %q", got, want)
409	}
410	if !bytes.Equal(pubKey.GetValue(), serializedPubKey) {
411		t.Errorf("value = %v, want %v", pubKey.GetValue(), serializedPubKey)
412	}
413	if got, want := pubKey.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PUBLIC; got != want {
414		t.Errorf("Key material type = %d, want %d", got, want)
415	}
416}
417
418func TestPrivateKeyManagerDoesSupport(t *testing.T) {
419	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
420	if err != nil {
421		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
422	}
423	if !km.DoesSupport(hpkePrivateKeyTypeURL) {
424		t.Errorf("DoesSupport(%q) = false, want true", hpkePrivateKeyTypeURL)
425	}
426	unsupportedKeyTypeURL := "unsupported.key.type"
427	if km.DoesSupport(unsupportedKeyTypeURL) {
428		t.Errorf("DoesSupport(%q) = true, want false", unsupportedKeyTypeURL)
429	}
430}
431
432func TestPrivateKeyManagerTypeURL(t *testing.T) {
433	km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL)
434	if err != nil {
435		t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err)
436	}
437	if km.TypeURL() != hpkePrivateKeyTypeURL {
438		t.Errorf("TypeURL = %q, want %q", km.TypeURL(), hpkePrivateKeyTypeURL)
439	}
440}
441