summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cms/cms_ess.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_ess.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_ess.c')
-rw-r--r--src/lib/libcrypto/cms/cms_ess.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/lib/libcrypto/cms/cms_ess.c b/src/lib/libcrypto/cms/cms_ess.c
new file mode 100644
index 0000000000..4780231c22
--- /dev/null
+++ b/src/lib/libcrypto/cms/cms_ess.c
@@ -0,0 +1,337 @@
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/rand.h>
14#include <openssl/x509v3.h>
15#include <openssl/err.h>
16#include <openssl/cms.h>
17#include "cms_lcl.h"
18
19IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
20
21/* ESS services: for now just Signed Receipt related */
22
23int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
24{
25 ASN1_STRING *str;
26 CMS_ReceiptRequest *rr = NULL;
27 if (prr)
28 *prr = NULL;
29 str = CMS_signed_get0_data_by_OBJ(si,
30 OBJ_nid2obj
31 (NID_id_smime_aa_receiptRequest), -3,
32 V_ASN1_SEQUENCE);
33 if (!str)
34 return 0;
35
36 rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
37 if (!rr)
38 return -1;
39 if (prr)
40 *prr = rr;
41 else
42 CMS_ReceiptRequest_free(rr);
43 return 1;
44}
45
46CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
47 int allorfirst,
48 STACK_OF(GENERAL_NAMES)
49 *receiptList, STACK_OF(GENERAL_NAMES)
50 *receiptsTo)
51{
52 CMS_ReceiptRequest *rr = NULL;
53
54 rr = CMS_ReceiptRequest_new();
55 if (rr == NULL)
56 goto merr;
57 if (id)
58 ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen);
59 else {
60 if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
61 goto merr;
62 if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
63 goto err;
64 }
65
66 sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
67 rr->receiptsTo = receiptsTo;
68
69 if (receiptList) {
70 rr->receiptsFrom->type = 1;
71 rr->receiptsFrom->d.receiptList = receiptList;
72 } else {
73 rr->receiptsFrom->type = 0;
74 rr->receiptsFrom->d.allOrFirstTier = allorfirst;
75 }
76
77 return rr;
78
79 merr:
80 CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
81
82 err:
83 CMS_ReceiptRequest_free(rr);
84 return NULL;
85
86}
87
88int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
89{
90 unsigned char *rrder = NULL;
91 int rrderlen, r = 0;
92
93 rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
94 if (rrderlen < 0)
95 goto merr;
96
97 if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
98 V_ASN1_SEQUENCE, rrder, rrderlen))
99 goto merr;
100
101 r = 1;
102
103 merr:
104 if (!r)
105 CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
106
107 OPENSSL_free(rrder);
108
109 return r;
110
111}
112
113void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
114 ASN1_STRING **pcid,
115 int *pallorfirst,
116 STACK_OF(GENERAL_NAMES) **plist,
117 STACK_OF(GENERAL_NAMES) **prto)
118{
119 if (pcid)
120 *pcid = rr->signedContentIdentifier;
121 if (rr->receiptsFrom->type == 0) {
122 if (pallorfirst)
123 *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
124 if (plist)
125 *plist = NULL;
126 } else {
127 if (pallorfirst)
128 *pallorfirst = -1;
129 if (plist)
130 *plist = rr->receiptsFrom->d.receiptList;
131 }
132 if (prto)
133 *prto = rr->receiptsTo;
134}
135
136/* Digest a SignerInfo structure for msgSigDigest attribute processing */
137
138static int cms_msgSigDigest(CMS_SignerInfo *si,
139 unsigned char *dig, unsigned int *diglen)
140{
141 const EVP_MD *md;
142 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
143 if (md == NULL)
144 return 0;
145 if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
146 si->signedAttrs, dig, diglen))
147 return 0;
148 return 1;
149}
150
151/* Add a msgSigDigest attribute to a SignerInfo */
152
153int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
154{
155 unsigned char dig[EVP_MAX_MD_SIZE];
156 unsigned int diglen;
157 if (!cms_msgSigDigest(src, dig, &diglen)) {
158 CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
159 return 0;
160 }
161 if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
162 V_ASN1_OCTET_STRING, dig, diglen)) {
163 CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
164 return 0;
165 }
166 return 1;
167}
168
169/* Verify signed receipt after it has already passed normal CMS verify */
170
171int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
172{
173 int r = 0, i;
174 CMS_ReceiptRequest *rr = NULL;
175 CMS_Receipt *rct = NULL;
176 STACK_OF(CMS_SignerInfo) *sis, *osis;
177 CMS_SignerInfo *si, *osi = NULL;
178 ASN1_OCTET_STRING *msig, **pcont;
179 ASN1_OBJECT *octype;
180 unsigned char dig[EVP_MAX_MD_SIZE];
181 unsigned int diglen;
182
183 /* Get SignerInfos, also checks SignedData content type */
184 osis = CMS_get0_SignerInfos(req_cms);
185 sis = CMS_get0_SignerInfos(cms);
186 if (!osis || !sis)
187 goto err;
188
189 if (sk_CMS_SignerInfo_num(sis) != 1) {
190 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER);
191 goto err;
192 }
193
194 /* Check receipt content type */
195 if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) {
196 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT);
197 goto err;
198 }
199
200 /* Extract and decode receipt content */
201 pcont = CMS_get0_content(cms);
202 if (!pcont || !*pcont) {
203 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT);
204 goto err;
205 }
206
207 rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt));
208
209 if (!rct) {
210 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR);
211 goto err;
212 }
213
214 /* Locate original request */
215
216 for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++) {
217 osi = sk_CMS_SignerInfo_value(osis, i);
218 if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue))
219 break;
220 }
221
222 if (i == sk_CMS_SignerInfo_num(osis)) {
223 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE);
224 goto err;
225 }
226
227 si = sk_CMS_SignerInfo_value(sis, 0);
228
229 /* Get msgSigDigest value and compare */
230
231 msig = CMS_signed_get0_data_by_OBJ(si,
232 OBJ_nid2obj
233 (NID_id_smime_aa_msgSigDigest), -3,
234 V_ASN1_OCTET_STRING);
235
236 if (!msig) {
237 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST);
238 goto err;
239 }
240
241 if (!cms_msgSigDigest(osi, dig, &diglen)) {
242 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR);
243 goto err;
244 }
245
246 if (diglen != (unsigned int)msig->length) {
247 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
248 goto err;
249 }
250
251 if (memcmp(dig, msig->data, diglen)) {
252 CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
253 CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
254 goto err;
255 }
256
257 /* Compare content types */
258
259 octype = CMS_signed_get0_data_by_OBJ(osi,
260 OBJ_nid2obj(NID_pkcs9_contentType),
261 -3, V_ASN1_OBJECT);
262 if (!octype) {
263 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE);
264 goto err;
265 }
266
267 /* Compare details in receipt request */
268
269 if (OBJ_cmp(octype, rct->contentType)) {
270 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH);
271 goto err;
272 }
273
274 /* Get original receipt request details */
275
276 if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) {
277 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST);
278 goto err;
279 }
280
281 if (ASN1_STRING_cmp(rr->signedContentIdentifier,
282 rct->signedContentIdentifier)) {
283 CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENTIDENTIFIER_MISMATCH);
284 goto err;
285 }
286
287 r = 1;
288
289 err:
290 CMS_ReceiptRequest_free(rr);
291 M_ASN1_free_of(rct, CMS_Receipt);
292 return r;
293
294}
295
296/*
297 * Encode a Receipt into an OCTET STRING read for including into content of a
298 * SignedData ContentInfo.
299 */
300
301ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
302{
303 CMS_Receipt rct;
304 CMS_ReceiptRequest *rr = NULL;
305 ASN1_OBJECT *ctype;
306 ASN1_OCTET_STRING *os = NULL;
307
308 /* Get original receipt request */
309
310 /* Get original receipt request details */
311
312 if (CMS_get1_ReceiptRequest(si, &rr) <= 0) {
313 CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
314 goto err;
315 }
316
317 /* Get original content type */
318
319 ctype = CMS_signed_get0_data_by_OBJ(si,
320 OBJ_nid2obj(NID_pkcs9_contentType),
321 -3, V_ASN1_OBJECT);
322 if (!ctype) {
323 CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
324 goto err;
325 }
326
327 rct.version = 1;
328 rct.contentType = ctype;
329 rct.signedContentIdentifier = rr->signedContentIdentifier;
330 rct.originatorSignatureValue = si->signature;
331
332 os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL);
333
334 err:
335 CMS_ReceiptRequest_free(rr);
336 return os;
337}