xref: /aosp_15_r20/external/tink/go/keyderivation/prf_based_deriver_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 keyderivation
18
19import (
20	"bytes"
21	"encoding/hex"
22	"fmt"
23	"testing"
24
25	"google.golang.org/protobuf/proto"
26	"github.com/google/tink/go/aead"
27	"github.com/google/tink/go/core/registry"
28	"github.com/google/tink/go/daead"
29	"github.com/google/tink/go/insecurecleartextkeyset"
30	"github.com/google/tink/go/mac"
31	"github.com/google/tink/go/prf"
32	"github.com/google/tink/go/signature"
33	"github.com/google/tink/go/streamingaead"
34	aesgcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
35	commonpb "github.com/google/tink/go/proto/common_go_proto"
36	hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto"
37	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
38)
39
40func TestPRFBasedDeriver(t *testing.T) {
41	prfs := []struct {
42		name     string
43		template *tinkpb.KeyTemplate
44	}{
45		{
46			name:     "HKDF_SHA256",
47			template: prf.HKDFSHA256PRFKeyTemplate(),
48		},
49	}
50	// Derivation names match KEY_TEMPLATE_NAMES in
51	// https://github.com/google/tink/blob/cd96c47ced3f72199832573cdccf18719dc7c73b/testing/cross_language/util/utilities.py.
52	derivations := []struct {
53		name     string
54		template *tinkpb.KeyTemplate
55	}{
56		{
57			name:     "AES128_GCM",
58			template: aead.AES128GCMKeyTemplate(),
59		},
60		{
61			name:     "AES256_GCM",
62			template: aead.AES256GCMKeyTemplate(),
63		},
64		{
65			name:     "AES256_GCM_RAW",
66			template: aead.AES256GCMNoPrefixKeyTemplate(),
67		},
68		{
69			name:     "XCHACHA20_POLY1305",
70			template: aead.XChaCha20Poly1305KeyTemplate(),
71		},
72		{
73			name:     "AES256_SIV",
74			template: daead.AESSIVKeyTemplate(),
75		},
76		{
77			name:     "HMAC_SHA256_128BITTAG",
78			template: mac.HMACSHA256Tag128KeyTemplate(),
79		},
80		{
81			name:     "HMAC_SHA256_256BITTAG",
82			template: mac.HMACSHA256Tag256KeyTemplate(),
83		},
84		{
85			name:     "HMAC_SHA512_256BITTAG",
86			template: mac.HMACSHA512Tag256KeyTemplate(),
87		},
88		{
89			name:     "HMAC_SHA512_512BITTAG",
90			template: mac.HMACSHA512Tag512KeyTemplate(),
91		},
92		{
93			name:     "HKDF_SHA256",
94			template: prf.HKDFSHA256PRFKeyTemplate(),
95		},
96		{
97			name:     "HMAC_SHA256_PRF",
98			template: prf.HMACSHA256PRFKeyTemplate(),
99		},
100		{
101			name:     "HMAC_SHA512_PRF",
102			template: prf.HMACSHA512PRFKeyTemplate(),
103		},
104		{
105			name:     "ED25519",
106			template: signature.ED25519KeyTemplate(),
107		},
108		{
109			name:     "AES128_GCM_HKDF_4KB",
110			template: streamingaead.AES128GCMHKDF4KBKeyTemplate(),
111		},
112		{
113			name:     "AES128_GCM_HKDF_1MB",
114			template: streamingaead.AES128GCMHKDF1MBKeyTemplate(),
115		},
116		{
117			name:     "AES256_GCM_HKDF_4KB",
118			template: streamingaead.AES256GCMHKDF4KBKeyTemplate(),
119		},
120		{
121			name:     "AES256_GCM_HKDF_1MB",
122			template: streamingaead.AES256GCMHKDF1MBKeyTemplate(),
123		},
124	}
125	salts := [][]byte{nil, []byte("salt")}
126	for _, prf := range prfs {
127		for _, der := range derivations {
128			for _, salt := range salts {
129				name := fmt.Sprintf("%s_%s", prf.name, der.name)
130				if salt != nil {
131					name += "_with_salt"
132				}
133				t.Run(name, func(t *testing.T) {
134					prfKeyData, err := registry.NewKeyData(prf.template)
135					if err != nil {
136						t.Fatalf("registry.NewKeyData() err = %v, want nil", err)
137					}
138					d, err := newPRFBasedDeriver(prfKeyData, der.template)
139					if err != nil {
140						t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err)
141					}
142					if _, err := d.DeriveKeyset(salt); err != nil {
143						t.Errorf("DeriveKeyset() err = %v, want nil", err)
144					}
145					// We cannot test the derived keyset handle because, at this point, it
146					// is filled with placeholder values for the key ID, status, and
147					// output prefix type fields.
148				})
149			}
150		}
151	}
152}
153
154func TestPRFBasedDeriverWithHKDFRFCVectorForAESGCM(t *testing.T) {
155	// This is the only HKDF vector that uses an accepted hash function and has
156	// key size >= 32-bytes.
157	// https://www.rfc-editor.org/rfc/rfc5869#appendix-A.2
158	vec := struct {
159		hash   commonpb.HashType
160		key    string
161		salt   string
162		info   string
163		outLen int
164		okm    string
165	}{
166		hash:   commonpb.HashType_SHA256,
167		key:    "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
168		salt:   "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
169		info:   "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
170		outLen: 82,
171		okm:    "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87",
172	}
173	prfKeyValue, err := hex.DecodeString(vec.key)
174	if err != nil {
175		t.Fatalf("hex.DecodeString() err = %v, want nil", err)
176	}
177	prfSalt, err := hex.DecodeString(vec.salt)
178	if err != nil {
179		t.Fatalf("hex.DecodeString() err = %v, want nil", err)
180	}
181	derivationSalt, err := hex.DecodeString(vec.info)
182	if err != nil {
183		t.Fatalf("hex.DecodeString() err = %v, want nil", err)
184	}
185	wantKeyValue, err := hex.DecodeString(vec.okm)
186	if err != nil {
187		t.Fatalf("hex.DecodeString() err = %v, want nil", err)
188	}
189
190	prfKey := &hkdfpb.HkdfPrfKey{
191		Version: 0,
192		Params: &hkdfpb.HkdfPrfParams{
193			Hash: vec.hash,
194			Salt: prfSalt,
195		},
196		KeyValue: prfKeyValue,
197	}
198	serializedPRFKey, err := proto.Marshal(prfKey)
199	if err != nil {
200		t.Fatalf("proto.Marshal() err = %v, want nil", err)
201	}
202	prfKeyData := &tinkpb.KeyData{
203		TypeUrl:         prf.HKDFSHA256PRFKeyTemplate().GetTypeUrl(),
204		Value:           serializedPRFKey,
205		KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
206	}
207
208	for _, test := range []struct {
209		name               string
210		derivedKeyTemplate *tinkpb.KeyTemplate
211	}{
212		{
213			name:               "AES128_GCM",
214			derivedKeyTemplate: aead.AES128GCMKeyTemplate(),
215		},
216		{
217			name:               "AES256_GCM",
218			derivedKeyTemplate: aead.AES256GCMKeyTemplate(),
219		},
220		{
221			name:               "AES256_GCM_RAW",
222			derivedKeyTemplate: aead.AES256GCMNoPrefixKeyTemplate(),
223		},
224	} {
225		t.Run(test.name, func(t *testing.T) {
226			// Derive keyset.
227			d, err := newPRFBasedDeriver(prfKeyData, test.derivedKeyTemplate)
228			if err != nil {
229				t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err)
230			}
231			derivedHandle, err := d.DeriveKeyset(derivationSalt)
232			if err != nil {
233				t.Fatalf("DeriveKeyset() err = %v, want nil", err)
234			}
235			derivedKeyset := insecurecleartextkeyset.KeysetMaterial(derivedHandle)
236
237			// Verify keyset.
238			if len(derivedKeyset.GetKey()) != 1 {
239				t.Fatalf("len(keyset) = %d, want 1", len(derivedKeyset.GetKey()))
240			}
241			key := derivedKeyset.GetKey()[0]
242			if derivedKeyset.GetPrimaryKeyId() != key.GetKeyId() {
243				t.Fatal("keyset has no primary key")
244			}
245			// Verify key attributes set by prfBasedDeriver.
246			if got, want := key.GetStatus(), tinkpb.KeyStatusType_UNKNOWN_STATUS; got != want {
247				t.Errorf("derived key status = %s, want %s", got, want)
248			}
249			if got, want := key.GetOutputPrefixType(), tinkpb.OutputPrefixType_UNKNOWN_PREFIX; got != want {
250				t.Errorf("derived key output prefix type = %s, want %s", got, want)
251			}
252			// Verify key value.
253			derivedKeyFormat := &aesgcmpb.AesGcmKeyFormat{}
254			if err := proto.Unmarshal(test.derivedKeyTemplate.GetValue(), derivedKeyFormat); err != nil {
255				t.Fatalf("proto.Unmarshal() err = %v, want nil", err)
256			}
257			wantKeySize := int(derivedKeyFormat.GetKeySize())
258			aesGCMKey := &aesgcmpb.AesGcmKey{}
259			if err := proto.Unmarshal(key.GetKeyData().GetValue(), aesGCMKey); err != nil {
260				t.Fatalf("proto.Unmarshal() err = %v, want nil", err)
261			}
262			gotKeyValue := aesGCMKey.GetKeyValue()
263			if len(gotKeyValue) != wantKeySize {
264				t.Errorf("derived key value length = %d, want %d", len(gotKeyValue), wantKeySize)
265			}
266			if !bytes.Equal(gotKeyValue, wantKeyValue[:wantKeySize]) {
267				t.Errorf("derived key value = %q, want %q", gotKeyValue, wantKeyValue[:wantKeySize])
268			}
269		})
270	}
271}
272
273func TestNewPRFBasedDeriverRejectsInvalidInputs(t *testing.T) {
274	validPRFKeyData, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate())
275	if err != nil {
276		t.Fatalf("registry.NewKeyData() err = %v, want nil", err)
277	}
278	validDerivedKeyTemplate := aead.AES128GCMKeyTemplate()
279	if _, err := newPRFBasedDeriver(validPRFKeyData, validDerivedKeyTemplate); err != nil {
280		t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err)
281	}
282	invalidPRFKeyData, err := registry.NewKeyData(aead.AES128GCMKeyTemplate())
283	if err != nil {
284		t.Fatalf("registry.NewKeyData() err = %v, want nil", err)
285	}
286	// The derivation of KeysetDeriver keyset handles is not supported, i.e. a
287	// KeysetDeriver key template cannot be used as the derivedKeyTemplate
288	// argument in newPRFBasedDeriver().
289	invalidDerivedKeyTemplate, err := CreatePRFBasedKeyTemplate(prf.HKDFSHA256PRFKeyTemplate(), aead.AES128GCMKeyTemplate())
290	if err != nil {
291		t.Fatalf("CreatePRFBasedKeyTemplate() err = %v, want nil", err)
292	}
293	for _, test := range []struct {
294		name               string
295		prfKeyData         *tinkpb.KeyData
296		derivedKeyTemplate *tinkpb.KeyTemplate
297	}{
298		{
299			name: "nil inputs",
300		},
301		{
302			name:               "nil PRF key data",
303			derivedKeyTemplate: validDerivedKeyTemplate,
304		},
305		{
306			name:       "nil derived template",
307			prfKeyData: validPRFKeyData,
308		},
309		{
310			name:               "invalid PRF key data",
311			prfKeyData:         invalidPRFKeyData,
312			derivedKeyTemplate: validDerivedKeyTemplate,
313		},
314		{
315			name:               "invalid derived template",
316			prfKeyData:         validPRFKeyData,
317			derivedKeyTemplate: invalidDerivedKeyTemplate,
318		},
319	} {
320		t.Run(test.name, func(t *testing.T) {
321			if _, err := newPRFBasedDeriver(test.prfKeyData, test.derivedKeyTemplate); err == nil {
322				t.Errorf("newPRFBasedDeriver() err = nil, want non-nil")
323			}
324		})
325	}
326}
327