1// Copyright 2020 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 prf 18 19import ( 20 "errors" 21 "fmt" 22 "io" 23 24 "google.golang.org/protobuf/proto" 25 "github.com/google/tink/go/core/registry" 26 "github.com/google/tink/go/keyset" 27 "github.com/google/tink/go/prf/subtle" 28 "github.com/google/tink/go/subtle/random" 29 commonpb "github.com/google/tink/go/proto/common_go_proto" 30 hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" 31 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 32) 33 34const ( 35 hkdfprfKeyVersion = 0 36 hkdfprfTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" 37) 38 39var errInvalidHKDFPRFKey = errors.New("hkdf_prf_key_manager: invalid key") 40var errInvalidHKDFPRFKeyFormat = errors.New("hkdf_prf_key_manager: invalid key format") 41 42// hkdfprfKeyManager generates new HKDF PRF keys and produces new instances of HKDF. 43type hkdfprfKeyManager struct{} 44 45// Assert that hkdfprfKeyManager implements the KeyManager interface. 46var _ registry.KeyManager = (*hkdfprfKeyManager)(nil) 47 48// Primitive constructs a HKDF instance for the given serialized HKDFKey. 49func (km *hkdfprfKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 50 if len(serializedKey) == 0 { 51 return nil, errInvalidHKDFPRFKey 52 } 53 key := new(hkdfpb.HkdfPrfKey) 54 if err := proto.Unmarshal(serializedKey, key); err != nil { 55 return nil, errInvalidHKDFPRFKey 56 } 57 if err := km.validateKey(key); err != nil { 58 return nil, err 59 } 60 hash := commonpb.HashType_name[int32(key.Params.Hash)] 61 hkdf, err := subtle.NewHKDFPRF(hash, key.KeyValue, key.Params.Salt) 62 if err != nil { 63 return nil, err 64 } 65 return hkdf, nil 66} 67 68// NewKey generates a new HKDFPRFKey according to specification in the given HKDFPRFKeyFormat. 69func (km *hkdfprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 70 if len(serializedKeyFormat) == 0 { 71 return nil, errInvalidHKDFPRFKeyFormat 72 } 73 keyFormat := new(hkdfpb.HkdfPrfKeyFormat) 74 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 75 return nil, errInvalidHKDFPRFKeyFormat 76 } 77 if err := km.validateKeyFormat(keyFormat); err != nil { 78 return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err) 79 } 80 keyValue := random.GetRandomBytes(keyFormat.KeySize) 81 return &hkdfpb.HkdfPrfKey{ 82 Version: hkdfprfKeyVersion, 83 Params: keyFormat.Params, 84 KeyValue: keyValue, 85 }, nil 86} 87 88// NewKeyData generates a new KeyData according to specification in the given 89// serialized HKDFPRFKeyFormat. This should be used solely by the key management API. 90func (km *hkdfprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 91 key, err := km.NewKey(serializedKeyFormat) 92 if err != nil { 93 return nil, err 94 } 95 serializedKey, err := proto.Marshal(key) 96 if err != nil { 97 return nil, errInvalidHKDFPRFKeyFormat 98 } 99 100 return &tinkpb.KeyData{ 101 TypeUrl: hkdfprfTypeURL, 102 Value: serializedKey, 103 KeyMaterialType: km.KeyMaterialType(), 104 }, nil 105} 106 107// DoesSupport checks whether this KeyManager supports the given key type. 108func (km *hkdfprfKeyManager) DoesSupport(typeURL string) bool { 109 return typeURL == hkdfprfTypeURL 110} 111 112// TypeURL returns the type URL of keys managed by this KeyManager. 113func (km *hkdfprfKeyManager) TypeURL() string { 114 return hkdfprfTypeURL 115} 116 117// KeyMaterialType returns the key material type of this KeyManager. 118func (km *hkdfprfKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { 119 return tinkpb.KeyData_SYMMETRIC 120} 121 122// DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. 123func (km *hkdfprfKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { 124 if len(serializedKeyFormat) == 0 { 125 return nil, errInvalidHKDFPRFKeyFormat 126 } 127 keyFormat := new(hkdfpb.HkdfPrfKeyFormat) 128 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 129 return nil, errInvalidHKDFPRFKeyFormat 130 } 131 if err := km.validateKeyFormat(keyFormat); err != nil { 132 return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err) 133 } 134 if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), hkdfprfKeyVersion); err != nil { 135 return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key version: %s", err) 136 } 137 138 keyValue := make([]byte, keyFormat.GetKeySize()) 139 if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { 140 return nil, fmt.Errorf("hkdf_prf_key_manager: not enough pseudorandomness given") 141 } 142 143 return &hkdfpb.HkdfPrfKey{ 144 Version: hkdfprfKeyVersion, 145 Params: keyFormat.Params, 146 KeyValue: keyValue, 147 }, nil 148} 149 150// validateKey validates the given HKDFPRFKey. It only validates the version of the 151// key because other parameters will be validated in primitive construction. 152func (km *hkdfprfKeyManager) validateKey(key *hkdfpb.HkdfPrfKey) error { 153 err := keyset.ValidateKeyVersion(key.Version, hkdfprfKeyVersion) 154 if err != nil { 155 return fmt.Errorf("hkdf_prf_key_manager: invalid version: %s", err) 156 } 157 keySize := uint32(len(key.KeyValue)) 158 hash := commonpb.HashType_name[int32(key.Params.Hash)] 159 return subtle.ValidateHKDFPRFParams(hash, keySize, key.Params.Salt) 160} 161 162// validateKeyFormat validates the given HKDFKeyFormat 163func (km *hkdfprfKeyManager) validateKeyFormat(format *hkdfpb.HkdfPrfKeyFormat) error { 164 if format.Params == nil { 165 return fmt.Errorf("null HKDF params") 166 } 167 hash := commonpb.HashType_name[int32(format.Params.Hash)] 168 return subtle.ValidateHKDFPRFParams(hash, format.KeySize, format.Params.Salt) 169} 170