File: | src/lib/libcrypto/cms/cms_ess.c |
Warning: | line 209, column 7 Access to field 'digestAlgorithm' results in a dereference of a null pointer (loaded from variable 'si') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: cms_ess.c,v 1.21 2019/08/11 14:19:09 jsing Exp $ */ | |||
2 | /* | |||
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | |||
4 | * project. | |||
5 | */ | |||
6 | /* ==================================================================== | |||
7 | * Copyright (c) 2008 The OpenSSL Project. All rights reserved. | |||
8 | * | |||
9 | * Redistribution and use in source and binary forms, with or without | |||
10 | * modification, are permitted provided that the following conditions | |||
11 | * are met: | |||
12 | * | |||
13 | * 1. Redistributions of source code must retain the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer. | |||
15 | * | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in | |||
18 | * the documentation and/or other materials provided with the | |||
19 | * distribution. | |||
20 | * | |||
21 | * 3. All advertising materials mentioning features or use of this | |||
22 | * software must display the following acknowledgment: | |||
23 | * "This product includes software developed by the OpenSSL Project | |||
24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |||
25 | * | |||
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
27 | * endorse or promote products derived from this software without | |||
28 | * prior written permission. For written permission, please contact | |||
29 | * licensing@OpenSSL.org. | |||
30 | * | |||
31 | * 5. Products derived from this software may not be called "OpenSSL" | |||
32 | * nor may "OpenSSL" appear in their names without prior written | |||
33 | * permission of the OpenSSL Project. | |||
34 | * | |||
35 | * 6. Redistributions of any form whatsoever must retain the following | |||
36 | * acknowledgment: | |||
37 | * "This product includes software developed by the OpenSSL Project | |||
38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |||
39 | * | |||
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |||
52 | * ==================================================================== | |||
53 | */ | |||
54 | ||||
55 | #include <string.h> | |||
56 | ||||
57 | #include "cryptlib.h" | |||
58 | #include <openssl/asn1t.h> | |||
59 | #include <openssl/pem.h> | |||
60 | #include <openssl/rand.h> | |||
61 | #include <openssl/x509v3.h> | |||
62 | #include <openssl/err.h> | |||
63 | #include <openssl/cms.h> | |||
64 | #include "cms_lcl.h" | |||
65 | ||||
66 | ||||
67 | CMS_ReceiptRequest * | |||
68 | d2i_CMS_ReceiptRequest(CMS_ReceiptRequest **a, const unsigned char **in, long len) | |||
69 | { | |||
70 | return (CMS_ReceiptRequest *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | |||
71 | &CMS_ReceiptRequest_it); | |||
72 | } | |||
73 | ||||
74 | int | |||
75 | i2d_CMS_ReceiptRequest(CMS_ReceiptRequest *a, unsigned char **out) | |||
76 | { | |||
77 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ReceiptRequest_it); | |||
78 | } | |||
79 | ||||
80 | CMS_ReceiptRequest * | |||
81 | CMS_ReceiptRequest_new(void) | |||
82 | { | |||
83 | return (CMS_ReceiptRequest *)ASN1_item_new(&CMS_ReceiptRequest_it); | |||
84 | } | |||
85 | ||||
86 | void | |||
87 | CMS_ReceiptRequest_free(CMS_ReceiptRequest *a) | |||
88 | { | |||
89 | ASN1_item_free((ASN1_VALUE *)a, &CMS_ReceiptRequest_it); | |||
90 | } | |||
91 | ||||
92 | /* ESS services: for now just Signed Receipt related */ | |||
93 | ||||
94 | int | |||
95 | CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr) | |||
96 | { | |||
97 | ASN1_STRING *str; | |||
98 | CMS_ReceiptRequest *rr = NULL((void*)0); | |||
99 | ||||
100 | if (prr) | |||
101 | *prr = NULL((void*)0); | |||
102 | str = CMS_signed_get0_data_by_OBJ(si, | |||
103 | OBJ_nid2obj(NID_id_smime_aa_receiptRequest212), -3, V_ASN1_SEQUENCE16); | |||
104 | if (!str) | |||
105 | return 0; | |||
106 | ||||
107 | rr = ASN1_item_unpack(str, &CMS_ReceiptRequest_it); | |||
108 | if (!rr) | |||
109 | return -1; | |||
110 | if (prr) | |||
111 | *prr = rr; | |||
112 | else | |||
113 | CMS_ReceiptRequest_free(rr); | |||
114 | ||||
115 | return 1; | |||
116 | } | |||
117 | ||||
118 | CMS_ReceiptRequest * | |||
119 | CMS_ReceiptRequest_create0(unsigned char *id, int idlen, int allorfirst, | |||
120 | STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES *receiptList, STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES *receiptsTo) | |||
121 | { | |||
122 | CMS_ReceiptRequest *rr = NULL((void*)0); | |||
123 | ||||
124 | rr = CMS_ReceiptRequest_new(); | |||
125 | if (rr == NULL((void*)0)) | |||
126 | goto merr; | |||
127 | if (id) | |||
128 | ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); | |||
129 | else { | |||
130 | if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL((void*)0), 32)) | |||
131 | goto merr; | |||
132 | arc4random_buf(rr->signedContentIdentifier->data, 32); | |||
133 | } | |||
134 | ||||
135 | sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free)sk_pop_free(((_STACK*) (1 ? (rr->receiptsTo) : (struct stack_st_GENERAL_NAMES *)0)), ((void (*)(void *)) ((1 ? (GENERAL_NAMES_free) : (void (*)(GENERAL_NAMES *))0)))); | |||
136 | rr->receiptsTo = receiptsTo; | |||
137 | ||||
138 | if (receiptList) { | |||
139 | rr->receiptsFrom->type = 1; | |||
140 | rr->receiptsFrom->d.receiptList = receiptList; | |||
141 | } else { | |||
142 | rr->receiptsFrom->type = 0; | |||
143 | rr->receiptsFrom->d.allOrFirstTier = allorfirst; | |||
144 | } | |||
145 | ||||
146 | return rr; | |||
147 | ||||
148 | merr: | |||
149 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,149); | |||
150 | CMS_ReceiptRequest_free(rr); | |||
151 | ||||
152 | return NULL((void*)0); | |||
153 | } | |||
154 | ||||
155 | int | |||
156 | CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr) | |||
157 | { | |||
158 | unsigned char *rrder = NULL((void*)0); | |||
159 | int rrderlen, r = 0; | |||
160 | ||||
161 | rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder); | |||
162 | if (rrderlen < 0) | |||
163 | goto merr; | |||
164 | ||||
165 | if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest212, | |||
166 | V_ASN1_SEQUENCE16, rrder, rrderlen)) | |||
167 | goto merr; | |||
168 | ||||
169 | r = 1; | |||
170 | ||||
171 | merr: | |||
172 | if (!r) | |||
173 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,173); | |||
174 | ||||
175 | free(rrder); | |||
176 | ||||
177 | return r; | |||
178 | } | |||
179 | ||||
180 | void | |||
181 | CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid, | |||
182 | int *pallorfirst, STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES **plist, | |||
183 | STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES **prto) | |||
184 | { | |||
185 | if (pcid) | |||
186 | *pcid = rr->signedContentIdentifier; | |||
187 | if (rr->receiptsFrom->type == 0) { | |||
188 | if (pallorfirst) | |||
189 | *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier; | |||
190 | if (plist) | |||
191 | *plist = NULL((void*)0); | |||
192 | } else { | |||
193 | if (pallorfirst) | |||
194 | *pallorfirst = -1; | |||
195 | if (plist) | |||
196 | *plist = rr->receiptsFrom->d.receiptList; | |||
197 | } | |||
198 | if (prto) | |||
199 | *prto = rr->receiptsTo; | |||
200 | } | |||
201 | ||||
202 | /* Digest a SignerInfo structure for msgSigDigest attribute processing */ | |||
203 | ||||
204 | static int | |||
205 | cms_msgSigDigest(CMS_SignerInfo *si, unsigned char *dig, unsigned int *diglen) | |||
206 | { | |||
207 | const EVP_MD *md; | |||
208 | ||||
209 | md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid(si->digestAlgorithm ->algorithm))); | |||
| ||||
210 | if (md == NULL((void*)0)) | |||
211 | return 0; | |||
212 | if (!ASN1_item_digest(&CMS_Attributes_Verify_it, md, | |||
213 | si->signedAttrs, dig, diglen)) | |||
214 | return 0; | |||
215 | ||||
216 | return 1; | |||
217 | } | |||
218 | ||||
219 | /* Add a msgSigDigest attribute to a SignerInfo */ | |||
220 | ||||
221 | int | |||
222 | cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) | |||
223 | { | |||
224 | unsigned char dig[EVP_MAX_MD_SIZE64]; | |||
225 | unsigned int diglen; | |||
226 | ||||
227 | if (!cms_msgSigDigest(src, dig, &diglen)) { | |||
228 | CMSerror(CMS_R_MSGSIGDIGEST_ERROR)ERR_put_error(46,(0xfff),(172),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,228); | |||
229 | return 0; | |||
230 | } | |||
231 | if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest216, | |||
232 | V_ASN1_OCTET_STRING4, dig, diglen)) { | |||
233 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,233); | |||
234 | return 0; | |||
235 | } | |||
236 | ||||
237 | return 1; | |||
238 | } | |||
239 | ||||
240 | /* Verify signed receipt after it has already passed normal CMS verify */ | |||
241 | ||||
242 | int | |||
243 | cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) | |||
244 | { | |||
245 | int r = 0, i; | |||
246 | CMS_ReceiptRequest *rr = NULL((void*)0); | |||
247 | CMS_Receipt *rct = NULL((void*)0); | |||
248 | STACK_OF(CMS_SignerInfo)struct stack_st_CMS_SignerInfo *sis, *osis; | |||
249 | CMS_SignerInfo *si, *osi = NULL((void*)0); | |||
| ||||
250 | ASN1_OCTET_STRING *msig, **pcont; | |||
251 | ASN1_OBJECT *octype; | |||
252 | unsigned char dig[EVP_MAX_MD_SIZE64]; | |||
253 | unsigned int diglen; | |||
254 | ||||
255 | /* Get SignerInfos, also checks SignedData content type */ | |||
256 | osis = CMS_get0_SignerInfos(req_cms); | |||
257 | sis = CMS_get0_SignerInfos(cms); | |||
258 | if (!osis || !sis) | |||
259 | goto err; | |||
260 | ||||
261 | if (sk_CMS_SignerInfo_num(sis)sk_num(((_STACK*) (1 ? (sis) : (struct stack_st_CMS_SignerInfo *)0))) != 1) { | |||
262 | CMSerror(CMS_R_NEED_ONE_SIGNER)ERR_put_error(46,(0xfff),(164),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,262); | |||
263 | goto err; | |||
264 | } | |||
265 | ||||
266 | /* Check receipt content type */ | |||
267 | if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt204) { | |||
268 | CMSerror(CMS_R_NOT_A_SIGNED_RECEIPT)ERR_put_error(46,(0xfff),(165),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,268); | |||
269 | goto err; | |||
270 | } | |||
271 | ||||
272 | /* Extract and decode receipt content */ | |||
273 | pcont = CMS_get0_content(cms); | |||
274 | if (!pcont || !*pcont) { | |||
275 | CMSerror(CMS_R_NO_CONTENT)ERR_put_error(46,(0xfff),(127),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,275); | |||
276 | goto err; | |||
277 | } | |||
278 | ||||
279 | rct = ASN1_item_unpack(*pcont, &CMS_Receipt_it); | |||
280 | ||||
281 | if (!rct) { | |||
282 | CMSerror(CMS_R_RECEIPT_DECODE_ERROR)ERR_put_error(46,(0xfff),(169),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,282); | |||
283 | goto err; | |||
284 | } | |||
285 | ||||
286 | /* Locate original request */ | |||
287 | ||||
288 | for (i = 0; i < sk_CMS_SignerInfo_num(osis)sk_num(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0))); i++) { | |||
289 | osi = sk_CMS_SignerInfo_value(osis, i)((CMS_SignerInfo *)sk_value(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0)), (i))); | |||
290 | if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue)) | |||
291 | break; | |||
292 | } | |||
293 | ||||
294 | if (i == sk_CMS_SignerInfo_num(osis)sk_num(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0)))) { | |||
295 | CMSerror(CMS_R_NO_MATCHING_SIGNATURE)ERR_put_error(46,(0xfff),(166),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,295); | |||
296 | goto err; | |||
297 | } | |||
298 | ||||
299 | si = sk_CMS_SignerInfo_value(sis, 0)((CMS_SignerInfo *)sk_value(((_STACK*) (1 ? (sis) : (struct stack_st_CMS_SignerInfo *)0)), (0))); | |||
300 | ||||
301 | /* Get msgSigDigest value and compare */ | |||
302 | ||||
303 | msig = CMS_signed_get0_data_by_OBJ(si, | |||
304 | OBJ_nid2obj(NID_id_smime_aa_msgSigDigest216), -3, V_ASN1_OCTET_STRING4); | |||
305 | ||||
306 | if (!msig) { | |||
307 | CMSerror(CMS_R_NO_MSGSIGDIGEST)ERR_put_error(46,(0xfff),(167),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,307); | |||
308 | goto err; | |||
309 | } | |||
310 | ||||
311 | if (!cms_msgSigDigest(osi, dig, &diglen)) { | |||
312 | CMSerror(CMS_R_MSGSIGDIGEST_ERROR)ERR_put_error(46,(0xfff),(172),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,312); | |||
313 | goto err; | |||
314 | } | |||
315 | ||||
316 | if (diglen != (unsigned int)msig->length) { | |||
317 | CMSerror(CMS_R_MSGSIGDIGEST_WRONG_LENGTH)ERR_put_error(46,(0xfff),(163),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,317); | |||
318 | goto err; | |||
319 | } | |||
320 | ||||
321 | if (memcmp(dig, msig->data, diglen)) { | |||
322 | CMSerror(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE)ERR_put_error(46,(0xfff),(162),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,322); | |||
323 | goto err; | |||
324 | } | |||
325 | ||||
326 | /* Compare content types */ | |||
327 | ||||
328 | octype = CMS_signed_get0_data_by_OBJ(osi, | |||
329 | OBJ_nid2obj(NID_pkcs9_contentType50), -3, V_ASN1_OBJECT6); | |||
330 | if (!octype) { | |||
331 | CMSerror(CMS_R_NO_CONTENT_TYPE)ERR_put_error(46,(0xfff),(173),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,331); | |||
332 | goto err; | |||
333 | } | |||
334 | ||||
335 | /* Compare details in receipt request */ | |||
336 | ||||
337 | if (OBJ_cmp(octype, rct->contentType)) { | |||
338 | CMSerror(CMS_R_CONTENT_TYPE_MISMATCH)ERR_put_error(46,(0xfff),(171),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,338); | |||
339 | goto err; | |||
340 | } | |||
341 | ||||
342 | /* Get original receipt request details */ | |||
343 | ||||
344 | if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) { | |||
345 | CMSerror(CMS_R_NO_RECEIPT_REQUEST)ERR_put_error(46,(0xfff),(168),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,345); | |||
346 | goto err; | |||
347 | } | |||
348 | ||||
349 | if (ASN1_STRING_cmp(rr->signedContentIdentifier, | |||
350 | rct->signedContentIdentifier)) { | |||
351 | CMSerror(CMS_R_CONTENTIDENTIFIER_MISMATCH)ERR_put_error(46,(0xfff),(170),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,351); | |||
352 | goto err; | |||
353 | } | |||
354 | ||||
355 | r = 1; | |||
356 | ||||
357 | err: | |||
358 | CMS_ReceiptRequest_free(rr); | |||
359 | ASN1_item_free((ASN1_VALUE *)rct, &CMS_Receipt_it); | |||
360 | return r; | |||
361 | } | |||
362 | ||||
363 | /* | |||
364 | * Encode a Receipt into an OCTET STRING read for including into content of a | |||
365 | * SignedData ContentInfo. | |||
366 | */ | |||
367 | ||||
368 | ASN1_OCTET_STRING * | |||
369 | cms_encode_Receipt(CMS_SignerInfo *si) | |||
370 | { | |||
371 | CMS_Receipt rct; | |||
372 | CMS_ReceiptRequest *rr = NULL((void*)0); | |||
373 | ASN1_OBJECT *ctype; | |||
374 | ASN1_OCTET_STRING *os = NULL((void*)0); | |||
375 | ||||
376 | /* Get original receipt request */ | |||
377 | ||||
378 | /* Get original receipt request details */ | |||
379 | ||||
380 | if (CMS_get1_ReceiptRequest(si, &rr) <= 0) { | |||
381 | CMSerror(CMS_R_NO_RECEIPT_REQUEST)ERR_put_error(46,(0xfff),(168),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,381); | |||
382 | goto err; | |||
383 | } | |||
384 | ||||
385 | /* Get original content type */ | |||
386 | ||||
387 | ctype = CMS_signed_get0_data_by_OBJ(si, | |||
388 | OBJ_nid2obj(NID_pkcs9_contentType50), -3, V_ASN1_OBJECT6); | |||
389 | if (!ctype) { | |||
390 | CMSerror(CMS_R_NO_CONTENT_TYPE)ERR_put_error(46,(0xfff),(173),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,390); | |||
391 | goto err; | |||
392 | } | |||
393 | ||||
394 | rct.version = 1; | |||
395 | rct.contentType = ctype; | |||
396 | rct.signedContentIdentifier = rr->signedContentIdentifier; | |||
397 | rct.originatorSignatureValue = si->signature; | |||
398 | ||||
399 | os = ASN1_item_pack(&rct, &CMS_Receipt_it, NULL((void*)0)); | |||
400 | ||||
401 | err: | |||
402 | CMS_ReceiptRequest_free(rr); | |||
403 | return os; | |||
404 | } |