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 }