diff options
Diffstat (limited to 'src/lib/libcrypto/cms/cms_kari.c')
| -rw-r--r-- | src/lib/libcrypto/cms/cms_kari.c | 636 |
1 files changed, 318 insertions, 318 deletions
diff --git a/src/lib/libcrypto/cms/cms_kari.c b/src/lib/libcrypto/cms/cms_kari.c index 8a52d8401c..7aad3c755b 100644 --- a/src/lib/libcrypto/cms/cms_kari.c +++ b/src/lib/libcrypto/cms/cms_kari.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: cms_kari.c,v 1.4 2019/08/10 16:39:17 jsing Exp $ */ | 1 | /* $OpenBSD: cms_kari.c,v 1.5 2019/08/10 16:42:20 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
| 4 | * project. | 4 | * project. |
| @@ -65,19 +65,19 @@ | |||
| 65 | /* Key Agreement Recipient Info (KARI) routines */ | 65 | /* Key Agreement Recipient Info (KARI) routines */ |
| 66 | 66 | ||
| 67 | int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, | 67 | int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, |
| 68 | X509_ALGOR **palg, | 68 | X509_ALGOR **palg, |
| 69 | ASN1_OCTET_STRING **pukm) | 69 | ASN1_OCTET_STRING **pukm) |
| 70 | { | 70 | { |
| 71 | if (ri->type != CMS_RECIPINFO_AGREE) { | 71 | if (ri->type != CMS_RECIPINFO_AGREE) { |
| 72 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, | 72 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, |
| 73 | CMS_R_NOT_KEY_AGREEMENT); | 73 | CMS_R_NOT_KEY_AGREEMENT); |
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | if (palg) | 76 | if (palg) |
| 77 | *palg = ri->d.kari->keyEncryptionAlgorithm; | 77 | *palg = ri->d.kari->keyEncryptionAlgorithm; |
| 78 | if (pukm) | 78 | if (pukm) |
| 79 | *pukm = ri->d.kari->ukm; | 79 | *pukm = ri->d.kari->ukm; |
| 80 | return 1; | 80 | return 1; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /* Retrieve recipient encrypted keys from a kari */ | 83 | /* Retrieve recipient encrypted keys from a kari */ |
| @@ -85,142 +85,142 @@ int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, | |||
| 85 | STACK_OF(CMS_RecipientEncryptedKey) | 85 | STACK_OF(CMS_RecipientEncryptedKey) |
| 86 | *CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri) | 86 | *CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri) |
| 87 | { | 87 | { |
| 88 | if (ri->type != CMS_RECIPINFO_AGREE) { | 88 | if (ri->type != CMS_RECIPINFO_AGREE) { |
| 89 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, | 89 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, |
| 90 | CMS_R_NOT_KEY_AGREEMENT); | 90 | CMS_R_NOT_KEY_AGREEMENT); |
| 91 | return NULL; | 91 | return NULL; |
| 92 | } | 92 | } |
| 93 | return ri->d.kari->recipientEncryptedKeys; | 93 | return ri->d.kari->recipientEncryptedKeys; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, | 96 | int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, |
| 97 | X509_ALGOR **pubalg, | 97 | X509_ALGOR **pubalg, |
| 98 | ASN1_BIT_STRING **pubkey, | 98 | ASN1_BIT_STRING **pubkey, |
| 99 | ASN1_OCTET_STRING **keyid, | 99 | ASN1_OCTET_STRING **keyid, |
| 100 | X509_NAME **issuer, | 100 | X509_NAME **issuer, |
| 101 | ASN1_INTEGER **sno) | 101 | ASN1_INTEGER **sno) |
| 102 | { | 102 | { |
| 103 | CMS_OriginatorIdentifierOrKey *oik; | 103 | CMS_OriginatorIdentifierOrKey *oik; |
| 104 | if (ri->type != CMS_RECIPINFO_AGREE) { | 104 | if (ri->type != CMS_RECIPINFO_AGREE) { |
| 105 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, | 105 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, |
| 106 | CMS_R_NOT_KEY_AGREEMENT); | 106 | CMS_R_NOT_KEY_AGREEMENT); |
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
| 109 | oik = ri->d.kari->originator; | 109 | oik = ri->d.kari->originator; |
| 110 | if (issuer) | 110 | if (issuer) |
| 111 | *issuer = NULL; | 111 | *issuer = NULL; |
| 112 | if (sno) | 112 | if (sno) |
| 113 | *sno = NULL; | 113 | *sno = NULL; |
| 114 | if (keyid) | 114 | if (keyid) |
| 115 | *keyid = NULL; | 115 | *keyid = NULL; |
| 116 | if (pubalg) | 116 | if (pubalg) |
| 117 | *pubalg = NULL; | 117 | *pubalg = NULL; |
| 118 | if (pubkey) | 118 | if (pubkey) |
| 119 | *pubkey = NULL; | 119 | *pubkey = NULL; |
| 120 | if (oik->type == CMS_OIK_ISSUER_SERIAL) { | 120 | if (oik->type == CMS_OIK_ISSUER_SERIAL) { |
| 121 | if (issuer) | 121 | if (issuer) |
| 122 | *issuer = oik->d.issuerAndSerialNumber->issuer; | 122 | *issuer = oik->d.issuerAndSerialNumber->issuer; |
| 123 | if (sno) | 123 | if (sno) |
| 124 | *sno = oik->d.issuerAndSerialNumber->serialNumber; | 124 | *sno = oik->d.issuerAndSerialNumber->serialNumber; |
| 125 | } else if (oik->type == CMS_OIK_KEYIDENTIFIER) { | 125 | } else if (oik->type == CMS_OIK_KEYIDENTIFIER) { |
| 126 | if (keyid) | 126 | if (keyid) |
| 127 | *keyid = oik->d.subjectKeyIdentifier; | 127 | *keyid = oik->d.subjectKeyIdentifier; |
| 128 | } else if (oik->type == CMS_OIK_PUBKEY) { | 128 | } else if (oik->type == CMS_OIK_PUBKEY) { |
| 129 | if (pubalg) | 129 | if (pubalg) |
| 130 | *pubalg = oik->d.originatorKey->algorithm; | 130 | *pubalg = oik->d.originatorKey->algorithm; |
| 131 | if (pubkey) | 131 | if (pubkey) |
| 132 | *pubkey = oik->d.originatorKey->publicKey; | 132 | *pubkey = oik->d.originatorKey->publicKey; |
| 133 | } else | 133 | } else |
| 134 | return 0; | 134 | return 0; |
| 135 | return 1; | 135 | return 1; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert) | 138 | int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert) |
| 139 | { | 139 | { |
| 140 | CMS_OriginatorIdentifierOrKey *oik; | 140 | CMS_OriginatorIdentifierOrKey *oik; |
| 141 | if (ri->type != CMS_RECIPINFO_AGREE) { | 141 | if (ri->type != CMS_RECIPINFO_AGREE) { |
| 142 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, | 142 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, |
| 143 | CMS_R_NOT_KEY_AGREEMENT); | 143 | CMS_R_NOT_KEY_AGREEMENT); |
| 144 | return -2; | 144 | return -2; |
| 145 | } | 145 | } |
| 146 | oik = ri->d.kari->originator; | 146 | oik = ri->d.kari->originator; |
| 147 | if (oik->type == CMS_OIK_ISSUER_SERIAL) | 147 | if (oik->type == CMS_OIK_ISSUER_SERIAL) |
| 148 | return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert); | 148 | return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert); |
| 149 | else if (oik->type == CMS_OIK_KEYIDENTIFIER) | 149 | else if (oik->type == CMS_OIK_KEYIDENTIFIER) |
| 150 | return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert); | 150 | return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert); |
| 151 | return -1; | 151 | return -1; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, | 154 | int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, |
| 155 | ASN1_OCTET_STRING **keyid, | 155 | ASN1_OCTET_STRING **keyid, |
| 156 | ASN1_GENERALIZEDTIME **tm, | 156 | ASN1_GENERALIZEDTIME **tm, |
| 157 | CMS_OtherKeyAttribute **other, | 157 | CMS_OtherKeyAttribute **other, |
| 158 | X509_NAME **issuer, ASN1_INTEGER **sno) | 158 | X509_NAME **issuer, ASN1_INTEGER **sno) |
| 159 | { | 159 | { |
| 160 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; | 160 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; |
| 161 | if (rid->type == CMS_REK_ISSUER_SERIAL) { | 161 | if (rid->type == CMS_REK_ISSUER_SERIAL) { |
| 162 | if (issuer) | 162 | if (issuer) |
| 163 | *issuer = rid->d.issuerAndSerialNumber->issuer; | 163 | *issuer = rid->d.issuerAndSerialNumber->issuer; |
| 164 | if (sno) | 164 | if (sno) |
| 165 | *sno = rid->d.issuerAndSerialNumber->serialNumber; | 165 | *sno = rid->d.issuerAndSerialNumber->serialNumber; |
| 166 | if (keyid) | 166 | if (keyid) |
| 167 | *keyid = NULL; | 167 | *keyid = NULL; |
| 168 | if (tm) | 168 | if (tm) |
| 169 | *tm = NULL; | 169 | *tm = NULL; |
| 170 | if (other) | 170 | if (other) |
| 171 | *other = NULL; | 171 | *other = NULL; |
| 172 | } else if (rid->type == CMS_REK_KEYIDENTIFIER) { | 172 | } else if (rid->type == CMS_REK_KEYIDENTIFIER) { |
| 173 | if (keyid) | 173 | if (keyid) |
| 174 | *keyid = rid->d.rKeyId->subjectKeyIdentifier; | 174 | *keyid = rid->d.rKeyId->subjectKeyIdentifier; |
| 175 | if (tm) | 175 | if (tm) |
| 176 | *tm = rid->d.rKeyId->date; | 176 | *tm = rid->d.rKeyId->date; |
| 177 | if (other) | 177 | if (other) |
| 178 | *other = rid->d.rKeyId->other; | 178 | *other = rid->d.rKeyId->other; |
| 179 | if (issuer) | 179 | if (issuer) |
| 180 | *issuer = NULL; | 180 | *issuer = NULL; |
| 181 | if (sno) | 181 | if (sno) |
| 182 | *sno = NULL; | 182 | *sno = NULL; |
| 183 | } else | 183 | } else |
| 184 | return 0; | 184 | return 0; |
| 185 | return 1; | 185 | return 1; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, | 188 | int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, |
| 189 | X509 *cert) | 189 | X509 *cert) |
| 190 | { | 190 | { |
| 191 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; | 191 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; |
| 192 | if (rid->type == CMS_REK_ISSUER_SERIAL) | 192 | if (rid->type == CMS_REK_ISSUER_SERIAL) |
| 193 | return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert); | 193 | return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert); |
| 194 | else if (rid->type == CMS_REK_KEYIDENTIFIER) | 194 | else if (rid->type == CMS_REK_KEYIDENTIFIER) |
| 195 | return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert); | 195 | return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert); |
| 196 | else | 196 | else |
| 197 | return -1; | 197 | return -1; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) | 200 | int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) |
| 201 | { | 201 | { |
| 202 | EVP_PKEY_CTX *pctx; | 202 | EVP_PKEY_CTX *pctx; |
| 203 | CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; | 203 | CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; |
| 204 | 204 | ||
| 205 | EVP_PKEY_CTX_free(kari->pctx); | 205 | EVP_PKEY_CTX_free(kari->pctx); |
| 206 | kari->pctx = NULL; | 206 | kari->pctx = NULL; |
| 207 | if (!pk) | 207 | if (!pk) |
| 208 | return 1; | 208 | return 1; |
| 209 | pctx = EVP_PKEY_CTX_new(pk, NULL); | 209 | pctx = EVP_PKEY_CTX_new(pk, NULL); |
| 210 | if (!pctx || !EVP_PKEY_derive_init(pctx)) | 210 | if (!pctx || !EVP_PKEY_derive_init(pctx)) |
| 211 | goto err; | 211 | goto err; |
| 212 | kari->pctx = pctx; | 212 | kari->pctx = pctx; |
| 213 | return 1; | 213 | return 1; |
| 214 | err: | 214 | err: |
| 215 | EVP_PKEY_CTX_free(pctx); | 215 | EVP_PKEY_CTX_free(pctx); |
| 216 | return 0; | 216 | return 0; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) | 219 | EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) |
| 220 | { | 220 | { |
| 221 | if (ri->type == CMS_RECIPINFO_AGREE) | 221 | if (ri->type == CMS_RECIPINFO_AGREE) |
| 222 | return ri->d.kari->ctx; | 222 | return ri->d.kari->ctx; |
| 223 | return NULL; | 223 | return NULL; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | /* | 226 | /* |
| @@ -229,231 +229,231 @@ EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) | |||
| 229 | */ | 229 | */ |
| 230 | 230 | ||
| 231 | static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, | 231 | static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, |
| 232 | const unsigned char *in, size_t inlen, | 232 | const unsigned char *in, size_t inlen, |
| 233 | CMS_KeyAgreeRecipientInfo *kari, int enc) | 233 | CMS_KeyAgreeRecipientInfo *kari, int enc) |
| 234 | { | 234 | { |
| 235 | /* Key encryption key */ | 235 | /* Key encryption key */ |
| 236 | unsigned char kek[EVP_MAX_KEY_LENGTH]; | 236 | unsigned char kek[EVP_MAX_KEY_LENGTH]; |
| 237 | size_t keklen; | 237 | size_t keklen; |
| 238 | int rv = 0; | 238 | int rv = 0; |
| 239 | unsigned char *out = NULL; | 239 | unsigned char *out = NULL; |
| 240 | int outlen; | 240 | int outlen; |
| 241 | keklen = EVP_CIPHER_CTX_key_length(kari->ctx); | 241 | keklen = EVP_CIPHER_CTX_key_length(kari->ctx); |
| 242 | if (keklen > EVP_MAX_KEY_LENGTH) | 242 | if (keklen > EVP_MAX_KEY_LENGTH) |
| 243 | return 0; | 243 | return 0; |
| 244 | /* Derive KEK */ | 244 | /* Derive KEK */ |
| 245 | if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) | 245 | if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) |
| 246 | goto err; | 246 | goto err; |
| 247 | /* Set KEK in context */ | 247 | /* Set KEK in context */ |
| 248 | if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) | 248 | if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) |
| 249 | goto err; | 249 | goto err; |
| 250 | /* obtain output length of ciphered key */ | 250 | /* obtain output length of ciphered key */ |
| 251 | if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) | 251 | if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) |
| 252 | goto err; | 252 | goto err; |
| 253 | out = OPENSSL_malloc(outlen); | 253 | out = OPENSSL_malloc(outlen); |
| 254 | if (out == NULL) | 254 | if (out == NULL) |
| 255 | goto err; | 255 | goto err; |
| 256 | if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) | 256 | if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) |
| 257 | goto err; | 257 | goto err; |
| 258 | *pout = out; | 258 | *pout = out; |
| 259 | *poutlen = (size_t)outlen; | 259 | *poutlen = (size_t)outlen; |
| 260 | rv = 1; | 260 | rv = 1; |
| 261 | 261 | ||
| 262 | err: | 262 | err: |
| 263 | OPENSSL_cleanse(kek, keklen); | 263 | OPENSSL_cleanse(kek, keklen); |
| 264 | if (!rv) | 264 | if (!rv) |
| 265 | OPENSSL_free(out); | 265 | OPENSSL_free(out); |
| 266 | EVP_CIPHER_CTX_reset(kari->ctx); | 266 | EVP_CIPHER_CTX_reset(kari->ctx); |
| 267 | /* FIXME: WHY IS kari->pctx freed here? /RL */ | 267 | /* FIXME: WHY IS kari->pctx freed here? /RL */ |
| 268 | EVP_PKEY_CTX_free(kari->pctx); | 268 | EVP_PKEY_CTX_free(kari->pctx); |
| 269 | kari->pctx = NULL; | 269 | kari->pctx = NULL; |
| 270 | return rv; | 270 | return rv; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, | 273 | int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, |
| 274 | CMS_RecipientInfo *ri, | 274 | CMS_RecipientInfo *ri, |
| 275 | CMS_RecipientEncryptedKey *rek) | 275 | CMS_RecipientEncryptedKey *rek) |
| 276 | { | 276 | { |
| 277 | int rv = 0; | 277 | int rv = 0; |
| 278 | unsigned char *enckey = NULL, *cek = NULL; | 278 | unsigned char *enckey = NULL, *cek = NULL; |
| 279 | size_t enckeylen; | 279 | size_t enckeylen; |
| 280 | size_t ceklen; | 280 | size_t ceklen; |
| 281 | CMS_EncryptedContentInfo *ec; | 281 | CMS_EncryptedContentInfo *ec; |
| 282 | enckeylen = rek->encryptedKey->length; | 282 | enckeylen = rek->encryptedKey->length; |
| 283 | enckey = rek->encryptedKey->data; | 283 | enckey = rek->encryptedKey->data; |
| 284 | /* Setup all parameters to derive KEK */ | 284 | /* Setup all parameters to derive KEK */ |
| 285 | if (!cms_env_asn1_ctrl(ri, 1)) | 285 | if (!cms_env_asn1_ctrl(ri, 1)) |
| 286 | goto err; | 286 | goto err; |
| 287 | /* Attempt to decrypt CEK */ | 287 | /* Attempt to decrypt CEK */ |
| 288 | if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0)) | 288 | if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0)) |
| 289 | goto err; | 289 | goto err; |
| 290 | ec = cms->d.envelopedData->encryptedContentInfo; | 290 | ec = cms->d.envelopedData->encryptedContentInfo; |
| 291 | OPENSSL_clear_free(ec->key, ec->keylen); | 291 | OPENSSL_clear_free(ec->key, ec->keylen); |
| 292 | ec->key = cek; | 292 | ec->key = cek; |
| 293 | ec->keylen = ceklen; | 293 | ec->keylen = ceklen; |
| 294 | cek = NULL; | 294 | cek = NULL; |
| 295 | rv = 1; | 295 | rv = 1; |
| 296 | err: | 296 | err: |
| 297 | OPENSSL_free(cek); | 297 | OPENSSL_free(cek); |
| 298 | return rv; | 298 | return rv; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | /* Create ephemeral key and initialise context based on it */ | 301 | /* Create ephemeral key and initialise context based on it */ |
| 302 | static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, | 302 | static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, |
| 303 | EVP_PKEY *pk) | 303 | EVP_PKEY *pk) |
| 304 | { | 304 | { |
| 305 | EVP_PKEY_CTX *pctx = NULL; | 305 | EVP_PKEY_CTX *pctx = NULL; |
| 306 | EVP_PKEY *ekey = NULL; | 306 | EVP_PKEY *ekey = NULL; |
| 307 | int rv = 0; | 307 | int rv = 0; |
| 308 | pctx = EVP_PKEY_CTX_new(pk, NULL); | 308 | pctx = EVP_PKEY_CTX_new(pk, NULL); |
| 309 | if (!pctx) | 309 | if (!pctx) |
| 310 | goto err; | 310 | goto err; |
| 311 | if (EVP_PKEY_keygen_init(pctx) <= 0) | 311 | if (EVP_PKEY_keygen_init(pctx) <= 0) |
| 312 | goto err; | 312 | goto err; |
| 313 | if (EVP_PKEY_keygen(pctx, &ekey) <= 0) | 313 | if (EVP_PKEY_keygen(pctx, &ekey) <= 0) |
| 314 | goto err; | 314 | goto err; |
| 315 | EVP_PKEY_CTX_free(pctx); | 315 | EVP_PKEY_CTX_free(pctx); |
| 316 | pctx = EVP_PKEY_CTX_new(ekey, NULL); | 316 | pctx = EVP_PKEY_CTX_new(ekey, NULL); |
| 317 | if (!pctx) | 317 | if (!pctx) |
| 318 | goto err; | 318 | goto err; |
| 319 | if (EVP_PKEY_derive_init(pctx) <= 0) | 319 | if (EVP_PKEY_derive_init(pctx) <= 0) |
| 320 | goto err; | 320 | goto err; |
| 321 | kari->pctx = pctx; | 321 | kari->pctx = pctx; |
| 322 | rv = 1; | 322 | rv = 1; |
| 323 | err: | 323 | err: |
| 324 | if (!rv) | 324 | if (!rv) |
| 325 | EVP_PKEY_CTX_free(pctx); | 325 | EVP_PKEY_CTX_free(pctx); |
| 326 | EVP_PKEY_free(ekey); | 326 | EVP_PKEY_free(ekey); |
| 327 | return rv; | 327 | return rv; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | /* Initialise a kari based on passed certificate and key */ | 330 | /* Initialise a kari based on passed certificate and key */ |
| 331 | 331 | ||
| 332 | int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, | 332 | int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, |
| 333 | EVP_PKEY *pk, unsigned int flags) | 333 | EVP_PKEY *pk, unsigned int flags) |
| 334 | { | 334 | { |
| 335 | CMS_KeyAgreeRecipientInfo *kari; | 335 | CMS_KeyAgreeRecipientInfo *kari; |
| 336 | CMS_RecipientEncryptedKey *rek = NULL; | 336 | CMS_RecipientEncryptedKey *rek = NULL; |
| 337 | 337 | ||
| 338 | ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); | 338 | ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); |
| 339 | if (!ri->d.kari) | 339 | if (!ri->d.kari) |
| 340 | return 0; | 340 | return 0; |
| 341 | ri->type = CMS_RECIPINFO_AGREE; | 341 | ri->type = CMS_RECIPINFO_AGREE; |
| 342 | 342 | ||
| 343 | kari = ri->d.kari; | 343 | kari = ri->d.kari; |
| 344 | kari->version = 3; | 344 | kari->version = 3; |
| 345 | 345 | ||
| 346 | rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); | 346 | rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); |
| 347 | if (rek == NULL) | 347 | if (rek == NULL) |
| 348 | return 0; | 348 | return 0; |
| 349 | 349 | ||
| 350 | if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { | 350 | if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { |
| 351 | M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); | 351 | M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); |
| 352 | return 0; | 352 | return 0; |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | if (flags & CMS_USE_KEYID) { | 355 | if (flags & CMS_USE_KEYID) { |
| 356 | rek->rid->type = CMS_REK_KEYIDENTIFIER; | 356 | rek->rid->type = CMS_REK_KEYIDENTIFIER; |
| 357 | rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); | 357 | rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); |
| 358 | if (rek->rid->d.rKeyId == NULL) | 358 | if (rek->rid->d.rKeyId == NULL) |
| 359 | return 0; | 359 | return 0; |
| 360 | if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) | 360 | if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) |
| 361 | return 0; | 361 | return 0; |
| 362 | } else { | 362 | } else { |
| 363 | rek->rid->type = CMS_REK_ISSUER_SERIAL; | 363 | rek->rid->type = CMS_REK_ISSUER_SERIAL; |
| 364 | if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) | 364 | if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) |
| 365 | return 0; | 365 | return 0; |
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | /* Create ephemeral key */ | 368 | /* Create ephemeral key */ |
| 369 | if (!cms_kari_create_ephemeral_key(kari, pk)) | 369 | if (!cms_kari_create_ephemeral_key(kari, pk)) |
| 370 | return 0; | 370 | return 0; |
| 371 | 371 | ||
| 372 | EVP_PKEY_up_ref(pk); | 372 | EVP_PKEY_up_ref(pk); |
| 373 | rek->pkey = pk; | 373 | rek->pkey = pk; |
| 374 | return 1; | 374 | return 1; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, | 377 | static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, |
| 378 | const EVP_CIPHER *cipher) | 378 | const EVP_CIPHER *cipher) |
| 379 | { | 379 | { |
| 380 | EVP_CIPHER_CTX *ctx = kari->ctx; | 380 | EVP_CIPHER_CTX *ctx = kari->ctx; |
| 381 | const EVP_CIPHER *kekcipher; | 381 | const EVP_CIPHER *kekcipher; |
| 382 | int keylen = EVP_CIPHER_key_length(cipher); | 382 | int keylen = EVP_CIPHER_key_length(cipher); |
| 383 | /* If a suitable wrap algorithm is already set nothing to do */ | 383 | /* If a suitable wrap algorithm is already set nothing to do */ |
| 384 | kekcipher = EVP_CIPHER_CTX_cipher(ctx); | 384 | kekcipher = EVP_CIPHER_CTX_cipher(ctx); |
| 385 | 385 | ||
| 386 | if (kekcipher) { | 386 | if (kekcipher) { |
| 387 | if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) | 387 | if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) |
| 388 | return 0; | 388 | return 0; |
| 389 | return 1; | 389 | return 1; |
| 390 | } | 390 | } |
| 391 | /* | 391 | /* |
| 392 | * Pick a cipher based on content encryption cipher. If it is DES3 use | 392 | * Pick a cipher based on content encryption cipher. If it is DES3 use |
| 393 | * DES3 wrap otherwise use AES wrap similar to key size. | 393 | * DES3 wrap otherwise use AES wrap similar to key size. |
| 394 | */ | 394 | */ |
| 395 | #ifndef OPENSSL_NO_DES | 395 | #ifndef OPENSSL_NO_DES |
| 396 | if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) | 396 | if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) |
| 397 | kekcipher = EVP_des_ede3_wrap(); | 397 | kekcipher = EVP_des_ede3_wrap(); |
| 398 | else | 398 | else |
| 399 | #endif | 399 | #endif |
| 400 | if (keylen <= 16) | 400 | if (keylen <= 16) |
| 401 | kekcipher = EVP_aes_128_wrap(); | 401 | kekcipher = EVP_aes_128_wrap(); |
| 402 | else if (keylen <= 24) | 402 | else if (keylen <= 24) |
| 403 | kekcipher = EVP_aes_192_wrap(); | 403 | kekcipher = EVP_aes_192_wrap(); |
| 404 | else | 404 | else |
| 405 | kekcipher = EVP_aes_256_wrap(); | 405 | kekcipher = EVP_aes_256_wrap(); |
| 406 | return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); | 406 | return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | /* Encrypt content key in key agreement recipient info */ | 409 | /* Encrypt content key in key agreement recipient info */ |
| 410 | 410 | ||
| 411 | int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, | 411 | int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, |
| 412 | CMS_RecipientInfo *ri) | 412 | CMS_RecipientInfo *ri) |
| 413 | { | 413 | { |
| 414 | CMS_KeyAgreeRecipientInfo *kari; | 414 | CMS_KeyAgreeRecipientInfo *kari; |
| 415 | CMS_EncryptedContentInfo *ec; | 415 | CMS_EncryptedContentInfo *ec; |
| 416 | CMS_RecipientEncryptedKey *rek; | 416 | CMS_RecipientEncryptedKey *rek; |
| 417 | STACK_OF(CMS_RecipientEncryptedKey) *reks; | 417 | STACK_OF(CMS_RecipientEncryptedKey) *reks; |
| 418 | int i; | 418 | int i; |
| 419 | 419 | ||
| 420 | if (ri->type != CMS_RECIPINFO_AGREE) { | 420 | if (ri->type != CMS_RECIPINFO_AGREE) { |
| 421 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); | 421 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); |
| 422 | return 0; | 422 | return 0; |
| 423 | } | 423 | } |
| 424 | kari = ri->d.kari; | 424 | kari = ri->d.kari; |
| 425 | reks = kari->recipientEncryptedKeys; | 425 | reks = kari->recipientEncryptedKeys; |
| 426 | ec = cms->d.envelopedData->encryptedContentInfo; | 426 | ec = cms->d.envelopedData->encryptedContentInfo; |
| 427 | /* Initialise wrap algorithm parameters */ | 427 | /* Initialise wrap algorithm parameters */ |
| 428 | if (!cms_wrap_init(kari, ec->cipher)) | 428 | if (!cms_wrap_init(kari, ec->cipher)) |
| 429 | return 0; | 429 | return 0; |
| 430 | /* | 430 | /* |
| 431 | * If no originator key set up initialise for ephemeral key the public key | 431 | * If no originator key set up initialise for ephemeral key the public key |
| 432 | * ASN1 structure will set the actual public key value. | 432 | * ASN1 structure will set the actual public key value. |
| 433 | */ | 433 | */ |
| 434 | if (kari->originator->type == -1) { | 434 | if (kari->originator->type == -1) { |
| 435 | CMS_OriginatorIdentifierOrKey *oik = kari->originator; | 435 | CMS_OriginatorIdentifierOrKey *oik = kari->originator; |
| 436 | oik->type = CMS_OIK_PUBKEY; | 436 | oik->type = CMS_OIK_PUBKEY; |
| 437 | oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); | 437 | oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); |
| 438 | if (!oik->d.originatorKey) | 438 | if (!oik->d.originatorKey) |
| 439 | return 0; | 439 | return 0; |
| 440 | } | 440 | } |
| 441 | /* Initialise KDF algorithm */ | 441 | /* Initialise KDF algorithm */ |
| 442 | if (!cms_env_asn1_ctrl(ri, 0)) | 442 | if (!cms_env_asn1_ctrl(ri, 0)) |
| 443 | return 0; | 443 | return 0; |
| 444 | /* For each rek, derive KEK, encrypt CEK */ | 444 | /* For each rek, derive KEK, encrypt CEK */ |
| 445 | for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { | 445 | for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { |
| 446 | unsigned char *enckey; | 446 | unsigned char *enckey; |
| 447 | size_t enckeylen; | 447 | size_t enckeylen; |
| 448 | rek = sk_CMS_RecipientEncryptedKey_value(reks, i); | 448 | rek = sk_CMS_RecipientEncryptedKey_value(reks, i); |
| 449 | if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) | 449 | if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) |
| 450 | return 0; | 450 | return 0; |
| 451 | if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, | 451 | if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, |
| 452 | kari, 1)) | 452 | kari, 1)) |
| 453 | return 0; | 453 | return 0; |
| 454 | ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); | 454 | ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | return 1; | 457 | return 1; |
| 458 | 458 | ||
| 459 | } | 459 | } |
