xref: /aosp_15_r20/external/tink/go/mac/mac_factory_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2018 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 mac_test
18
19import (
20	"bytes"
21	"fmt"
22	"strings"
23	"testing"
24
25	"github.com/google/go-cmp/cmp"
26	"github.com/google/go-cmp/cmp/cmpopts"
27	"google.golang.org/protobuf/proto"
28	"github.com/google/tink/go/core/cryptofmt"
29	"github.com/google/tink/go/core/registry"
30	"github.com/google/tink/go/insecurecleartextkeyset"
31	"github.com/google/tink/go/internal/internalregistry"
32	"github.com/google/tink/go/internal/testing/stubkeymanager"
33	"github.com/google/tink/go/keyset"
34	"github.com/google/tink/go/mac/internal/mactest"
35	"github.com/google/tink/go/mac"
36	"github.com/google/tink/go/monitoring"
37	"github.com/google/tink/go/signature"
38	"github.com/google/tink/go/subtle/random"
39	"github.com/google/tink/go/testing/fakemonitoring"
40	"github.com/google/tink/go/testkeyset"
41	"github.com/google/tink/go/testutil"
42	"github.com/google/tink/go/tink"
43
44	commonpb "github.com/google/tink/go/proto/common_go_proto"
45	hmacpb "github.com/google/tink/go/proto/hmac_go_proto"
46	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
47)
48
49func TestFactoryMultipleKeys(t *testing.T) {
50	tagSize := uint32(16)
51	keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_TINK)
52	primaryKey := keyset.Key[0]
53	if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_TINK {
54		t.Errorf("expect a tink key")
55	}
56	keysetHandle, err := testkeyset.NewHandle(keyset)
57	if err != nil {
58		t.Errorf("testkeyset.NewHandle failed: %s", err)
59	}
60
61	p, err := mac.New(keysetHandle)
62	if err != nil {
63		t.Errorf("mac.New failed: %s", err)
64	}
65	expectedPrefix, err := cryptofmt.OutputPrefix(primaryKey)
66	if err != nil {
67		t.Errorf("cryptofmt.OutputPrefix failed: %s", err)
68	}
69
70	if err := verifyMacPrimitive(p, p, expectedPrefix, tagSize); err != nil {
71		t.Errorf("invalid primitive: %s", err)
72	}
73
74	// mac with a primary RAW key, verify with the keyset
75	rawKey := keyset.Key[1]
76	if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW {
77		t.Errorf("expect a raw key")
78	}
79	keyset2 := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey})
80	keysetHandle2, err := testkeyset.NewHandle(keyset2)
81	if err != nil {
82		t.Errorf("testkeyset.NewHandle failed: %s", err)
83	}
84
85	p2, err := mac.New(keysetHandle2)
86	if err != nil {
87		t.Errorf("mac.New failed: %s", err)
88	}
89	if err := verifyMacPrimitive(p2, p, cryptofmt.RawPrefix, tagSize); err != nil {
90		t.Errorf("invalid primitive: %s", err)
91	}
92
93	// mac with a random key not in the keyset, verify with the keyset should fail
94	keyset2 = testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_TINK)
95	primaryKey = keyset2.Key[0]
96	expectedPrefix, _ = cryptofmt.OutputPrefix(primaryKey)
97	keysetHandle2, err = testkeyset.NewHandle(keyset2)
98	if err != nil {
99		t.Errorf("testkeyset.NewHandle failed: %s", err)
100	}
101
102	p2, err = mac.New(keysetHandle2)
103	if err != nil {
104		t.Errorf("mac.New: cannot get primitive from keyset handle")
105	}
106	err = verifyMacPrimitive(p2, p, expectedPrefix, tagSize)
107	if err == nil || !strings.Contains(err.Error(), "mac verification failed") {
108		t.Errorf("Invalid MAC, shouldn't return valid")
109	}
110}
111
112func TestFactoryRawKey(t *testing.T) {
113	tagSize := uint32(16)
114	keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_RAW)
115	primaryKey := keyset.Key[0]
116	if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW {
117		t.Errorf("expect a raw key")
118	}
119	keysetHandle, err := testkeyset.NewHandle(keyset)
120	if err != nil {
121		t.Errorf("testkeyset.NewHandle failed: %s", err)
122	}
123	p, err := mac.New(keysetHandle)
124	if err != nil {
125		t.Errorf("mac.New failed: %s", err)
126	}
127	if err := verifyMacPrimitive(p, p, cryptofmt.RawPrefix, tagSize); err != nil {
128		t.Errorf("invalid primitive: %s", err)
129	}
130}
131
132func TestFactoryLegacyKey(t *testing.T) {
133	tagSize := uint32(16)
134	keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_LEGACY)
135	primaryKey := keyset.Key[0]
136	if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY {
137		t.Errorf("expect a legacy key")
138	}
139	keysetHandle, err := testkeyset.NewHandle(keyset)
140	if err != nil {
141		t.Errorf("testkeyset.NewHandle failed: %s", err)
142	}
143	p, err := mac.New(keysetHandle)
144	if err != nil {
145		t.Errorf("mac.New failed: %s", err)
146	}
147	data := []byte("some data")
148	tag, err := p.ComputeMAC(data)
149	if err != nil {
150		t.Errorf("mac computation failed: %s", err)
151	}
152	if err = p.VerifyMAC(tag, data); err != nil {
153		t.Errorf("mac verification failed: %s", err)
154	}
155}
156
157func TestFactoryLegacyFixedKeyFixedTag(t *testing.T) {
158	tagSize := uint32(16)
159	params := testutil.NewHMACParams(commonpb.HashType_SHA256, tagSize)
160	keyValue := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
161	key := &hmacpb.HmacKey{
162		Version:  0,
163		Params:   params,
164		KeyValue: keyValue,
165	}
166	serializedKey, err := proto.Marshal(key)
167	if err != nil {
168		t.Errorf("failed serializing proto: %v", err)
169	}
170	keyData := &tinkpb.KeyData{
171		TypeUrl:         "type.googleapis.com/google.crypto.tink.HmacKey",
172		Value:           serializedKey,
173		KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
174	}
175	keyset := testutil.NewTestKeyset(keyData, tinkpb.OutputPrefixType_LEGACY)
176	primaryKey := keyset.Key[0]
177	if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY {
178		t.Errorf("expect a legacy key")
179	}
180	keysetHandle, err := testkeyset.NewHandle(keyset)
181	if err != nil {
182		t.Errorf("testkeyset.NewHandle failed: %s", err)
183	}
184	p, err := mac.New(keysetHandle)
185	if err != nil {
186		t.Errorf("mac.New failed: %s", err)
187	}
188	data := []byte("hello")
189	tag := []byte{0, 0, 0, 0, 42, 64, 150, 12, 207, 250, 175, 32, 216, 164, 77, 69, 28, 29, 204, 235, 75}
190	if err = p.VerifyMAC(tag, data); err != nil {
191		t.Errorf("compatibleTag verification failed: %s", err)
192	}
193}
194
195func verifyMacPrimitive(computePrimitive, verifyPrimitive tink.MAC, expectedPrefix string, tagSize uint32) error {
196	data := []byte("hello")
197	tag, err := computePrimitive.ComputeMAC(data)
198	if err != nil {
199		return fmt.Errorf("mac computation failed: %s", err)
200	}
201	prefixSize := len(expectedPrefix)
202	if string(tag[:prefixSize]) != expectedPrefix {
203		return fmt.Errorf("incorrect prefix")
204	}
205	if prefixSize+int(tagSize) != len(tag) {
206		return fmt.Errorf("incorrect tag length")
207	}
208	if err = verifyPrimitive.VerifyMAC(tag, data); err != nil {
209		return fmt.Errorf("mac verification failed: %s", err)
210	}
211
212	// Modify plaintext or tag and make sure VerifyMAC failed.
213	var dataAndTag []byte
214	dataAndTag = append(dataAndTag, data...)
215	dataAndTag = append(dataAndTag, tag...)
216	if err = verifyPrimitive.VerifyMAC(dataAndTag[len(data):], dataAndTag[:len(data)]); err != nil {
217		return fmt.Errorf("mac verification failed: %s", err)
218	}
219	for i := 0; i < len(dataAndTag); i++ {
220		tmp := dataAndTag[i]
221		for j := 0; j < 8; j++ {
222			dataAndTag[i] ^= 1 << uint8(j)
223			if err = verifyPrimitive.VerifyMAC(dataAndTag[len(data):], dataAndTag[:len(data)]); err == nil {
224				return fmt.Errorf("invalid tag or plaintext, mac should be invalid")
225			}
226			dataAndTag[i] = tmp
227		}
228	}
229	return nil
230}
231
232func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) {
233	wrongKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate())
234	if err != nil {
235		t.Fatalf("failed to build *keyset.Handle: %s", err)
236	}
237
238	_, err = mac.New(wrongKH)
239	if err == nil {
240		t.Fatal("calling New() with wrong *keyset.Handle should fail")
241	}
242}
243
244func TestFactoryWithValidPrimitiveSetType(t *testing.T) {
245	goodKH, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
246	if err != nil {
247		t.Fatalf("failed to build *keyset.Handle: %s", err)
248	}
249
250	_, err = mac.New(goodKH)
251	if err != nil {
252		t.Fatalf("calling New() with good *keyset.Handle failed: %s", err)
253	}
254}
255
256func TestPrimitiveFactoryMonitoringWithoutAnnotationsDoesNotLog(t *testing.T) {
257	defer internalregistry.ClearMonitoringClient()
258	client := fakemonitoring.NewClient("fake-client")
259	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
260		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
261	}
262	kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
263	if err != nil {
264		t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) err = %v, want nil", err)
265	}
266	p, err := mac.New(kh)
267	if err != nil {
268		t.Fatalf("mac.New() err = %v, want nil", err)
269	}
270	data := []byte("data")
271	tag, err := p.ComputeMAC(data)
272	if err != nil {
273		t.Fatalf("p.ComputeMAC() err = %v, want nil", err)
274	}
275	if err := p.VerifyMAC(tag, data); err != nil {
276		t.Fatalf("p.Verify() err = %v, want nil", err)
277	}
278	got := client.Events()
279	if len(got) != 0 {
280		t.Errorf("len(client.Events()) = %d, want 0", len(got))
281	}
282}
283
284func TestFactoryWithMonitoringPrimitiveWithMultipleKeysLogsComputeVerify(t *testing.T) {
285	defer internalregistry.ClearMonitoringClient()
286	client := fakemonitoring.NewClient("fake-client")
287	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
288		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
289	}
290	manager := keyset.NewManager()
291	keyIDs := make([]uint32, 4, 4)
292	var err error
293	for i, tm := range []*tinkpb.KeyTemplate{
294		mac.HMACSHA256Tag256KeyTemplate(),
295		mac.HMACSHA256Tag128KeyTemplate(),
296		mac.HMACSHA512Tag512KeyTemplate(),
297		mac.AESCMACTag128KeyTemplate(),
298	} {
299		keyIDs[i], err = manager.Add(tm)
300		if err != nil {
301			t.Fatalf("manager.Add() err = %v, want nil", err)
302		}
303	}
304	if err := manager.SetPrimary(keyIDs[1]); err != nil {
305		t.Fatalf("manager.SetPrimary(%d) err = %v, want nil", keyIDs[1], err)
306	}
307	if err := manager.Disable(keyIDs[0]); err != nil {
308		t.Fatalf("manager.Disable(%d) err = %v, want nil", keyIDs[0], err)
309	}
310	kh, err := manager.Handle()
311	if err != nil {
312		t.Fatalf("manager.Handle() err = %v, want nil", err)
313	}
314	// Annotations are only supported throught the `insecurecleartextkeyset` API.
315	buff := &bytes.Buffer{}
316	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
317		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
318	}
319	annotations := map[string]string{"foo": "bar"}
320	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
321	if err != nil {
322		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
323	}
324	p, err := mac.New(mh)
325	if err != nil {
326		t.Fatalf("mac.New() err = %v, want nil", err)
327	}
328	data := random.GetRandomBytes(50)
329	tag, err := p.ComputeMAC(data)
330	if err != nil {
331		t.Fatalf("p.ComputeMAC() err = %v, want nil", err)
332	}
333	if err := p.VerifyMAC(tag, data); err != nil {
334		t.Fatalf("p.VerifyMAC() err = %v, want nil", err)
335	}
336	failures := len(client.Failures())
337	if failures != 0 {
338		t.Errorf("len(client.Failures()) = %d, want 0", failures)
339	}
340	got := client.Events()
341	wantKeysetInfo := &monitoring.KeysetInfo{
342		Annotations:  annotations,
343		PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(),
344		Entries: []*monitoring.Entry{
345			{
346				KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
347				Status:    monitoring.Enabled,
348				KeyType:   "tink.HmacKey",
349				KeyPrefix: "TINK",
350			},
351			{
352				KeyID:     keyIDs[2],
353				Status:    monitoring.Enabled,
354				KeyType:   "tink.HmacKey",
355				KeyPrefix: "TINK",
356			},
357			{
358				KeyID:     keyIDs[3],
359				Status:    monitoring.Enabled,
360				KeyType:   "tink.AesCmacKey",
361				KeyPrefix: "TINK",
362			},
363		},
364	}
365	want := []*fakemonitoring.LogEvent{
366		{
367			KeyID:    kh.KeysetInfo().GetPrimaryKeyId(),
368			NumBytes: len(data),
369			Context: monitoring.NewContext(
370				"mac",
371				"compute",
372				wantKeysetInfo,
373			),
374		},
375		{
376			KeyID:    kh.KeysetInfo().GetPrimaryKeyId(),
377			NumBytes: len(data),
378			Context: monitoring.NewContext(
379				"mac",
380				"verify",
381				wantKeysetInfo,
382			),
383		},
384	}
385	// sort by keyID to avoid non deterministic order.
386	entryLessFunc := func(a, b *monitoring.Entry) bool {
387		return a.KeyID < b.KeyID
388	}
389	if !cmp.Equal(got, want, cmpopts.SortSlices(entryLessFunc)) {
390		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
391	}
392}
393
394func TestPrimitiveFactoryWithMonitoringAnnotationsComputeFailureIsLogged(t *testing.T) {
395	defer internalregistry.ClearMonitoringClient()
396	client := fakemonitoring.NewClient("fake-client")
397	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
398		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
399	}
400	// Since this key type will be registered in the registry,
401	// we create a very unique typeURL to avoid colliding with other tests.
402	typeURL := "TestPrimitiveFactoryWithMonitoringComputeFailureIsLogged"
403	template := &tinkpb.KeyTemplate{
404		TypeUrl:          typeURL,
405		OutputPrefixType: tinkpb.OutputPrefixType_LEGACY,
406	}
407	km := &stubkeymanager.StubKeyManager{
408		URL:  typeURL,
409		Prim: &mactest.AlwaysFailingMAC{Error: fmt.Errorf("system failure")},
410		Key:  &hmacpb.HmacKey{},
411		KeyData: &tinkpb.KeyData{
412			TypeUrl: template.TypeUrl,
413			Value:   []byte("some_data"),
414		},
415	}
416	if err := registry.RegisterKeyManager(km); err != nil {
417		t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err)
418	}
419	kh, err := keyset.NewHandle(template)
420	if err != nil {
421		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
422	}
423	// Annotations are only supported throught the `insecurecleartextkeyset` API.
424	buff := &bytes.Buffer{}
425	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
426		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
427	}
428	annotations := map[string]string{"foo": "bar"}
429	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
430	if err != nil {
431		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
432	}
433	m, err := mac.New(mh)
434	if err != nil {
435		t.Fatalf("mac.New() err = %v, want nil", err)
436	}
437	if _, err := m.ComputeMAC([]byte("some_data")); err == nil {
438		t.Fatalf("m.ComputeMAC() err = nil, want non-nil error")
439	}
440	got := client.Failures()
441	want := []*fakemonitoring.LogFailure{
442		{
443			Context: monitoring.NewContext(
444				"mac",
445				"compute",
446				monitoring.NewKeysetInfo(
447					annotations,
448					kh.KeysetInfo().GetPrimaryKeyId(),
449					[]*monitoring.Entry{
450						{
451							KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
452							Status:    monitoring.Enabled,
453							KeyType:   typeURL,
454							KeyPrefix: "LEGACY",
455						},
456					},
457				),
458			),
459		},
460	}
461	if !cmp.Equal(got, want) {
462		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
463	}
464}
465
466func TestPrimitiveFactoryWithMonitoringAnnotationsVerifyFailureIsLogged(t *testing.T) {
467	defer internalregistry.ClearMonitoringClient()
468	client := fakemonitoring.NewClient("fake-client")
469	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
470		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
471	}
472	kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
473	if err != nil {
474		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
475	}
476	// Annotations are only supported throught the `insecurecleartextkeyset` API.
477	buff := &bytes.Buffer{}
478	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
479		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
480	}
481	annotations := map[string]string{"foo": "bar"}
482	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
483	if err != nil {
484		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
485	}
486	m, err := mac.New(mh)
487	if err != nil {
488		t.Fatalf("mac.New() err = %v, want nil", err)
489	}
490	if err := m.VerifyMAC(nil, nil); err == nil {
491		t.Fatalf("m.VerifyMAC() err = nil, want non-nil error")
492	}
493	got := client.Failures()
494	want := []*fakemonitoring.LogFailure{
495		{
496			Context: monitoring.NewContext(
497				"mac",
498				"verify",
499				monitoring.NewKeysetInfo(
500					annotations,
501					kh.KeysetInfo().GetPrimaryKeyId(),
502					[]*monitoring.Entry{
503						{
504							KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
505							Status:    monitoring.Enabled,
506							KeyType:   "tink.HmacKey",
507							KeyPrefix: "TINK",
508						},
509					},
510				),
511			),
512		},
513	}
514	if !cmp.Equal(got, want) {
515		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
516	}
517}
518
519func TestPrimitiveFactoryMonitoringWithAnnotationsMultiplePrimitivesLogOperations(t *testing.T) {
520	defer internalregistry.ClearMonitoringClient()
521	client := fakemonitoring.NewClient("fake-client")
522	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
523		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
524	}
525	templates := []*tinkpb.KeyTemplate{
526		mac.HMACSHA256Tag256KeyTemplate(),
527		mac.AESCMACTag128KeyTemplate()}
528	handles := make([]*keyset.Handle, len(templates))
529	var err error
530	annotations := map[string]string{"foo": "bar"}
531	for i, tm := range templates {
532		handles[i], err = keyset.NewHandle(tm)
533		if err != nil {
534			t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
535		}
536		// Annotations are only supported throught the `insecurecleartextkeyset` API.
537		buff := &bytes.Buffer{}
538		if err := insecurecleartextkeyset.Write(handles[i], keyset.NewBinaryWriter(buff)); err != nil {
539			t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
540		}
541		mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
542		if err != nil {
543			t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
544		}
545		p, err := mac.New(mh)
546		if err != nil {
547			t.Fatalf("mac.New() err = %v, want nil", err)
548		}
549		if _, err := p.ComputeMAC([]byte(tm.GetTypeUrl())); err != nil {
550			t.Fatalf("p.ComputeMAC() err = %v, want nil", err)
551		}
552	}
553	got := client.Events()
554	want := []*fakemonitoring.LogEvent{
555		{
556			KeyID:    handles[0].KeysetInfo().GetPrimaryKeyId(),
557			NumBytes: len(templates[0].GetTypeUrl()),
558			Context: monitoring.NewContext(
559				"mac",
560				"compute",
561				monitoring.NewKeysetInfo(
562					annotations,
563					handles[0].KeysetInfo().GetPrimaryKeyId(),
564					[]*monitoring.Entry{
565						{
566							KeyID:     handles[0].KeysetInfo().GetPrimaryKeyId(),
567							Status:    monitoring.Enabled,
568							KeyType:   "tink.HmacKey",
569							KeyPrefix: "TINK",
570						},
571					},
572				),
573			),
574		},
575		{
576			KeyID:    handles[1].KeysetInfo().GetPrimaryKeyId(),
577			NumBytes: len(templates[1].GetTypeUrl()),
578			Context: monitoring.NewContext(
579				"mac",
580				"compute",
581				monitoring.NewKeysetInfo(
582					annotations,
583					handles[1].KeysetInfo().GetPrimaryKeyId(),
584					[]*monitoring.Entry{
585						{
586							KeyID:     handles[1].KeysetInfo().GetPrimaryKeyId(),
587							Status:    monitoring.Enabled,
588							KeyType:   "tink.AesCmacKey",
589							KeyPrefix: "TINK",
590						},
591					},
592				),
593			),
594		},
595	}
596	if !cmp.Equal(got, want) {
597		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
598	}
599}
600
601func TestPrimitiveFactoryMonitoringWithAnnotationsComputeVerifyLogs(t *testing.T) {
602	defer internalregistry.ClearMonitoringClient()
603	client := fakemonitoring.NewClient("fake-client")
604	if err := internalregistry.RegisterMonitoringClient(client); err != nil {
605		t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err)
606	}
607	kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
608	if err != nil {
609		t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
610	}
611	// Annotations are only supported throught the `insecurecleartextkeyset` API.
612	buff := &bytes.Buffer{}
613	if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil {
614		t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err)
615	}
616	annotations := map[string]string{"foo": "bar"}
617	mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations))
618	if err != nil {
619		t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err)
620	}
621	p, err := mac.New(mh)
622	if err != nil {
623		t.Fatalf("mac.New() err = %v, want nil", err)
624	}
625	data := []byte("data")
626	tag, err := p.ComputeMAC(data)
627	if err != nil {
628		t.Fatalf("p.ComputeMAC() err = %v, want nil", err)
629	}
630	if err := p.VerifyMAC(tag, data); err != nil {
631		t.Fatalf("p.Verify() err = %v, want nil", err)
632	}
633	got := client.Events()
634	wantKeysetInfo := monitoring.NewKeysetInfo(
635		annotations,
636		kh.KeysetInfo().GetPrimaryKeyId(),
637		[]*monitoring.Entry{
638			{
639				KeyID:     kh.KeysetInfo().GetPrimaryKeyId(),
640				Status:    monitoring.Enabled,
641				KeyType:   "tink.HmacKey",
642				KeyPrefix: "TINK",
643			},
644		},
645	)
646	want := []*fakemonitoring.LogEvent{
647		&fakemonitoring.LogEvent{
648			Context:  monitoring.NewContext("mac", "compute", wantKeysetInfo),
649			KeyID:    kh.KeysetInfo().GetPrimaryKeyId(),
650			NumBytes: len(data),
651		},
652		&fakemonitoring.LogEvent{
653			Context:  monitoring.NewContext("mac", "verify", wantKeysetInfo),
654			KeyID:    kh.KeysetInfo().GetPrimaryKeyId(),
655			NumBytes: len(data),
656		},
657	}
658	if !cmp.Equal(got, want) {
659		t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want))
660	}
661}
662