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 18 19import ( 20 "bytes" 21 "encoding/hex" 22 "fmt" 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/daead" 29 "github.com/google/tink/go/insecurecleartextkeyset" 30 "github.com/google/tink/go/mac" 31 "github.com/google/tink/go/prf" 32 "github.com/google/tink/go/signature" 33 "github.com/google/tink/go/streamingaead" 34 aesgcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" 35 commonpb "github.com/google/tink/go/proto/common_go_proto" 36 hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" 37 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 38) 39 40func TestPRFBasedDeriver(t *testing.T) { 41 prfs := []struct { 42 name string 43 template *tinkpb.KeyTemplate 44 }{ 45 { 46 name: "HKDF_SHA256", 47 template: prf.HKDFSHA256PRFKeyTemplate(), 48 }, 49 } 50 // Derivation names match KEY_TEMPLATE_NAMES in 51 // https://github.com/google/tink/blob/cd96c47ced3f72199832573cdccf18719dc7c73b/testing/cross_language/util/utilities.py. 52 derivations := []struct { 53 name string 54 template *tinkpb.KeyTemplate 55 }{ 56 { 57 name: "AES128_GCM", 58 template: aead.AES128GCMKeyTemplate(), 59 }, 60 { 61 name: "AES256_GCM", 62 template: aead.AES256GCMKeyTemplate(), 63 }, 64 { 65 name: "AES256_GCM_RAW", 66 template: aead.AES256GCMNoPrefixKeyTemplate(), 67 }, 68 { 69 name: "XCHACHA20_POLY1305", 70 template: aead.XChaCha20Poly1305KeyTemplate(), 71 }, 72 { 73 name: "AES256_SIV", 74 template: daead.AESSIVKeyTemplate(), 75 }, 76 { 77 name: "HMAC_SHA256_128BITTAG", 78 template: mac.HMACSHA256Tag128KeyTemplate(), 79 }, 80 { 81 name: "HMAC_SHA256_256BITTAG", 82 template: mac.HMACSHA256Tag256KeyTemplate(), 83 }, 84 { 85 name: "HMAC_SHA512_256BITTAG", 86 template: mac.HMACSHA512Tag256KeyTemplate(), 87 }, 88 { 89 name: "HMAC_SHA512_512BITTAG", 90 template: mac.HMACSHA512Tag512KeyTemplate(), 91 }, 92 { 93 name: "HKDF_SHA256", 94 template: prf.HKDFSHA256PRFKeyTemplate(), 95 }, 96 { 97 name: "HMAC_SHA256_PRF", 98 template: prf.HMACSHA256PRFKeyTemplate(), 99 }, 100 { 101 name: "HMAC_SHA512_PRF", 102 template: prf.HMACSHA512PRFKeyTemplate(), 103 }, 104 { 105 name: "ED25519", 106 template: signature.ED25519KeyTemplate(), 107 }, 108 { 109 name: "AES128_GCM_HKDF_4KB", 110 template: streamingaead.AES128GCMHKDF4KBKeyTemplate(), 111 }, 112 { 113 name: "AES128_GCM_HKDF_1MB", 114 template: streamingaead.AES128GCMHKDF1MBKeyTemplate(), 115 }, 116 { 117 name: "AES256_GCM_HKDF_4KB", 118 template: streamingaead.AES256GCMHKDF4KBKeyTemplate(), 119 }, 120 { 121 name: "AES256_GCM_HKDF_1MB", 122 template: streamingaead.AES256GCMHKDF1MBKeyTemplate(), 123 }, 124 } 125 salts := [][]byte{nil, []byte("salt")} 126 for _, prf := range prfs { 127 for _, der := range derivations { 128 for _, salt := range salts { 129 name := fmt.Sprintf("%s_%s", prf.name, der.name) 130 if salt != nil { 131 name += "_with_salt" 132 } 133 t.Run(name, func(t *testing.T) { 134 prfKeyData, err := registry.NewKeyData(prf.template) 135 if err != nil { 136 t.Fatalf("registry.NewKeyData() err = %v, want nil", err) 137 } 138 d, err := newPRFBasedDeriver(prfKeyData, der.template) 139 if err != nil { 140 t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) 141 } 142 if _, err := d.DeriveKeyset(salt); err != nil { 143 t.Errorf("DeriveKeyset() err = %v, want nil", err) 144 } 145 // We cannot test the derived keyset handle because, at this point, it 146 // is filled with placeholder values for the key ID, status, and 147 // output prefix type fields. 148 }) 149 } 150 } 151 } 152} 153 154func TestPRFBasedDeriverWithHKDFRFCVectorForAESGCM(t *testing.T) { 155 // This is the only HKDF vector that uses an accepted hash function and has 156 // key size >= 32-bytes. 157 // https://www.rfc-editor.org/rfc/rfc5869#appendix-A.2 158 vec := struct { 159 hash commonpb.HashType 160 key string 161 salt string 162 info string 163 outLen int 164 okm string 165 }{ 166 hash: commonpb.HashType_SHA256, 167 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", 168 salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", 169 info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 170 outLen: 82, 171 okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", 172 } 173 prfKeyValue, err := hex.DecodeString(vec.key) 174 if err != nil { 175 t.Fatalf("hex.DecodeString() err = %v, want nil", err) 176 } 177 prfSalt, err := hex.DecodeString(vec.salt) 178 if err != nil { 179 t.Fatalf("hex.DecodeString() err = %v, want nil", err) 180 } 181 derivationSalt, err := hex.DecodeString(vec.info) 182 if err != nil { 183 t.Fatalf("hex.DecodeString() err = %v, want nil", err) 184 } 185 wantKeyValue, err := hex.DecodeString(vec.okm) 186 if err != nil { 187 t.Fatalf("hex.DecodeString() err = %v, want nil", err) 188 } 189 190 prfKey := &hkdfpb.HkdfPrfKey{ 191 Version: 0, 192 Params: &hkdfpb.HkdfPrfParams{ 193 Hash: vec.hash, 194 Salt: prfSalt, 195 }, 196 KeyValue: prfKeyValue, 197 } 198 serializedPRFKey, err := proto.Marshal(prfKey) 199 if err != nil { 200 t.Fatalf("proto.Marshal() err = %v, want nil", err) 201 } 202 prfKeyData := &tinkpb.KeyData{ 203 TypeUrl: prf.HKDFSHA256PRFKeyTemplate().GetTypeUrl(), 204 Value: serializedPRFKey, 205 KeyMaterialType: tinkpb.KeyData_SYMMETRIC, 206 } 207 208 for _, test := range []struct { 209 name string 210 derivedKeyTemplate *tinkpb.KeyTemplate 211 }{ 212 { 213 name: "AES128_GCM", 214 derivedKeyTemplate: aead.AES128GCMKeyTemplate(), 215 }, 216 { 217 name: "AES256_GCM", 218 derivedKeyTemplate: aead.AES256GCMKeyTemplate(), 219 }, 220 { 221 name: "AES256_GCM_RAW", 222 derivedKeyTemplate: aead.AES256GCMNoPrefixKeyTemplate(), 223 }, 224 } { 225 t.Run(test.name, func(t *testing.T) { 226 // Derive keyset. 227 d, err := newPRFBasedDeriver(prfKeyData, test.derivedKeyTemplate) 228 if err != nil { 229 t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) 230 } 231 derivedHandle, err := d.DeriveKeyset(derivationSalt) 232 if err != nil { 233 t.Fatalf("DeriveKeyset() err = %v, want nil", err) 234 } 235 derivedKeyset := insecurecleartextkeyset.KeysetMaterial(derivedHandle) 236 237 // Verify keyset. 238 if len(derivedKeyset.GetKey()) != 1 { 239 t.Fatalf("len(keyset) = %d, want 1", len(derivedKeyset.GetKey())) 240 } 241 key := derivedKeyset.GetKey()[0] 242 if derivedKeyset.GetPrimaryKeyId() != key.GetKeyId() { 243 t.Fatal("keyset has no primary key") 244 } 245 // Verify key attributes set by prfBasedDeriver. 246 if got, want := key.GetStatus(), tinkpb.KeyStatusType_UNKNOWN_STATUS; got != want { 247 t.Errorf("derived key status = %s, want %s", got, want) 248 } 249 if got, want := key.GetOutputPrefixType(), tinkpb.OutputPrefixType_UNKNOWN_PREFIX; got != want { 250 t.Errorf("derived key output prefix type = %s, want %s", got, want) 251 } 252 // Verify key value. 253 derivedKeyFormat := &aesgcmpb.AesGcmKeyFormat{} 254 if err := proto.Unmarshal(test.derivedKeyTemplate.GetValue(), derivedKeyFormat); err != nil { 255 t.Fatalf("proto.Unmarshal() err = %v, want nil", err) 256 } 257 wantKeySize := int(derivedKeyFormat.GetKeySize()) 258 aesGCMKey := &aesgcmpb.AesGcmKey{} 259 if err := proto.Unmarshal(key.GetKeyData().GetValue(), aesGCMKey); err != nil { 260 t.Fatalf("proto.Unmarshal() err = %v, want nil", err) 261 } 262 gotKeyValue := aesGCMKey.GetKeyValue() 263 if len(gotKeyValue) != wantKeySize { 264 t.Errorf("derived key value length = %d, want %d", len(gotKeyValue), wantKeySize) 265 } 266 if !bytes.Equal(gotKeyValue, wantKeyValue[:wantKeySize]) { 267 t.Errorf("derived key value = %q, want %q", gotKeyValue, wantKeyValue[:wantKeySize]) 268 } 269 }) 270 } 271} 272 273func TestNewPRFBasedDeriverRejectsInvalidInputs(t *testing.T) { 274 validPRFKeyData, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) 275 if err != nil { 276 t.Fatalf("registry.NewKeyData() err = %v, want nil", err) 277 } 278 validDerivedKeyTemplate := aead.AES128GCMKeyTemplate() 279 if _, err := newPRFBasedDeriver(validPRFKeyData, validDerivedKeyTemplate); err != nil { 280 t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) 281 } 282 invalidPRFKeyData, err := registry.NewKeyData(aead.AES128GCMKeyTemplate()) 283 if err != nil { 284 t.Fatalf("registry.NewKeyData() err = %v, want nil", err) 285 } 286 // The derivation of KeysetDeriver keyset handles is not supported, i.e. a 287 // KeysetDeriver key template cannot be used as the derivedKeyTemplate 288 // argument in newPRFBasedDeriver(). 289 invalidDerivedKeyTemplate, err := CreatePRFBasedKeyTemplate(prf.HKDFSHA256PRFKeyTemplate(), aead.AES128GCMKeyTemplate()) 290 if err != nil { 291 t.Fatalf("CreatePRFBasedKeyTemplate() err = %v, want nil", err) 292 } 293 for _, test := range []struct { 294 name string 295 prfKeyData *tinkpb.KeyData 296 derivedKeyTemplate *tinkpb.KeyTemplate 297 }{ 298 { 299 name: "nil inputs", 300 }, 301 { 302 name: "nil PRF key data", 303 derivedKeyTemplate: validDerivedKeyTemplate, 304 }, 305 { 306 name: "nil derived template", 307 prfKeyData: validPRFKeyData, 308 }, 309 { 310 name: "invalid PRF key data", 311 prfKeyData: invalidPRFKeyData, 312 derivedKeyTemplate: validDerivedKeyTemplate, 313 }, 314 { 315 name: "invalid derived template", 316 prfKeyData: validPRFKeyData, 317 derivedKeyTemplate: invalidDerivedKeyTemplate, 318 }, 319 } { 320 t.Run(test.name, func(t *testing.T) { 321 if _, err := newPRFBasedDeriver(test.prfKeyData, test.derivedKeyTemplate); err == nil { 322 t.Errorf("newPRFBasedDeriver() err = nil, want non-nil") 323 } 324 }) 325 } 326} 327