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