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