File: | src/lib/libcrypto/cms/cms_ess.c |
Warning: | line 213, 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.23 2023/07/08 08:26:26 beck 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_local.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 | LCRYPTO_ALIAS(d2i_CMS_ReceiptRequest)asm(""); | |||
74 | ||||
75 | int | |||
76 | i2d_CMS_ReceiptRequest(CMS_ReceiptRequest *a, unsigned char **out) | |||
77 | { | |||
78 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ReceiptRequest_it); | |||
79 | } | |||
80 | LCRYPTO_ALIAS(i2d_CMS_ReceiptRequest)asm(""); | |||
81 | ||||
82 | CMS_ReceiptRequest * | |||
83 | CMS_ReceiptRequest_new(void) | |||
84 | { | |||
85 | return (CMS_ReceiptRequest *)ASN1_item_new(&CMS_ReceiptRequest_it); | |||
86 | } | |||
87 | LCRYPTO_ALIAS(CMS_ReceiptRequest_new)asm(""); | |||
88 | ||||
89 | void | |||
90 | CMS_ReceiptRequest_free(CMS_ReceiptRequest *a) | |||
91 | { | |||
92 | ASN1_item_free((ASN1_VALUE *)a, &CMS_ReceiptRequest_it); | |||
93 | } | |||
94 | LCRYPTO_ALIAS(CMS_ReceiptRequest_free)asm(""); | |||
95 | ||||
96 | /* ESS services: for now just Signed Receipt related */ | |||
97 | ||||
98 | int | |||
99 | CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr) | |||
100 | { | |||
101 | ASN1_STRING *str; | |||
102 | CMS_ReceiptRequest *rr = NULL((void *)0); | |||
103 | ||||
104 | if (prr) | |||
105 | *prr = NULL((void *)0); | |||
106 | str = CMS_signed_get0_data_by_OBJ(si, | |||
107 | OBJ_nid2obj(NID_id_smime_aa_receiptRequest212), -3, V_ASN1_SEQUENCE16); | |||
108 | if (!str) | |||
109 | return 0; | |||
110 | ||||
111 | rr = ASN1_item_unpack(str, &CMS_ReceiptRequest_it); | |||
112 | if (!rr) | |||
113 | return -1; | |||
114 | if (prr) | |||
115 | *prr = rr; | |||
116 | else | |||
117 | CMS_ReceiptRequest_free(rr); | |||
118 | ||||
119 | return 1; | |||
120 | } | |||
121 | ||||
122 | CMS_ReceiptRequest * | |||
123 | CMS_ReceiptRequest_create0(unsigned char *id, int idlen, int allorfirst, | |||
124 | STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES *receiptList, STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES *receiptsTo) | |||
125 | { | |||
126 | CMS_ReceiptRequest *rr = NULL((void *)0); | |||
127 | ||||
128 | rr = CMS_ReceiptRequest_new(); | |||
129 | if (rr == NULL((void *)0)) | |||
130 | goto merr; | |||
131 | if (id) | |||
132 | ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); | |||
133 | else { | |||
134 | if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL((void *)0), 32)) | |||
135 | goto merr; | |||
136 | arc4random_buf(rr->signedContentIdentifier->data, 32); | |||
137 | } | |||
138 | ||||
139 | 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)))); | |||
140 | rr->receiptsTo = receiptsTo; | |||
141 | ||||
142 | if (receiptList) { | |||
143 | rr->receiptsFrom->type = 1; | |||
144 | rr->receiptsFrom->d.receiptList = receiptList; | |||
145 | } else { | |||
146 | rr->receiptsFrom->type = 0; | |||
147 | rr->receiptsFrom->d.allOrFirstTier = allorfirst; | |||
148 | } | |||
149 | ||||
150 | return rr; | |||
151 | ||||
152 | merr: | |||
153 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,153); | |||
154 | CMS_ReceiptRequest_free(rr); | |||
155 | ||||
156 | return NULL((void *)0); | |||
157 | } | |||
158 | ||||
159 | int | |||
160 | CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr) | |||
161 | { | |||
162 | unsigned char *rrder = NULL((void *)0); | |||
163 | int rrderlen, r = 0; | |||
164 | ||||
165 | rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder); | |||
166 | if (rrderlen < 0) | |||
167 | goto merr; | |||
168 | ||||
169 | if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest212, | |||
170 | V_ASN1_SEQUENCE16, rrder, rrderlen)) | |||
171 | goto merr; | |||
172 | ||||
173 | r = 1; | |||
174 | ||||
175 | merr: | |||
176 | if (!r) | |||
177 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,177); | |||
178 | ||||
179 | free(rrder); | |||
180 | ||||
181 | return r; | |||
182 | } | |||
183 | ||||
184 | void | |||
185 | CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid, | |||
186 | int *pallorfirst, STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES **plist, | |||
187 | STACK_OF(GENERAL_NAMES)struct stack_st_GENERAL_NAMES **prto) | |||
188 | { | |||
189 | if (pcid) | |||
190 | *pcid = rr->signedContentIdentifier; | |||
191 | if (rr->receiptsFrom->type == 0) { | |||
192 | if (pallorfirst) | |||
193 | *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier; | |||
194 | if (plist) | |||
195 | *plist = NULL((void *)0); | |||
196 | } else { | |||
197 | if (pallorfirst) | |||
198 | *pallorfirst = -1; | |||
199 | if (plist) | |||
200 | *plist = rr->receiptsFrom->d.receiptList; | |||
201 | } | |||
202 | if (prto) | |||
203 | *prto = rr->receiptsTo; | |||
204 | } | |||
205 | ||||
206 | /* Digest a SignerInfo structure for msgSigDigest attribute processing */ | |||
207 | ||||
208 | static int | |||
209 | cms_msgSigDigest(CMS_SignerInfo *si, unsigned char *dig, unsigned int *diglen) | |||
210 | { | |||
211 | const EVP_MD *md; | |||
212 | ||||
213 | md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid(si->digestAlgorithm ->algorithm))); | |||
| ||||
214 | if (md == NULL((void *)0)) | |||
215 | return 0; | |||
216 | if (!ASN1_item_digest(&CMS_Attributes_Verify_it, md, | |||
217 | si->signedAttrs, dig, diglen)) | |||
218 | return 0; | |||
219 | ||||
220 | return 1; | |||
221 | } | |||
222 | ||||
223 | /* Add a msgSigDigest attribute to a SignerInfo */ | |||
224 | ||||
225 | int | |||
226 | cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) | |||
227 | { | |||
228 | unsigned char dig[EVP_MAX_MD_SIZE64]; | |||
229 | unsigned int diglen; | |||
230 | ||||
231 | if (!cms_msgSigDigest(src, dig, &diglen)) { | |||
232 | CMSerror(CMS_R_MSGSIGDIGEST_ERROR)ERR_put_error(46,(0xfff),(172),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,232); | |||
233 | return 0; | |||
234 | } | |||
235 | if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest216, | |||
236 | V_ASN1_OCTET_STRING4, dig, diglen)) { | |||
237 | CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,237); | |||
238 | return 0; | |||
239 | } | |||
240 | ||||
241 | return 1; | |||
242 | } | |||
243 | ||||
244 | /* Verify signed receipt after it has already passed normal CMS verify */ | |||
245 | ||||
246 | int | |||
247 | cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) | |||
248 | { | |||
249 | int r = 0, i; | |||
250 | CMS_ReceiptRequest *rr = NULL((void *)0); | |||
251 | CMS_Receipt *rct = NULL((void *)0); | |||
252 | STACK_OF(CMS_SignerInfo)struct stack_st_CMS_SignerInfo *sis, *osis; | |||
253 | CMS_SignerInfo *si, *osi = NULL((void *)0); | |||
| ||||
254 | ASN1_OCTET_STRING *msig, **pcont; | |||
255 | ASN1_OBJECT *octype; | |||
256 | unsigned char dig[EVP_MAX_MD_SIZE64]; | |||
257 | unsigned int diglen; | |||
258 | ||||
259 | /* Get SignerInfos, also checks SignedData content type */ | |||
260 | osis = CMS_get0_SignerInfos(req_cms); | |||
261 | sis = CMS_get0_SignerInfos(cms); | |||
262 | if (!osis || !sis) | |||
263 | goto err; | |||
264 | ||||
265 | if (sk_CMS_SignerInfo_num(sis)sk_num(((_STACK*) (1 ? (sis) : (struct stack_st_CMS_SignerInfo *)0))) != 1) { | |||
266 | CMSerror(CMS_R_NEED_ONE_SIGNER)ERR_put_error(46,(0xfff),(164),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,266); | |||
267 | goto err; | |||
268 | } | |||
269 | ||||
270 | /* Check receipt content type */ | |||
271 | if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt204) { | |||
272 | CMSerror(CMS_R_NOT_A_SIGNED_RECEIPT)ERR_put_error(46,(0xfff),(165),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,272); | |||
273 | goto err; | |||
274 | } | |||
275 | ||||
276 | /* Extract and decode receipt content */ | |||
277 | pcont = CMS_get0_content(cms); | |||
278 | if (!pcont || !*pcont) { | |||
279 | CMSerror(CMS_R_NO_CONTENT)ERR_put_error(46,(0xfff),(127),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,279); | |||
280 | goto err; | |||
281 | } | |||
282 | ||||
283 | rct = ASN1_item_unpack(*pcont, &CMS_Receipt_it); | |||
284 | ||||
285 | if (!rct) { | |||
286 | CMSerror(CMS_R_RECEIPT_DECODE_ERROR)ERR_put_error(46,(0xfff),(169),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,286); | |||
287 | goto err; | |||
288 | } | |||
289 | ||||
290 | /* Locate original request */ | |||
291 | ||||
292 | for (i = 0; i < sk_CMS_SignerInfo_num(osis)sk_num(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0))); i++) { | |||
293 | osi = sk_CMS_SignerInfo_value(osis, i)((CMS_SignerInfo *)sk_value(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0)), (i))); | |||
294 | if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue)) | |||
295 | break; | |||
296 | } | |||
297 | ||||
298 | if (i == sk_CMS_SignerInfo_num(osis)sk_num(((_STACK*) (1 ? (osis) : (struct stack_st_CMS_SignerInfo *)0)))) { | |||
299 | CMSerror(CMS_R_NO_MATCHING_SIGNATURE)ERR_put_error(46,(0xfff),(166),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,299); | |||
300 | goto err; | |||
301 | } | |||
302 | ||||
303 | si = sk_CMS_SignerInfo_value(sis, 0)((CMS_SignerInfo *)sk_value(((_STACK*) (1 ? (sis) : (struct stack_st_CMS_SignerInfo *)0)), (0))); | |||
304 | ||||
305 | /* Get msgSigDigest value and compare */ | |||
306 | ||||
307 | msig = CMS_signed_get0_data_by_OBJ(si, | |||
308 | OBJ_nid2obj(NID_id_smime_aa_msgSigDigest216), -3, V_ASN1_OCTET_STRING4); | |||
309 | ||||
310 | if (!msig) { | |||
311 | CMSerror(CMS_R_NO_MSGSIGDIGEST)ERR_put_error(46,(0xfff),(167),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,311); | |||
312 | goto err; | |||
313 | } | |||
314 | ||||
315 | if (!cms_msgSigDigest(osi, dig, &diglen)) { | |||
316 | CMSerror(CMS_R_MSGSIGDIGEST_ERROR)ERR_put_error(46,(0xfff),(172),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,316); | |||
317 | goto err; | |||
318 | } | |||
319 | ||||
320 | if (diglen != (unsigned int)msig->length) { | |||
321 | CMSerror(CMS_R_MSGSIGDIGEST_WRONG_LENGTH)ERR_put_error(46,(0xfff),(163),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,321); | |||
322 | goto err; | |||
323 | } | |||
324 | ||||
325 | if (memcmp(dig, msig->data, diglen)) { | |||
326 | CMSerror(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE)ERR_put_error(46,(0xfff),(162),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,326); | |||
327 | goto err; | |||
328 | } | |||
329 | ||||
330 | /* Compare content types */ | |||
331 | ||||
332 | octype = CMS_signed_get0_data_by_OBJ(osi, | |||
333 | OBJ_nid2obj(NID_pkcs9_contentType50), -3, V_ASN1_OBJECT6); | |||
334 | if (!octype) { | |||
335 | CMSerror(CMS_R_NO_CONTENT_TYPE)ERR_put_error(46,(0xfff),(173),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,335); | |||
336 | goto err; | |||
337 | } | |||
338 | ||||
339 | /* Compare details in receipt request */ | |||
340 | ||||
341 | if (OBJ_cmp(octype, rct->contentType)) { | |||
342 | CMSerror(CMS_R_CONTENT_TYPE_MISMATCH)ERR_put_error(46,(0xfff),(171),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,342); | |||
343 | goto err; | |||
344 | } | |||
345 | ||||
346 | /* Get original receipt request details */ | |||
347 | ||||
348 | if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) { | |||
349 | CMSerror(CMS_R_NO_RECEIPT_REQUEST)ERR_put_error(46,(0xfff),(168),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,349); | |||
350 | goto err; | |||
351 | } | |||
352 | ||||
353 | if (ASN1_STRING_cmp(rr->signedContentIdentifier, | |||
354 | rct->signedContentIdentifier)) { | |||
355 | CMSerror(CMS_R_CONTENTIDENTIFIER_MISMATCH)ERR_put_error(46,(0xfff),(170),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,355); | |||
356 | goto err; | |||
357 | } | |||
358 | ||||
359 | r = 1; | |||
360 | ||||
361 | err: | |||
362 | CMS_ReceiptRequest_free(rr); | |||
363 | ASN1_item_free((ASN1_VALUE *)rct, &CMS_Receipt_it); | |||
364 | return r; | |||
365 | } | |||
366 | ||||
367 | /* | |||
368 | * Encode a Receipt into an OCTET STRING read for including into content of a | |||
369 | * SignedData ContentInfo. | |||
370 | */ | |||
371 | ||||
372 | ASN1_OCTET_STRING * | |||
373 | cms_encode_Receipt(CMS_SignerInfo *si) | |||
374 | { | |||
375 | CMS_Receipt rct; | |||
376 | CMS_ReceiptRequest *rr = NULL((void *)0); | |||
377 | ASN1_OBJECT *ctype; | |||
378 | ASN1_OCTET_STRING *os = NULL((void *)0); | |||
379 | ||||
380 | /* Get original receipt request */ | |||
381 | ||||
382 | /* Get original receipt request details */ | |||
383 | ||||
384 | if (CMS_get1_ReceiptRequest(si, &rr) <= 0) { | |||
385 | CMSerror(CMS_R_NO_RECEIPT_REQUEST)ERR_put_error(46,(0xfff),(168),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,385); | |||
386 | goto err; | |||
387 | } | |||
388 | ||||
389 | /* Get original content type */ | |||
390 | ||||
391 | ctype = CMS_signed_get0_data_by_OBJ(si, | |||
392 | OBJ_nid2obj(NID_pkcs9_contentType50), -3, V_ASN1_OBJECT6); | |||
393 | if (!ctype) { | |||
394 | CMSerror(CMS_R_NO_CONTENT_TYPE)ERR_put_error(46,(0xfff),(173),"/usr/src/lib/libcrypto/cms/cms_ess.c" ,394); | |||
395 | goto err; | |||
396 | } | |||
397 | ||||
398 | rct.version = 1; | |||
399 | rct.contentType = ctype; | |||
400 | rct.signedContentIdentifier = rr->signedContentIdentifier; | |||
401 | rct.originatorSignatureValue = si->signature; | |||
402 | ||||
403 | os = ASN1_item_pack(&rct, &CMS_Receipt_it, NULL((void *)0)); | |||
404 | ||||
405 | err: | |||
406 | CMS_ReceiptRequest_free(rr); | |||
407 | return os; | |||
408 | } |