xref: /aosp_15_r20/external/tink/go/keyderivation/keyderivation_key_templates_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_test
18
19import (
20	"bytes"
21	"fmt"
22	"testing"
23
24	"github.com/google/tink/go/aead"
25	"github.com/google/tink/go/keyderivation"
26	"github.com/google/tink/go/keyset"
27	"github.com/google/tink/go/prf"
28	"github.com/google/tink/go/subtle/random"
29	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
30)
31
32func TestPRFBasedKeyTemplateDerivesAESGCMKeyset(t *testing.T) {
33	plaintext := random.GetRandomBytes(16)
34	associatedData := random.GetRandomBytes(8)
35	prfs := []struct {
36		name     string
37		template *tinkpb.KeyTemplate
38	}{
39		{
40			name:     "HKDF-SHA256",
41			template: prf.HKDFSHA256PRFKeyTemplate(),
42		},
43	}
44	derivations := []struct {
45		name     string
46		template *tinkpb.KeyTemplate
47	}{
48		{
49			name:     "AES128GCM",
50			template: aead.AES128GCMKeyTemplate(),
51		},
52		{
53			name:     "AES256GCM",
54			template: aead.AES256GCMKeyTemplate(),
55		},
56		{
57			name:     "AES256GCMNoPrefix",
58			template: aead.AES256GCMNoPrefixKeyTemplate(),
59		},
60	}
61	for _, prf := range prfs {
62		for _, der := range derivations {
63			for _, salt := range [][]byte{nil, []byte("salt")} {
64				name := fmt.Sprintf("%s_%s", prf.name, der.name)
65				if salt != nil {
66					name += "_with_salt"
67				}
68				t.Run(name, func(t *testing.T) {
69					template, err := keyderivation.CreatePRFBasedKeyTemplate(prf.template, der.template)
70					if err != nil {
71						t.Fatalf("CreatePRFBasedKeyTemplate() err = %v, want nil", err)
72					}
73					handle, err := keyset.NewHandle(template)
74					if err != nil {
75						t.Fatalf("keyset.NewHandle() err = %v, want nil", err)
76					}
77					d, err := keyderivation.New(handle)
78					if err != nil {
79						t.Fatalf("keyderivation.New() err = %v, want nil", err)
80					}
81					derivedHandle, err := d.DeriveKeyset(salt)
82					if err != nil {
83						t.Fatalf("DeriveKeyset() err = %v, want nil", err)
84					}
85					a, err := aead.New(derivedHandle)
86					if err != nil {
87						t.Fatalf("aead.New() err = %v, want nil", err)
88					}
89					ciphertext, err := a.Encrypt(plaintext, associatedData)
90					if err != nil {
91						t.Fatalf("Encrypt() err = %v, want nil", err)
92					}
93					gotPlaintext, err := a.Decrypt(ciphertext, associatedData)
94					if err != nil {
95						t.Fatalf("Decrypt() err = %v, want nil", err)
96					}
97					if !bytes.Equal(gotPlaintext, plaintext) {
98						t.Errorf("Decrypt() = %v, want %v", gotPlaintext, plaintext)
99					}
100				})
101			}
102		}
103	}
104}
105
106func TestInvalidPRFBasedDeriverKeyTemplates(t *testing.T) {
107	for _, test := range []struct {
108		name               string
109		prfKeyTemplate     *tinkpb.KeyTemplate
110		derivedKeyTemplate *tinkpb.KeyTemplate
111	}{
112		{
113			name: "nil templates",
114		},
115		{
116			name:               "nil PRF key template",
117			derivedKeyTemplate: aead.AES128GCMKeyTemplate(),
118		},
119		{
120			name:           "nil derived key template",
121			prfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(),
122		},
123		{
124			name:               "malformed PRF key template",
125			prfKeyTemplate:     &tinkpb.KeyTemplate{TypeUrl: "\xff"},
126			derivedKeyTemplate: aead.AES128GCMKeyTemplate(),
127		},
128		// AES128CTRHMACSHA256KeyTemplate() is an unsupported derived key template
129		// because DeriveKey() is not implemented in the AES-CTR-HMAC key manager.
130		// TODO(b/227682336): Add mock key manager that doesn't derive keys.
131		{
132			name:               "unsupported templates",
133			prfKeyTemplate:     aead.AES128GCMKeyTemplate(),
134			derivedKeyTemplate: aead.AES128CTRHMACSHA256KeyTemplate()},
135		{
136			name:               "unsupported PRF key template",
137			prfKeyTemplate:     aead.AES128GCMKeyTemplate(),
138			derivedKeyTemplate: aead.AES128GCMKeyTemplate(),
139		},
140		{
141			name:               "unsupported derived key template",
142			prfKeyTemplate:     prf.HKDFSHA256PRFKeyTemplate(),
143			derivedKeyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(),
144		},
145	} {
146		t.Run(test.name, func(t *testing.T) {
147			if _, err := keyderivation.CreatePRFBasedKeyTemplate(test.prfKeyTemplate, test.derivedKeyTemplate); err == nil {
148				t.Error("CreatePRFBasedKeyTemplate() err = nil, want non-nil")
149			}
150		})
151	}
152}
153