xref: /aosp_15_r20/external/tink/go/internal/internalregistry/key_derivation_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 internalregistry_test
18
19import (
20	"bytes"
21	"errors"
22	"sync"
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/internal/internalregistry"
29	"github.com/google/tink/go/internal/testing/stubkeymanager"
30	"github.com/google/tink/go/subtle/random"
31	gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
32	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
33)
34
35const (
36	typeURLRoot           = "TestDeriveKeyFails"
37	unregisteredKMTypeURL = typeURLRoot + "UnregisteredKeyManager"
38	notDerivableKMTypeURL = typeURLRoot + "NotDerivableKeyManager"
39	failingKMTypeURL      = typeURLRoot + "FailingKeyManager"
40)
41
42var once sync.Once
43
44func mustRegisterBadKeyManagers(t *testing.T) {
45	t.Helper()
46	// The registry does not allow a key manager to be registered more than once.
47	once.Do(func() {
48		notDerivableKM := &stubkeymanager.StubKeyManager{URL: notDerivableKMTypeURL}
49		if err := registry.RegisterKeyManager(notDerivableKM); err != nil {
50			t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err)
51		}
52
53		failingKM := &stubkeymanager.StubDerivableKeyManager{
54			StubKeyManager: stubkeymanager.StubKeyManager{
55				URL: failingKMTypeURL,
56			},
57			DerErr: errors.New("failing"),
58		}
59		if err := registry.RegisterKeyManager(failingKM); err != nil {
60			t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err)
61		}
62	})
63}
64
65func TestDerivableKeyManagers(t *testing.T) {
66	mustRegisterBadKeyManagers(t)
67	for _, typeURL := range []string{
68		aead.AES128GCMKeyTemplate().GetTypeUrl(),
69		aead.AES256GCMKeyTemplate().GetTypeUrl(),
70		failingKMTypeURL,
71	} {
72		t.Run(typeURL, func(t *testing.T) {
73			if err := internalregistry.AllowKeyDerivation(typeURL); err != nil {
74				t.Fatalf("internalregistry.AllowKeyDerivation() err = %v, want nil", err)
75			}
76			if !internalregistry.CanDeriveKeys(typeURL) {
77				t.Errorf("internalregistry.CanDeriveKeys() = false, want true")
78			}
79		})
80	}
81}
82
83func TestDerivableKeyManagersRejectsInvalidInputs(t *testing.T) {
84	mustRegisterBadKeyManagers(t)
85	for _, typeURL := range []string{
86		"",
87		unregisteredKMTypeURL,
88		notDerivableKMTypeURL,
89	} {
90		t.Run(typeURL, func(t *testing.T) {
91			if err := internalregistry.AllowKeyDerivation(typeURL); err == nil {
92				t.Error("internalregistry.AllowKeyDerivation() err = nil, want non-nil")
93			}
94			if internalregistry.CanDeriveKeys(typeURL) {
95				t.Errorf("internalregistry.CanDeriveKeys() = true, want false")
96			}
97		})
98	}
99}
100
101func TestDeriveKey(t *testing.T) {
102	for _, test := range []struct {
103		name            string
104		keyTemplate     *tinkpb.KeyTemplate
105		keySize         uint32
106		keyMaterialType tinkpb.KeyData_KeyMaterialType
107	}{
108		{
109			name:            "AES-128-GCM",
110			keyTemplate:     aead.AES128GCMKeyTemplate(),
111			keySize:         16,
112			keyMaterialType: tinkpb.KeyData_SYMMETRIC,
113		},
114		{
115			name:            "AES-256-GCM",
116			keyTemplate:     aead.AES256GCMKeyTemplate(),
117			keySize:         32,
118			keyMaterialType: tinkpb.KeyData_SYMMETRIC,
119		},
120	} {
121		t.Run(test.name, func(t *testing.T) {
122			buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize))
123			keyData, err := internalregistry.DeriveKey(test.keyTemplate, buf)
124			if err != nil {
125				t.Fatalf("internalregistry.DeriveKey() err = %v, want nil", err)
126			}
127			if got, want := keyData.GetTypeUrl(), test.keyTemplate.GetTypeUrl(); got != want {
128				t.Errorf("TypeUrl = %s, want %s", got, want)
129			}
130			key := &gcmpb.AesGcmKey{}
131			if err := proto.Unmarshal(keyData.GetValue(), key); err != nil {
132				t.Errorf("proto.Unmarshal() err = %v, want nil", err)
133			}
134			if got, want := len(key.GetKeyValue()), int(test.keySize); got != want {
135				t.Errorf("len(KeyValue) = %d, want %d", got, want)
136			}
137			if got, want := keyData.GetKeyMaterialType(), test.keyMaterialType; got != want {
138				t.Errorf("KeyMaterialType = %s, want %s", got, want)
139			}
140		})
141	}
142}
143
144func TestDeriveKeyFails(t *testing.T) {
145	mustRegisterBadKeyManagers(t)
146	rand := random.GetRandomBytes(32)
147	for _, test := range []struct {
148		name        string
149		keyTemplate *tinkpb.KeyTemplate
150		randLen     uint32
151	}{
152		{
153			name:        "not enough randomness",
154			keyTemplate: aead.AES128GCMKeyTemplate(),
155			randLen:     15},
156		{
157			name:    "nil key template",
158			randLen: 32},
159		{
160			name:        "derivation-disallowed but registered key manager",
161			keyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(),
162			randLen:     32,
163		},
164		{
165			name: "derivation-allowed but unregistered key manager",
166			keyTemplate: &tinkpb.KeyTemplate{
167				TypeUrl:          unregisteredKMTypeURL,
168				Value:            rand,
169				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
170			},
171			randLen: 32,
172		},
173		{
174			"does not implement DerivableKeyManager",
175			&tinkpb.KeyTemplate{
176				TypeUrl:          notDerivableKMTypeURL,
177				Value:            rand,
178				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
179			},
180			32,
181		},
182		{
183			"key manager with failing DeriveKey()",
184			&tinkpb.KeyTemplate{
185				TypeUrl:          failingKMTypeURL,
186				Value:            rand,
187				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
188			},
189			32,
190		},
191	} {
192		t.Run(test.name, func(t *testing.T) {
193			buf := bytes.NewBuffer(random.GetRandomBytes(test.randLen))
194			if _, err := internalregistry.DeriveKey(test.keyTemplate, buf); err == nil {
195				t.Error("internalregistry.DeriveKey() err = nil, want non-nil")
196			}
197		})
198	}
199}
200