github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/aead/aes_cbc_hmac_aead_key_manager.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package aead 8 9 import ( 10 "errors" 11 "fmt" 12 13 subtleaead "github.com/google/tink/go/aead/subtle" 14 "github.com/google/tink/go/keyset" 15 subtlemac "github.com/google/tink/go/mac/subtle" 16 commonpb "github.com/google/tink/go/proto/common_go_proto" 17 hmacpb "github.com/google/tink/go/proto/hmac_go_proto" 18 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 19 "github.com/google/tink/go/subtle/random" 20 "google.golang.org/protobuf/proto" 21 22 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle" 23 cbcpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/aes_cbc_go_proto" 24 aeadpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/aes_cbc_hmac_aead_go_proto" 25 ) 26 27 const ( 28 aesCBCHMACAEADKeyVersion = 0 29 aesCBCHMACAEADTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.AesCbcHmacAeadKey" 30 minHMACKeySizeInBytes = 16 31 minTagSizeInBytes = 10 32 33 // maxTagSize. 34 maxTagSizeSHA1 = 20 35 maxTagSizeSHA224 = 28 36 maxTagSizeSHA256 = 32 37 maxTagSizeSHA384 = 48 38 maxTagSizeSHA512 = 64 39 ) 40 41 // common errors. 42 var ( 43 errInvalidAESCBCHMACAEADKey = fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid key") 44 errInvalidAESCBCHMACAEADKeyFormat = fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid key format") 45 maxTagSize = map[commonpb.HashType]uint32{ //nolint:gochecknoglobals 46 commonpb.HashType_SHA1: maxTagSizeSHA1, 47 commonpb.HashType_SHA224: maxTagSizeSHA224, 48 commonpb.HashType_SHA256: maxTagSizeSHA256, 49 commonpb.HashType_SHA384: maxTagSizeSHA384, 50 commonpb.HashType_SHA512: maxTagSizeSHA512, 51 } 52 ) 53 54 // aesCBCHMACAEADKeyManager is an implementation of KeyManager interface. 55 // It generates new AESCBCHMACAEADKey keys and produces new instances of EncryptThenAuthenticate subtle. 56 type aesCBCHMACAEADKeyManager struct{} 57 58 // newAESCBCHMACAEADKeyManager creates a new aesCBCHMACAEADKeyManager. 59 func newAESCBCHMACAEADKeyManager() *aesCBCHMACAEADKeyManager { 60 return new(aesCBCHMACAEADKeyManager) 61 } 62 63 // Primitive creates an AEAD for the given serialized AESCBCHMACAEADKey proto. 64 func (km *aesCBCHMACAEADKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 65 if len(serializedKey) == 0 { 66 return nil, errInvalidAESCBCHMACAEADKey 67 } 68 69 key := new(aeadpb.AesCbcHmacAeadKey) 70 if err := proto.Unmarshal(serializedKey, key); err != nil { 71 return nil, errInvalidAESCBCHMACAEADKey 72 } 73 74 if err := km.validateKey(key); err != nil { 75 return nil, fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 76 } 77 78 cbc, err := subtle.NewAESCBC(key.AesCbcKey.KeyValue) 79 if err != nil { 80 return nil, fmt.Errorf("aes_cbc_hmac_aead_key_manager: cannot create new primitive: %w", err) 81 } 82 83 hmacKey := key.HmacKey 84 85 hmac, err := subtlemac.NewHMAC(hmacKey.Params.Hash.String(), hmacKey.KeyValue, hmacKey.Params.TagSize) 86 if err != nil { 87 return nil, fmt.Errorf("aes_cbc_hmac_aead_key_manager: cannot create hmac primitive, error: %w", err) 88 } 89 90 aead, err := subtleaead.NewEncryptThenAuthenticate(cbc, hmac, int(hmacKey.Params.TagSize)) 91 if err != nil { 92 return nil, fmt.Errorf("aes_cbc_hmac_aead_key_manager: cannot create encrypt then authenticate primitive,"+ 93 " error: %w", err) 94 } 95 96 return aead, nil 97 } 98 99 // NewKey creates a new key according to the given serialized AesCbcHmacAeadKeyFormat. 100 func (km *aesCBCHMACAEADKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 101 if len(serializedKeyFormat) == 0 { 102 return nil, errInvalidAESCBCHMACAEADKeyFormat 103 } 104 105 keyFormat := new(aeadpb.AesCbcHmacAeadKeyFormat) 106 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 107 return nil, errInvalidAESCBCHMACAEADKeyFormat 108 } 109 110 if err := km.validateKeyFormat(keyFormat); err != nil { 111 return nil, fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid key format: %w", err) 112 } 113 114 return &aeadpb.AesCbcHmacAeadKey{ 115 Version: aesCBCHMACAEADKeyVersion, 116 AesCbcKey: &cbcpb.AesCbcKey{ 117 Version: aesCBCHMACAEADKeyVersion, 118 KeyValue: random.GetRandomBytes(keyFormat.AesCbcKeyFormat.KeySize), 119 }, 120 HmacKey: &hmacpb.HmacKey{ 121 Version: aesCBCHMACAEADKeyVersion, 122 KeyValue: random.GetRandomBytes(keyFormat.HmacKeyFormat.KeySize), 123 Params: keyFormat.HmacKeyFormat.Params, 124 }, 125 }, nil 126 } 127 128 // NewKeyData creates a new KeyData according to specification in the given serialized 129 // AesCbcHmacAeadKeyFormat. 130 // It should be used solely by the key management API. 131 func (km *aesCBCHMACAEADKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 132 key, err := km.NewKey(serializedKeyFormat) 133 if err != nil { 134 return nil, err 135 } 136 137 serializedKey, err := proto.Marshal(key) 138 if err != nil { 139 return nil, err 140 } 141 142 return &tinkpb.KeyData{ 143 TypeUrl: km.TypeURL(), 144 Value: serializedKey, 145 KeyMaterialType: tinkpb.KeyData_SYMMETRIC, 146 }, nil 147 } 148 149 // DoesSupport indicates if this key manager supports the given key type. 150 func (km *aesCBCHMACAEADKeyManager) DoesSupport(typeURL string) bool { 151 return typeURL == aesCBCHMACAEADTypeURL 152 } 153 154 // TypeURL returns the key type of keys managed by this key manager. 155 func (km *aesCBCHMACAEADKeyManager) TypeURL() string { 156 return aesCBCHMACAEADTypeURL 157 } 158 159 // validateKey validates the given AesCbcHmacAeadKey proto. 160 func (km *aesCBCHMACAEADKeyManager) validateKey(key *aeadpb.AesCbcHmacAeadKey) error { 161 if err := keyset.ValidateKeyVersion(key.Version, aesCBCHMACAEADKeyVersion); err != nil { 162 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 163 } 164 165 if err := keyset.ValidateKeyVersion(key.AesCbcKey.Version, aesCBCHMACAEADKeyVersion); err != nil { 166 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 167 } 168 169 if err := keyset.ValidateKeyVersion(key.HmacKey.Version, aesCBCHMACAEADKeyVersion); err != nil { 170 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 171 } 172 173 // Validate AesCtrKey. 174 keySize := uint32(len(key.AesCbcKey.KeyValue)) 175 if err := subtle.ValidateAESKeySize(keySize); err != nil { 176 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 177 } 178 179 return nil 180 } 181 182 // validateKeyFormat validates the given AesCbcHmacAeadKeyFormat proto. 183 func (km *aesCBCHMACAEADKeyManager) validateKeyFormat(format *aeadpb.AesCbcHmacAeadKeyFormat) error { 184 // Validate AesCtrKeyFormat. 185 if err := subtle.ValidateAESKeySize(format.AesCbcKeyFormat.KeySize); err != nil { 186 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: %w", err) 187 } 188 189 // Validate HmacKeyFormat. 190 hmacKeyFormat := format.HmacKeyFormat 191 if hmacKeyFormat.KeySize < minHMACKeySizeInBytes { 192 return errors.New("aes_cbc_hmac_aead_key_manager: HMAC KeySize is too small") 193 } 194 195 if hmacKeyFormat.Params.TagSize < minTagSizeInBytes { 196 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid HmacParams: TagSize %d is too small", 197 hmacKeyFormat.Params.TagSize) 198 } 199 200 tagSize, ok := maxTagSize[hmacKeyFormat.Params.Hash] 201 if !ok { 202 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid HmacParams: HashType %q not supported", 203 hmacKeyFormat.Params.Hash) 204 } 205 206 if hmacKeyFormat.Params.TagSize > tagSize { 207 return fmt.Errorf("aes_cbc_hmac_aead_key_manager: invalid HmacParams: TagSize %d is too big for HashType %q", 208 hmacKeyFormat.Params.TagSize, hmacKeyFormat.Params.Hash) 209 } 210 211 return nil 212 }