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