]> WPIA git - cassiopeia.git/blobdiff - lib/openssl/crypto/cms/cms_ess.c
add: execute openssl fetcher to fetch openssl 1.0.1j
[cassiopeia.git] / lib / openssl / crypto / cms / cms_ess.c
diff --git a/lib/openssl/crypto/cms/cms_ess.c b/lib/openssl/crypto/cms/cms_ess.c
new file mode 100644 (file)
index 0000000..90c0b82
--- /dev/null
@@ -0,0 +1,420 @@
+/* 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) <= 0)
+               {
+               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) <= 0)
+               {
+               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;
+
+       }
+
+