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  }