github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/composite/ecdh/ecdh_key_template.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package ecdh
     8  
     9  import (
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/google/tink/go/aead"
    12  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    13  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    14  
    15  	cbcaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead"
    16  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle"
    17  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    18  )
    19  
    20  // AEADAlg represents the AEAD implementation algorithm used by ECDH.
    21  type AEADAlg int
    22  
    23  const (
    24  	// AES256GCM AEAD.
    25  	AES256GCM = iota + 1
    26  	// XC20P AEAD.
    27  	XC20P
    28  	// AES128CBCHMACSHA256 AEAD.
    29  	AES128CBCHMACSHA256
    30  	// AES192CBCHMACSHA384 AEAD.
    31  	AES192CBCHMACSHA384
    32  	// AES256CBCHMACSHA384 AEAD.
    33  	AES256CBCHMACSHA384
    34  	// AES256CBCHMACSHA512 AEAD.
    35  	AES256CBCHMACSHA512
    36  )
    37  
    38  // EncryptionAlgLabel maps AEADAlg to its label.
    39  var EncryptionAlgLabel = map[AEADAlg]string{ //nolint:gochecknoglobals
    40  	AES256GCM:           "AES256GCM",
    41  	XC20P:               "XC20P",
    42  	AES128CBCHMACSHA256: "AES128CBCHMACSHA256",
    43  	AES192CBCHMACSHA384: "AES192CBCHMACSHA384",
    44  	AES256CBCHMACSHA384: "AES256CBCHMACSHA384",
    45  	AES256CBCHMACSHA512: "AES256CBCHMACSHA512",
    46  }
    47  
    48  // NISTP256ECDHKWKeyTemplate is a KeyTemplate that generates a key that accepts a CEK for JWE content
    49  // encryption. CEK wrapping is done outside of this Tink key (in the tinkcrypto service).
    50  // Keys from this template represent a valid recipient public/private key pairs and can be stored in the KMS. The
    51  // recipient key represented in this key template uses the following key wrapping curve:
    52  //   - NIST curve P-256.
    53  //
    54  // Keys created with this template are mainly used for key wrapping of a cek. They are independent of the AEAD content
    55  // encryption algorithm.
    56  func NISTP256ECDHKWKeyTemplate() *tinkpb.KeyTemplate {
    57  	// aesGCM is set to pass key generation in the key manager, it's irrelevant to the key or its intended use.
    58  	return createKeyTemplate(true, AES256GCM, commonpb.EllipticCurveType_NIST_P256, nil)
    59  }
    60  
    61  // NISTP384ECDHKWKeyTemplate is a KeyTemplate that generates a key that accepts a CEK for JWE content
    62  // encryption. CEK wrapping is done outside of this Tink key (in the tinkcrypto service).
    63  // Keys from this template represent a valid recipient public/private key pairs and can be stored in the KMS. The
    64  // recipient key represented in this key template uses the following key wrapping curve:
    65  //   - NIST curve P-384
    66  //
    67  // Keys created with this template are mainly used for key wrapping of a cek. They are independent of the AEAD content
    68  // encryption algorithm.
    69  func NISTP384ECDHKWKeyTemplate() *tinkpb.KeyTemplate {
    70  	// aesGCM is set to pass key generation in the key manager, it's irrelevant to the key or its intended use.
    71  	return createKeyTemplate(true, AES256GCM, commonpb.EllipticCurveType_NIST_P384, nil)
    72  }
    73  
    74  // NISTP521ECDHKWKeyTemplate is a KeyTemplate that generates a key that accepts a CEK for JWE content
    75  // encryption. CEK wrapping is done outside of this Tink key (in the tinkcrypto service).
    76  // Keys from this template represent a valid recipient public/private key pairs and can be stored in the KMS. The
    77  // recipient key represented in this key template uses the following key wrapping curve:
    78  //   - NIST curve P-521
    79  //
    80  // Keys created with this template are mainly used for key wrapping of a cek. They are independent of the AEAD content
    81  // encryption algorithm.
    82  func NISTP521ECDHKWKeyTemplate() *tinkpb.KeyTemplate {
    83  	// aesGCM is set to pass key generation in the key manager, it's irrelevant to the key or its intended use.
    84  	return createKeyTemplate(true, AES256GCM, commonpb.EllipticCurveType_NIST_P521, nil)
    85  }
    86  
    87  // X25519ECDHKWKeyTemplate is a KeyTemplate that generates a key that accepts a CEK for JWE content
    88  // encryption. CEK wrapping is done outside of this Tink key (in the tinkcrypto service).
    89  // Keys from this template represent a valid recipient public/private key pairs and can be stored in the KMS.The
    90  // recipient key represented in this key template uses the following key wrapping curve:
    91  //   - Curve25519
    92  //
    93  // Keys created with this template are mainly used for key wrapping of a cek. They are independent of the AEAD content
    94  // encryption algorithm.
    95  func X25519ECDHKWKeyTemplate() *tinkpb.KeyTemplate {
    96  	// xc20p is set to pass key generation in the key manager, it's irrelevant to the key or its intended use.
    97  	return createKeyTemplate(false, XC20P, commonpb.EllipticCurveType_CURVE25519, nil)
    98  }
    99  
   100  // KeyTemplateForECDHPrimitiveWithCEK is similar to NISTP256ECDHKWKeyTemplate but adding the cek to execute the
   101  // CompositeEncrypt primitive for encrypting a message targeted to one ore more recipients. KW is not executed by this
   102  // template, so it is ignored and set to NIST P Curved key by default.
   103  // Keys from this template offer valid CompositeEncrypt primitive execution only and should not be stored in the KMS.
   104  // The key created from this template has no recipient key info linked to it. It is exclusively used for primitive
   105  // execution using content encryption. Available content encryption algorithms:
   106  //   - AES256GCM, XChacaha20Poly1305, AES128CBC+HMAC256, AES192CBC+HMAC384, AES256CBC+HMAC384, AES256CBC+HMAC512
   107  //
   108  // It works with both key wrapping modes (executed outside of the key primitive created by this template):
   109  // NIST P kw or XC20P kw
   110  // cek should be of size:
   111  // - 32 bytes for AES256GCM, XChacaha20Poly1305, AES128CBC+HMAC256.
   112  // - 48 bytes for AES192CBC+HMAC384.
   113  // - 56 bytes for AES256CBC+HMAC384.
   114  // - 64 bytes for AES256CBC+HMAC512.
   115  func KeyTemplateForECDHPrimitiveWithCEK(cek []byte, nistpKW bool, encAlg AEADAlg) *tinkpb.KeyTemplate {
   116  	// the curve passed in the template below is ignored when executing the primitive, it's hardcoded to pass key
   117  	// key format validation only.
   118  	return createKeyTemplate(nistpKW, encAlg, 0, cek)
   119  }
   120  
   121  // createKeyTemplate creates a new ECDH-AEAD key template with the set cek for primitive execution. Boolean flag used:
   122  //   - nistpKW flag to state if kw is either NIST P curves (true) or Curve25519 (false)
   123  //   - encAlg + cek to determine the the nested AEAD key template to use
   124  func createKeyTemplate(nistpKW bool, encAlg AEADAlg, c commonpb.EllipticCurveType,
   125  	cek []byte) *tinkpb.KeyTemplate {
   126  	typeURL, keyType, encTemplate := getTypeParams(nistpKW, encAlg, cek)
   127  
   128  	format := &ecdhpb.EcdhAeadKeyFormat{
   129  		Params: &ecdhpb.EcdhAeadParams{
   130  			KwParams: &ecdhpb.EcdhKwParams{
   131  				CurveType: c,
   132  				KeyType:   keyType,
   133  			},
   134  			EncParams: &ecdhpb.EcdhAeadEncParams{
   135  				AeadEnc: encTemplate,
   136  				CEK:     cek,
   137  			},
   138  			EcPointFormat: commonpb.EcPointFormat_UNCOMPRESSED,
   139  		},
   140  	}
   141  
   142  	serializedFormat, err := proto.Marshal(format)
   143  	if err != nil {
   144  		panic("failed to marshal EcdhAeadKeyFormat proto")
   145  	}
   146  
   147  	return &tinkpb.KeyTemplate{
   148  		TypeUrl:          typeURL,
   149  		Value:            serializedFormat,
   150  		OutputPrefixType: tinkpb.OutputPrefixType_RAW,
   151  	}
   152  }
   153  
   154  func getTypeParams(nistpKW bool, encAlg AEADAlg, cek []byte) (string, ecdhpb.KeyType, *tinkpb.KeyTemplate) {
   155  	var (
   156  		keyTemplate *tinkpb.KeyTemplate
   157  		twoKeys     = 2
   158  	)
   159  
   160  	switch encAlg {
   161  	case AES256GCM:
   162  		keyTemplate = aead.AES256GCMKeyTemplate()
   163  	case AES128CBCHMACSHA256, AES192CBCHMACSHA384, AES256CBCHMACSHA384, AES256CBCHMACSHA512:
   164  		switch len(cek) {
   165  		case subtle.AES128Size * twoKeys:
   166  			keyTemplate = cbcaead.AES128CBCHMACSHA256KeyTemplate()
   167  		case subtle.AES192Size * twoKeys:
   168  			keyTemplate = cbcaead.AES192CBCHMACSHA384KeyTemplate()
   169  		case subtle.AES256Size + subtle.AES192Size:
   170  			keyTemplate = cbcaead.AES256CBCHMACSHA384KeyTemplate()
   171  		case subtle.AES256Size * twoKeys:
   172  			keyTemplate = cbcaead.AES256CBCHMACSHA512KeyTemplate()
   173  		}
   174  	case XC20P:
   175  		keyTemplate = aead.XChaCha20Poly1305KeyTemplate()
   176  	}
   177  
   178  	if nistpKW {
   179  		return nistpECDHKWPrivateKeyTypeURL, ecdhpb.KeyType_EC, keyTemplate
   180  	}
   181  
   182  	return x25519ECDHKWPrivateKeyTypeURL, ecdhpb.KeyType_OKP, keyTemplate
   183  }