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