]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_sd.c
And so it begins...
[thirdparty/openssl.git] / crypto / cms / cms_sd.c
CommitLineData
8931b30d
DSH
1/* crypto/cms/cms_sd.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 "cms_lcl.h"
61#include "asn1_locl.h"
62
63/* CMS SignedData Utilities */
64
65DECLARE_ASN1_ITEM(CMS_SignedData)
66
67static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
68 {
69 if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed)
70 {
71 CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
72 return NULL;
73 }
74 return cms->d.signedData;
75 }
76
77static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
78 {
79 if (cms->d.other == NULL)
80 {
81 cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
82 if (!cms->d.signedData)
83 {
84 CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE);
85 return NULL;
86 }
87 cms->d.signedData->version = 1;
88 cms->d.signedData->encapContentInfo->eContentType =
89 OBJ_nid2obj(NID_pkcs7_data);
90 ASN1_OBJECT_free(cms->contentType);
91 cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
92 return cms->d.signedData;
93 }
94 return cms_get0_signed(cms);
95 }
96
97/* Just initialize SignedData e.g. for certs only structure */
98
99int CMS_SignedData_init(CMS_ContentInfo *cms)
100 {
101 if (cms_signed_data_init(cms))
102 return 1;
103 else
104 return 0;
105 }
106
107/* Check structures and fixup version numbers (if necessary) */
108
109static void cms_sd_set_version(CMS_SignedData *sd)
110 {
111 int i;
112 CMS_CertificateChoices *cch;
113 CMS_RevocationInfoChoice *rch;
114 CMS_SignerInfo *si;
115
116 for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++)
117 {
118 cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
119 if (cch->type == CMS_CERTCHOICE_OTHER)
120 {
121 if (sd->version < 5)
122 sd->version = 5;
123 }
124 else if (cch->type == CMS_CERTCHOICE_V2ACERT)
125 {
126 if (sd->version < 4)
127 sd->version = 4;
128 }
129 else if (cch->type == CMS_CERTCHOICE_V1ACERT)
130 {
131 if (sd->version < 3)
132 sd->version = 3;
133 }
134 }
135
136 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++)
137 {
138 rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
139 if (rch->type == CMS_REVCHOICE_OTHER)
140 {
141 if (sd->version < 5)
142 sd->version = 5;
143 }
144 }
145
146 if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
147 && (sd->version < 3))
148 sd->version = 3;
149
150 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++)
151 {
152 si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
153 if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
154 {
155 if (si->version < 3)
156 si->version = 3;
157 if (sd->version < 3)
158 sd->version = 3;
159 }
160 else
161 sd->version = 1;
162 }
163
164 if (sd->version < 1)
165 sd->version = 1;
166
167 }
168
169/* Copy an existing messageDigest value */
170
171static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
172 {
173 STACK_OF(CMS_SignerInfo) *sinfos;
174 CMS_SignerInfo *sitmp;
175 int i;
176 sinfos = CMS_get0_SignerInfos(cms);
177 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
178 {
179 ASN1_OCTET_STRING *messageDigest;
180 sitmp = sk_CMS_SignerInfo_value(sinfos, i);
181 if (sitmp == si)
182 continue;
183 if (CMS_signed_get_attr_count(sitmp) < 0)
184 continue;
185 if (OBJ_cmp(si->digestAlgorithm->algorithm,
186 sitmp->digestAlgorithm->algorithm))
187 continue;
188 messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
189 OBJ_nid2obj(NID_pkcs9_messageDigest),
190 -3, V_ASN1_OCTET_STRING);
191 if (!messageDigest)
192 {
193 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST,
194 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
195 return 0;
196 }
197
198 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
199 V_ASN1_OCTET_STRING,
200 messageDigest, -1))
201 return 1;
202 else
203 return 0;
204 }
205 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST);
206 return 0;
207 }
208
209int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
210 {
211 switch(type)
212 {
213 case CMS_SIGNERINFO_ISSUER_SERIAL:
214 sid->d.issuerAndSerialNumber =
215 M_ASN1_new_of(CMS_IssuerAndSerialNumber);
216 if (!sid->d.issuerAndSerialNumber)
217 goto merr;
218 if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer,
219 X509_get_issuer_name(cert)))
220 goto merr;
221 if (!ASN1_STRING_copy(
222 sid->d.issuerAndSerialNumber->serialNumber,
223 X509_get_serialNumber(cert)))
224 goto merr;
225 break;
226
227 case CMS_SIGNERINFO_KEYIDENTIFIER:
228 sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid);
229 if (!sid->d.subjectKeyIdentifier)
230 goto merr;
231 break;
232
233 default:
234 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
235 return 0;
236 }
237
238 sid->type = type;
239
240 return 1;
241
242 merr:
243 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE);
244 return 0;
245
246 }
247
248int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
249 ASN1_OCTET_STRING **keyid,
250 X509_NAME **issuer, ASN1_INTEGER **sno)
251 {
252 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
253 {
254 if (issuer)
255 *issuer = sid->d.issuerAndSerialNumber->issuer;
256 if (sno)
257 *sno = sid->d.issuerAndSerialNumber->serialNumber;
258 }
259 else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
260 {
261 if (keyid)
262 *keyid = sid->d.subjectKeyIdentifier;
263 }
264 else
265 return 0;
266 return 1;
267 }
268
269int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
270 {
271 int ret;
272 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
273 {
274 ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer,
275 X509_get_issuer_name(cert));
276 if (ret)
277 return ret;
278 return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber,
279 X509_get_serialNumber(cert));
280 }
281 else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
282 {
283 X509_check_purpose(cert, -1, -1);
284 if (!cert->skid)
285 return -1;
286 return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier,
287 cert->skid);
288 }
289 else
290 return -1;
291 }
292
293CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
294 X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
295 unsigned int flags)
296 {
297 CMS_SignedData *sd;
298 CMS_SignerInfo *si = NULL;
299 X509_ALGOR *alg;
300 int i, type;
301 if(!X509_check_private_key(signer, pk))
302 {
303 CMSerr(CMS_F_CMS_ADD1_SIGNER,
304 CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
305 return NULL;
306 }
307 sd = cms_signed_data_init(cms);
308 if (!sd)
309 goto err;
310 si = M_ASN1_new_of(CMS_SignerInfo);
311 if (!si)
312 goto merr;
313 X509_check_purpose(signer, -1, -1);
314
315 CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
316 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
317
318 si->pkey = pk;
319 si->signer = signer;
320
321 if (flags & CMS_USE_KEYID)
322 {
323 si->version = 3;
324 if (sd->version < 3)
325 sd->version = 3;
326 type = CMS_SIGNERINFO_KEYIDENTIFIER;
327 }
328 else
329 {
330 type = CMS_SIGNERINFO_ISSUER_SERIAL;
331 si->version = 1;
332 }
333
334 if (!cms_set1_SignerIdentifier(si->sid, signer, type))
335 goto err;
336
337 if (md == NULL)
338 {
339 int def_nid;
340 if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
341 goto err;
342 md = EVP_get_digestbynid(def_nid);
343 if (md == NULL)
344 {
345 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
346 goto err;
347 }
348 }
349
350 if (!md)
351 {
352 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
353 goto err;
354 }
355
356 cms_DigestAlgorithm_set(si->digestAlgorithm, md);
357
358 /* See if digest is present in digestAlgorithms */
359 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++)
360 {
361 ASN1_OBJECT *aoid;
362 alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
363 X509_ALGOR_get0(&aoid, NULL, NULL, alg);
364 if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
365 break;
366 }
367
368 if (i == sk_X509_ALGOR_num(sd->digestAlgorithms))
369 {
370 alg = X509_ALGOR_new();
371 if (!alg)
372 goto merr;
373 cms_DigestAlgorithm_set(alg, md);
374 if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg))
375 {
376 X509_ALGOR_free(alg);
377 goto merr;
378 }
379 }
380
381 if (pk->ameth && pk->ameth->pkey_ctrl)
382 {
383 i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN,
384 0, si);
385 if (i == -2)
386 {
387 CMSerr(CMS_F_CMS_ADD1_SIGNER,
388 CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
389 goto err;
390 }
391 if (i <= 0)
392 {
393 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE);
394 goto err;
395 }
396 }
397
398 if (!(flags & CMS_NOATTR))
399 {
400 /* Copy content type across */
401 ASN1_OBJECT *ctype =
402 OBJ_dup(sd->encapContentInfo->eContentType);
403 if (!ctype)
404 goto merr;
405 i = CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
406 V_ASN1_OBJECT, ctype, -1);
407 ASN1_OBJECT_free(ctype);
408 if (i <= 0)
409 goto merr;
410 if (!(flags & CMS_NOSMIMECAP))
411 {
412 STACK_OF(X509_ALGOR) *smcap = NULL;
413 i = CMS_add_standard_smimecap(&smcap);
414 if (i)
415 i = CMS_add_smimecap(si, smcap);
416 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
417 if (!i)
418 goto merr;
419 }
420 if (flags & CMS_REUSE_DIGEST)
421 {
422 if (!cms_copy_messageDigest(cms, si))
423 goto err;
424 if (!(flags & CMS_PARTIAL) &&
425 !CMS_SignerInfo_sign(si))
426 goto err;
427 }
428 }
429
430 if (!(flags & CMS_NOCERTS))
431 {
432 /* NB ignore -1 return for duplicate cert */
433 if (!CMS_add1_cert(cms, signer))
434 goto merr;
435 }
436
437 if (!sd->signerInfos)
438 sd->signerInfos = sk_CMS_SignerInfo_new_null();
439 if (!sd->signerInfos ||
440 !sk_CMS_SignerInfo_push(sd->signerInfos, si))
441 goto merr;
442
443 return si;
444
445 merr:
446 CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
447 err:
448 if (si)
449 M_ASN1_free_of(si, CMS_SignerInfo);
450 return NULL;
451
452 }
453
454int CMS_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
455 {
456 ASN1_TIME *tt;
457 int r = 0;
458 if (t)
459 tt = t;
460 else
461 tt = X509_gmtime_adj(NULL, 0);
462
463 if (!tt)
464 goto merr;
465
466 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
467 tt->type, tt, -1) <= 0)
468 goto merr;
469
470 r = 1;
471
472 merr:
473
474 if (!t)
475 ASN1_TIME_free(tt);
476
477 if (!r)
478 CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE);
479
480 return r;
481
482 }
483
484STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
485 {
486 CMS_SignedData *sd;
487 sd = cms_get0_signed(cms);
488 if (!sd)
489 return NULL;
490 return sd->signerInfos;
491 }
492
493STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
494 {
495 STACK_OF(X509) *signers = NULL;
496 STACK_OF(CMS_SignerInfo) *sinfos;
497 CMS_SignerInfo *si;
498 int i;
499 sinfos = CMS_get0_SignerInfos(cms);
500 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
501 {
502 si = sk_CMS_SignerInfo_value(sinfos, i);
503 if (si->signer)
504 {
505 if (!signers)
506 {
507 signers = sk_X509_new_null();
508 if (!signers)
509 return NULL;
510 }
511 if (!sk_X509_push(signers, si->signer))
512 {
513 sk_X509_free(signers);
514 return NULL;
515 }
516 }
517 }
518 return signers;
519 }
520
521void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
522 {
523 if (signer)
524 {
525 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
526 if (si->pkey)
527 EVP_PKEY_free(si->pkey);
528 si->pkey = X509_get_pubkey(signer);
529 }
530 if (si->signer)
531 X509_free(si->signer);
532 si->signer = signer;
533 }
534
535int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
536 ASN1_OCTET_STRING **keyid,
537 X509_NAME **issuer, ASN1_INTEGER **sno)
538 {
539 return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
540 }
541
542int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
543 {
544 return cms_SignerIdentifier_cert_cmp(si->sid, cert);
545 }
546
547int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
548 unsigned int flags)
549 {
550 CMS_SignedData *sd;
551 CMS_SignerInfo *si;
552 CMS_CertificateChoices *cch;
553 STACK_OF(CMS_CertificateChoices) *certs;
554 X509 *x;
555 int i, j;
556 int ret = 0;
557 sd = cms_get0_signed(cms);
558 if (!sd)
559 return -1;
560 certs = sd->certificates;
561 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++)
562 {
563 si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
564 if (si->signer)
565 continue;
566
567 for (j = 0; j < sk_X509_num(scerts); j++)
568 {
569 x = sk_X509_value(scerts, j);
570 if (CMS_SignerInfo_cert_cmp(si, x) == 0)
571 {
572 CMS_SignerInfo_set1_signer_cert(si, x);
573 ret++;
574 break;
575 }
576 }
577
578 if (si->signer || (flags & CMS_NOINTERN))
579 continue;
580
581 for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++)
582 {
583 cch = sk_CMS_CertificateChoices_value(certs, j);
584 if (cch->type != 0)
585 continue;
586 x = cch->d.certificate;
587 if (CMS_SignerInfo_cert_cmp(si, x) == 0)
588 {
589 CMS_SignerInfo_set1_signer_cert(si, x);
590 ret++;
591 break;
592 }
593 }
594 }
595 return ret;
596 }
597
598void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer,
599 X509_ALGOR **pdig, X509_ALGOR **psig)
600 {
601 if (pk)
602 *pk = si->pkey;
603 if (signer)
604 *signer = si->signer;
605 if (pdig)
606 *pdig = si->digestAlgorithm;
607 if (psig)
608 *psig = si->signatureAlgorithm;
609 }
610
611int cms_SignerInfo_content_sign(CMS_SignerInfo *si, BIO *chain)
612 {
613 EVP_MD_CTX mctx;
614 int r = 0;
615 EVP_MD_CTX_init(&mctx);
616
617
618 if (!si->pkey)
619 {
620 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
621 return 0;
622 }
623
624 if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
625 goto err;
626
627 /* If any signed attributes calculate and add messageDigest attribute */
628
629 if (CMS_signed_get_attr_count(si) >= 0)
630 {
631 unsigned char md[EVP_MAX_MD_SIZE];
632 unsigned int mdlen;
633 EVP_DigestFinal_ex(&mctx, md, &mdlen);
634 if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
635 V_ASN1_OCTET_STRING,
636 md, mdlen))
637 goto err;
638 if (!CMS_SignerInfo_sign(si))
639 goto err;
640 }
641 else
642 {
643 unsigned char *sig;
644 unsigned int siglen;
645 sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
646 if (!sig)
647 {
648 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN,
649 ERR_R_MALLOC_FAILURE);
650 goto err;
651 }
652 if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey))
653 {
654 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN,
655 CMS_R_SIGNFINAL_ERROR);
656 OPENSSL_free(sig);
657 goto err;
658 }
659 ASN1_STRING_set0(si->signature, sig, siglen);
660 }
661
662 r = 1;
663
664 err:
665 EVP_MD_CTX_cleanup(&mctx);
666 return r;
667
668 }
669
670int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
671 {
672 STACK_OF(CMS_SignerInfo) *sinfos;
673 CMS_SignerInfo *si;
674 int i;
675 sinfos = CMS_get0_SignerInfos(cms);
676 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
677 {
678 si = sk_CMS_SignerInfo_value(sinfos, i);
679 if (!cms_SignerInfo_content_sign(si, chain))
680 return 0;
681 }
682 return 1;
683 }
684
685int CMS_SignerInfo_sign(CMS_SignerInfo *si)
686 {
687 EVP_MD_CTX mctx;
688 EVP_PKEY_CTX *pctx;
689 unsigned char *abuf = NULL;
690 int alen;
691 size_t siglen;
692 const EVP_MD *md = NULL;
693
694 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
695 if (md == NULL)
696 return 0;
697
698 EVP_MD_CTX_init(&mctx);
699
700 if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0)
701 {
702 if (!CMS_add1_signingTime(si, NULL))
703 goto err;
704 }
705
706 if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
707 goto err;
708
709 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
710 EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0)
711 {
712 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
713 goto err;
714 }
715
716 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf,
717 ASN1_ITEM_rptr(CMS_Attributes_Sign));
718 if(!abuf)
719 goto err;
720 if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
721 goto err;
722 if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
723 goto err;
724 OPENSSL_free(abuf);
725 abuf = OPENSSL_malloc(siglen);
726 if(!abuf)
727 goto err;
728 if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
729 goto err;
730
731 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
732 EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0)
733 {
734 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
735 goto err;
736 }
737
738 EVP_MD_CTX_cleanup(&mctx);
739
740 ASN1_STRING_set0(si->signature, abuf, siglen);
741
742 return 1;
743
744 err:
745 if (abuf)
746 OPENSSL_free(abuf);
747 EVP_MD_CTX_cleanup(&mctx);
748 return 0;
749
750 }
751
752int CMS_SignerInfo_verify(CMS_SignerInfo *si)
753 {
754 EVP_MD_CTX mctx;
755 EVP_PKEY_CTX *pctx;
756 unsigned char *abuf = NULL;
757 int alen, r = -1;
758 const EVP_MD *md = NULL;
759
760 if (!si->pkey)
761 {
762 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
763 return -1;
764 }
765
766 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
767 if (md == NULL)
768 return -1;
769 EVP_MD_CTX_init(&mctx);
770 if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
771 goto err;
772
773 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf,
774 ASN1_ITEM_rptr(CMS_Attributes_Verify));
775 if(!abuf)
776 goto err;
777 r = EVP_DigestVerifyUpdate(&mctx, abuf, alen);
778 OPENSSL_free(abuf);
779 if (r <= 0)
780 {
781 r = -1;
782 goto err;
783 }
784 r = EVP_DigestVerifyFinal(&mctx,
785 si->signature->data, si->signature->length);
786 if (!r)
787 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
788 err:
789 EVP_MD_CTX_cleanup(&mctx);
790 return r;
791 }
792
793/* Create a chain of digest BIOs from a CMS ContentInfo */
794
795BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
796 {
797 int i;
798 CMS_SignedData *sd;
799 BIO *chain = NULL;
800 sd = cms_get0_signed(cms);
801 cms_sd_set_version(sd);
802 if (!sd)
803 return NULL;
804 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++)
805 {
806 X509_ALGOR *digestAlgorithm;
807 BIO *mdbio;
808 digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
809 mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
810 if (!mdbio)
811 goto err;
812 if (chain)
813 BIO_push(chain, mdbio);
814 else
815 chain = mdbio;
816 }
817 return chain;
818 err:
819 if (chain)
820 BIO_free_all(chain);
821 return NULL;
822 }
823
824int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
825 {
826 ASN1_OCTET_STRING *os = NULL;
827 EVP_MD_CTX mctx;
828 int r = -1;
829 EVP_MD_CTX_init(&mctx);
830 /* If we have any signed attributes look for messageDigest value */
831 if (CMS_signed_get_attr_count(si) >= 0)
832 {
833 os = CMS_signed_get0_data_by_OBJ(si,
834 OBJ_nid2obj(NID_pkcs9_messageDigest),
835 -3, V_ASN1_OCTET_STRING);
836 if (!os)
837 {
838 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
839 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
840 goto err;
841 }
842 }
843
844 if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
845 goto err;
846
847 /* If messageDigest found compare it */
848
849 if (os)
850 {
851 unsigned char mval[EVP_MAX_MD_SIZE];
852 unsigned int mlen;
853 if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0)
854 {
855 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
856 CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
857 goto err;
858 }
859 if (mlen != os->length)
860 {
861 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
862 CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
863 goto err;
864 }
865
866 if (memcmp(mval, os->data, mlen))
867 {
868 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
869 CMS_R_VERIFICATION_FAILURE);
870 r = 0;
871 }
872 else
873 r = 1;
874 }
875 else
876 {
877 r = EVP_VerifyFinal(&mctx, si->signature->data,
878 si->signature->length, si->pkey);
879 if (r <= 0)
880 {
881 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
882 CMS_R_VERIFICATION_FAILURE);
883 r = 0;
884 }
885 }
886
887 err:
888 EVP_MD_CTX_cleanup(&mctx);
889 return r;
890
891 }
892
893int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
894 {
895 unsigned char *smder = NULL;
896 int smderlen, r;
897 smderlen = i2d_X509_ALGORS(algs, &smder);
898 if (smderlen <= 0)
899 return 0;
900 r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
901 V_ASN1_SEQUENCE, smder, smderlen);
902 OPENSSL_free(smder);
903 return r;
904 }
905
906int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
907 int algnid, int keysize)
908 {
909 X509_ALGOR *alg;
910 ASN1_INTEGER *key = NULL;
911 if (keysize > 0)
912 {
913 key = ASN1_INTEGER_new();
914 if (!key || !ASN1_INTEGER_set(key, keysize))
915 return 0;
916 }
917 alg = X509_ALGOR_new();
918 if (!alg)
919 {
920 if (key)
921 ASN1_INTEGER_free(key);
922 return 0;
923 }
924
925 X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
926 key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
927 if (!*algs)
928 *algs = sk_X509_ALGOR_new_null();
929 if (!*algs || !sk_X509_ALGOR_push(*algs, alg))
930 {
931 X509_ALGOR_free(alg);
932 return 0;
933 }
934 return 1;
935 }
936
937/* Check to see if a cipher exists and if so add S/MIME capabilities */
938
939static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
940 {
941 if (EVP_get_cipherbynid(nid))
942 return CMS_add_simple_smimecap(sk, nid, arg);
943 return 1;
944 }
945
946static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
947 {
948 if (EVP_get_digestbynid(nid))
949 return CMS_add_simple_smimecap(sk, nid, arg);
950 return 1;
951 }
952
953int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
954 {
955 if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
956 || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
957 || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
958 || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
959 || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
960 || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
961 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
962 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
963 || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
964 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
965 return 0;
966 return 1;
967 }