diff options
author | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
---|---|---|
committer | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
commit | eb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch) | |
tree | edb6da6af7e865d488dc1a29309f1e1ec226e603 /src/lib/libcrypto/cms/cms_env.c | |
parent | 247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff) | |
download | openbsd-tb_20250414.tar.gz openbsd-tb_20250414.tar.bz2 openbsd-tb_20250414.zip |
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/lib/libcrypto/cms/cms_env.c')
-rw-r--r-- | src/lib/libcrypto/cms/cms_env.c | 996 |
1 files changed, 0 insertions, 996 deletions
diff --git a/src/lib/libcrypto/cms/cms_env.c b/src/lib/libcrypto/cms/cms_env.c deleted file mode 100644 index 629d23215e..0000000000 --- a/src/lib/libcrypto/cms/cms_env.c +++ /dev/null | |||
@@ -1,996 +0,0 @@ | |||
1 | /* $OpenBSD: cms_env.c,v 1.28 2024/11/01 18:42:10 tb Exp $ */ | ||
2 | /* | ||
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | ||
4 | * project. | ||
5 | */ | ||
6 | /* ==================================================================== | ||
7 | * Copyright (c) 2008 The OpenSSL Project. All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer. | ||
15 | * | ||
16 | * 2. Redistributions in binary form must reproduce the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer in | ||
18 | * the documentation and/or other materials provided with the | ||
19 | * distribution. | ||
20 | * | ||
21 | * 3. All advertising materials mentioning features or use of this | ||
22 | * software must display the following acknowledgment: | ||
23 | * "This product includes software developed by the OpenSSL Project | ||
24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | ||
25 | * | ||
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
27 | * endorse or promote products derived from this software without | ||
28 | * prior written permission. For written permission, please contact | ||
29 | * licensing@OpenSSL.org. | ||
30 | * | ||
31 | * 5. Products derived from this software may not be called "OpenSSL" | ||
32 | * nor may "OpenSSL" appear in their names without prior written | ||
33 | * permission of the OpenSSL Project. | ||
34 | * | ||
35 | * 6. Redistributions of any form whatsoever must retain the following | ||
36 | * acknowledgment: | ||
37 | * "This product includes software developed by the OpenSSL Project | ||
38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | ||
39 | * | ||
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
52 | * ==================================================================== | ||
53 | */ | ||
54 | |||
55 | #include <stdlib.h> | ||
56 | #include <string.h> | ||
57 | |||
58 | #include <openssl/aes.h> | ||
59 | #include <openssl/asn1.h> | ||
60 | #include <openssl/bio.h> | ||
61 | #include <openssl/cms.h> | ||
62 | #include <openssl/err.h> | ||
63 | #include <openssl/evp.h> | ||
64 | #include <openssl/objects.h> | ||
65 | #include <openssl/x509.h> | ||
66 | |||
67 | #include "cms_local.h" | ||
68 | #include "evp_local.h" | ||
69 | |||
70 | /* CMS EnvelopedData Utilities */ | ||
71 | |||
72 | CMS_EnvelopedData * | ||
73 | cms_get0_enveloped(CMS_ContentInfo *cms) | ||
74 | { | ||
75 | if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { | ||
76 | CMSerror(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); | ||
77 | return NULL; | ||
78 | } | ||
79 | return cms->d.envelopedData; | ||
80 | } | ||
81 | |||
82 | static CMS_EnvelopedData * | ||
83 | cms_enveloped_data_init(CMS_ContentInfo *cms) | ||
84 | { | ||
85 | if (cms->d.other == NULL) { | ||
86 | cms->d.envelopedData = (CMS_EnvelopedData *)ASN1_item_new(&CMS_EnvelopedData_it); | ||
87 | if (!cms->d.envelopedData) { | ||
88 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
89 | return NULL; | ||
90 | } | ||
91 | cms->d.envelopedData->version = 0; | ||
92 | cms->d.envelopedData->encryptedContentInfo->contentType = | ||
93 | OBJ_nid2obj(NID_pkcs7_data); | ||
94 | ASN1_OBJECT_free(cms->contentType); | ||
95 | cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); | ||
96 | return cms->d.envelopedData; | ||
97 | } | ||
98 | return cms_get0_enveloped(cms); | ||
99 | } | ||
100 | |||
101 | int | ||
102 | cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd) | ||
103 | { | ||
104 | EVP_PKEY *pkey; | ||
105 | int i; | ||
106 | |||
107 | if (ri->type == CMS_RECIPINFO_TRANS) | ||
108 | pkey = ri->d.ktri->pkey; | ||
109 | else if (ri->type == CMS_RECIPINFO_AGREE) { | ||
110 | EVP_PKEY_CTX *pctx = ri->d.kari->pctx; | ||
111 | if (!pctx) | ||
112 | return 0; | ||
113 | pkey = EVP_PKEY_CTX_get0_pkey(pctx); | ||
114 | if (!pkey) | ||
115 | return 0; | ||
116 | } else | ||
117 | return 0; | ||
118 | if (!pkey->ameth || !pkey->ameth->pkey_ctrl) | ||
119 | return 1; | ||
120 | i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri); | ||
121 | if (i == -2) { | ||
122 | CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | ||
123 | return 0; | ||
124 | } | ||
125 | if (i <= 0) { | ||
126 | CMSerror(CMS_R_CTRL_FAILURE); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | STACK_OF(CMS_RecipientInfo) * | ||
134 | CMS_get0_RecipientInfos(CMS_ContentInfo *cms) | ||
135 | { | ||
136 | CMS_EnvelopedData *env; | ||
137 | |||
138 | env = cms_get0_enveloped(cms); | ||
139 | if (!env) | ||
140 | return NULL; | ||
141 | |||
142 | return env->recipientInfos; | ||
143 | } | ||
144 | LCRYPTO_ALIAS(CMS_get0_RecipientInfos); | ||
145 | |||
146 | int | ||
147 | CMS_RecipientInfo_type(CMS_RecipientInfo *ri) | ||
148 | { | ||
149 | return ri->type; | ||
150 | } | ||
151 | LCRYPTO_ALIAS(CMS_RecipientInfo_type); | ||
152 | |||
153 | EVP_PKEY_CTX * | ||
154 | CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri) | ||
155 | { | ||
156 | if (ri->type == CMS_RECIPINFO_TRANS) | ||
157 | return ri->d.ktri->pctx; | ||
158 | else if (ri->type == CMS_RECIPINFO_AGREE) | ||
159 | return ri->d.kari->pctx; | ||
160 | |||
161 | return NULL; | ||
162 | } | ||
163 | LCRYPTO_ALIAS(CMS_RecipientInfo_get0_pkey_ctx); | ||
164 | |||
165 | CMS_ContentInfo * | ||
166 | CMS_EnvelopedData_create(const EVP_CIPHER *cipher) | ||
167 | { | ||
168 | CMS_ContentInfo *cms; | ||
169 | CMS_EnvelopedData *env; | ||
170 | |||
171 | cms = CMS_ContentInfo_new(); | ||
172 | if (cms == NULL) | ||
173 | goto merr; | ||
174 | env = cms_enveloped_data_init(cms); | ||
175 | if (env == NULL) | ||
176 | goto merr; | ||
177 | if (!cms_EncryptedContent_init(env->encryptedContentInfo, cipher, | ||
178 | NULL, 0)) | ||
179 | goto merr; | ||
180 | |||
181 | return cms; | ||
182 | |||
183 | merr: | ||
184 | CMS_ContentInfo_free(cms); | ||
185 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
186 | return NULL; | ||
187 | } | ||
188 | LCRYPTO_ALIAS(CMS_EnvelopedData_create); | ||
189 | |||
190 | /* Key Transport Recipient Info (KTRI) routines */ | ||
191 | |||
192 | /* Initialise a ktri based on passed certificate and key */ | ||
193 | |||
194 | static int | ||
195 | cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk, | ||
196 | unsigned int flags) | ||
197 | { | ||
198 | CMS_KeyTransRecipientInfo *ktri; | ||
199 | int idtype; | ||
200 | |||
201 | ri->d.ktri = (CMS_KeyTransRecipientInfo *)ASN1_item_new(&CMS_KeyTransRecipientInfo_it); | ||
202 | if (!ri->d.ktri) | ||
203 | return 0; | ||
204 | ri->type = CMS_RECIPINFO_TRANS; | ||
205 | |||
206 | ktri = ri->d.ktri; | ||
207 | |||
208 | if (flags & CMS_USE_KEYID) { | ||
209 | ktri->version = 2; | ||
210 | idtype = CMS_RECIPINFO_KEYIDENTIFIER; | ||
211 | } else { | ||
212 | ktri->version = 0; | ||
213 | idtype = CMS_RECIPINFO_ISSUER_SERIAL; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Not a typo: RecipientIdentifier and SignerIdentifier are the same | ||
218 | * structure. | ||
219 | */ | ||
220 | |||
221 | if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype)) | ||
222 | return 0; | ||
223 | |||
224 | X509_up_ref(recip); | ||
225 | EVP_PKEY_up_ref(pk); | ||
226 | |||
227 | ktri->pkey = pk; | ||
228 | ktri->recip = recip; | ||
229 | |||
230 | if (flags & CMS_KEY_PARAM) { | ||
231 | ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); | ||
232 | if (ktri->pctx == NULL) | ||
233 | return 0; | ||
234 | if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0) | ||
235 | return 0; | ||
236 | } else if (!cms_env_asn1_ctrl(ri, 0)) | ||
237 | return 0; | ||
238 | |||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * Add a recipient certificate using appropriate type of RecipientInfo | ||
244 | */ | ||
245 | |||
246 | CMS_RecipientInfo * | ||
247 | CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) | ||
248 | { | ||
249 | CMS_RecipientInfo *ri = NULL; | ||
250 | CMS_EnvelopedData *env; | ||
251 | EVP_PKEY *pk = NULL; | ||
252 | |||
253 | env = cms_get0_enveloped(cms); | ||
254 | if (!env) | ||
255 | goto err; | ||
256 | |||
257 | /* Initialize recipient info */ | ||
258 | ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it); | ||
259 | if (!ri) | ||
260 | goto merr; | ||
261 | |||
262 | pk = X509_get0_pubkey(recip); | ||
263 | if (!pk) { | ||
264 | CMSerror(CMS_R_ERROR_GETTING_PUBLIC_KEY); | ||
265 | goto err; | ||
266 | } | ||
267 | |||
268 | switch (cms_pkey_get_ri_type(pk)) { | ||
269 | |||
270 | case CMS_RECIPINFO_TRANS: | ||
271 | if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags)) | ||
272 | goto err; | ||
273 | break; | ||
274 | |||
275 | case CMS_RECIPINFO_AGREE: | ||
276 | if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags)) | ||
277 | goto err; | ||
278 | break; | ||
279 | |||
280 | default: | ||
281 | CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | ||
282 | goto err; | ||
283 | |||
284 | } | ||
285 | |||
286 | if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) | ||
287 | goto merr; | ||
288 | |||
289 | return ri; | ||
290 | |||
291 | merr: | ||
292 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
293 | err: | ||
294 | ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it); | ||
295 | return NULL; | ||
296 | } | ||
297 | LCRYPTO_ALIAS(CMS_add1_recipient_cert); | ||
298 | |||
299 | int | ||
300 | CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, EVP_PKEY **pk, | ||
301 | X509 **recip, X509_ALGOR **palg) | ||
302 | { | ||
303 | CMS_KeyTransRecipientInfo *ktri; | ||
304 | |||
305 | if (ri->type != CMS_RECIPINFO_TRANS) { | ||
306 | CMSerror(CMS_R_NOT_KEY_TRANSPORT); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | ktri = ri->d.ktri; | ||
311 | |||
312 | if (pk) | ||
313 | *pk = ktri->pkey; | ||
314 | if (recip) | ||
315 | *recip = ktri->recip; | ||
316 | if (palg) | ||
317 | *palg = ktri->keyEncryptionAlgorithm; | ||
318 | |||
319 | return 1; | ||
320 | } | ||
321 | LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_get0_algs); | ||
322 | |||
323 | int | ||
324 | CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, | ||
325 | ASN1_OCTET_STRING **keyid, X509_NAME **issuer, ASN1_INTEGER **sno) | ||
326 | { | ||
327 | CMS_KeyTransRecipientInfo *ktri; | ||
328 | |||
329 | if (ri->type != CMS_RECIPINFO_TRANS) { | ||
330 | CMSerror(CMS_R_NOT_KEY_TRANSPORT); | ||
331 | return 0; | ||
332 | } | ||
333 | ktri = ri->d.ktri; | ||
334 | |||
335 | return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno); | ||
336 | } | ||
337 | LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_get0_signer_id); | ||
338 | |||
339 | int | ||
340 | CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) | ||
341 | { | ||
342 | if (ri->type != CMS_RECIPINFO_TRANS) { | ||
343 | CMSerror(CMS_R_NOT_KEY_TRANSPORT); | ||
344 | return -2; | ||
345 | } | ||
346 | |||
347 | return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); | ||
348 | } | ||
349 | LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_cert_cmp); | ||
350 | |||
351 | int | ||
352 | CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) | ||
353 | { | ||
354 | if (ri->type != CMS_RECIPINFO_TRANS) { | ||
355 | CMSerror(CMS_R_NOT_KEY_TRANSPORT); | ||
356 | return 0; | ||
357 | } | ||
358 | EVP_PKEY_free(ri->d.ktri->pkey); | ||
359 | ri->d.ktri->pkey = pkey; | ||
360 | |||
361 | return 1; | ||
362 | } | ||
363 | LCRYPTO_ALIAS(CMS_RecipientInfo_set0_pkey); | ||
364 | |||
365 | /* Encrypt content key in key transport recipient info */ | ||
366 | |||
367 | static int | ||
368 | cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
369 | { | ||
370 | CMS_KeyTransRecipientInfo *ktri; | ||
371 | CMS_EncryptedContentInfo *ec; | ||
372 | EVP_PKEY_CTX *pctx; | ||
373 | unsigned char *ek = NULL; | ||
374 | size_t eklen; | ||
375 | |||
376 | int ret = 0; | ||
377 | |||
378 | if (ri->type != CMS_RECIPINFO_TRANS) { | ||
379 | CMSerror(CMS_R_NOT_KEY_TRANSPORT); | ||
380 | return 0; | ||
381 | } | ||
382 | ktri = ri->d.ktri; | ||
383 | ec = cms->d.envelopedData->encryptedContentInfo; | ||
384 | |||
385 | pctx = ktri->pctx; | ||
386 | |||
387 | if (pctx) { | ||
388 | if (!cms_env_asn1_ctrl(ri, 0)) | ||
389 | goto err; | ||
390 | } else { | ||
391 | pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); | ||
392 | if (pctx == NULL) | ||
393 | return 0; | ||
394 | |||
395 | if (EVP_PKEY_encrypt_init(pctx) <= 0) | ||
396 | goto err; | ||
397 | } | ||
398 | |||
399 | if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, | ||
400 | EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) { | ||
401 | CMSerror(CMS_R_CTRL_ERROR); | ||
402 | goto err; | ||
403 | } | ||
404 | |||
405 | if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) | ||
406 | goto err; | ||
407 | |||
408 | ek = malloc(eklen); | ||
409 | |||
410 | if (ek == NULL) { | ||
411 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
412 | goto err; | ||
413 | } | ||
414 | |||
415 | if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) | ||
416 | goto err; | ||
417 | |||
418 | ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); | ||
419 | ek = NULL; | ||
420 | |||
421 | ret = 1; | ||
422 | |||
423 | err: | ||
424 | EVP_PKEY_CTX_free(pctx); | ||
425 | ktri->pctx = NULL; | ||
426 | free(ek); | ||
427 | |||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | /* Decrypt content key from KTRI */ | ||
432 | |||
433 | static int | ||
434 | cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
435 | { | ||
436 | CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; | ||
437 | EVP_PKEY *pkey = ktri->pkey; | ||
438 | unsigned char *ek = NULL; | ||
439 | size_t eklen; | ||
440 | size_t fixlen = 0; | ||
441 | int ret = 0; | ||
442 | CMS_EncryptedContentInfo *ec; | ||
443 | |||
444 | ec = cms->d.envelopedData->encryptedContentInfo; | ||
445 | |||
446 | if (ktri->pkey == NULL) { | ||
447 | CMSerror(CMS_R_NO_PRIVATE_KEY); | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | if (cms->d.envelopedData->encryptedContentInfo->havenocert && | ||
452 | !cms->d.envelopedData->encryptedContentInfo->debug) { | ||
453 | X509_ALGOR *calg = ec->contentEncryptionAlgorithm; | ||
454 | const EVP_CIPHER *ciph; | ||
455 | |||
456 | if ((ciph = EVP_get_cipherbyobj(calg->algorithm)) == NULL) { | ||
457 | CMSerror(CMS_R_UNKNOWN_CIPHER); | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | fixlen = EVP_CIPHER_key_length(ciph); | ||
462 | } | ||
463 | |||
464 | ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); | ||
465 | if (ktri->pctx == NULL) | ||
466 | return 0; | ||
467 | |||
468 | if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0) | ||
469 | goto err; | ||
470 | |||
471 | if (!cms_env_asn1_ctrl(ri, 1)) | ||
472 | goto err; | ||
473 | |||
474 | if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT, | ||
475 | EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { | ||
476 | CMSerror(CMS_R_CTRL_ERROR); | ||
477 | goto err; | ||
478 | } | ||
479 | |||
480 | if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen, ktri->encryptedKey->data, | ||
481 | ktri->encryptedKey->length) <= 0 || eklen == 0 || | ||
482 | (fixlen != 0 && eklen != fixlen)) { | ||
483 | CMSerror(CMS_R_CMS_LIB); | ||
484 | goto err; | ||
485 | } | ||
486 | |||
487 | ek = malloc(eklen); | ||
488 | |||
489 | if (ek == NULL) { | ||
490 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
491 | goto err; | ||
492 | } | ||
493 | |||
494 | if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, ktri->encryptedKey->data, | ||
495 | ktri->encryptedKey->length) <= 0) { | ||
496 | CMSerror(CMS_R_CMS_LIB); | ||
497 | goto err; | ||
498 | } | ||
499 | |||
500 | ret = 1; | ||
501 | |||
502 | freezero(ec->key, ec->keylen); | ||
503 | ec->key = ek; | ||
504 | ec->keylen = eklen; | ||
505 | |||
506 | err: | ||
507 | EVP_PKEY_CTX_free(ktri->pctx); | ||
508 | ktri->pctx = NULL; | ||
509 | if (!ret) | ||
510 | free(ek); | ||
511 | |||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | /* Key Encrypted Key (KEK) RecipientInfo routines */ | ||
516 | |||
517 | int | ||
518 | CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, const unsigned char *id, | ||
519 | size_t idlen) | ||
520 | { | ||
521 | ASN1_OCTET_STRING tmp_os; | ||
522 | CMS_KEKRecipientInfo *kekri; | ||
523 | |||
524 | if (ri->type != CMS_RECIPINFO_KEK) { | ||
525 | CMSerror(CMS_R_NOT_KEK); | ||
526 | return -2; | ||
527 | } | ||
528 | kekri = ri->d.kekri; | ||
529 | tmp_os.type = V_ASN1_OCTET_STRING; | ||
530 | tmp_os.flags = 0; | ||
531 | tmp_os.data = (unsigned char *)id; | ||
532 | tmp_os.length = (int)idlen; | ||
533 | |||
534 | return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier); | ||
535 | } | ||
536 | LCRYPTO_ALIAS(CMS_RecipientInfo_kekri_id_cmp); | ||
537 | |||
538 | /* For now hard code AES key wrap info */ | ||
539 | |||
540 | static size_t | ||
541 | aes_wrap_keylen(int nid) | ||
542 | { | ||
543 | switch (nid) { | ||
544 | case NID_id_aes128_wrap: | ||
545 | return 16; | ||
546 | |||
547 | case NID_id_aes192_wrap: | ||
548 | return 24; | ||
549 | |||
550 | case NID_id_aes256_wrap: | ||
551 | return 32; | ||
552 | |||
553 | default: | ||
554 | return 0; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | CMS_RecipientInfo * | ||
559 | CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, unsigned char *key, | ||
560 | size_t keylen, unsigned char *id, size_t idlen, ASN1_GENERALIZEDTIME *date, | ||
561 | ASN1_OBJECT *otherTypeId, ASN1_TYPE *otherType) | ||
562 | { | ||
563 | CMS_RecipientInfo *ri = NULL; | ||
564 | CMS_EnvelopedData *env; | ||
565 | CMS_KEKRecipientInfo *kekri; | ||
566 | |||
567 | env = cms_get0_enveloped(cms); | ||
568 | if (!env) | ||
569 | goto err; | ||
570 | |||
571 | if (nid == NID_undef) { | ||
572 | switch (keylen) { | ||
573 | case 16: | ||
574 | nid = NID_id_aes128_wrap; | ||
575 | break; | ||
576 | |||
577 | case 24: | ||
578 | nid = NID_id_aes192_wrap; | ||
579 | break; | ||
580 | |||
581 | case 32: | ||
582 | nid = NID_id_aes256_wrap; | ||
583 | break; | ||
584 | |||
585 | default: | ||
586 | CMSerror(CMS_R_INVALID_KEY_LENGTH); | ||
587 | goto err; | ||
588 | } | ||
589 | |||
590 | } else { | ||
591 | |||
592 | size_t exp_keylen = aes_wrap_keylen(nid); | ||
593 | |||
594 | if (!exp_keylen) { | ||
595 | CMSerror(CMS_R_UNSUPPORTED_KEK_ALGORITHM); | ||
596 | goto err; | ||
597 | } | ||
598 | |||
599 | if (keylen != exp_keylen) { | ||
600 | CMSerror(CMS_R_INVALID_KEY_LENGTH); | ||
601 | goto err; | ||
602 | } | ||
603 | |||
604 | } | ||
605 | |||
606 | /* Initialize recipient info */ | ||
607 | ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it); | ||
608 | if (!ri) | ||
609 | goto merr; | ||
610 | |||
611 | ri->d.kekri = (CMS_KEKRecipientInfo *)ASN1_item_new(&CMS_KEKRecipientInfo_it); | ||
612 | if (!ri->d.kekri) | ||
613 | goto merr; | ||
614 | ri->type = CMS_RECIPINFO_KEK; | ||
615 | |||
616 | kekri = ri->d.kekri; | ||
617 | |||
618 | if (otherTypeId) { | ||
619 | kekri->kekid->other = (CMS_OtherKeyAttribute *)ASN1_item_new(&CMS_OtherKeyAttribute_it); | ||
620 | if (kekri->kekid->other == NULL) | ||
621 | goto merr; | ||
622 | } | ||
623 | |||
624 | if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) | ||
625 | goto merr; | ||
626 | |||
627 | /* After this point no calls can fail */ | ||
628 | |||
629 | kekri->version = 4; | ||
630 | |||
631 | kekri->key = key; | ||
632 | kekri->keylen = keylen; | ||
633 | |||
634 | ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); | ||
635 | |||
636 | kekri->kekid->date = date; | ||
637 | |||
638 | if (kekri->kekid->other) { | ||
639 | kekri->kekid->other->keyAttrId = otherTypeId; | ||
640 | kekri->kekid->other->keyAttr = otherType; | ||
641 | } | ||
642 | |||
643 | X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, | ||
644 | OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); | ||
645 | |||
646 | return ri; | ||
647 | |||
648 | merr: | ||
649 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
650 | err: | ||
651 | ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it); | ||
652 | return NULL; | ||
653 | } | ||
654 | LCRYPTO_ALIAS(CMS_add0_recipient_key); | ||
655 | |||
656 | int | ||
657 | CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg, | ||
658 | ASN1_OCTET_STRING **pid, ASN1_GENERALIZEDTIME **pdate, | ||
659 | ASN1_OBJECT **potherid, ASN1_TYPE **pothertype) | ||
660 | { | ||
661 | CMS_KEKIdentifier *rkid; | ||
662 | |||
663 | if (ri->type != CMS_RECIPINFO_KEK) { | ||
664 | CMSerror(CMS_R_NOT_KEK); | ||
665 | return 0; | ||
666 | } | ||
667 | rkid = ri->d.kekri->kekid; | ||
668 | if (palg) | ||
669 | *palg = ri->d.kekri->keyEncryptionAlgorithm; | ||
670 | if (pid) | ||
671 | *pid = rkid->keyIdentifier; | ||
672 | if (pdate) | ||
673 | *pdate = rkid->date; | ||
674 | if (potherid) { | ||
675 | if (rkid->other) | ||
676 | *potherid = rkid->other->keyAttrId; | ||
677 | else | ||
678 | *potherid = NULL; | ||
679 | } | ||
680 | if (pothertype) { | ||
681 | if (rkid->other) | ||
682 | *pothertype = rkid->other->keyAttr; | ||
683 | else | ||
684 | *pothertype = NULL; | ||
685 | } | ||
686 | |||
687 | return 1; | ||
688 | } | ||
689 | LCRYPTO_ALIAS(CMS_RecipientInfo_kekri_get0_id); | ||
690 | |||
691 | int | ||
692 | CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, unsigned char *key, | ||
693 | size_t keylen) | ||
694 | { | ||
695 | CMS_KEKRecipientInfo *kekri; | ||
696 | |||
697 | if (ri->type != CMS_RECIPINFO_KEK) { | ||
698 | CMSerror(CMS_R_NOT_KEK); | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | kekri = ri->d.kekri; | ||
703 | kekri->key = key; | ||
704 | kekri->keylen = keylen; | ||
705 | return 1; | ||
706 | } | ||
707 | LCRYPTO_ALIAS(CMS_RecipientInfo_set0_key); | ||
708 | |||
709 | /* Encrypt content key in KEK recipient info */ | ||
710 | |||
711 | static int | ||
712 | cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
713 | { | ||
714 | CMS_EncryptedContentInfo *ec; | ||
715 | CMS_KEKRecipientInfo *kekri; | ||
716 | AES_KEY actx; | ||
717 | unsigned char *wkey = NULL; | ||
718 | int wkeylen; | ||
719 | int r = 0; | ||
720 | |||
721 | ec = cms->d.envelopedData->encryptedContentInfo; | ||
722 | kekri = ri->d.kekri; | ||
723 | |||
724 | if (!kekri->key) { | ||
725 | CMSerror(CMS_R_NO_KEY); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) { | ||
730 | CMSerror(CMS_R_ERROR_SETTING_KEY); | ||
731 | goto err; | ||
732 | } | ||
733 | |||
734 | wkey = malloc(ec->keylen + 8); | ||
735 | if (wkey == NULL) { | ||
736 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
737 | goto err; | ||
738 | } | ||
739 | |||
740 | wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); | ||
741 | if (wkeylen <= 0) { | ||
742 | CMSerror(CMS_R_WRAP_ERROR); | ||
743 | goto err; | ||
744 | } | ||
745 | |||
746 | ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); | ||
747 | |||
748 | r = 1; | ||
749 | |||
750 | err: | ||
751 | if (!r) | ||
752 | free(wkey); | ||
753 | explicit_bzero(&actx, sizeof(actx)); | ||
754 | |||
755 | return r; | ||
756 | } | ||
757 | |||
758 | /* Decrypt content key in KEK recipient info */ | ||
759 | |||
760 | static int | ||
761 | cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
762 | { | ||
763 | CMS_EncryptedContentInfo *ec; | ||
764 | CMS_KEKRecipientInfo *kekri; | ||
765 | AES_KEY actx; | ||
766 | unsigned char *ukey = NULL; | ||
767 | int ukeylen; | ||
768 | int r = 0, wrap_nid; | ||
769 | |||
770 | ec = cms->d.envelopedData->encryptedContentInfo; | ||
771 | kekri = ri->d.kekri; | ||
772 | |||
773 | if (!kekri->key) { | ||
774 | CMSerror(CMS_R_NO_KEY); | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); | ||
779 | if (aes_wrap_keylen(wrap_nid) != kekri->keylen) { | ||
780 | CMSerror(CMS_R_INVALID_KEY_LENGTH); | ||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | /* If encrypted key length is invalid don't bother */ | ||
785 | |||
786 | if (kekri->encryptedKey->length < 16) { | ||
787 | CMSerror(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); | ||
788 | goto err; | ||
789 | } | ||
790 | |||
791 | if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) { | ||
792 | CMSerror(CMS_R_ERROR_SETTING_KEY); | ||
793 | goto err; | ||
794 | } | ||
795 | |||
796 | ukey = malloc(kekri->encryptedKey->length - 8); | ||
797 | if (ukey == NULL) { | ||
798 | CMSerror(ERR_R_MALLOC_FAILURE); | ||
799 | goto err; | ||
800 | } | ||
801 | |||
802 | ukeylen = AES_unwrap_key(&actx, NULL, ukey, kekri->encryptedKey->data, | ||
803 | kekri->encryptedKey->length); | ||
804 | |||
805 | if (ukeylen <= 0) { | ||
806 | CMSerror(CMS_R_UNWRAP_ERROR); | ||
807 | goto err; | ||
808 | } | ||
809 | |||
810 | freezero(ec->key, ec->keylen); | ||
811 | ec->key = ukey; | ||
812 | ec->keylen = ukeylen; | ||
813 | |||
814 | r = 1; | ||
815 | |||
816 | err: | ||
817 | |||
818 | if (!r) | ||
819 | free(ukey); | ||
820 | explicit_bzero(&actx, sizeof(actx)); | ||
821 | |||
822 | return r; | ||
823 | } | ||
824 | |||
825 | int | ||
826 | CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
827 | { | ||
828 | switch (ri->type) { | ||
829 | case CMS_RECIPINFO_TRANS: | ||
830 | return cms_RecipientInfo_ktri_decrypt(cms, ri); | ||
831 | |||
832 | case CMS_RECIPINFO_KEK: | ||
833 | return cms_RecipientInfo_kekri_decrypt(cms, ri); | ||
834 | |||
835 | case CMS_RECIPINFO_PASS: | ||
836 | return cms_RecipientInfo_pwri_crypt(cms, ri, 0); | ||
837 | |||
838 | default: | ||
839 | CMSerror(CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE); | ||
840 | return 0; | ||
841 | } | ||
842 | } | ||
843 | LCRYPTO_ALIAS(CMS_RecipientInfo_decrypt); | ||
844 | |||
845 | int | ||
846 | CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | ||
847 | { | ||
848 | switch (ri->type) { | ||
849 | case CMS_RECIPINFO_TRANS: | ||
850 | return cms_RecipientInfo_ktri_encrypt(cms, ri); | ||
851 | |||
852 | case CMS_RECIPINFO_AGREE: | ||
853 | return cms_RecipientInfo_kari_encrypt(cms, ri); | ||
854 | |||
855 | case CMS_RECIPINFO_KEK: | ||
856 | return cms_RecipientInfo_kekri_encrypt(cms, ri); | ||
857 | |||
858 | case CMS_RECIPINFO_PASS: | ||
859 | return cms_RecipientInfo_pwri_crypt(cms, ri, 1); | ||
860 | |||
861 | default: | ||
862 | CMSerror(CMS_R_UNSUPPORTED_RECIPIENT_TYPE); | ||
863 | return 0; | ||
864 | } | ||
865 | } | ||
866 | LCRYPTO_ALIAS(CMS_RecipientInfo_encrypt); | ||
867 | |||
868 | /* Check structures and fixup version numbers (if necessary) */ | ||
869 | |||
870 | static void | ||
871 | cms_env_set_originfo_version(CMS_EnvelopedData *env) | ||
872 | { | ||
873 | CMS_OriginatorInfo *org = env->originatorInfo; | ||
874 | int i; | ||
875 | |||
876 | if (org == NULL) | ||
877 | return; | ||
878 | for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) { | ||
879 | CMS_CertificateChoices *cch; | ||
880 | |||
881 | cch = sk_CMS_CertificateChoices_value(org->certificates, i); | ||
882 | if (cch->type == CMS_CERTCHOICE_OTHER) { | ||
883 | env->version = 4; | ||
884 | return; | ||
885 | } else if (cch->type == CMS_CERTCHOICE_V2ACERT) { | ||
886 | if (env->version < 3) | ||
887 | env->version = 3; | ||
888 | } | ||
889 | } | ||
890 | |||
891 | for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) { | ||
892 | CMS_RevocationInfoChoice *rch; | ||
893 | |||
894 | rch = sk_CMS_RevocationInfoChoice_value(org->crls, i); | ||
895 | if (rch->type == CMS_REVCHOICE_OTHER) { | ||
896 | env->version = 4; | ||
897 | return; | ||
898 | } | ||
899 | } | ||
900 | } | ||
901 | |||
902 | static void | ||
903 | cms_env_set_version(CMS_EnvelopedData *env) | ||
904 | { | ||
905 | int i; | ||
906 | CMS_RecipientInfo *ri; | ||
907 | |||
908 | /* | ||
909 | * Can't set version higher than 4 so if 4 or more already nothing to do. | ||
910 | */ | ||
911 | if (env->version >= 4) | ||
912 | return; | ||
913 | |||
914 | cms_env_set_originfo_version(env); | ||
915 | |||
916 | if (env->version >= 3) | ||
917 | return; | ||
918 | |||
919 | for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) { | ||
920 | ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i); | ||
921 | if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) { | ||
922 | env->version = 3; | ||
923 | return; | ||
924 | } else if (ri->type != CMS_RECIPINFO_TRANS | ||
925 | || ri->d.ktri->version != 0) { | ||
926 | env->version = 2; | ||
927 | } | ||
928 | } | ||
929 | if (env->originatorInfo || env->unprotectedAttrs) | ||
930 | env->version = 2; | ||
931 | if (env->version == 2) | ||
932 | return; | ||
933 | env->version = 0; | ||
934 | } | ||
935 | |||
936 | BIO * | ||
937 | cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) | ||
938 | { | ||
939 | CMS_EncryptedContentInfo *ec; | ||
940 | STACK_OF(CMS_RecipientInfo) *rinfos; | ||
941 | CMS_RecipientInfo *ri; | ||
942 | int i, ok = 0; | ||
943 | BIO *ret; | ||
944 | |||
945 | /* Get BIO first to set up key */ | ||
946 | |||
947 | ec = cms->d.envelopedData->encryptedContentInfo; | ||
948 | ret = cms_EncryptedContent_init_bio(ec); | ||
949 | |||
950 | /* If error or no cipher end of processing */ | ||
951 | |||
952 | if (!ret || !ec->cipher) | ||
953 | return ret; | ||
954 | |||
955 | /* Now encrypt content key according to each RecipientInfo type */ | ||
956 | |||
957 | rinfos = cms->d.envelopedData->recipientInfos; | ||
958 | |||
959 | for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { | ||
960 | ri = sk_CMS_RecipientInfo_value(rinfos, i); | ||
961 | if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) { | ||
962 | CMSerror(CMS_R_ERROR_SETTING_RECIPIENTINFO); | ||
963 | goto err; | ||
964 | } | ||
965 | } | ||
966 | cms_env_set_version(cms->d.envelopedData); | ||
967 | |||
968 | ok = 1; | ||
969 | |||
970 | err: | ||
971 | ec->cipher = NULL; | ||
972 | freezero(ec->key, ec->keylen); | ||
973 | ec->key = NULL; | ||
974 | ec->keylen = 0; | ||
975 | if (ok) | ||
976 | return ret; | ||
977 | BIO_free(ret); | ||
978 | return NULL; | ||
979 | } | ||
980 | |||
981 | /* | ||
982 | * Get RecipientInfo type (if any) supported by a key (public or private). To | ||
983 | * retain compatibility with previous behaviour if the ctrl value isn't | ||
984 | * supported we assume key transport. | ||
985 | */ | ||
986 | int | ||
987 | cms_pkey_get_ri_type(EVP_PKEY *pk) | ||
988 | { | ||
989 | if (pk->ameth && pk->ameth->pkey_ctrl) { | ||
990 | int i, r; | ||
991 | i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r); | ||
992 | if (i > 0) | ||
993 | return r; | ||
994 | } | ||
995 | return CMS_RECIPINFO_TRANS; | ||
996 | } | ||