1// Copyright 2019 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 daead 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/daead/subtle" 27 "github.com/google/tink/go/keyset" 28 "github.com/google/tink/go/subtle/random" 29 30 aspb "github.com/google/tink/go/proto/aes_siv_go_proto" 31 tpb "github.com/google/tink/go/proto/tink_go_proto" 32) 33 34const ( 35 aesSIVKeyVersion = 0 36 aesSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesSivKey" 37) 38 39var ( 40 errInvalidAESSIVKeyFormat = errors.New("aes_siv_key_manager: invalid key format") 41 errInvalidAESSIVKeySize = fmt.Errorf("aes_siv_key_manager: key size != %d", subtle.AESSIVKeySize) 42) 43 44// aesSIVKeyManager generates AES-SIV keys and produces instances of AES-SIV. 45type aesSIVKeyManager struct{} 46 47// Assert that aesSIVKeyManager implements the KeyManager interface. 48var _ registry.KeyManager = (*aesSIVKeyManager)(nil) 49 50// Primitive constructs an AES-SIV for the given serialized AesSivKey. 51func (km *aesSIVKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 52 if len(serializedKey) == 0 { 53 return nil, errors.New("aes_siv_key_manager: invalid key") 54 } 55 key := new(aspb.AesSivKey) 56 if err := proto.Unmarshal(serializedKey, key); err != nil { 57 return nil, err 58 } 59 if err := km.validateKey(key); err != nil { 60 return nil, err 61 } 62 ret, err := subtle.NewAESSIV(key.KeyValue) 63 if err != nil { 64 return nil, fmt.Errorf("aes_siv_key_manager: cannot create new primitive: %v", err) 65 } 66 return ret, nil 67} 68 69// NewKey generates a new AesSivKey. serializedKeyFormat is optional because 70// there is only one valid key format. 71func (km *aesSIVKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 72 // A nil serializedKeyFormat is acceptable. If specified, validate. 73 if serializedKeyFormat != nil { 74 keyFormat := new(aspb.AesSivKeyFormat) 75 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 76 return nil, errInvalidAESSIVKeyFormat 77 } 78 if keyFormat.KeySize != subtle.AESSIVKeySize { 79 return nil, errInvalidAESSIVKeySize 80 } 81 } 82 return &aspb.AesSivKey{ 83 Version: aesSIVKeyVersion, 84 KeyValue: random.GetRandomBytes(subtle.AESSIVKeySize), 85 }, nil 86} 87 88// NewKeyData generates a new KeyData. serializedKeyFormat is optional because 89// there is only one valid key format. This should be used solely by the key 90// management API. 91func (km *aesSIVKeyManager) NewKeyData(serializedKeyFormat []byte) (*tpb.KeyData, error) { 92 key, err := km.NewKey(serializedKeyFormat) 93 if err != nil { 94 return nil, err 95 } 96 serializedKey, err := proto.Marshal(key) 97 if err != nil { 98 return nil, fmt.Errorf("aes_siv_key_manager: %v", err) 99 } 100 return &tpb.KeyData{ 101 TypeUrl: aesSIVTypeURL, 102 Value: serializedKey, 103 KeyMaterialType: km.KeyMaterialType(), 104 }, nil 105} 106 107// DoesSupport checks whether this key manager supports the given key type. 108func (km *aesSIVKeyManager) DoesSupport(typeURL string) bool { 109 return typeURL == aesSIVTypeURL 110} 111 112// TypeURL returns the type URL of keys managed by this key manager. 113func (km *aesSIVKeyManager) TypeURL() string { 114 return aesSIVTypeURL 115} 116 117// KeyMaterialType returns the key material type of this key manager. 118func (km *aesSIVKeyManager) KeyMaterialType() tpb.KeyData_KeyMaterialType { 119 return tpb.KeyData_SYMMETRIC 120} 121 122// DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. 123// Unlike NewKey, DeriveKey validates serializedKeyFormat. 124func (km *aesSIVKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { 125 keyFormat := new(aspb.AesSivKeyFormat) 126 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 127 return nil, errInvalidAESSIVKeyFormat 128 } 129 if keyFormat.GetKeySize() != subtle.AESSIVKeySize { 130 return nil, errInvalidAESSIVKeySize 131 } 132 if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), aesSIVKeyVersion); err != nil { 133 return nil, fmt.Errorf("aes_siv_key_manager: invalid key version: %s", err) 134 } 135 136 keyValue := make([]byte, subtle.AESSIVKeySize) 137 if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { 138 return nil, fmt.Errorf("aes_siv_key_manager: not enough pseudorandomness given") 139 } 140 return &aspb.AesSivKey{ 141 Version: aesSIVKeyVersion, 142 KeyValue: keyValue, 143 }, nil 144} 145 146// validateKey validates the given AesSivKey. 147func (km *aesSIVKeyManager) validateKey(key *aspb.AesSivKey) error { 148 err := keyset.ValidateKeyVersion(key.Version, aesSIVKeyVersion) 149 if err != nil { 150 return fmt.Errorf("aes_siv_key_manager: %v", err) 151 } 152 keySize := uint32(len(key.KeyValue)) 153 if keySize != subtle.AESSIVKeySize { 154 return errInvalidAESSIVKeySize 155 } 156 return nil 157} 158