11590Srgrimes/* crypto/cms/cms_ess.c */
21590Srgrimes/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
31590Srgrimes * project.
41590Srgrimes */
51590Srgrimes/* ====================================================================
61590Srgrimes * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
71590Srgrimes *
81590Srgrimes * Redistribution and use in source and binary forms, with or without
91590Srgrimes * modification, are permitted provided that the following conditions
101590Srgrimes * are met:
111590Srgrimes *
121590Srgrimes * 1. Redistributions of source code must retain the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer.
141590Srgrimes *
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in
171590Srgrimes *    the documentation and/or other materials provided with the
181590Srgrimes *    distribution.
191590Srgrimes *
201590Srgrimes * 3. All advertising materials mentioning features or use of this
211590Srgrimes *    software must display the following acknowledgment:
221590Srgrimes *    "This product includes software developed by the OpenSSL Project
231590Srgrimes *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
241590Srgrimes *
251590Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
261590Srgrimes *    endorse or promote products derived from this software without
271590Srgrimes *    prior written permission. For written permission, please contact
281590Srgrimes *    licensing@OpenSSL.org.
291590Srgrimes *
301590Srgrimes * 5. Products derived from this software may not be called "OpenSSL"
3127443Scharnier *    nor may "OpenSSL" appear in their names without prior written
321590Srgrimes *    permission of the OpenSSL Project.
331590Srgrimes *
341590Srgrimes * 6. Redistributions of any form whatsoever must retain the following
351590Srgrimes *    acknowledgment:
361590Srgrimes *    "This product includes software developed by the OpenSSL Project
3727443Scharnier *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
381590Srgrimes *
3927443Scharnier * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
401590Srgrimes * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4199112Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4299112Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
431590Srgrimes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4455206Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
452215Scsgr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
462215Scsgr * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4755206Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
481590Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
491590Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50100824Sdwmalone * OF THE POSSIBILITY OF SUCH DAMAGE.
511590Srgrimes * ====================================================================
52100824Sdwmalone */
531590Srgrimes
541590Srgrimes#include "cryptlib.h"
551590Srgrimes#include <openssl/asn1t.h>
56165758Srodrigc#include <openssl/pem.h>
57176471Sdes#include <openssl/rand.h>
58219043Sdchagin#include <openssl/x509v3.h>
59176471Sdes#include <openssl/err.h>
60219043Sdchagin#include <openssl/cms.h>
61176471Sdes#include "cms_lcl.h"
62176471Sdes
63176471SdesDECLARE_ASN1_ITEM(CMS_ReceiptRequest)
64176471SdesDECLARE_ASN1_ITEM(CMS_Receipt)
65176471Sdes
66176471SdesIMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
67176471Sdes
68190168Sdelphij/* ESS services: for now just Signed Receipt related */
69176471Sdes
70190168Sdelphijint CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
71165916Sjhb	{
7227443Scharnier	ASN1_STRING *str;
73176471Sdes	CMS_ReceiptRequest *rr = NULL;
74176471Sdes	if (prr)
7527443Scharnier		*prr = NULL;
76176471Sdes	str = CMS_signed_get0_data_by_OBJ(si,
771590Srgrimes				OBJ_nid2obj(NID_id_smime_aa_receiptRequest),
781590Srgrimes					-3, V_ASN1_SEQUENCE);
791590Srgrimes	if (!str)
80176471Sdes		return 0;
8127443Scharnier
8227443Scharnier	rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
831590Srgrimes	if (!rr)
84158766Snetchild		return -1;
851590Srgrimes	if (prr)
86219043Sdchagin		*prr = rr;
87219043Sdchagin	else
88100824Sdwmalone		CMS_ReceiptRequest_free(rr);
89100824Sdwmalone	return 1;
90219043Sdchagin	}
91219043Sdchagin
92100824SdwmaloneCMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
93115759Speter				int allorfirst,
94115759Speter				STACK_OF(GENERAL_NAMES) *receiptList,
95100824Sdwmalone				STACK_OF(GENERAL_NAMES) *receiptsTo)
96219138Sdchagin	{
97100824Sdwmalone	CMS_ReceiptRequest *rr = NULL;
98226329Sdes
99226329Sdes	rr = CMS_ReceiptRequest_new();
100100824Sdwmalone	if (!rr)
101176471Sdes		goto merr;
102176471Sdes	if (id)
103176471Sdes		ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen);
104226269Sdes	else
105233925Sjhb		{
106233925Sjhb		if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
107100824Sdwmalone			goto merr;
108226157Sdes		if (RAND_pseudo_bytes(rr->signedContentIdentifier->data, 32)
109100824Sdwmalone					<= 0)
110176471Sdes			goto err;
111219043Sdchagin		}
112100824Sdwmalone
1131590Srgrimes	sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
1141590Srgrimes	rr->receiptsTo = receiptsTo;
115176471Sdes
1161590Srgrimes	if (receiptList)
1171590Srgrimes		{
118226262Sdes		rr->receiptsFrom->type = 1;
119226262Sdes		rr->receiptsFrom->d.receiptList = receiptList;
120226262Sdes		}
121226262Sdes	else
122226262Sdes		{
123226262Sdes		rr->receiptsFrom->type = 0;
124226262Sdes		rr->receiptsFrom->d.allOrFirstTier = allorfirst;
125226262Sdes		}
126226164Sdes
127219138Sdchagin	return rr;
128219138Sdchagin
129219138Sdchagin	merr:
130219138Sdchagin	CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
131219138Sdchagin
132219138Sdchagin	err:
133219138Sdchagin	if (rr)
134219138Sdchagin		CMS_ReceiptRequest_free(rr);
135219138Sdchagin
136219138Sdchagin	return NULL;
137219138Sdchagin
138219138Sdchagin	}
139219138Sdchagin
140219138Sdchaginint CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
141219138Sdchagin	{
142219138Sdchagin	unsigned char *rrder = NULL;
143219138Sdchagin	int rrderlen, r = 0;
144219138Sdchagin
145219138Sdchagin	rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
146219138Sdchagin	if (rrderlen < 0)
147219138Sdchagin		goto merr;
148219138Sdchagin
149219138Sdchagin	if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
150219138Sdchagin					V_ASN1_SEQUENCE, rrder, rrderlen))
151219138Sdchagin		goto merr;
152219138Sdchagin
153219043Sdchagin	r = 1;
154219043Sdchagin
155219043Sdchagin	merr:
156219043Sdchagin	if (!r)
157219043Sdchagin		CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
158219043Sdchagin
159219043Sdchagin	if (rrder)
160219043Sdchagin		OPENSSL_free(rrder);
161219043Sdchagin
162100824Sdwmalone	return r;
163100824Sdwmalone
1641590Srgrimes	}
1651590Srgrimes
166100824Sdwmalonevoid CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
1671590Srgrimes					ASN1_STRING **pcid,
168112201Sjhb					int *pallorfirst,
169115759Speter					STACK_OF(GENERAL_NAMES) **plist,
170219043Sdchagin					STACK_OF(GENERAL_NAMES) **prto)
1711590Srgrimes	{
172226153Sdes	if (pcid)
17311823Sache		*pcid = rr->signedContentIdentifier;
174219043Sdchagin	if (rr->receiptsFrom->type == 0)
175226153Sdes		{
176219043Sdchagin		if (pallorfirst)
177219043Sdchagin			*pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
178219043Sdchagin		if (plist)
1791590Srgrimes			*plist = NULL;
1801590Srgrimes		}
1811590Srgrimes	else
1821590Srgrimes		{
1831590Srgrimes		if (pallorfirst)
1841590Srgrimes			*pallorfirst = -1;
1851590Srgrimes		if (plist)
1861590Srgrimes			*plist = rr->receiptsFrom->d.receiptList;
1871590Srgrimes		}
1881590Srgrimes	if (prto)
1891590Srgrimes		*prto = rr->receiptsTo;
1901590Srgrimes	}
1911590Srgrimes
1921590Srgrimes/* Digest a SignerInfo structure for msgSigDigest attribute processing */
1931590Srgrimes
194115759Speterstatic int cms_msgSigDigest(CMS_SignerInfo *si,
195115759Speter				unsigned char *dig, unsigned int *diglen)
196115759Speter	{
197176471Sdes	const EVP_MD *md;
198176471Sdes	md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
199176471Sdes	if (md == NULL)
200152331Srwatson		return 0;
201152331Srwatson	if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
202152331Srwatson						si->signedAttrs, dig, diglen))
203123187Speter		return 0;
204123187Speter	return 1;
205123187Speter	}
206151930Srwatson
207151930Srwatson/* Add a msgSigDigest attribute to a SignerInfo */
208151930Srwatson
2091590Srgrimesint cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
2101590Srgrimes	{
2111590Srgrimes	unsigned char dig[EVP_MAX_MD_SIZE];
2121590Srgrimes	unsigned int diglen;
2131590Srgrimes	if (!cms_msgSigDigest(src, dig, &diglen))
2141590Srgrimes		{
2151590Srgrimes		CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
2161590Srgrimes		return 0;
21727443Scharnier		}
21827443Scharnier	if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
2191590Srgrimes					V_ASN1_OCTET_STRING, dig, diglen))
2201590Srgrimes		{
2211590Srgrimes		CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
2221590Srgrimes		return 0;
2231590Srgrimes		}
22419853Sfenner	return 1;
2251590Srgrimes	}
2261590Srgrimes
227226153Sdes/* Verify signed receipt after it has already passed normal CMS verify */
22827443Scharnier
22927443Scharnierint cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
23027443Scharnier	{
23127443Scharnier	int r = 0, i;
232219043Sdchagin	CMS_ReceiptRequest *rr = NULL;
233112201Sjhb	CMS_Receipt *rct = NULL;
2341590Srgrimes	STACK_OF(CMS_SignerInfo) *sis, *osis;
235112201Sjhb	CMS_SignerInfo *si, *osi = NULL;
236112201Sjhb	ASN1_OCTET_STRING *msig, **pcont;
237151930Srwatson	ASN1_OBJECT *octype;
238226153Sdes	unsigned char dig[EVP_MAX_MD_SIZE];
239203551Sjh	unsigned int diglen;
240203551Sjh
241203551Sjh	/* Get SignerInfos, also checks SignedData content type */
242203551Sjh	osis = CMS_get0_SignerInfos(req_cms);
243203551Sjh	sis = CMS_get0_SignerInfos(cms);
244151930Srwatson	if (!osis || !sis)
245151930Srwatson		goto err;
246226153Sdes
247203551Sjh	if (sk_CMS_SignerInfo_num(sis) != 1)
248112201Sjhb		{
249112201Sjhb		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER);
250112201Sjhb		goto err;
251112201Sjhb		}
2521590Srgrimes
253115759Speter	/* Check receipt content type */
254115759Speter	if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt)
25527443Scharnier		{
25627443Scharnier		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT);
2571590Srgrimes		goto err;
258226153Sdes		}
25927443Scharnier
26027443Scharnier	/* Extract and decode receipt content */
2611590Srgrimes	pcont = CMS_get0_content(cms);
2621590Srgrimes	if (!pcont || !*pcont)
26327443Scharnier		{
26427443Scharnier		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT);
265219043Sdchagin		goto err;
266219043Sdchagin		}
267219043Sdchagin
268115759Speter	rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt));
269115759Speter
2701590Srgrimes	if (!rct)
2711590Srgrimes		{
272112201Sjhb		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR);
2731590Srgrimes		goto err;
2741590Srgrimes		}
275219138Sdchagin
276219138Sdchagin	/* Locate original request */
277219138Sdchagin
278219138Sdchagin	for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++)
279219138Sdchagin		{
280219138Sdchagin		osi = sk_CMS_SignerInfo_value(osis, i);
2811590Srgrimes		if (!ASN1_STRING_cmp(osi->signature,
2821590Srgrimes					rct->originatorSignatureValue))
283219138Sdchagin			break;
284219138Sdchagin		}
285219138Sdchagin
286219138Sdchagin	if (i == sk_CMS_SignerInfo_num(osis))
287219138Sdchagin		{
288219138Sdchagin		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE);
2891590Srgrimes		goto err;
2901590Srgrimes		}
291189707Sjhb
2921590Srgrimes	si = sk_CMS_SignerInfo_value(sis, 0);
2931590Srgrimes
2941590Srgrimes	/* Get msgSigDigest value and compare */
2951590Srgrimes
2961590Srgrimes	msig = CMS_signed_get0_data_by_OBJ(si,
2971590Srgrimes				OBJ_nid2obj(NID_id_smime_aa_msgSigDigest),
298219138Sdchagin					-3, V_ASN1_OCTET_STRING);
2991590Srgrimes
3001590Srgrimes	if (!msig)
3011590Srgrimes		{
3021590Srgrimes		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST);
30318400Sphk		goto err;
30418470Sphk		}
30518400Sphk
306176471Sdes	if (!cms_msgSigDigest(osi, dig, &diglen))
307176471Sdes		{
308176471Sdes		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR);
309226269Sdes		goto err;
310226269Sdes		}
311233925Sjhb
312233925Sjhb	if (diglen != (unsigned int)msig->length)
313233925Sjhb			{
314233925Sjhb			CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
315233925Sjhb				CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
316233925Sjhb			goto err;
317233925Sjhb			}
318112203Sjhb
319112203Sjhb	if (memcmp(dig, msig->data, diglen))
320112203Sjhb			{
3211590Srgrimes			CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
3221590Srgrimes				CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
323226153Sdes			goto err;
3241590Srgrimes			}
325100824Sdwmalone
3261590Srgrimes	/* Compare content types */
3271590Srgrimes
328100824Sdwmalone	octype = CMS_signed_get0_data_by_OBJ(osi,
329100824Sdwmalone				OBJ_nid2obj(NID_pkcs9_contentType),
3301590Srgrimes					-3, V_ASN1_OBJECT);
3311590Srgrimes	if (!octype)
3321590Srgrimes		{
3331590Srgrimes		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE);
334226153Sdes		goto err;
3351590Srgrimes		}
3361590Srgrimes
3371590Srgrimes	/* Compare details in receipt request */
3381590Srgrimes
3391590Srgrimes	if (OBJ_cmp(octype, rct->contentType))
340219043Sdchagin		{
341219043Sdchagin		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH);
342219043Sdchagin		goto err;
343219043Sdchagin		}
344219043Sdchagin
345219043Sdchagin	/* Get original receipt request details */
346219043Sdchagin
347219043Sdchagin	if (CMS_get1_ReceiptRequest(osi, &rr) <= 0)
348219043Sdchagin		{
349219043Sdchagin		CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST);
350219043Sdchagin		goto err;
351219043Sdchagin		}
352219043Sdchagin
353219043Sdchagin	if (ASN1_STRING_cmp(rr->signedContentIdentifier,
354219043Sdchagin					rct->signedContentIdentifier))
355219043Sdchagin		{
356219043Sdchagin		CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
357219043Sdchagin					CMS_R_CONTENTIDENTIFIER_MISMATCH);
358219043Sdchagin		goto err;
359219043Sdchagin		}
360219043Sdchagin
361219043Sdchagin	r = 1;
362219043Sdchagin
363219043Sdchagin	err:
364219043Sdchagin	if (rr)
365219043Sdchagin		CMS_ReceiptRequest_free(rr);
366219043Sdchagin	if (rct)
367219043Sdchagin		M_ASN1_free_of(rct, CMS_Receipt);
368219043Sdchagin
369219043Sdchagin	return r;
370219043Sdchagin
371219043Sdchagin	}
372219043Sdchagin
373219043Sdchagin/* Encode a Receipt into an OCTET STRING read for including into content of
374219043Sdchagin * a SignedData ContentInfo.
375219043Sdchagin */
376219043Sdchagin
377219043SdchaginASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
378219043Sdchagin	{
379219043Sdchagin	CMS_Receipt rct;
380219043Sdchagin	CMS_ReceiptRequest *rr = NULL;
381219043Sdchagin	ASN1_OBJECT *ctype;
382219043Sdchagin	ASN1_OCTET_STRING *os = NULL;
383219043Sdchagin
384219043Sdchagin	/* Get original receipt request */
385219043Sdchagin
386219043Sdchagin	/* Get original receipt request details */
387219043Sdchagin
388219043Sdchagin	if (CMS_get1_ReceiptRequest(si, &rr) <= 0)
389219043Sdchagin		{
390219043Sdchagin		CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
391219043Sdchagin		goto err;
392219043Sdchagin		}
393219043Sdchagin
394219043Sdchagin	/* Get original content type */
395219043Sdchagin
396219043Sdchagin	ctype = CMS_signed_get0_data_by_OBJ(si,
397219043Sdchagin				OBJ_nid2obj(NID_pkcs9_contentType),
398219043Sdchagin					-3, V_ASN1_OBJECT);
399219043Sdchagin	if (!ctype)
400219043Sdchagin		{
401219043Sdchagin		CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
402219043Sdchagin		goto err;
403219043Sdchagin		}
404219043Sdchagin
405219043Sdchagin	rct.version = 1;
406219043Sdchagin	rct.contentType = ctype;
407219043Sdchagin	rct.signedContentIdentifier = rr->signedContentIdentifier;
408219043Sdchagin	rct.originatorSignatureValue = si->signature;
409219043Sdchagin
410219043Sdchagin	os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL);
411219043Sdchagin
412219043Sdchagin	err:
413219043Sdchagin	if (rr)
414219043Sdchagin		CMS_ReceiptRequest_free(rr);
415219043Sdchagin
416219043Sdchagin	return os;
417219043Sdchagin
418100824Sdwmalone	}
419100824Sdwmalone
4201590Srgrimes
4211590Srgrimes