2 * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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
10 #include "internal/cryptlib.h"
11 #include <openssl/asn1t.h>
12 #include <openssl/pem.h>
13 #include <openssl/rand.h>
14 #include <openssl/x509v3.h>
15 #include <openssl/err.h>
16 #include <openssl/cms.h>
17 #include <openssl/ess.h>
18 #include "crypto/ess.h"
19 #include "crypto/cms.h"
20 #include "crypto/x509.h"
21 #include "cms_local.h"
23 DEFINE_STACK_OF(ESS_CERT_ID
)
24 DEFINE_STACK_OF(ESS_CERT_ID_V2
)
26 IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest
)
30 int CMS_get1_ReceiptRequest(CMS_SignerInfo
*si
, CMS_ReceiptRequest
**prr
)
33 CMS_ReceiptRequest
*rr
;
34 ASN1_OBJECT
*obj
= OBJ_nid2obj(NID_id_smime_aa_receiptRequest
);
38 str
= CMS_signed_get0_data_by_OBJ(si
, obj
, -3, V_ASN1_SEQUENCE
);
42 rr
= ASN1_item_unpack(str
, ASN1_ITEM_rptr(CMS_ReceiptRequest
));
48 CMS_ReceiptRequest_free(rr
);
53 First, get the ESS_SIGNING_CERT(V2) signed attribute from |si|.
54 Then check matching of each cert of trust |chain| with one of
55 the |cert_ids|(Hash+IssuerID) list from this ESS_SIGNING_CERT.
56 Derived from ts_check_signing_certs()
58 int ess_check_signing_certs(CMS_SignerInfo
*si
, STACK_OF(X509
) *chain
)
60 ESS_SIGNING_CERT
*ss
= NULL
;
61 ESS_SIGNING_CERT_V2
*ssv2
= NULL
;
65 if (cms_signerinfo_get_signing_cert(si
, &ss
) > 0 && ss
->cert_ids
!= NULL
) {
66 STACK_OF(ESS_CERT_ID
) *cert_ids
= ss
->cert_ids
;
68 cert
= sk_X509_value(chain
, 0);
69 if (ess_find_cert(cert_ids
, cert
) != 0)
73 * Check the other certificates of the chain.
74 * Fail if no signing certificate ids found for each certificate.
76 if (sk_ESS_CERT_ID_num(cert_ids
) > 1) {
77 /* for each chain cert, try to find its cert id */
78 for (i
= 1; i
< sk_X509_num(chain
); ++i
) {
79 cert
= sk_X509_value(chain
, i
);
80 if (ess_find_cert(cert_ids
, cert
) < 0)
84 } else if (cms_signerinfo_get_signing_cert_v2(si
, &ssv2
) > 0
85 && ssv2
->cert_ids
!= NULL
) {
86 STACK_OF(ESS_CERT_ID_V2
) *cert_ids_v2
= ssv2
->cert_ids
;
88 cert
= sk_X509_value(chain
, 0);
89 if (ess_find_cert_v2(cert_ids_v2
, cert
) != 0)
93 * Check the other certificates of the chain.
94 * Fail if no signing certificate ids found for each certificate.
96 if (sk_ESS_CERT_ID_V2_num(cert_ids_v2
) > 1) {
97 /* for each chain cert, try to find its cert id */
98 for (i
= 1; i
< sk_X509_num(chain
); ++i
) {
99 cert
= sk_X509_value(chain
, i
);
100 if (ess_find_cert_v2(cert_ids_v2
, cert
) < 0)
105 CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS
,
106 CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE
);
112 CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS
,
113 CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR
);
115 ESS_SIGNING_CERT_free(ss
);
116 ESS_SIGNING_CERT_V2_free(ssv2
);
120 CMS_ReceiptRequest
*CMS_ReceiptRequest_create0_with_libctx(
121 unsigned char *id
, int idlen
, int allorfirst
,
122 STACK_OF(GENERAL_NAMES
) *receiptList
, STACK_OF(GENERAL_NAMES
) *receiptsTo
,
123 OPENSSL_CTX
*libctx
, const char *propq
)
125 CMS_ReceiptRequest
*rr
;
127 rr
= CMS_ReceiptRequest_new();
131 ASN1_STRING_set0(rr
->signedContentIdentifier
, id
, idlen
);
133 if (!ASN1_STRING_set(rr
->signedContentIdentifier
, NULL
, 32))
135 if (RAND_bytes_ex(libctx
, rr
->signedContentIdentifier
->data
, 32) <= 0)
139 sk_GENERAL_NAMES_pop_free(rr
->receiptsTo
, GENERAL_NAMES_free
);
140 rr
->receiptsTo
= receiptsTo
;
142 if (receiptList
!= NULL
) {
143 rr
->receiptsFrom
->type
= 1;
144 rr
->receiptsFrom
->d
.receiptList
= receiptList
;
146 rr
->receiptsFrom
->type
= 0;
147 rr
->receiptsFrom
->d
.allOrFirstTier
= allorfirst
;
153 CMSerr(0, ERR_R_MALLOC_FAILURE
);
156 CMS_ReceiptRequest_free(rr
);
161 CMS_ReceiptRequest
*CMS_ReceiptRequest_create0(
162 unsigned char *id
, int idlen
, int allorfirst
,
163 STACK_OF(GENERAL_NAMES
) *receiptList
, STACK_OF(GENERAL_NAMES
) *receiptsTo
)
165 return CMS_ReceiptRequest_create0_with_libctx(id
, idlen
, allorfirst
,
166 receiptList
, receiptsTo
,
170 int CMS_add1_ReceiptRequest(CMS_SignerInfo
*si
, CMS_ReceiptRequest
*rr
)
172 unsigned char *rrder
= NULL
;
175 rrderlen
= i2d_CMS_ReceiptRequest(rr
, &rrder
);
179 if (!CMS_signed_add1_attr_by_NID(si
, NID_id_smime_aa_receiptRequest
,
180 V_ASN1_SEQUENCE
, rrder
, rrderlen
))
187 CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST
, ERR_R_MALLOC_FAILURE
);
195 void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest
*rr
,
198 STACK_OF(GENERAL_NAMES
) **plist
,
199 STACK_OF(GENERAL_NAMES
) **prto
)
202 *pcid
= rr
->signedContentIdentifier
;
203 if (rr
->receiptsFrom
->type
== 0) {
204 if (pallorfirst
!= NULL
)
205 *pallorfirst
= (int)rr
->receiptsFrom
->d
.allOrFirstTier
;
209 if (pallorfirst
!= NULL
)
212 *plist
= rr
->receiptsFrom
->d
.receiptList
;
215 *prto
= rr
->receiptsTo
;
218 /* Digest a SignerInfo structure for msgSigDigest attribute processing */
220 static int cms_msgSigDigest(CMS_SignerInfo
*si
,
221 unsigned char *dig
, unsigned int *diglen
)
223 const EVP_MD
*md
= EVP_get_digestbyobj(si
->digestAlgorithm
->algorithm
);
227 if (!asn1_item_digest_with_libctx(ASN1_ITEM_rptr(CMS_Attributes_Verify
), md
,
228 si
->signedAttrs
, dig
, diglen
,
229 si
->cms_ctx
->libctx
, si
->cms_ctx
->propq
))
234 /* Add a msgSigDigest attribute to a SignerInfo */
236 int cms_msgSigDigest_add1(CMS_SignerInfo
*dest
, CMS_SignerInfo
*src
)
238 unsigned char dig
[EVP_MAX_MD_SIZE
];
241 if (!cms_msgSigDigest(src
, dig
, &diglen
)) {
242 CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1
, CMS_R_MSGSIGDIGEST_ERROR
);
245 if (!CMS_signed_add1_attr_by_NID(dest
, NID_id_smime_aa_msgSigDigest
,
246 V_ASN1_OCTET_STRING
, dig
, diglen
)) {
247 CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1
, ERR_R_MALLOC_FAILURE
);
253 /* Verify signed receipt after it has already passed normal CMS verify */
255 int cms_Receipt_verify(CMS_ContentInfo
*cms
, CMS_ContentInfo
*req_cms
)
258 CMS_ReceiptRequest
*rr
= NULL
;
259 CMS_Receipt
*rct
= NULL
;
260 STACK_OF(CMS_SignerInfo
) *sis
, *osis
;
261 CMS_SignerInfo
*si
, *osi
= NULL
;
262 ASN1_OCTET_STRING
*msig
, **pcont
;
264 unsigned char dig
[EVP_MAX_MD_SIZE
];
267 /* Get SignerInfos, also checks SignedData content type */
268 osis
= CMS_get0_SignerInfos(req_cms
);
269 sis
= CMS_get0_SignerInfos(cms
);
273 if (sk_CMS_SignerInfo_num(sis
) != 1) {
274 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NEED_ONE_SIGNER
);
278 /* Check receipt content type */
279 if (OBJ_obj2nid(CMS_get0_eContentType(cms
)) != NID_id_smime_ct_receipt
) {
280 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NOT_A_SIGNED_RECEIPT
);
284 /* Extract and decode receipt content */
285 pcont
= CMS_get0_content(cms
);
286 if (pcont
== NULL
|| *pcont
== NULL
) {
287 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NO_CONTENT
);
291 rct
= ASN1_item_unpack(*pcont
, ASN1_ITEM_rptr(CMS_Receipt
));
294 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_RECEIPT_DECODE_ERROR
);
298 /* Locate original request */
300 for (i
= 0; i
< sk_CMS_SignerInfo_num(osis
); i
++) {
301 osi
= sk_CMS_SignerInfo_value(osis
, i
);
302 if (!ASN1_STRING_cmp(osi
->signature
, rct
->originatorSignatureValue
))
306 if (i
== sk_CMS_SignerInfo_num(osis
)) {
307 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NO_MATCHING_SIGNATURE
);
311 si
= sk_CMS_SignerInfo_value(sis
, 0);
313 /* Get msgSigDigest value and compare */
315 msig
= CMS_signed_get0_data_by_OBJ(si
,
317 (NID_id_smime_aa_msgSigDigest
), -3,
318 V_ASN1_OCTET_STRING
);
321 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NO_MSGSIGDIGEST
);
325 if (!cms_msgSigDigest(osi
, dig
, &diglen
)) {
326 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_MSGSIGDIGEST_ERROR
);
330 if (diglen
!= (unsigned int)msig
->length
) {
331 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_MSGSIGDIGEST_WRONG_LENGTH
);
335 if (memcmp(dig
, msig
->data
, diglen
)) {
336 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
,
337 CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE
);
341 /* Compare content types */
343 octype
= CMS_signed_get0_data_by_OBJ(osi
,
344 OBJ_nid2obj(NID_pkcs9_contentType
),
347 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NO_CONTENT_TYPE
);
351 /* Compare details in receipt request */
353 if (OBJ_cmp(octype
, rct
->contentType
)) {
354 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_CONTENT_TYPE_MISMATCH
);
358 /* Get original receipt request details */
360 if (CMS_get1_ReceiptRequest(osi
, &rr
) <= 0) {
361 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_NO_RECEIPT_REQUEST
);
365 if (ASN1_STRING_cmp(rr
->signedContentIdentifier
,
366 rct
->signedContentIdentifier
)) {
367 CMSerr(CMS_F_CMS_RECEIPT_VERIFY
, CMS_R_CONTENTIDENTIFIER_MISMATCH
);
374 CMS_ReceiptRequest_free(rr
);
375 M_ASN1_free_of(rct
, CMS_Receipt
);
381 * Encode a Receipt into an OCTET STRING read for including into content of a
382 * SignedData ContentInfo.
385 ASN1_OCTET_STRING
*cms_encode_Receipt(CMS_SignerInfo
*si
)
388 CMS_ReceiptRequest
*rr
= NULL
;
390 ASN1_OCTET_STRING
*os
= NULL
;
392 /* Get original receipt request */
394 /* Get original receipt request details */
396 if (CMS_get1_ReceiptRequest(si
, &rr
) <= 0) {
397 CMSerr(CMS_F_CMS_ENCODE_RECEIPT
, CMS_R_NO_RECEIPT_REQUEST
);
401 /* Get original content type */
403 ctype
= CMS_signed_get0_data_by_OBJ(si
,
404 OBJ_nid2obj(NID_pkcs9_contentType
),
407 CMSerr(CMS_F_CMS_ENCODE_RECEIPT
, CMS_R_NO_CONTENT_TYPE
);
412 rct
.contentType
= ctype
;
413 rct
.signedContentIdentifier
= rr
->signedContentIdentifier
;
414 rct
.originatorSignatureValue
= si
->signature
;
416 os
= ASN1_item_pack(&rct
, ASN1_ITEM_rptr(CMS_Receipt
), NULL
);
419 CMS_ReceiptRequest_free(rr
);
424 * Add signer certificate's V2 digest |sc| to a SignerInfo structure |si|
427 int cms_add1_signing_cert_v2(CMS_SignerInfo
*si
, ESS_SIGNING_CERT_V2
*sc
)
429 ASN1_STRING
*seq
= NULL
;
430 unsigned char *p
, *pp
= NULL
;
433 /* Add SigningCertificateV2 signed attribute to the signer info. */
434 len
= i2d_ESS_SIGNING_CERT_V2(sc
, NULL
);
435 if (len
<= 0 || (pp
= OPENSSL_malloc(len
)) == NULL
)
438 i2d_ESS_SIGNING_CERT_V2(sc
, &p
);
439 if (!(seq
= ASN1_STRING_new()) || !ASN1_STRING_set(seq
, pp
, len
))
443 if (!CMS_signed_add1_attr_by_NID(si
, NID_id_smime_aa_signingCertificateV2
,
444 V_ASN1_SEQUENCE
, seq
, -1))
446 ASN1_STRING_free(seq
);
449 CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT_V2
, ERR_R_MALLOC_FAILURE
);
450 ASN1_STRING_free(seq
);
456 * Add signer certificate's digest |sc| to a SignerInfo structure |si|
459 int cms_add1_signing_cert(CMS_SignerInfo
*si
, ESS_SIGNING_CERT
*sc
)
461 ASN1_STRING
*seq
= NULL
;
462 unsigned char *p
, *pp
= NULL
;
465 /* Add SigningCertificate signed attribute to the signer info. */
466 len
= i2d_ESS_SIGNING_CERT(sc
, NULL
);
467 if (len
<= 0 || (pp
= OPENSSL_malloc(len
)) == NULL
)
470 i2d_ESS_SIGNING_CERT(sc
, &p
);
471 if (!(seq
= ASN1_STRING_new()) || !ASN1_STRING_set(seq
, pp
, len
))
475 if (!CMS_signed_add1_attr_by_NID(si
, NID_id_smime_aa_signingCertificate
,
476 V_ASN1_SEQUENCE
, seq
, -1))
478 ASN1_STRING_free(seq
);
481 CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT
, ERR_R_MALLOC_FAILURE
);
482 ASN1_STRING_free(seq
);