blob: ae0fb9e02ca6709c4ac58d8733cf8e7faa934518 [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package internalregistry_test
import (
"bytes"
"errors"
"sync"
"testing"
"google.golang.org/protobuf/proto"
"github.com/google/tink/go/aead"
"github.com/google/tink/go/core/registry"
"github.com/google/tink/go/internal/internalregistry"
"github.com/google/tink/go/internal/testing/stubkeymanager"
"github.com/google/tink/go/subtle/random"
gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
tinkpb "github.com/google/tink/go/proto/tink_go_proto"
)
const (
typeURLRoot = "TestDeriveKeyFails"
unregisteredKMTypeURL = typeURLRoot + "UnregisteredKeyManager"
notDerivableKMTypeURL = typeURLRoot + "NotDerivableKeyManager"
failingKMTypeURL = typeURLRoot + "FailingKeyManager"
)
var once sync.Once
func mustRegisterBadKeyManagers(t *testing.T) {
t.Helper()
// The registry does not allow a key manager to be registered more than once.
once.Do(func() {
notDerivableKM := &stubkeymanager.StubKeyManager{URL: notDerivableKMTypeURL}
if err := registry.RegisterKeyManager(notDerivableKM); err != nil {
t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err)
}
failingKM := &stubkeymanager.StubDerivableKeyManager{
StubKeyManager: stubkeymanager.StubKeyManager{
URL: failingKMTypeURL,
},
DerErr: errors.New("failing"),
}
if err := registry.RegisterKeyManager(failingKM); err != nil {
t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err)
}
})
}
func TestDerivableKeyManagers(t *testing.T) {
mustRegisterBadKeyManagers(t)
for _, typeURL := range []string{
aead.AES128GCMKeyTemplate().GetTypeUrl(),
aead.AES256GCMKeyTemplate().GetTypeUrl(),
failingKMTypeURL,
} {
t.Run(typeURL, func(t *testing.T) {
if err := internalregistry.AllowKeyDerivation(typeURL); err != nil {
t.Fatalf("internalregistry.AllowKeyDerivation() err = %v, want nil", err)
}
if !internalregistry.CanDeriveKeys(typeURL) {
t.Errorf("internalregistry.CanDeriveKeys() = false, want true")
}
})
}
}
func TestDerivableKeyManagersRejectsInvalidInputs(t *testing.T) {
mustRegisterBadKeyManagers(t)
for _, typeURL := range []string{
"",
unregisteredKMTypeURL,
notDerivableKMTypeURL,
} {
t.Run(typeURL, func(t *testing.T) {
if err := internalregistry.AllowKeyDerivation(typeURL); err == nil {
t.Error("internalregistry.AllowKeyDerivation() err = nil, want non-nil")
}
if internalregistry.CanDeriveKeys(typeURL) {
t.Errorf("internalregistry.CanDeriveKeys() = true, want false")
}
})
}
}
func TestDeriveKey(t *testing.T) {
for _, test := range []struct {
name string
keyTemplate *tinkpb.KeyTemplate
keySize uint32
keyMaterialType tinkpb.KeyData_KeyMaterialType
}{
{
name: "AES-128-GCM",
keyTemplate: aead.AES128GCMKeyTemplate(),
keySize: 16,
keyMaterialType: tinkpb.KeyData_SYMMETRIC,
},
{
name: "AES-256-GCM",
keyTemplate: aead.AES256GCMKeyTemplate(),
keySize: 32,
keyMaterialType: tinkpb.KeyData_SYMMETRIC,
},
} {
t.Run(test.name, func(t *testing.T) {
buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize))
keyData, err := internalregistry.DeriveKey(test.keyTemplate, buf)
if err != nil {
t.Fatalf("internalregistry.DeriveKey() err = %v, want nil", err)
}
if got, want := keyData.GetTypeUrl(), test.keyTemplate.GetTypeUrl(); got != want {
t.Errorf("TypeUrl = %s, want %s", got, want)
}
key := &gcmpb.AesGcmKey{}
if err := proto.Unmarshal(keyData.GetValue(), key); err != nil {
t.Errorf("proto.Unmarshal() err = %v, want nil", err)
}
if got, want := len(key.GetKeyValue()), int(test.keySize); got != want {
t.Errorf("len(KeyValue) = %d, want %d", got, want)
}
if got, want := keyData.GetKeyMaterialType(), test.keyMaterialType; got != want {
t.Errorf("KeyMaterialType = %s, want %s", got, want)
}
})
}
}
func TestDeriveKeyFails(t *testing.T) {
mustRegisterBadKeyManagers(t)
rand := random.GetRandomBytes(32)
for _, test := range []struct {
name string
keyTemplate *tinkpb.KeyTemplate
randLen uint32
}{
{
name: "not enough randomness",
keyTemplate: aead.AES128GCMKeyTemplate(),
randLen: 15},
{
name: "nil key template",
randLen: 32},
{
name: "derivation-disallowed but registered key manager",
keyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(),
randLen: 32,
},
{
name: "derivation-allowed but unregistered key manager",
keyTemplate: &tinkpb.KeyTemplate{
TypeUrl: unregisteredKMTypeURL,
Value: rand,
OutputPrefixType: tinkpb.OutputPrefixType_TINK,
},
randLen: 32,
},
{
"does not implement DerivableKeyManager",
&tinkpb.KeyTemplate{
TypeUrl: notDerivableKMTypeURL,
Value: rand,
OutputPrefixType: tinkpb.OutputPrefixType_TINK,
},
32,
},
{
"key manager with failing DeriveKey()",
&tinkpb.KeyTemplate{
TypeUrl: failingKMTypeURL,
Value: rand,
OutputPrefixType: tinkpb.OutputPrefixType_TINK,
},
32,
},
} {
t.Run(test.name, func(t *testing.T) {
buf := bytes.NewBuffer(random.GetRandomBytes(test.randLen))
if _, err := internalregistry.DeriveKey(test.keyTemplate, buf); err == nil {
t.Error("internalregistry.DeriveKey() err = nil, want non-nil")
}
})
}
}
OSZAR »