]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
33388b44 | 2 | * Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. |
17c2764d | 3 | * |
08ddd302 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
17c2764d DSH |
8 | */ |
9 | ||
41bbba53 P |
10 | /* |
11 | * Low level key APIs (DH etc) are deprecated for public use, but still ok for | |
12 | * internal use. | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
b39fc560 | 16 | #include "internal/cryptlib.h" |
17c2764d DSH |
17 | #include <openssl/asn1t.h> |
18 | #include <openssl/pem.h> | |
19 | #include <openssl/x509v3.h> | |
20 | #include <openssl/err.h> | |
21 | #include <openssl/cms.h> | |
17c2764d | 22 | #include <openssl/aes.h> |
706457b7 | 23 | #include "cms_local.h" |
25f2138b | 24 | #include "crypto/asn1.h" |
17c2764d | 25 | |
852c2ed2 RS |
26 | DEFINE_STACK_OF(CMS_RecipientEncryptedKey) |
27 | ||
17c2764d DSH |
28 | /* Key Agreement Recipient Info (KARI) routines */ |
29 | ||
30 | int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, | |
0f113f3e MC |
31 | X509_ALGOR **palg, |
32 | ASN1_OCTET_STRING **pukm) | |
33 | { | |
34 | if (ri->type != CMS_RECIPINFO_AGREE) { | |
35 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, | |
36 | CMS_R_NOT_KEY_AGREEMENT); | |
37 | return 0; | |
38 | } | |
39 | if (palg) | |
40 | *palg = ri->d.kari->keyEncryptionAlgorithm; | |
41 | if (pukm) | |
42 | *pukm = ri->d.kari->ukm; | |
43 | return 1; | |
44 | } | |
17c2764d DSH |
45 | |
46 | /* Retrieve recipient encrypted keys from a kari */ | |
47 | ||
0f113f3e MC |
48 | STACK_OF(CMS_RecipientEncryptedKey) |
49 | *CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri) | |
50 | { | |
51 | if (ri->type != CMS_RECIPINFO_AGREE) { | |
52 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, | |
53 | CMS_R_NOT_KEY_AGREEMENT); | |
54 | return NULL; | |
55 | } | |
56 | return ri->d.kari->recipientEncryptedKeys; | |
57 | } | |
17c2764d DSH |
58 | |
59 | int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, | |
0f113f3e MC |
60 | X509_ALGOR **pubalg, |
61 | ASN1_BIT_STRING **pubkey, | |
62 | ASN1_OCTET_STRING **keyid, | |
63 | X509_NAME **issuer, | |
64 | ASN1_INTEGER **sno) | |
65 | { | |
66 | CMS_OriginatorIdentifierOrKey *oik; | |
c1669f41 | 67 | |
0f113f3e MC |
68 | if (ri->type != CMS_RECIPINFO_AGREE) { |
69 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, | |
70 | CMS_R_NOT_KEY_AGREEMENT); | |
71 | return 0; | |
72 | } | |
73 | oik = ri->d.kari->originator; | |
74 | if (issuer) | |
75 | *issuer = NULL; | |
76 | if (sno) | |
77 | *sno = NULL; | |
78 | if (keyid) | |
79 | *keyid = NULL; | |
80 | if (pubalg) | |
81 | *pubalg = NULL; | |
82 | if (pubkey) | |
83 | *pubkey = NULL; | |
84 | if (oik->type == CMS_OIK_ISSUER_SERIAL) { | |
85 | if (issuer) | |
86 | *issuer = oik->d.issuerAndSerialNumber->issuer; | |
87 | if (sno) | |
88 | *sno = oik->d.issuerAndSerialNumber->serialNumber; | |
89 | } else if (oik->type == CMS_OIK_KEYIDENTIFIER) { | |
90 | if (keyid) | |
91 | *keyid = oik->d.subjectKeyIdentifier; | |
92 | } else if (oik->type == CMS_OIK_PUBKEY) { | |
93 | if (pubalg) | |
94 | *pubalg = oik->d.originatorKey->algorithm; | |
95 | if (pubkey) | |
96 | *pubkey = oik->d.originatorKey->publicKey; | |
97 | } else | |
98 | return 0; | |
99 | return 1; | |
100 | } | |
17c2764d DSH |
101 | |
102 | int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert) | |
0f113f3e MC |
103 | { |
104 | CMS_OriginatorIdentifierOrKey *oik; | |
c1669f41 | 105 | |
0f113f3e MC |
106 | if (ri->type != CMS_RECIPINFO_AGREE) { |
107 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, | |
108 | CMS_R_NOT_KEY_AGREEMENT); | |
109 | return -2; | |
110 | } | |
111 | oik = ri->d.kari->originator; | |
112 | if (oik->type == CMS_OIK_ISSUER_SERIAL) | |
113 | return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert); | |
114 | else if (oik->type == CMS_OIK_KEYIDENTIFIER) | |
115 | return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert); | |
116 | return -1; | |
117 | } | |
17c2764d DSH |
118 | |
119 | int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, | |
0f113f3e MC |
120 | ASN1_OCTET_STRING **keyid, |
121 | ASN1_GENERALIZEDTIME **tm, | |
122 | CMS_OtherKeyAttribute **other, | |
123 | X509_NAME **issuer, ASN1_INTEGER **sno) | |
124 | { | |
125 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; | |
c1669f41 | 126 | |
0f113f3e MC |
127 | if (rid->type == CMS_REK_ISSUER_SERIAL) { |
128 | if (issuer) | |
129 | *issuer = rid->d.issuerAndSerialNumber->issuer; | |
130 | if (sno) | |
131 | *sno = rid->d.issuerAndSerialNumber->serialNumber; | |
132 | if (keyid) | |
133 | *keyid = NULL; | |
134 | if (tm) | |
135 | *tm = NULL; | |
136 | if (other) | |
137 | *other = NULL; | |
138 | } else if (rid->type == CMS_REK_KEYIDENTIFIER) { | |
139 | if (keyid) | |
140 | *keyid = rid->d.rKeyId->subjectKeyIdentifier; | |
141 | if (tm) | |
142 | *tm = rid->d.rKeyId->date; | |
143 | if (other) | |
144 | *other = rid->d.rKeyId->other; | |
145 | if (issuer) | |
146 | *issuer = NULL; | |
147 | if (sno) | |
148 | *sno = NULL; | |
149 | } else | |
150 | return 0; | |
151 | return 1; | |
152 | } | |
17c2764d DSH |
153 | |
154 | int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, | |
0f113f3e MC |
155 | X509 *cert) |
156 | { | |
157 | CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; | |
c1669f41 | 158 | |
0f113f3e MC |
159 | if (rid->type == CMS_REK_ISSUER_SERIAL) |
160 | return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert); | |
161 | else if (rid->type == CMS_REK_KEYIDENTIFIER) | |
162 | return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert); | |
163 | else | |
164 | return -1; | |
165 | } | |
17c2764d | 166 | |
71434aed | 167 | int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *pk, X509 *peer) |
0f113f3e MC |
168 | { |
169 | EVP_PKEY_CTX *pctx; | |
170 | CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; | |
25aaa98a RS |
171 | |
172 | EVP_PKEY_CTX_free(kari->pctx); | |
173 | kari->pctx = NULL; | |
12a765a5 | 174 | if (pk == NULL) |
0f113f3e | 175 | return 1; |
71434aed | 176 | |
c1669f41 SL |
177 | pctx = EVP_PKEY_CTX_new_from_pkey(kari->cms_ctx->libctx, pk, |
178 | kari->cms_ctx->propq); | |
12a765a5 | 179 | if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0) |
0f113f3e | 180 | goto err; |
71434aed DB |
181 | |
182 | if (peer != NULL) { | |
183 | EVP_PKEY *pub_pkey = X509_get0_pubkey(peer); | |
184 | ||
185 | if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0) | |
186 | goto err; | |
187 | } | |
188 | ||
0f113f3e MC |
189 | kari->pctx = pctx; |
190 | return 1; | |
191 | err: | |
c5ba2d99 | 192 | EVP_PKEY_CTX_free(pctx); |
0f113f3e MC |
193 | return 0; |
194 | } | |
17c2764d | 195 | |
71434aed DB |
196 | int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) |
197 | { | |
198 | return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL); | |
199 | } | |
200 | ||
17c2764d | 201 | EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) |
0f113f3e MC |
202 | { |
203 | if (ri->type == CMS_RECIPINFO_AGREE) | |
846ec07d | 204 | return ri->d.kari->ctx; |
0f113f3e MC |
205 | return NULL; |
206 | } | |
207 | ||
208 | /* | |
209 | * Derive KEK and decrypt/encrypt with it to produce either the original CEK | |
210 | * or the encrypted CEK. | |
17c2764d DSH |
211 | */ |
212 | ||
0f113f3e MC |
213 | static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, |
214 | const unsigned char *in, size_t inlen, | |
215 | CMS_KeyAgreeRecipientInfo *kari, int enc) | |
216 | { | |
217 | /* Key encryption key */ | |
218 | unsigned char kek[EVP_MAX_KEY_LENGTH]; | |
219 | size_t keklen; | |
220 | int rv = 0; | |
221 | unsigned char *out = NULL; | |
222 | int outlen; | |
c1669f41 | 223 | |
846ec07d | 224 | keklen = EVP_CIPHER_CTX_key_length(kari->ctx); |
0f113f3e MC |
225 | if (keklen > EVP_MAX_KEY_LENGTH) |
226 | return 0; | |
227 | /* Derive KEK */ | |
228 | if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) | |
229 | goto err; | |
230 | /* Set KEK in context */ | |
846ec07d | 231 | if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) |
0f113f3e MC |
232 | goto err; |
233 | /* obtain output length of ciphered key */ | |
846ec07d | 234 | if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) |
0f113f3e MC |
235 | goto err; |
236 | out = OPENSSL_malloc(outlen); | |
90945fa3 | 237 | if (out == NULL) |
0f113f3e | 238 | goto err; |
846ec07d | 239 | if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) |
0f113f3e MC |
240 | goto err; |
241 | *pout = out; | |
242 | *poutlen = (size_t)outlen; | |
243 | rv = 1; | |
244 | ||
245 | err: | |
246 | OPENSSL_cleanse(kek, keklen); | |
b548a1f1 | 247 | if (!rv) |
0f113f3e | 248 | OPENSSL_free(out); |
846ec07d RL |
249 | EVP_CIPHER_CTX_reset(kari->ctx); |
250 | /* FIXME: WHY IS kari->pctx freed here? /RL */ | |
0f113f3e MC |
251 | EVP_PKEY_CTX_free(kari->pctx); |
252 | kari->pctx = NULL; | |
253 | return rv; | |
254 | } | |
255 | ||
256 | int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, | |
257 | CMS_RecipientInfo *ri, | |
258 | CMS_RecipientEncryptedKey *rek) | |
259 | { | |
260 | int rv = 0; | |
261 | unsigned char *enckey = NULL, *cek = NULL; | |
262 | size_t enckeylen; | |
263 | size_t ceklen; | |
264 | CMS_EncryptedContentInfo *ec; | |
aec8de1a RL |
265 | |
266 | { | |
267 | /* | |
268 | * TODO(3.0) Remove this when we have functionality to deserialize | |
269 | * parameters in EVP_PKEY form from an X509_ALGOR. | |
270 | * This is needed to be able to replace the EC_KEY specific decoding | |
271 | * that happens in ecdh_cms_set_peerkey() (crypto/ec/ec_ameth.c) | |
272 | * | |
273 | * THIS IS TEMPORARY | |
274 | */ | |
275 | EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); | |
276 | EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); | |
277 | ||
278 | EVP_PKEY_get0(pkey); | |
279 | if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) { | |
280 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT, | |
281 | CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
282 | goto err; | |
283 | } | |
284 | } | |
285 | ||
0f113f3e MC |
286 | enckeylen = rek->encryptedKey->length; |
287 | enckey = rek->encryptedKey->data; | |
288 | /* Setup all parameters to derive KEK */ | |
289 | if (!cms_env_asn1_ctrl(ri, 1)) | |
290 | goto err; | |
291 | /* Attempt to decrypt CEK */ | |
292 | if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0)) | |
293 | goto err; | |
924663c3 | 294 | ec = cms_get0_env_enc_content(cms); |
4b45c6e5 | 295 | OPENSSL_clear_free(ec->key, ec->keylen); |
0f113f3e MC |
296 | ec->key = cek; |
297 | ec->keylen = ceklen; | |
298 | cek = NULL; | |
299 | rv = 1; | |
300 | err: | |
b548a1f1 | 301 | OPENSSL_free(cek); |
0f113f3e MC |
302 | return rv; |
303 | } | |
17c2764d DSH |
304 | |
305 | /* Create ephemeral key and initialise context based on it */ | |
306 | static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, | |
0f113f3e MC |
307 | EVP_PKEY *pk) |
308 | { | |
309 | EVP_PKEY_CTX *pctx = NULL; | |
310 | EVP_PKEY *ekey = NULL; | |
311 | int rv = 0; | |
c1669f41 | 312 | const CMS_CTX *ctx = kari->cms_ctx; |
12a765a5 | 313 | |
c1669f41 | 314 | pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pk, ctx->propq); |
12a765a5 | 315 | if (pctx == NULL) |
0f113f3e MC |
316 | goto err; |
317 | if (EVP_PKEY_keygen_init(pctx) <= 0) | |
318 | goto err; | |
319 | if (EVP_PKEY_keygen(pctx, &ekey) <= 0) | |
320 | goto err; | |
321 | EVP_PKEY_CTX_free(pctx); | |
c1669f41 | 322 | pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ekey, ctx->propq); |
12a765a5 | 323 | if (pctx == NULL) |
0f113f3e MC |
324 | goto err; |
325 | if (EVP_PKEY_derive_init(pctx) <= 0) | |
326 | goto err; | |
327 | kari->pctx = pctx; | |
328 | rv = 1; | |
329 | err: | |
c5ba2d99 | 330 | if (!rv) |
0f113f3e | 331 | EVP_PKEY_CTX_free(pctx); |
c5ba2d99 | 332 | EVP_PKEY_free(ekey); |
0f113f3e MC |
333 | return rv; |
334 | } | |
17c2764d | 335 | |
71434aed | 336 | /* Set originator private key and initialise context based on it */ |
c1669f41 SL |
337 | static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari, |
338 | EVP_PKEY *originatorPrivKey ) | |
71434aed DB |
339 | { |
340 | EVP_PKEY_CTX *pctx = NULL; | |
341 | int rv = 0; | |
c1669f41 | 342 | const CMS_CTX *ctx = kari->cms_ctx; |
71434aed | 343 | |
c1669f41 | 344 | pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, originatorPrivKey, ctx->propq); |
71434aed DB |
345 | if (pctx == NULL) |
346 | goto err; | |
347 | if (EVP_PKEY_derive_init(pctx) <= 0) | |
348 | goto err; | |
349 | ||
350 | kari->pctx = pctx; | |
351 | rv = 1; | |
352 | err: | |
353 | if (rv == 0) | |
354 | EVP_PKEY_CTX_free(pctx); | |
355 | return rv; | |
356 | } | |
357 | ||
b754a8a1 | 358 | /* Initialise a kari based on passed certificate and key */ |
17c2764d | 359 | |
c1669f41 SL |
360 | int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, |
361 | EVP_PKEY *recipPubKey, X509 *originator, | |
362 | EVP_PKEY *originatorPrivKey, unsigned int flags, | |
363 | const CMS_CTX *ctx) | |
0f113f3e MC |
364 | { |
365 | CMS_KeyAgreeRecipientInfo *kari; | |
366 | CMS_RecipientEncryptedKey *rek = NULL; | |
367 | ||
368 | ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); | |
c1669f41 | 369 | if (ri->d.kari == NULL) |
0f113f3e MC |
370 | return 0; |
371 | ri->type = CMS_RECIPINFO_AGREE; | |
372 | ||
373 | kari = ri->d.kari; | |
374 | kari->version = 3; | |
c1669f41 | 375 | kari->cms_ctx = ctx; |
0f113f3e MC |
376 | |
377 | rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); | |
b754a8a1 DD |
378 | if (rek == NULL) |
379 | return 0; | |
380 | ||
0f113f3e MC |
381 | if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { |
382 | M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); | |
383 | return 0; | |
384 | } | |
385 | ||
386 | if (flags & CMS_USE_KEYID) { | |
387 | rek->rid->type = CMS_REK_KEYIDENTIFIER; | |
7a317fa0 DSH |
388 | rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); |
389 | if (rek->rid->d.rKeyId == NULL) | |
390 | return 0; | |
0f113f3e MC |
391 | if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) |
392 | return 0; | |
393 | } else { | |
394 | rek->rid->type = CMS_REK_ISSUER_SERIAL; | |
395 | if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) | |
396 | return 0; | |
397 | } | |
398 | ||
71434aed DB |
399 | if (originatorPrivKey == NULL && originator == NULL) { |
400 | /* Create ephemeral key */ | |
401 | if (!cms_kari_create_ephemeral_key(kari, recipPubKey)) | |
402 | return 0; | |
403 | } else { | |
1f74259d P |
404 | /* Use originator key */ |
405 | CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator; | |
71434aed | 406 | |
1f74259d | 407 | if (originatorPrivKey == NULL || originator == NULL) |
71434aed | 408 | return 0; |
0f113f3e | 409 | |
1f74259d P |
410 | if (flags & CMS_USE_ORIGINATOR_KEYID) { |
411 | oik->type = CMS_OIK_KEYIDENTIFIER; | |
412 | oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new(); | |
413 | if (oik->d.subjectKeyIdentifier == NULL) | |
414 | return 0; | |
415 | if (!cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator)) | |
416 | return 0; | |
417 | } else { | |
418 | oik->type = CMS_REK_ISSUER_SERIAL; | |
419 | if (!cms_set1_ias(&oik->d.issuerAndSerialNumber, originator)) | |
420 | return 0; | |
421 | } | |
422 | ||
423 | if (!cms_kari_set_originator_private_key(kari, originatorPrivKey)) | |
424 | return 0; | |
71434aed DB |
425 | } |
426 | ||
427 | EVP_PKEY_up_ref(recipPubKey); | |
428 | rek->pkey = recipPubKey; | |
0f113f3e MC |
429 | return 1; |
430 | } | |
17c2764d DSH |
431 | |
432 | static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, | |
0f113f3e MC |
433 | const EVP_CIPHER *cipher) |
434 | { | |
c1669f41 | 435 | const CMS_CTX *cms_ctx = kari->cms_ctx; |
846ec07d | 436 | EVP_CIPHER_CTX *ctx = kari->ctx; |
0f113f3e | 437 | const EVP_CIPHER *kekcipher; |
c1669f41 SL |
438 | EVP_CIPHER *fetched_kekcipher; |
439 | const char *kekcipher_name; | |
3e47e7b4 | 440 | int keylen; |
71434aed DB |
441 | int ret; |
442 | ||
0f113f3e MC |
443 | /* If a suitable wrap algorithm is already set nothing to do */ |
444 | kekcipher = EVP_CIPHER_CTX_cipher(ctx); | |
71434aed | 445 | if (kekcipher != NULL) { |
0f113f3e MC |
446 | if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) |
447 | return 0; | |
448 | return 1; | |
449 | } | |
3e47e7b4 P |
450 | if (cipher == NULL) |
451 | return 0; | |
452 | keylen = EVP_CIPHER_key_length(cipher); | |
453 | if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) { | |
41bbba53 | 454 | /* TODO: make this not get a method we can call directly */ |
71434aed DB |
455 | ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER, |
456 | 0, &kekcipher); | |
457 | if (ret <= 0) | |
458 | return 0; | |
459 | ||
460 | if (kekcipher != NULL) { | |
461 | if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) | |
462 | return 0; | |
c1669f41 SL |
463 | kekcipher_name = EVP_CIPHER_name(kekcipher); |
464 | goto enc; | |
71434aed DB |
465 | } |
466 | } | |
467 | ||
0f113f3e MC |
468 | /* |
469 | * Pick a cipher based on content encryption cipher. If it is DES3 use | |
470 | * DES3 wrap otherwise use AES wrap similar to key size. | |
471 | */ | |
96bea000 | 472 | #ifndef OPENSSL_NO_DES |
0f113f3e | 473 | if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) |
c1669f41 | 474 | kekcipher_name = SN_id_smime_alg_CMS3DESwrap; |
96bea000 MC |
475 | else |
476 | #endif | |
477 | if (keylen <= 16) | |
c1669f41 | 478 | kekcipher_name = SN_id_aes128_wrap; |
0f113f3e | 479 | else if (keylen <= 24) |
c1669f41 | 480 | kekcipher_name = SN_id_aes192_wrap; |
0f113f3e | 481 | else |
c1669f41 SL |
482 | kekcipher_name = SN_id_aes256_wrap; |
483 | enc: | |
484 | fetched_kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, kekcipher_name, | |
485 | cms_ctx->propq); | |
486 | if (fetched_kekcipher == NULL) | |
487 | return 0; | |
488 | ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL); | |
489 | EVP_CIPHER_free(fetched_kekcipher); | |
490 | return ret; | |
0f113f3e | 491 | } |
17c2764d DSH |
492 | |
493 | /* Encrypt content key in key agreement recipient info */ | |
494 | ||
9fdcc21f | 495 | int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms, |
0f113f3e MC |
496 | CMS_RecipientInfo *ri) |
497 | { | |
498 | CMS_KeyAgreeRecipientInfo *kari; | |
499 | CMS_EncryptedContentInfo *ec; | |
500 | CMS_RecipientEncryptedKey *rek; | |
501 | STACK_OF(CMS_RecipientEncryptedKey) *reks; | |
502 | int i; | |
503 | ||
aec8de1a RL |
504 | { |
505 | /* | |
506 | * TODO(3.0) Remove this when we have figured out all the details | |
507 | * need to set up encryption right. With legacy keys, a *lot* is | |
508 | * happening in the CMS specific EVP_PKEY_ASN1_METHOD functions, | |
509 | * such as automatically setting a default KDF type, KDF digest, | |
510 | * all that kind of stuff. | |
511 | * With EVP_SIGNATURE, setting a default digest is done by getting | |
512 | * the default MD for the key, and then inject that back into the | |
513 | * signature implementation... we could do something similar with | |
514 | * CMS, possibly using CMS specific OSSL_PARAM keys, just like we | |
515 | * have for certain AlgorithmIdentifier retrievals. | |
516 | * | |
517 | * THIS IS TEMPORARY | |
518 | */ | |
519 | EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); | |
520 | EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); | |
521 | ||
522 | EVP_PKEY_get0(pkey); | |
523 | if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) { | |
524 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, | |
525 | CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
526 | return 0; | |
527 | } | |
528 | } | |
529 | ||
0f113f3e MC |
530 | if (ri->type != CMS_RECIPINFO_AGREE) { |
531 | CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); | |
532 | return 0; | |
533 | } | |
534 | kari = ri->d.kari; | |
535 | reks = kari->recipientEncryptedKeys; | |
924663c3 | 536 | ec = cms_get0_env_enc_content(cms); |
0f113f3e MC |
537 | /* Initialise wrap algorithm parameters */ |
538 | if (!cms_wrap_init(kari, ec->cipher)) | |
539 | return 0; | |
540 | /* | |
0d4fb843 | 541 | * If no originator key set up initialise for ephemeral key the public key |
0f113f3e MC |
542 | * ASN1 structure will set the actual public key value. |
543 | */ | |
544 | if (kari->originator->type == -1) { | |
545 | CMS_OriginatorIdentifierOrKey *oik = kari->originator; | |
546 | oik->type = CMS_OIK_PUBKEY; | |
547 | oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); | |
548 | if (!oik->d.originatorKey) | |
549 | return 0; | |
550 | } | |
551 | /* Initialise KDF algorithm */ | |
552 | if (!cms_env_asn1_ctrl(ri, 0)) | |
553 | return 0; | |
554 | /* For each rek, derive KEK, encrypt CEK */ | |
555 | for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { | |
556 | unsigned char *enckey; | |
557 | size_t enckeylen; | |
558 | rek = sk_CMS_RecipientEncryptedKey_value(reks, i); | |
559 | if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) | |
560 | return 0; | |
561 | if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, | |
562 | kari, 1)) | |
563 | return 0; | |
564 | ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); | |
565 | } | |
566 | ||
567 | return 1; | |
0f113f3e | 568 | } |