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