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 23 "google.golang.org/protobuf/proto" 24 "github.com/google/tink/go/keyset" 25 "github.com/google/tink/go/prf/subtle" 26 "github.com/google/tink/go/subtle/random" 27 cmacpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto" 28 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 29) 30 31const ( 32 aescmacprfKeyVersion = 0 33 aescmacprfTypeURL = "type.googleapis.com/google.crypto.tink.AesCmacPrfKey" 34) 35 36var errInvalidAESCMACPRFKey = errors.New("aes_cmac_prf_key_manager: invalid key") 37var errInvalidAESCMACPRFKeyFormat = errors.New("aes_cmac_prf_key_manager: invalid key format") 38 39// aescmacprfKeyManager generates new AES-CMAC keys and produces new instances of AES-CMAC. 40type aescmacprfKeyManager struct{} 41 42// Primitive constructs a AES-CMAC instance for the given serialized AESCMACPRFKey. 43func (km *aescmacprfKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 44 if len(serializedKey) == 0 { 45 return nil, errInvalidAESCMACPRFKey 46 } 47 key := new(cmacpb.AesCmacPrfKey) 48 if err := proto.Unmarshal(serializedKey, key); err != nil { 49 return nil, errInvalidAESCMACPRFKey 50 } 51 if err := km.validateKey(key); err != nil { 52 return nil, err 53 } 54 return subtle.NewAESCMACPRF(key.KeyValue) 55} 56 57// NewKey generates a new AESCMACPRFKey according to specification in the given AESCMACPRFKeyFormat. 58func (km *aescmacprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 59 if len(serializedKeyFormat) == 0 { 60 return nil, errInvalidAESCMACPRFKeyFormat 61 } 62 keyFormat := new(cmacpb.AesCmacPrfKeyFormat) 63 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 64 return nil, errInvalidAESCMACPRFKeyFormat 65 } 66 if err := km.validateKeyFormat(keyFormat); err != nil { 67 return nil, fmt.Errorf("aes_cmac_prf_key_manager: invalid key format: %s", err) 68 } 69 keyValue := random.GetRandomBytes(keyFormat.KeySize) 70 return &cmacpb.AesCmacPrfKey{ 71 Version: aescmacprfKeyVersion, 72 KeyValue: keyValue, 73 }, nil 74} 75 76// NewKeyData generates a new KeyData according to specification in the given 77// serialized AESCMACPRFKeyFormat. This should be used solely by the key management API. 78func (km *aescmacprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 79 key, err := km.NewKey(serializedKeyFormat) 80 if err != nil { 81 return nil, err 82 } 83 serializedKey, err := proto.Marshal(key) 84 if err != nil { 85 return nil, errInvalidAESCMACPRFKeyFormat 86 } 87 88 return &tinkpb.KeyData{ 89 TypeUrl: aescmacprfTypeURL, 90 Value: serializedKey, 91 KeyMaterialType: tinkpb.KeyData_SYMMETRIC, 92 }, nil 93} 94 95// DoesSupport checks whether this KeyManager supports the given key type. 96func (km *aescmacprfKeyManager) DoesSupport(typeURL string) bool { 97 return typeURL == aescmacprfTypeURL 98} 99 100// TypeURL returns the type URL of keys managed by this KeyManager. 101func (km *aescmacprfKeyManager) TypeURL() string { 102 return aescmacprfTypeURL 103} 104 105// validateKey validates the given AESCMACPRFKey. It only validates the version of the 106// key because other parameters will be validated in primitive construction. 107func (km *aescmacprfKeyManager) validateKey(key *cmacpb.AesCmacPrfKey) error { 108 err := keyset.ValidateKeyVersion(key.Version, aescmacprfKeyVersion) 109 if err != nil { 110 return fmt.Errorf("aes_cmac_prf_key_manager: invalid version: %s", err) 111 } 112 keySize := uint32(len(key.KeyValue)) 113 return subtle.ValidateAESCMACPRFParams(keySize) 114} 115 116// validateKeyFormat validates the given HMACKeyFormat 117func (km *aescmacprfKeyManager) validateKeyFormat(format *cmacpb.AesCmacPrfKeyFormat) error { 118 return subtle.ValidateAESCMACPRFParams(format.KeySize) 119} 120