summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cms/cms_sd.c
diff options
context:
space:
mode:
authorjsing <>2019-08-10 15:55:20 +0000
committerjsing <>2019-08-10 15:55:20 +0000
commita0845ead6d459f388701fe3fe8fa27635f4885f1 (patch)
treecfa2d4e7280cbfe7b7007556c8dcab6691e87b83 /src/lib/libcrypto/cms/cms_sd.c
parent38e170324f2dafb68786e79022ddafab241aad3d (diff)
downloadopenbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.gz
openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.bz2
openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.zip
Work towards supporting Cryptographic Message Syntax (CMS) in libcrypto.
Cryptographic Message Syntax (CMS) is a standard for cryptographically protecting messages, as defined in RFC 5652. It is derived from PKCS #7 version 1.5 and utilises various ASN.1 structures, making it complex and fairly heavyweight. Various protocols - including RPKI (RFC 6480) - have been built on top of it, which means it is necessary to support CMS, in order to support RPKI. This imports around 6,000 lines of code from OpenSSL 1.1.1, which is still under the original OpenSSL license. Further work will occur in tree. Requested by and discussed with many. ok deraadt@ tb@
Diffstat (limited to 'src/lib/libcrypto/cms/cms_sd.c')
-rw-r--r--src/lib/libcrypto/cms/cms_sd.c926
1 files changed, 926 insertions, 0 deletions
diff --git a/src/lib/libcrypto/cms/cms_sd.c b/src/lib/libcrypto/cms/cms_sd.c
new file mode 100644
index 0000000000..ff2d540b6a
--- /dev/null
+++ b/src/lib/libcrypto/cms/cms_sd.c
@@ -0,0 +1,926 @@
1/*
2 * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
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
8 */
9
10#include "internal/cryptlib.h"
11#include <openssl/asn1t.h>
12#include <openssl/pem.h>
13#include <openssl/x509.h>
14#include <openssl/x509v3.h>
15#include <openssl/err.h>
16#include <openssl/cms.h>
17#include "cms_lcl.h"
18#include "internal/asn1_int.h"
19#include "internal/evp_int.h"
20
21/* CMS SignedData Utilities */
22
23static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
24{
25 if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
26 CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
27 return NULL;
28 }
29 return cms->d.signedData;
30}
31
32static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
33{
34 if (cms->d.other == NULL) {
35 cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
36 if (!cms->d.signedData) {
37 CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE);
38 return NULL;
39 }
40 cms->d.signedData->version = 1;
41 cms->d.signedData->encapContentInfo->eContentType =
42 OBJ_nid2obj(NID_pkcs7_data);
43 cms->d.signedData->encapContentInfo->partial = 1;
44 ASN1_OBJECT_free(cms->contentType);
45 cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
46 return cms->d.signedData;
47 }
48 return cms_get0_signed(cms);
49}
50
51/* Just initialise SignedData e.g. for certs only structure */
52
53int CMS_SignedData_init(CMS_ContentInfo *cms)
54{
55 if (cms_signed_data_init(cms))
56 return 1;
57 else
58 return 0;
59}
60
61/* Check structures and fixup version numbers (if necessary) */
62
63static void cms_sd_set_version(CMS_SignedData *sd)
64{
65 int i;
66 CMS_CertificateChoices *cch;
67 CMS_RevocationInfoChoice *rch;
68 CMS_SignerInfo *si;
69
70 for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
71 cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
72 if (cch->type == CMS_CERTCHOICE_OTHER) {
73 if (sd->version < 5)
74 sd->version = 5;
75 } else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
76 if (sd->version < 4)
77 sd->version = 4;
78 } else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
79 if (sd->version < 3)
80 sd->version = 3;
81 }
82 }
83
84 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
85 rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
86 if (rch->type == CMS_REVCHOICE_OTHER) {
87 if (sd->version < 5)
88 sd->version = 5;
89 }
90 }
91
92 if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
93 && (sd->version < 3))
94 sd->version = 3;
95
96 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
97 si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
98 if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
99 if (si->version < 3)
100 si->version = 3;
101 if (sd->version < 3)
102 sd->version = 3;
103 } else if (si->version < 1)
104 si->version = 1;
105 }
106
107 if (sd->version < 1)
108 sd->version = 1;
109
110}
111
112/* Copy an existing messageDigest value */
113
114static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
115{
116 STACK_OF(CMS_SignerInfo) *sinfos;
117 CMS_SignerInfo *sitmp;
118 int i;
119 sinfos = CMS_get0_SignerInfos(cms);
120 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
121 ASN1_OCTET_STRING *messageDigest;
122 sitmp = sk_CMS_SignerInfo_value(sinfos, i);
123 if (sitmp == si)
124 continue;
125 if (CMS_signed_get_attr_count(sitmp) < 0)
126 continue;
127 if (OBJ_cmp(si->digestAlgorithm->algorithm,
128 sitmp->digestAlgorithm->algorithm))
129 continue;
130 messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
131 OBJ_nid2obj
132 (NID_pkcs9_messageDigest),
133 -3, V_ASN1_OCTET_STRING);
134 if (!messageDigest) {
135 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST,
136 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
137 return 0;
138 }
139
140 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
141 V_ASN1_OCTET_STRING,
142 messageDigest, -1))
143 return 1;
144 else
145 return 0;
146 }
147 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST);
148 return 0;
149}
150
151int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
152{
153 switch (type) {
154 case CMS_SIGNERINFO_ISSUER_SERIAL:
155 if (!cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
156 return 0;
157 break;
158
159 case CMS_SIGNERINFO_KEYIDENTIFIER:
160 if (!cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
161 return 0;
162 break;
163
164 default:
165 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
166 return 0;
167 }
168
169 sid->type = type;
170
171 return 1;
172}
173
174int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
175 ASN1_OCTET_STRING **keyid,
176 X509_NAME **issuer,
177 ASN1_INTEGER **sno)
178{
179 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
180 if (issuer)
181 *issuer = sid->d.issuerAndSerialNumber->issuer;
182 if (sno)
183 *sno = sid->d.issuerAndSerialNumber->serialNumber;
184 } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
185 if (keyid)
186 *keyid = sid->d.subjectKeyIdentifier;
187 } else
188 return 0;
189 return 1;
190}
191
192int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
193{
194 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
195 return cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
196 else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
197 return cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
198 else
199 return -1;
200}
201
202static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
203{
204 EVP_PKEY *pkey = si->pkey;
205 int i;
206 if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
207 return 1;
208 i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
209 if (i == -2) {
210 CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
211 return 0;
212 }
213 if (i <= 0) {
214 CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE);
215 return 0;
216 }
217 return 1;
218}
219
220CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
221 X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
222 unsigned int flags)
223{
224 CMS_SignedData *sd;
225 CMS_SignerInfo *si = NULL;
226 X509_ALGOR *alg;
227 int i, type;
228 if (!X509_check_private_key(signer, pk)) {
229 CMSerr(CMS_F_CMS_ADD1_SIGNER,
230 CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
231 return NULL;
232 }
233 sd = cms_signed_data_init(cms);
234 if (!sd)
235 goto err;
236 si = M_ASN1_new_of(CMS_SignerInfo);
237 if (!si)
238 goto merr;
239 /* Call for side-effect of computing hash and caching extensions */
240 X509_check_purpose(signer, -1, -1);
241
242 X509_up_ref(signer);
243 EVP_PKEY_up_ref(pk);
244
245 si->pkey = pk;
246 si->signer = signer;
247 si->mctx = EVP_MD_CTX_new();
248 si->pctx = NULL;
249
250 if (si->mctx == NULL) {
251 CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
252 goto err;
253 }
254
255 if (flags & CMS_USE_KEYID) {
256 si->version = 3;
257 if (sd->version < 3)
258 sd->version = 3;
259 type = CMS_SIGNERINFO_KEYIDENTIFIER;
260 } else {
261 type = CMS_SIGNERINFO_ISSUER_SERIAL;
262 si->version = 1;
263 }
264
265 if (!cms_set1_SignerIdentifier(si->sid, signer, type))
266 goto err;
267
268 if (md == NULL) {
269 int def_nid;
270 if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
271 goto err;
272 md = EVP_get_digestbynid(def_nid);
273 if (md == NULL) {
274 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
275 goto err;
276 }
277 }
278
279 if (!md) {
280 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
281 goto err;
282 }
283
284 X509_ALGOR_set_md(si->digestAlgorithm, md);
285
286 /* See if digest is present in digestAlgorithms */
287 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
288 const ASN1_OBJECT *aoid;
289 alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
290 X509_ALGOR_get0(&aoid, NULL, NULL, alg);
291 if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
292 break;
293 }
294
295 if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
296 alg = X509_ALGOR_new();
297 if (alg == NULL)
298 goto merr;
299 X509_ALGOR_set_md(alg, md);
300 if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
301 X509_ALGOR_free(alg);
302 goto merr;
303 }
304 }
305
306 if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
307 goto err;
308 if (!(flags & CMS_NOATTR)) {
309 /*
310 * Initialize signed attributes structure so other attributes
311 * such as signing time etc are added later even if we add none here.
312 */
313 if (!si->signedAttrs) {
314 si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
315 if (!si->signedAttrs)
316 goto merr;
317 }
318
319 if (!(flags & CMS_NOSMIMECAP)) {
320 STACK_OF(X509_ALGOR) *smcap = NULL;
321 i = CMS_add_standard_smimecap(&smcap);
322 if (i)
323 i = CMS_add_smimecap(si, smcap);
324 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
325 if (!i)
326 goto merr;
327 }
328 if (flags & CMS_REUSE_DIGEST) {
329 if (!cms_copy_messageDigest(cms, si))
330 goto err;
331 if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
332 !CMS_SignerInfo_sign(si))
333 goto err;
334 }
335 }
336
337 if (!(flags & CMS_NOCERTS)) {
338 /* NB ignore -1 return for duplicate cert */
339 if (!CMS_add1_cert(cms, signer))
340 goto merr;
341 }
342
343 if (flags & CMS_KEY_PARAM) {
344 if (flags & CMS_NOATTR) {
345 si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
346 if (si->pctx == NULL)
347 goto err;
348 if (EVP_PKEY_sign_init(si->pctx) <= 0)
349 goto err;
350 if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
351 goto err;
352 } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <=
353 0)
354 goto err;
355 }
356
357 if (!sd->signerInfos)
358 sd->signerInfos = sk_CMS_SignerInfo_new_null();
359 if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
360 goto merr;
361
362 return si;
363
364 merr:
365 CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
366 err:
367 M_ASN1_free_of(si, CMS_SignerInfo);
368 return NULL;
369
370}
371
372static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
373{
374 ASN1_TIME *tt;
375 int r = 0;
376 if (t)
377 tt = t;
378 else
379 tt = X509_gmtime_adj(NULL, 0);
380
381 if (!tt)
382 goto merr;
383
384 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
385 tt->type, tt, -1) <= 0)
386 goto merr;
387
388 r = 1;
389
390 merr:
391
392 if (!t)
393 ASN1_TIME_free(tt);
394
395 if (!r)
396 CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE);
397
398 return r;
399
400}
401
402EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
403{
404 return si->pctx;
405}
406
407EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
408{
409 return si->mctx;
410}
411
412STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
413{
414 CMS_SignedData *sd;
415 sd = cms_get0_signed(cms);
416 if (!sd)
417 return NULL;
418 return sd->signerInfos;
419}
420
421STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
422{
423 STACK_OF(X509) *signers = NULL;
424 STACK_OF(CMS_SignerInfo) *sinfos;
425 CMS_SignerInfo *si;
426 int i;
427 sinfos = CMS_get0_SignerInfos(cms);
428 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
429 si = sk_CMS_SignerInfo_value(sinfos, i);
430 if (si->signer) {
431 if (!signers) {
432 signers = sk_X509_new_null();
433 if (!signers)
434 return NULL;
435 }
436 if (!sk_X509_push(signers, si->signer)) {
437 sk_X509_free(signers);
438 return NULL;
439 }
440 }
441 }
442 return signers;
443}
444
445void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
446{
447 if (signer) {
448 X509_up_ref(signer);
449 EVP_PKEY_free(si->pkey);
450 si->pkey = X509_get_pubkey(signer);
451 }
452 X509_free(si->signer);
453 si->signer = signer;
454}
455
456int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
457 ASN1_OCTET_STRING **keyid,
458 X509_NAME **issuer, ASN1_INTEGER **sno)
459{
460 return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
461}
462
463int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
464{
465 return cms_SignerIdentifier_cert_cmp(si->sid, cert);
466}
467
468int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
469 unsigned int flags)
470{
471 CMS_SignedData *sd;
472 CMS_SignerInfo *si;
473 CMS_CertificateChoices *cch;
474 STACK_OF(CMS_CertificateChoices) *certs;
475 X509 *x;
476 int i, j;
477 int ret = 0;
478 sd = cms_get0_signed(cms);
479 if (!sd)
480 return -1;
481 certs = sd->certificates;
482 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
483 si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
484 if (si->signer)
485 continue;
486
487 for (j = 0; j < sk_X509_num(scerts); j++) {
488 x = sk_X509_value(scerts, j);
489 if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
490 CMS_SignerInfo_set1_signer_cert(si, x);
491 ret++;
492 break;
493 }
494 }
495
496 if (si->signer || (flags & CMS_NOINTERN))
497 continue;
498
499 for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
500 cch = sk_CMS_CertificateChoices_value(certs, j);
501 if (cch->type != 0)
502 continue;
503 x = cch->d.certificate;
504 if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
505 CMS_SignerInfo_set1_signer_cert(si, x);
506 ret++;
507 break;
508 }
509 }
510 }
511 return ret;
512}
513
514void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
515 X509 **signer, X509_ALGOR **pdig,
516 X509_ALGOR **psig)
517{
518 if (pk)
519 *pk = si->pkey;
520 if (signer)
521 *signer = si->signer;
522 if (pdig)
523 *pdig = si->digestAlgorithm;
524 if (psig)
525 *psig = si->signatureAlgorithm;
526}
527
528ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
529{
530 return si->signature;
531}
532
533static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
534 CMS_SignerInfo *si, BIO *chain)
535{
536 EVP_MD_CTX *mctx = EVP_MD_CTX_new();
537 int r = 0;
538 EVP_PKEY_CTX *pctx = NULL;
539
540 if (mctx == NULL) {
541 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
542 return 0;
543 }
544
545 if (!si->pkey) {
546 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
547 goto err;
548 }
549
550 if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
551 goto err;
552 /* Set SignerInfo algorithm details if we used custom parameter */
553 if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
554 goto err;
555
556 /*
557 * If any signed attributes calculate and add messageDigest attribute
558 */
559
560 if (CMS_signed_get_attr_count(si) >= 0) {
561 ASN1_OBJECT *ctype =
562 cms->d.signedData->encapContentInfo->eContentType;
563 unsigned char md[EVP_MAX_MD_SIZE];
564 unsigned int mdlen;
565 if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
566 goto err;
567 if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
568 V_ASN1_OCTET_STRING, md, mdlen))
569 goto err;
570 /* Copy content type across */
571 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
572 V_ASN1_OBJECT, ctype, -1) <= 0)
573 goto err;
574 if (!CMS_SignerInfo_sign(si))
575 goto err;
576 } else if (si->pctx) {
577 unsigned char *sig;
578 size_t siglen;
579 unsigned char md[EVP_MAX_MD_SIZE];
580 unsigned int mdlen;
581 pctx = si->pctx;
582 if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
583 goto err;
584 siglen = EVP_PKEY_size(si->pkey);
585 sig = OPENSSL_malloc(siglen);
586 if (sig == NULL) {
587 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
588 goto err;
589 }
590 if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
591 OPENSSL_free(sig);
592 goto err;
593 }
594 ASN1_STRING_set0(si->signature, sig, siglen);
595 } else {
596 unsigned char *sig;
597 unsigned int siglen;
598 sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
599 if (sig == NULL) {
600 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
601 goto err;
602 }
603 if (!EVP_SignFinal(mctx, sig, &siglen, si->pkey)) {
604 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR);
605 OPENSSL_free(sig);
606 goto err;
607 }
608 ASN1_STRING_set0(si->signature, sig, siglen);
609 }
610
611 r = 1;
612
613 err:
614 EVP_MD_CTX_free(mctx);
615 EVP_PKEY_CTX_free(pctx);
616 return r;
617
618}
619
620int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
621{
622 STACK_OF(CMS_SignerInfo) *sinfos;
623 CMS_SignerInfo *si;
624 int i;
625 sinfos = CMS_get0_SignerInfos(cms);
626 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
627 si = sk_CMS_SignerInfo_value(sinfos, i);
628 if (!cms_SignerInfo_content_sign(cms, si, chain))
629 return 0;
630 }
631 cms->d.signedData->encapContentInfo->partial = 0;
632 return 1;
633}
634
635int CMS_SignerInfo_sign(CMS_SignerInfo *si)
636{
637 EVP_MD_CTX *mctx = si->mctx;
638 EVP_PKEY_CTX *pctx = NULL;
639 unsigned char *abuf = NULL;
640 int alen;
641 size_t siglen;
642 const EVP_MD *md = NULL;
643
644 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
645 if (md == NULL)
646 return 0;
647
648 if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
649 if (!cms_add1_signingTime(si, NULL))
650 goto err;
651 }
652
653 if (si->pctx)
654 pctx = si->pctx;
655 else {
656 EVP_MD_CTX_reset(mctx);
657 if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
658 goto err;
659 si->pctx = pctx;
660 }
661
662 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
663 EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
664 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
665 goto err;
666 }
667
668 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
669 ASN1_ITEM_rptr(CMS_Attributes_Sign));
670 if (!abuf)
671 goto err;
672 if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
673 goto err;
674 if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
675 goto err;
676 OPENSSL_free(abuf);
677 abuf = OPENSSL_malloc(siglen);
678 if (abuf == NULL)
679 goto err;
680 if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
681 goto err;
682
683 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
684 EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
685 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
686 goto err;
687 }
688
689 EVP_MD_CTX_reset(mctx);
690
691 ASN1_STRING_set0(si->signature, abuf, siglen);
692
693 return 1;
694
695 err:
696 OPENSSL_free(abuf);
697 EVP_MD_CTX_reset(mctx);
698 return 0;
699
700}
701
702int CMS_SignerInfo_verify(CMS_SignerInfo *si)
703{
704 EVP_MD_CTX *mctx = NULL;
705 unsigned char *abuf = NULL;
706 int alen, r = -1;
707 const EVP_MD *md = NULL;
708
709 if (!si->pkey) {
710 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
711 return -1;
712 }
713
714 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
715 if (md == NULL)
716 return -1;
717 if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
718 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, ERR_R_MALLOC_FAILURE);
719 return -1;
720 }
721 mctx = si->mctx;
722 if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0)
723 goto err;
724
725 if (!cms_sd_asn1_ctrl(si, 1))
726 goto err;
727
728 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
729 ASN1_ITEM_rptr(CMS_Attributes_Verify));
730 if (!abuf)
731 goto err;
732 r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
733 OPENSSL_free(abuf);
734 if (r <= 0) {
735 r = -1;
736 goto err;
737 }
738 r = EVP_DigestVerifyFinal(mctx,
739 si->signature->data, si->signature->length);
740 if (r <= 0)
741 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
742 err:
743 EVP_MD_CTX_reset(mctx);
744 return r;
745}
746
747/* Create a chain of digest BIOs from a CMS ContentInfo */
748
749BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
750{
751 int i;
752 CMS_SignedData *sd;
753 BIO *chain = NULL;
754 sd = cms_get0_signed(cms);
755 if (!sd)
756 return NULL;
757 if (cms->d.signedData->encapContentInfo->partial)
758 cms_sd_set_version(sd);
759 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
760 X509_ALGOR *digestAlgorithm;
761 BIO *mdbio;
762 digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
763 mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
764 if (!mdbio)
765 goto err;
766 if (chain)
767 BIO_push(chain, mdbio);
768 else
769 chain = mdbio;
770 }
771 return chain;
772 err:
773 BIO_free_all(chain);
774 return NULL;
775}
776
777int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
778{
779 ASN1_OCTET_STRING *os = NULL;
780 EVP_MD_CTX *mctx = EVP_MD_CTX_new();
781 EVP_PKEY_CTX *pkctx = NULL;
782 int r = -1;
783 unsigned char mval[EVP_MAX_MD_SIZE];
784 unsigned int mlen;
785
786 if (mctx == NULL) {
787 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, ERR_R_MALLOC_FAILURE);
788 goto err;
789 }
790 /* If we have any signed attributes look for messageDigest value */
791 if (CMS_signed_get_attr_count(si) >= 0) {
792 os = CMS_signed_get0_data_by_OBJ(si,
793 OBJ_nid2obj(NID_pkcs9_messageDigest),
794 -3, V_ASN1_OCTET_STRING);
795 if (!os) {
796 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
797 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
798 goto err;
799 }
800 }
801
802 if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
803 goto err;
804
805 if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) {
806 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
807 CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
808 goto err;
809 }
810
811 /* If messageDigest found compare it */
812
813 if (os) {
814 if (mlen != (unsigned int)os->length) {
815 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
816 CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
817 goto err;
818 }
819
820 if (memcmp(mval, os->data, mlen)) {
821 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
822 CMS_R_VERIFICATION_FAILURE);
823 r = 0;
824 } else
825 r = 1;
826 } else {
827 const EVP_MD *md = EVP_MD_CTX_md(mctx);
828 pkctx = EVP_PKEY_CTX_new(si->pkey, NULL);
829 if (pkctx == NULL)
830 goto err;
831 if (EVP_PKEY_verify_init(pkctx) <= 0)
832 goto err;
833 if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
834 goto err;
835 si->pctx = pkctx;
836 if (!cms_sd_asn1_ctrl(si, 1))
837 goto err;
838 r = EVP_PKEY_verify(pkctx, si->signature->data,
839 si->signature->length, mval, mlen);
840 if (r <= 0) {
841 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
842 CMS_R_VERIFICATION_FAILURE);
843 r = 0;
844 }
845 }
846
847 err:
848 EVP_PKEY_CTX_free(pkctx);
849 EVP_MD_CTX_free(mctx);
850 return r;
851
852}
853
854int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
855{
856 unsigned char *smder = NULL;
857 int smderlen, r;
858 smderlen = i2d_X509_ALGORS(algs, &smder);
859 if (smderlen <= 0)
860 return 0;
861 r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
862 V_ASN1_SEQUENCE, smder, smderlen);
863 OPENSSL_free(smder);
864 return r;
865}
866
867int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
868 int algnid, int keysize)
869{
870 X509_ALGOR *alg;
871 ASN1_INTEGER *key = NULL;
872 if (keysize > 0) {
873 key = ASN1_INTEGER_new();
874 if (key == NULL || !ASN1_INTEGER_set(key, keysize))
875 return 0;
876 }
877 alg = X509_ALGOR_new();
878 if (alg == NULL) {
879 ASN1_INTEGER_free(key);
880 return 0;
881 }
882
883 X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
884 key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
885 if (*algs == NULL)
886 *algs = sk_X509_ALGOR_new_null();
887 if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) {
888 X509_ALGOR_free(alg);
889 return 0;
890 }
891 return 1;
892}
893
894/* Check to see if a cipher exists and if so add S/MIME capabilities */
895
896static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
897{
898 if (EVP_get_cipherbynid(nid))
899 return CMS_add_simple_smimecap(sk, nid, arg);
900 return 1;
901}
902
903static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
904{
905 if (EVP_get_digestbynid(nid))
906 return CMS_add_simple_smimecap(sk, nid, arg);
907 return 1;
908}
909
910int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
911{
912 if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
913 || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1)
914 || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1)
915 || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
916 || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
917 || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
918 || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
919 || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
920 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
921 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
922 || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
923 || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
924 return 0;
925 return 1;
926}