Support for verification of signed receipts.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 28 Mar 2008 13:15:39 +0000 (13:15 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 28 Mar 2008 13:15:39 +0000 (13:15 +0000)
CHANGES
apps/cms.c
crypto/cms/cms.h
crypto/cms/cms_asn1.c
crypto/cms/cms_err.c
crypto/cms/cms_ess.c
crypto/cms/cms_lcl.h
crypto/cms/cms_smime.c

diff --git a/CHANGES b/CHANGES
index 40c163b..2e1ab47 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -59,8 +59,9 @@
   *) Initial support for Cryptographic Message Syntax (aka CMS) based
      on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
      support for data, signedData, compressedData, digestedData and
-     encryptedData types currently included, more to come. Scripts to
-     check against RFC4134 examples draft.
+     encryptedData, envelopedData types included. Scripts to check against
+     RFC4134 examples draft and interop and consistency checks of many
+     content types and variants.
      [Steve Henson]
 
   *) Zlib compression BIO. This is a filter BIO which compressed and
index 7a63778..ef873ee 100644 (file)
@@ -91,6 +91,8 @@ static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
 #define SMIME_COMPRESS         (12 | SMIME_OP)
 #define SMIME_ENCRYPTED_DECRYPT        (13 | SMIME_IP)
 #define SMIME_ENCRYPTED_ENCRYPT        (14 | SMIME_OP)
+#define SMIME_SIGN_RECEIPT     (15 | SMIME_OP | SMIME_IP)
+#define SMIME_VERIFY_RECEIPT   (16 | SMIME_IP)
 
 int MAIN(int, char **);
 
@@ -101,17 +103,17 @@ int MAIN(int argc, char **argv)
        int ret = 0;
        char **args;
        const char *inmode = "r", *outmode = "w";
-       char *infile = NULL, *outfile = NULL;
+       char *infile = NULL, *outfile = NULL, *rctfile = NULL;
        char *signerfile = NULL, *recipfile = NULL;
        STACK *sksigners = NULL, *skkeys = NULL;
        char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
        const EVP_CIPHER *cipher = NULL;
-       CMS_ContentInfo *cms = NULL;
+       CMS_ContentInfo *cms = NULL, *rcms = NULL;
        X509_STORE *store = NULL;
        X509 *cert = NULL, *recip = NULL, *signer = NULL;
        EVP_PKEY *key = NULL;
        STACK_OF(X509) *encerts = NULL, *other = NULL;
-       BIO *in = NULL, *out = NULL, *indata = NULL;
+       BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
        int badarg = 0;
        int flags = CMS_DETACHED, noout = 0, print = 0;
        int rr_print = 0, rr_allorfirst = -1;
@@ -124,7 +126,7 @@ int MAIN(int argc, char **argv)
        int need_rand = 0;
        const EVP_MD *sign_md = NULL;
        int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
-        int keyform = FORMAT_PEM;
+        int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
 #ifndef OPENSSL_NO_ENGINE
        char *engine=NULL;
 #endif
@@ -161,6 +163,14 @@ int MAIN(int argc, char **argv)
                        operation = SMIME_RESIGN;
                else if (!strcmp (*args, "-verify"))
                        operation = SMIME_VERIFY;
+               else if (!strcmp(*args,"-verify_receipt"))
+                       {
+                       operation = SMIME_VERIFY_RECEIPT;
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       rctfile = *args;
+                       }
                else if (!strcmp (*args, "-cmsout"))
                        operation = SMIME_CMSOUT;
                else if (!strcmp (*args, "-data_out"))
@@ -425,6 +435,12 @@ int MAIN(int argc, char **argv)
                                goto argerr;
                        keyform = str2fmt(*++args);
                        }
+               else if (!strcmp (*args, "-rctform"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       rctformat = str2fmt(*++args);
+                       }
                else if (!strcmp (*args, "-certfile"))
                        {
                        if (!args[1])
@@ -770,6 +786,35 @@ int MAIN(int argc, char **argv)
                        }
                }
 
+       if (rctfile)
+               {
+               char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
+               if (!(rctin = BIO_new_file(rctfile, rctmode)))
+                       {
+                       BIO_printf (bio_err,
+                                "Can't open receipt file %s\n", rctfile);
+                       goto end;
+                       }
+               
+               if (rctformat == FORMAT_SMIME) 
+                       rcms = SMIME_read_CMS(rctin, NULL);
+               else if (rctformat == FORMAT_PEM) 
+                       rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
+               else if (rctformat == FORMAT_ASN1) 
+                       rcms = d2i_CMS_bio(rctin, NULL);
+               else
+                       {
+                       BIO_printf(bio_err, "Bad input format for receipt\n");
+                       goto end;
+                       }
+
+               if (!rcms)
+                       {
+                       BIO_printf(bio_err, "Error reading receipt\n");
+                       goto end;
+                       }
+               }
+
        if (outfile)
                {
                if (!(out = BIO_new_file(outfile, outmode)))
@@ -790,7 +835,7 @@ int MAIN(int argc, char **argv)
 #endif
                }
 
-       if (operation == SMIME_VERIFY)
+       if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT))
                {
                if (!(store = setup_verify(bio_err, CAfile, CApath)))
                        goto end;
@@ -1001,6 +1046,16 @@ int MAIN(int argc, char **argv)
                        receipt_request_print(bio_err, cms);
                                        
                }
+       else if (operation == SMIME_VERIFY_RECEIPT)
+               {
+               if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
+                       BIO_printf(bio_err, "Verification successful\n");
+               else
+                       {
+                       BIO_printf(bio_err, "Verification failure\n");
+                       goto end;
+                       }
+               }
        else
                {
                if (noout)
@@ -1068,6 +1123,8 @@ end:
        X509_free(signer);
        EVP_PKEY_free(key);
        CMS_ContentInfo_free(cms);
+       CMS_ContentInfo_free(rcms);
+       BIO_free(rctin);
        BIO_free(in);
        BIO_free(indata);
        BIO_free_all(out);
index 4cc5d93..22baa3e 100644 (file)
@@ -162,6 +162,10 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
                 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
 
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+                       STACK_OF(X509) *certs,
+                       X509_STORE *store, unsigned int flags);
+
 STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
 
 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
@@ -354,6 +358,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_GET0_REVOCATION_CHOICES               132
 #define CMS_F_CMS_GET0_SIGNED                           133
 #define CMS_F_CMS_RECEIPTREQUEST_CREATE0                159
+#define CMS_F_CMS_RECEIPT_VERIFY                        160
 #define CMS_F_CMS_RECIPIENTINFO_DECRYPT                         134
 #define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT           135
 #define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT           136
@@ -387,7 +392,9 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR     102
 #define CMS_R_CMS_DATAFINAL_ERROR                       103
 #define CMS_R_CMS_LIB                                   104
+#define CMS_R_CONTENTIDENTIFIER_MISMATCH                170
 #define CMS_R_CONTENT_NOT_FOUND                                 105
+#define CMS_R_CONTENT_TYPE_MISMATCH                     171
 #define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA          106
 #define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA           107
 #define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA              108
@@ -395,6 +402,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_CTRL_ERROR                                110
 #define CMS_R_CTRL_FAILURE                              111
 #define CMS_R_DECRYPT_ERROR                             112
+#define CMS_R_DIGEST_ERROR                              161
 #define CMS_R_ERROR_GETTING_PUBLIC_KEY                  113
 #define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE     114
 #define CMS_R_ERROR_SETTING_KEY                                 115
@@ -404,21 +412,31 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_MD_BIO_INIT_ERROR                                 119
 #define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH      120
 #define CMS_R_MESSAGEDIGEST_WRONG_LENGTH                121
+#define CMS_R_MSGSIGDIGEST_ERROR                        172
+#define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE                 162
+#define CMS_R_MSGSIGDIGEST_WRONG_LENGTH                         163
+#define CMS_R_NEED_ONE_SIGNER                           164
+#define CMS_R_NOT_A_SIGNED_RECEIPT                      165
 #define CMS_R_NOT_ENCRYPTED_DATA                        122
 #define CMS_R_NOT_KEK                                   123
 #define CMS_R_NOT_KEY_TRANSPORT                                 124
 #define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE           125
 #define CMS_R_NO_CIPHER                                         126
 #define CMS_R_NO_CONTENT                                127
+#define CMS_R_NO_CONTENT_TYPE                           173
 #define CMS_R_NO_DEFAULT_DIGEST                                 128
 #define CMS_R_NO_DIGEST_SET                             129
 #define CMS_R_NO_KEY                                    130
 #define CMS_R_NO_MATCHING_DIGEST                        131
 #define CMS_R_NO_MATCHING_RECIPIENT                     132
+#define CMS_R_NO_MATCHING_SIGNATURE                     166
+#define CMS_R_NO_MSGSIGDIGEST                           167
 #define CMS_R_NO_PRIVATE_KEY                            133
 #define CMS_R_NO_PUBLIC_KEY                             134
+#define CMS_R_NO_RECEIPT_REQUEST                        168
 #define CMS_R_NO_SIGNERS                                135
 #define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE    136
+#define CMS_R_RECEIPT_DECODE_ERROR                      169
 #define CMS_R_RECIPIENT_ERROR                           137
 #define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND              138
 #define CMS_R_SIGNFINAL_ERROR                           139
index 2979993..7f7132c 100644 (file)
@@ -371,3 +371,10 @@ ASN1_SEQUENCE(CMS_ReceiptRequest) = {
   ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES)
 } ASN1_SEQUENCE_END(CMS_ReceiptRequest)
 
+ASN1_SEQUENCE(CMS_Receipt) = {
+  ASN1_SIMPLE(CMS_Receipt, version, LONG),
+  ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT),
+  ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING),
+  ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_Receipt)
+
index 93e15e3..420a401 100644 (file)
@@ -107,10 +107,11 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES),  "CMS_GET0_REVOCATION_CHOICES"},
 {ERR_FUNC(CMS_F_CMS_GET0_SIGNED),      "CMS_GET0_SIGNED"},
 {ERR_FUNC(CMS_F_CMS_RECEIPTREQUEST_CREATE0),   "CMS_ReceiptRequest_create0"},
+{ERR_FUNC(CMS_F_CMS_RECEIPT_VERIFY),   "CMS_RECEIPT_VERIFY"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT),    "CMS_RecipientInfo_decrypt"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT),      "CMS_RECIPIENTINFO_KEKRI_DECRYPT"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT),      "CMS_RECIPIENTINFO_KEKRI_ENCRYPT"},
-{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID),      "CMS_RECIPIENTINFO_KEKRI_GET0_ID"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID),      "CMS_RecipientInfo_kekri_get0_id"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP),       "CMS_RecipientInfo_kekri_id_cmp"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP),      "CMS_RecipientInfo_ktri_cert_cmp"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT),       "CMS_RECIPIENTINFO_KTRI_DECRYPT"},
@@ -143,7 +144,9 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),"cipher parameter initialisation error"},
 {ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR)   ,"cms datafinal error"},
 {ERR_REASON(CMS_R_CMS_LIB)               ,"cms lib"},
+{ERR_REASON(CMS_R_CONTENTIDENTIFIER_MISMATCH),"contentidentifier mismatch"},
 {ERR_REASON(CMS_R_CONTENT_NOT_FOUND)     ,"content not found"},
+{ERR_REASON(CMS_R_CONTENT_TYPE_MISMATCH) ,"content type mismatch"},
 {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),"content type not compressed data"},
 {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),"content type not enveloped data"},
 {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),"content type not signed data"},
@@ -151,6 +154,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_CTRL_ERROR)            ,"ctrl error"},
 {ERR_REASON(CMS_R_CTRL_FAILURE)          ,"ctrl failure"},
 {ERR_REASON(CMS_R_DECRYPT_ERROR)         ,"decrypt error"},
+{ERR_REASON(CMS_R_DIGEST_ERROR)          ,"digest error"},
 {ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
 {ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
 {ERR_REASON(CMS_R_ERROR_SETTING_KEY)     ,"error setting key"},
@@ -160,21 +164,31 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"},
 {ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
 {ERR_REASON(CMS_R_MESSAGEDIGEST_WRONG_LENGTH),"messagedigest wrong length"},
+{ERR_REASON(CMS_R_MSGSIGDIGEST_ERROR)    ,"msgsigdigest error"},
+{ERR_REASON(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE),"msgsigdigest verification failure"},
+{ERR_REASON(CMS_R_MSGSIGDIGEST_WRONG_LENGTH),"msgsigdigest wrong length"},
+{ERR_REASON(CMS_R_NEED_ONE_SIGNER)       ,"need one signer"},
+{ERR_REASON(CMS_R_NOT_A_SIGNED_RECEIPT)  ,"not a signed receipt"},
 {ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA)    ,"not encrypted data"},
 {ERR_REASON(CMS_R_NOT_KEK)               ,"not kek"},
 {ERR_REASON(CMS_R_NOT_KEY_TRANSPORT)     ,"not key transport"},
 {ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"},
 {ERR_REASON(CMS_R_NO_CIPHER)             ,"no cipher"},
 {ERR_REASON(CMS_R_NO_CONTENT)            ,"no content"},
+{ERR_REASON(CMS_R_NO_CONTENT_TYPE)       ,"no content type"},
 {ERR_REASON(CMS_R_NO_DEFAULT_DIGEST)     ,"no default digest"},
 {ERR_REASON(CMS_R_NO_DIGEST_SET)         ,"no digest set"},
 {ERR_REASON(CMS_R_NO_KEY)                ,"no key"},
 {ERR_REASON(CMS_R_NO_MATCHING_DIGEST)    ,"no matching digest"},
 {ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"},
+{ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"},
+{ERR_REASON(CMS_R_NO_MSGSIGDIGEST)       ,"no msgsigdigest"},
 {ERR_REASON(CMS_R_NO_PRIVATE_KEY)        ,"no private key"},
 {ERR_REASON(CMS_R_NO_PUBLIC_KEY)         ,"no public key"},
+{ERR_REASON(CMS_R_NO_RECEIPT_REQUEST)    ,"no receipt request"},
 {ERR_REASON(CMS_R_NO_SIGNERS)            ,"no signers"},
 {ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"},
+{ERR_REASON(CMS_R_RECEIPT_DECODE_ERROR)  ,"receipt decode error"},
 {ERR_REASON(CMS_R_RECIPIENT_ERROR)       ,"recipient error"},
 {ERR_REASON(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),"signer certificate not found"},
 {ERR_REASON(CMS_R_SIGNFINAL_ERROR)       ,"signfinal error"},
index 9377217..ff9b2a8 100644 (file)
@@ -62,6 +62,7 @@
 #include "asn1_locl.h"
 
 DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
+DECLARE_ASN1_ITEM(CMS_Receipt)
 
 IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
 
@@ -189,5 +190,161 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
                *prto = rr->receiptsTo;
        }
 
+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;
+       }
+
+/* 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;
+       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;
+
+       }
index 5111617..ec644c3 100644 (file)
@@ -449,6 +449,8 @@ int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
                                const EVP_CIPHER *cipher,
                                const unsigned char *key, size_t keylen);
 
+int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
+
 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
        
 #ifdef  __cplusplus
index 6388df8..b37d17c 100644 (file)
@@ -65,18 +65,19 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
        int r = 0, i;
        BIO *tmpout = NULL;
 
-       if(flags & CMS_TEXT)
-               {
+       if (out == NULL)
+               tmpout = BIO_new(BIO_s_null());
+       else if (flags & CMS_TEXT)
                tmpout = BIO_new(BIO_s_mem());
-               if(!tmpout)
-                       {
-                       CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
-                       goto err;
-                       }
-               }
        else
                tmpout = out;
 
+       if(!tmpout)
+               {
+               CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
        /* Read all content through chain to process digest, decrypt etc */
        for (;;)
        {
@@ -419,6 +420,17 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
        return ret;
        }
 
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+                       STACK_OF(X509) *certs,
+                       X509_STORE *store, unsigned int flags)
+       {
+       int r;
+       r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
+       if (r <= 0)
+               return r;
+       return cms_Receipt_verify(rcms, ocms);
+       }
+
 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                                                BIO *data, unsigned int flags)
        {