xref: /aosp_15_r20/external/tink/go/prf/prf_set_factory_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 prf_test
18
19import (
20	"bytes"
21	"encoding/hex"
22	"fmt"
23	"testing"
24
25	"github.com/google/go-cmp/cmp"
26	"github.com/google/go-cmp/cmp/cmpopts"
27	"github.com/google/tink/go/insecurecleartextkeyset"
28	"github.com/google/tink/go/internal/internalregistry"
29	"github.com/google/tink/go/keyset"
30	"github.com/google/tink/go/mac"
31	"github.com/google/tink/go/monitoring"
32	"github.com/google/tink/go/prf"
33	"github.com/google/tink/go/testing/fakemonitoring"
34	"github.com/google/tink/go/testutil"
35	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
36)
37
38const (
39	maxAutocorrelation = 100
40)
41
42func addKeyAndReturnID(m *keyset.Manager, template *tinkpb.KeyTemplate) (uint32, error) {
43	keyID, err := m.Add(template)
44	if err != nil {
45		return 0, fmt.Errorf("Could not add key from the given template: %v", err)
46	}
47	err = m.SetPrimary(keyID)
48	if err != nil {
49		return 0, fmt.Errorf("Could set key as primary: %v", err)
50	}
51	return keyID, nil
52}
53
54func TestFactoryBasic(t *testing.T) {
55	manager := keyset.NewManager()
56	aescmacID, err := addKeyAndReturnID(manager, prf.AESCMACPRFKeyTemplate())
57	if err != nil {
58		t.Errorf("Could not add AES CMAC PRF key: %v", err)
59	}
60
61	hmacsha256ID, err := addKeyAndReturnID(manager, prf.HMACSHA256PRFKeyTemplate())
62	if err != nil {
63		t.Errorf("Could not add HMAC SHA256 PRF key: %v", err)
64	}
65	hkdfsha256ID, err := addKeyAndReturnID(manager, prf.HKDFSHA256PRFKeyTemplate())
66	if err != nil {
67		t.Errorf("Could not add HKDF SHA256 PRF key: %v", err)
68	}
69	hmacsha512ID, err := addKeyAndReturnID(manager, prf.HMACSHA512PRFKeyTemplate())
70	if err != nil {
71		t.Errorf("Could not add HMAC SHA512 PRF key: %v", err)
72	}
73	handle, err := manager.Handle()
74	if err != nil {
75		t.Errorf("Could not obtain handle: %v", err)
76	}
77	prfSet, err := prf.NewPRFSet(handle)
78	if err != nil {
79		t.Errorf("Could not create prf.Set with standard key templates: %v", err)
80	}
81	primaryID := prfSet.PrimaryID
82	if primaryID != hmacsha512ID {
83		t.Errorf("Primary ID %d should be the ID %d, which was added last", primaryID, hmacsha512ID)
84	}
85	for _, length := range []uint32{1, 10, 16, 17, 32, 33, 64, 65, 100, 8160, 8161} {
86		results := [][]byte{}
87		for id, prf := range prfSet.PRFs {
88			ok := true
89			switch {
90			case length > 16 && id == aescmacID:
91				ok = false
92			case length > 32 && id == hmacsha256ID:
93				ok = false
94			case length > 64 && id == hmacsha512ID:
95				ok = false
96			case length > 8160 && id == hkdfsha256ID:
97				ok = false
98			}
99
100			result1, err := prf.ComputePRF([]byte("The input"), length)
101			switch {
102			case err != nil && !ok:
103				continue
104			case err != nil:
105				t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err)
106				continue
107			case !ok:
108				t.Errorf("Expected to be unable to compute %d bytes PRF output", length)
109				continue
110			}
111			result2, err := prf.ComputePRF([]byte("The different input"), length)
112			switch {
113			case err != nil && !ok:
114				continue
115			case err != nil:
116				t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err)
117				continue
118			case !ok:
119				t.Errorf("Expected to be unable to compute %d bytes PRF output", length)
120				continue
121			}
122			result3, err := prf.ComputePRF([]byte("The input"), length)
123			switch {
124			case err != nil && !ok:
125				continue
126			case err != nil:
127				t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err)
128				continue
129			case !ok:
130				t.Errorf("Expected to be unable to compute %d bytes PRF output", length)
131				continue
132			}
133			if id == primaryID {
134				primaryResult, err := prfSet.ComputePrimaryPRF([]byte("The input"), length)
135				switch {
136				case err != nil && !ok:
137					continue
138				case err != nil:
139					t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err)
140					continue
141				case !ok:
142					t.Errorf("Expected to be unable to compute %d bytes PRF output", length)
143					continue
144				}
145				if hex.EncodeToString(result1) != hex.EncodeToString(primaryResult) {
146					t.Errorf("Expected manual call of ComputePRF of primary PRF and ComputePrimaryPRF with the same input to produce the same output, but got %q and %q", result1, primaryResult)
147				}
148			}
149			if hex.EncodeToString(result1) != hex.EncodeToString(result3) {
150				t.Errorf("Expected different calls with the same input to produce the same output, but got %q and %q", result1, result3)
151			}
152			results = append(results, result1)
153			results = append(results, result2)
154		}
155		runZTests(results, t)
156	}
157}
158
159func TestNonRawKeys(t *testing.T) {
160	template := prf.AESCMACPRFKeyTemplate()
161	template.OutputPrefixType = tinkpb.OutputPrefixType_TINK
162	h, err := keyset.NewHandle(template)
163	if err != nil {
164		t.Errorf("Couldn't create keyset: %v", err)
165	}
166	_, err = prf.NewPRFSet(h)
167	if err == nil {
168		t.Errorf("Expected non RAW prefix to fail to create prf.Set")
169	}
170	m := keyset.NewManagerFromHandle(h)
171	_, err = addKeyAndReturnID(m, prf.HMACSHA256PRFKeyTemplate())
172	if err != nil {
173		t.Errorf("Expected to be able to add keys to the keyset: %v", err)
174	}
175	h, err = m.Handle()
176	if err != nil {
177		t.Errorf("Expected to be able to create keyset handle: %v", err)
178	}
179	_, err = prf.NewPRFSet(h)
180	if err == nil {
181		t.Errorf("Expected mixed prefix keyset to fail to create prf.Set")
182	}
183}
184
185func TestNonPRFPrimitives(t *testing.T) {
186	template := mac.AESCMACTag128KeyTemplate()
187	template.OutputPrefixType = tinkpb.OutputPrefixType_RAW
188	h, err := keyset.NewHandle(template)
189	if err != nil {
190		t.Errorf("Couldn't create keyset: %v", err)
191	}
192	_, err = prf.NewPRFSet(h)
193	if err == nil {
194		t.Errorf("Expected non PRF primitive to fail to create prf.Set")
195	}
196	m := keyset.NewManagerFromHandle(h)
197	_, err = addKeyAndReturnID(m, prf.HMACSHA256PRFKeyTemplate())
198	if err != nil {
199		t.Errorf("Expected to be able to add keys to the keyset: %v", err)
200	}
201	h, err = m.Handle()
202	if err != nil {
203		t.Errorf("Expected to be able to create keyset handle: %v", err)
204	}
205	_, err = prf.NewPRFSet(h)
206	if err == nil {
207		t.Errorf("Expected mixed primitive keyset to fail to create prf.Set")
208	}
209}
210
211func runZTests(results [][]byte, t *testing.T) {
212	for i, result1 := range results {
213		if err := testutil.ZTestUniformString(result1); err != nil {
214			t.Errorf("Expected PRF output to pass uniformity z test: %v", err)
215		}
216		if len(result1) <= maxAutocorrelation {
217			if err := testutil.ZTestAutocorrelationUniformString(result1); err != nil {
218				t.Errorf("Expected PRF output to pass autocorrelation test: %v", err)
219			}
220		}
221		for j := i + 1; j < len(results); j++ {
222			result2 := results[j]
223			if err := testutil.ZTestCrosscorrelationUniformStrings(result1, result2); err != nil {
224				t.Errorf("Expected different PRF outputs to be uncorrelated: %v", err)
225			}
226		}
227	}
228}
229
230func TestPrimitiveFactoryComputePRFWithoutAnnotationsDoesNothing(t *testing.T) {
231	defer internalregistry.ClearMonitoringClient()
232	client := fakemonitoring.NewClient("fake-client")
233	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
234		t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err)
235	}
236	kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate())
237	if err != nil {
238		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
239	}
240	prfSet, err := prf.NewPRFSet(kh)
241	if err != nil {
242		t.Fatalf("prf.NewPRFSet() err = %v, want nil", err)
243	}
244	if _, err := prfSet.ComputePrimaryPRF([]byte("input_data"), 32); err != nil {
245		t.Fatalf("prfSet.ComputePrimaryPRF() err = %v, want nil", err)
246	}
247	failures := len(client.Failures())
248	if failures != 0 {
249		t.Errorf("len(client.Failures()) = %d, want 0", failures)
250	}
251	got := client.Events()
252	if got != nil {
253		t.Errorf("client.Events() = %v, want nil", got)
254	}
255}
256
257func TestPrimitiveFactoryMonitoringWithAnnotationsComputePRFFailureIsLogged(t *testing.T) {
258	defer internalregistry.ClearMonitoringClient()
259	client := fakemonitoring.NewClient("fake-client")
260	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
261		t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err)
262	}
263	kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate())
264	if err != nil {
265		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
266	}
267	buff := &bytes.Buffer{}
268	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
269		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
270	}
271	annotations := map[string]string{"foo": "bar"}
272	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
273	if err != nil {
274		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
275	}
276	prfSet, err := prf.NewPRFSet(mh)
277	if err != nil {
278		t.Fatalf("prf.NewPRFSet() err = %v, want nil", err)
279	}
280	data := []byte("input_data")
281	if _, err := prfSet.ComputePrimaryPRF(data, 64); err == nil {
282		t.Fatalf("prfSet.ComputePrimaryPRF() err = nil, want non-nil errors")
283	}
284	got := client.Failures()
285	want := []*fakemonitoring.LogFailure{
286		{
287			Context: monitoring.NewContext(
288				"prf",
289				"compute",
290				&monitoring.KeysetInfo{
291					Annotations: annotations,
292					Entries: []*monitoring.Entry{
293						{
294							KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
295							Status:    monitoring.Enabled,
296							KeyType:   "tink.HmacPrfKey",
297							KeyPrefix: "RAW",
298						},
299					},
300					PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(),
301				},
302			),
303		},
304	}
305	if diff := cmp.Diff(want, got); diff != "" {
306		t.Errorf("%v", diff)
307	}
308}
309
310func TestPrimitiveFactoryIndividualPrfWithAnnotatonsLogsCompute(t *testing.T) {
311	defer internalregistry.ClearMonitoringClient()
312	client := fakemonitoring.NewClient("fake-client")
313	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
314		t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err)
315	}
316	kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate())
317	if err != nil {
318		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
319	}
320	manager := keyset.NewManagerFromHandle(kh)
321	hmac512KeyID, err := manager.Add(prf.HMACSHA512PRFKeyTemplate())
322	if err != nil {
323		t.Fatalf("manager.Add() err = %v, want nil", err)
324	}
325	aesKeyID, err := manager.Add(prf.AESCMACPRFKeyTemplate())
326	if err != nil {
327		t.Fatalf("manager.Add() err = %v, want nil", err)
328	}
329	kh, err = manager.Handle()
330	if err != nil {
331		t.Fatalf("manager.Handle() err = %v, want nil", err)
332	}
333	buff := &bytes.Buffer{}
334	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
335		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
336	}
337	annotations := map[string]string{"foo": "bar"}
338	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
339	if err != nil {
340		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
341	}
342	prfSet, err := prf.NewPRFSet(mh)
343	if err != nil {
344		t.Fatalf("prf.NewPRFSet() err = %v, want nil", err)
345	}
346	for _, p := range prfSet.PRFs {
347		if _, err := p.ComputePRF([]byte("input_data"), 16); err != nil {
348			t.Fatalf("p.ComputePRF() err = %v, want nil", err)
349		}
350
351	}
352	got := client.Events()
353	wantKeysetInfo := &monitoring.KeysetInfo{
354		PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(),
355		Entries: []*monitoring.Entry{
356			{
357				KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
358				Status:    monitoring.Enabled,
359				KeyType:   "tink.HmacPrfKey",
360				KeyPrefix: "RAW",
361			},
362			{
363				KeyID:     hmac512KeyID,
364				Status:    monitoring.Enabled,
365				KeyType:   "tink.HmacPrfKey",
366				KeyPrefix: "RAW",
367			},
368			{
369				KeyID:     aesKeyID,
370				Status:    monitoring.Enabled,
371				KeyType:   "tink.AesCmacPrfKey",
372				KeyPrefix: "RAW",
373			},
374		},
375		Annotations: annotations,
376	}
377	want := []*fakemonitoring.LogEvent{
378		{
379			Context:  monitoring.NewContext("prf", "compute", wantKeysetInfo),
380			KeyID:    kh.KeysetInfo().GetKeyInfo()[0].GetKeyId(),
381			NumBytes: len("input_data"),
382		},
383		{
384			Context:  monitoring.NewContext("prf", "compute", wantKeysetInfo),
385			KeyID:    kh.KeysetInfo().GetKeyInfo()[1].GetKeyId(),
386			NumBytes: len("input_data"),
387		},
388		{
389			Context:  monitoring.NewContext("prf", "compute", wantKeysetInfo),
390			KeyID:    kh.KeysetInfo().GetKeyInfo()[2].GetKeyId(),
391			NumBytes: len("input_data"),
392		},
393	}
394	eventCmp := func(a, b *fakemonitoring.LogEvent) bool {
395		return a.KeyID < b.KeyID
396	}
397	if !cmp.Equal(got, want, cmpopts.SortSlices(eventCmp)) {
398		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
399	}
400
401}
402
403func TestPrimitiveFactoryWithMonitoringAnnotationsLogsComputePRF(t *testing.T) {
404	defer internalregistry.ClearMonitoringClient()
405	client := fakemonitoring.NewClient("fake-client")
406	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
407		t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err)
408	}
409	kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate())
410	if err != nil {
411		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
412	}
413	buff := &bytes.Buffer{}
414	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
415		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
416	}
417	annotations := map[string]string{"foo": "bar"}
418	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
419	if err != nil {
420		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
421	}
422	prfSet, err := prf.NewPRFSet(mh)
423	if err != nil {
424		t.Fatalf("prf.NewPRFSet() err = %v, want nil", err)
425	}
426	data := []byte("some_data")
427	if _, err := prfSet.ComputePrimaryPRF(data, 20); err != nil {
428		t.Fatalf("prfSet.ComputePrimaryPRF() err = %v, want nil", err)
429	}
430	got := client.Events()
431	wantKeysetInfo := &monitoring.KeysetInfo{
432		PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(),
433		Entries: []*monitoring.Entry{
434			{
435				KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
436				Status:    monitoring.Enabled,
437				KeyType:   "tink.HmacPrfKey",
438				KeyPrefix: "RAW",
439			},
440		},
441		Annotations: annotations,
442	}
443	want := []*fakemonitoring.LogEvent{
444		{
445			Context:  monitoring.NewContext("prf", "compute", wantKeysetInfo),
446			KeyID:    kh.KeysetInfo().GetPrimaryKeyId(),
447			NumBytes: len(data),
448		},
449	}
450	if !cmp.Equal(got, want) {
451		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
452	}
453}
454