123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /* crypto/cms/cms_ess.c */
- /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project.
- */
- /* ====================================================================
- * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- #include "cryptlib.h"
- #include <openssl/asn1t.h>
- #include <openssl/pem.h>
- #include <openssl/rand.h>
- #include <openssl/x509v3.h>
- #include <openssl/err.h>
- #include <openssl/cms.h>
- #include "cms_lcl.h"
- DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
- DECLARE_ASN1_ITEM(CMS_Receipt)
- IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
- /* ESS services: for now just Signed Receipt related */
- int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
- {
- ASN1_STRING *str;
- CMS_ReceiptRequest *rr = NULL;
- if (prr)
- *prr = NULL;
- str = CMS_signed_get0_data_by_OBJ(si,
- OBJ_nid2obj(NID_id_smime_aa_receiptRequest),
- -3, V_ASN1_SEQUENCE);
- if (!str)
- return 0;
- rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
- if (!rr)
- return -1;
- if (prr)
- *prr = rr;
- else
- CMS_ReceiptRequest_free(rr);
- return 1;
- }
- CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
- int allorfirst,
- STACK_OF(GENERAL_NAMES) *receiptList,
- STACK_OF(GENERAL_NAMES) *receiptsTo)
- {
- CMS_ReceiptRequest *rr = NULL;
- rr = CMS_ReceiptRequest_new();
- if (!rr)
- goto merr;
- if (id)
- ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen);
- else
- {
- if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
- goto merr;
- if (RAND_pseudo_bytes(rr->signedContentIdentifier->data, 32)
- <= 0)
- goto err;
- }
- sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
- rr->receiptsTo = receiptsTo;
- if (receiptList)
- {
- rr->receiptsFrom->type = 1;
- rr->receiptsFrom->d.receiptList = receiptList;
- }
- else
- {
- rr->receiptsFrom->type = 0;
- rr->receiptsFrom->d.allOrFirstTier = allorfirst;
- }
- return rr;
- merr:
- CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
- err:
- if (rr)
- CMS_ReceiptRequest_free(rr);
- return NULL;
-
- }
- int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
- {
- unsigned char *rrder = NULL;
- int rrderlen, r = 0;
- rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
- if (rrderlen < 0)
- goto merr;
- if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
- V_ASN1_SEQUENCE, rrder, rrderlen))
- goto merr;
- r = 1;
- merr:
- if (!r)
- CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
- if (rrder)
- OPENSSL_free(rrder);
- return r;
-
- }
- void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
- ASN1_STRING **pcid,
- int *pallorfirst,
- STACK_OF(GENERAL_NAMES) **plist,
- STACK_OF(GENERAL_NAMES) **prto)
- {
- if (pcid)
- *pcid = rr->signedContentIdentifier;
- if (rr->receiptsFrom->type == 0)
- {
- if (pallorfirst)
- *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
- if (plist)
- *plist = NULL;
- }
- else
- {
- if (pallorfirst)
- *pallorfirst = -1;
- if (plist)
- *plist = rr->receiptsFrom->d.receiptList;
- }
- if (prto)
- *prto = rr->receiptsTo;
- }
- /* Digest a SignerInfo structure for msgSigDigest attribute processing */
- static int cms_msgSigDigest(CMS_SignerInfo *si,
- unsigned char *dig, unsigned int *diglen)
- {
- const EVP_MD *md;
- md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
- if (md == NULL)
- return 0;
- if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
- si->signedAttrs, dig, diglen))
- return 0;
- return 1;
- }
- /* Add a msgSigDigest attribute to a SignerInfo */
- int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
- {
- unsigned char dig[EVP_MAX_MD_SIZE];
- unsigned int diglen;
- if (!cms_msgSigDigest(src, dig, &diglen))
- {
- CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
- return 0;
- }
- if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
- V_ASN1_OCTET_STRING, dig, diglen))
- {
- CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
- }
- /* Verify signed receipt after it has already passed normal CMS verify */
- int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
- {
- int r = 0, i;
- CMS_ReceiptRequest *rr = NULL;
- CMS_Receipt *rct = NULL;
- STACK_OF(CMS_SignerInfo) *sis, *osis;
- CMS_SignerInfo *si, *osi = NULL;
- ASN1_OCTET_STRING *msig, **pcont;
- ASN1_OBJECT *octype;
- unsigned char dig[EVP_MAX_MD_SIZE];
- unsigned int diglen;
- /* Get SignerInfos, also checks SignedData content type */
- osis = CMS_get0_SignerInfos(req_cms);
- sis = CMS_get0_SignerInfos(cms);
- if (!osis || !sis)
- goto err;
- if (sk_CMS_SignerInfo_num(sis) != 1)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER);
- goto err;
- }
- /* Check receipt content type */
- if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT);
- goto err;
- }
- /* Extract and decode receipt content */
- pcont = CMS_get0_content(cms);
- if (!pcont || !*pcont)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT);
- goto err;
- }
- rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt));
- if (!rct)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR);
- goto err;
- }
- /* Locate original request */
- for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++)
- {
- osi = sk_CMS_SignerInfo_value(osis, i);
- if (!ASN1_STRING_cmp(osi->signature,
- rct->originatorSignatureValue))
- break;
- }
- if (i == sk_CMS_SignerInfo_num(osis))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE);
- goto err;
- }
- si = sk_CMS_SignerInfo_value(sis, 0);
- /* Get msgSigDigest value and compare */
- msig = CMS_signed_get0_data_by_OBJ(si,
- OBJ_nid2obj(NID_id_smime_aa_msgSigDigest),
- -3, V_ASN1_OCTET_STRING);
- if (!msig)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST);
- goto err;
- }
- if (!cms_msgSigDigest(osi, dig, &diglen))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR);
- goto err;
- }
- if (diglen != (unsigned int)msig->length)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
- CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
- goto err;
- }
- if (memcmp(dig, msig->data, diglen))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
- CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
- goto err;
- }
- /* Compare content types */
- octype = CMS_signed_get0_data_by_OBJ(osi,
- OBJ_nid2obj(NID_pkcs9_contentType),
- -3, V_ASN1_OBJECT);
- if (!octype)
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE);
- goto err;
- }
- /* Compare details in receipt request */
- if (OBJ_cmp(octype, rct->contentType))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH);
- goto err;
- }
- /* Get original receipt request details */
- if (!CMS_get1_ReceiptRequest(osi, &rr))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST);
- goto err;
- }
- if (ASN1_STRING_cmp(rr->signedContentIdentifier,
- rct->signedContentIdentifier))
- {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
- CMS_R_CONTENTIDENTIFIER_MISMATCH);
- goto err;
- }
- r = 1;
- err:
- if (rr)
- CMS_ReceiptRequest_free(rr);
- if (rct)
- M_ASN1_free_of(rct, CMS_Receipt);
- return r;
- }
- /* Encode a Receipt into an OCTET STRING read for including into content of
- * a SignedData ContentInfo.
- */
- ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
- {
- CMS_Receipt rct;
- CMS_ReceiptRequest *rr = NULL;
- ASN1_OBJECT *ctype;
- ASN1_OCTET_STRING *os = NULL;
- /* Get original receipt request */
- /* Get original receipt request details */
- if (!CMS_get1_ReceiptRequest(si, &rr))
- {
- CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
- goto err;
- }
- /* Get original content type */
- ctype = CMS_signed_get0_data_by_OBJ(si,
- OBJ_nid2obj(NID_pkcs9_contentType),
- -3, V_ASN1_OBJECT);
- if (!ctype)
- {
- CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
- goto err;
- }
- rct.version = 1;
- rct.contentType = ctype;
- rct.signedContentIdentifier = rr->signedContentIdentifier;
- rct.originatorSignatureValue = si->signature;
- os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL);
- err:
- if (rr)
- CMS_ReceiptRequest_free(rr);
- return os;
- }
|