Signed Receipt Request utility functions and option on CMS utility to
authorDr. Stephen Henson <steve@openssl.org>
Wed, 26 Mar 2008 13:10:21 +0000 (13:10 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 26 Mar 2008 13:10:21 +0000 (13:10 +0000)
print out receipt requests.

apps/cms.c
crypto/cms/Makefile
crypto/cms/cms.h
crypto/cms/cms_asn1.c
crypto/cms/cms_err.c
crypto/cms/cms_ess.c [new file with mode: 0644]
crypto/cms/cms_lcl.h
crypto/stack/safestack.h
crypto/x509v3/v3_genn.c

index 9607ec5..eb1dc3e 100644 (file)
@@ -70,6 +70,7 @@
 #define PROG cms_main
 static int save_certs(char *signerfile, STACK_OF(X509) *signers);
 static int smime_cb(int ok, X509_STORE_CTX *ctx);
+static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
 
 #define SMIME_OP       0x10
 #define SMIME_IP       0x20
@@ -111,6 +112,7 @@ int MAIN(int argc, char **argv)
        BIO *in = NULL, *out = NULL, *indata = NULL;
        int badarg = 0;
        int flags = CMS_DETACHED, noout = 0, print = 0;
+       int rr_print = 0;
        char *to = NULL, *from = NULL, *subject = NULL;
        char *CAfile = NULL, *CApath = NULL;
        char *passargin = NULL, *passin = NULL;
@@ -244,6 +246,8 @@ int MAIN(int argc, char **argv)
                                flags |= CMS_CRLFEOL;
                else if (!strcmp (*args, "-noout"))
                                noout = 1;
+               else if (!strcmp (*args, "-receipt_request_print"))
+                               rr_print = 1;
                else if (!strcmp (*args, "-print"))
                                {
                                noout = 1;
@@ -939,6 +943,9 @@ int MAIN(int argc, char **argv)
                                }
                        sk_X509_free(signers);
                        }
+               if (rr_print)
+                       receipt_request_print(bio_err, cms);
+                                       
                }
        else
                {
@@ -1041,4 +1048,75 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx)
 
        }
 
+static void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
+       {
+       STACK_OF(GENERAL_NAME) *gens;
+       GENERAL_NAME *gen;
+       int i, j;
+       for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++)
+               {
+               gens = sk_GENERAL_NAMES_value(gns, i);
+               for (j = 0; j < sk_GENERAL_NAME_num(gens); j++)
+                       {
+                       gen = sk_GENERAL_NAME_value(gens, j);
+                       BIO_puts(out, "    ");
+                       GENERAL_NAME_print(out, gen);
+                       BIO_puts(out, "\n");
+                       }
+               }
+       return;
+       }
+
+static void receipt_request_print(BIO *out, CMS_ContentInfo *cms)
+       {
+       STACK_OF(CMS_SignerInfo) *sis;
+       CMS_SignerInfo *si;
+       CMS_ReceiptRequest *rr;
+       int allorfirst;
+       STACK_OF(GENERAL_NAMES) *rto, *rlist;
+       ASN1_STRING *scid;
+       int i, rv;
+       sis = CMS_get0_SignerInfos(cms);
+       for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++)
+               {
+               si = sk_CMS_SignerInfo_value(sis, i);
+               rv = CMS_get1_ReceiptRequest(si, &rr);
+               BIO_printf(bio_err, "Signer %d:\n", i + 1);
+               if (rv == 0)
+                       BIO_puts(bio_err, "  No Receipt Request\n");
+               else if (rv < 0)
+                       {
+                       BIO_puts(bio_err, "  Receipt Request Parse Error\n");
+                       ERR_print_errors(bio_err);
+                       }
+               else
+                       {
+                       char *id;
+                       int idlen;
+                       CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
+                                                       &rlist, &rto);
+                       BIO_puts(out, "  Signed Content ID:\n");
+                       idlen = ASN1_STRING_length(scid);
+                       id = (char *)ASN1_STRING_data(scid);
+                       BIO_dump_indent(out, id, idlen, 4);
+                       BIO_puts(out, "  Receipts From");
+                       if (rlist)
+                               {
+                               BIO_puts(out, " List:\n");
+                               gnames_stack_print(out, rlist);
+                               }
+                       else if (allorfirst == 1)
+                               BIO_puts(out, ": First Tier\n");
+                       else if (allorfirst == 0)
+                               BIO_puts(out, ": All\n");
+                       else
+                               BIO_printf(out, " Unknown (%d)\n", allorfirst);
+                       BIO_puts(out, "  Receipts To:\n");
+                       gnames_stack_print(out, rto);
+                       }
+               if (rr)
+                       CMS_ReceiptRequest_free(rr);
+               }
+       }
+
 #endif
index a251164..affda88 100644 (file)
@@ -18,9 +18,9 @@ APPS=
 
 LIB=$(TOP)/libcrypto.a
 LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
-       cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c
+       cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c
 LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \
-       cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o
+       cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o
 
 SRC= $(LIBSRC)
 
index 797f86b..15205bb 100644 (file)
@@ -75,7 +75,9 @@ typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
 typedef struct CMS_Receipt_st CMS_Receipt;
 
 DECLARE_STACK_OF(CMS_SignerInfo)
+DECLARE_STACK_OF(GENERAL_NAMES)
 DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
+DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
 DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 
 #define CMS_SIGNERINFO_ISSUER_SERIAL   0
@@ -283,6 +285,22 @@ int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
 void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
                                        int lastpos, int type);
 
+#ifdef HEADER_X509V3_H
+
+int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
+int CMS_add1_ReceiptRequest(CMS_SignerInfo *si,
+                               unsigned char *id, int idlen,
+                               int allorfirst,
+                               STACK_OF(GENERAL_NAMES) *receiptList,
+                               STACK_OF(GENERAL_NAMES) *receiptsTo);
+void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
+                                       ASN1_STRING **pcid,
+                                       int *pallorfirst,
+                                       STACK_OF(GENERAL_NAMES) **plist,
+                                       STACK_OF(GENERAL_NAMES) **prto);
+
+#endif
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -294,6 +312,7 @@ void ERR_load_CMS_strings(void);
 /* Function codes. */
 #define CMS_F_CHECK_CONTENT                             99
 #define CMS_F_CMS_ADD0_RECIPIENT_KEY                    100
+#define CMS_F_CMS_ADD1_RECEIPTREQUEST                   158
 #define CMS_F_CMS_ADD1_RECIPIENT_CERT                   101
 #define CMS_F_CMS_ADD1_SIGNER                           102
 #define CMS_F_CMS_ADD1_SIGNINGTIME                      103
index bef043a..2979993 100644 (file)
@@ -362,11 +362,12 @@ ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify)
 
 ASN1_CHOICE(CMS_ReceiptsFrom) = {
   ASN1_IMP(CMS_ReceiptsFrom, d.allOrFirstTier, LONG, 0),
-  ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAME, 1)
+  ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1)
 } ASN1_CHOICE_END(CMS_ReceiptsFrom)
 
 ASN1_SEQUENCE(CMS_ReceiptRequest) = {
   ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING),
-  ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom)
+  ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom),
+  ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES)
 } ASN1_SEQUENCE_END(CMS_ReceiptRequest)
 
index 51a3ade..7b1294c 100644 (file)
@@ -72,6 +72,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
        {
 {ERR_FUNC(CMS_F_CHECK_CONTENT),        "CHECK_CONTENT"},
 {ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY),       "CMS_add0_recipient_key"},
+{ERR_FUNC(CMS_F_CMS_ADD1_RECEIPTREQUEST),      "CMS_ADD1_RECEIPTREQUEST"},
 {ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),      "CMS_add1_recipient_cert"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),      "CMS_add1_signer"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"},
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
new file mode 100644 (file)
index 0000000..00cd9dc
--- /dev/null
@@ -0,0 +1,184 @@
+/* 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"
+#include "asn1_locl.h"
+
+DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
+
+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;
+       }
+
+int CMS_add1_ReceiptRequest(CMS_SignerInfo *si,
+                               unsigned char *id, int idlen,
+                               int allorfirst,
+                               STACK_OF(GENERAL_NAMES) *receiptList,
+                               STACK_OF(GENERAL_NAMES) *receiptsTo)
+       {
+       CMS_ReceiptRequest *rr = NULL;
+       STACK_OF(GENERAL_NAMES) *tmpto = NULL;
+       unsigned char *rrder = NULL;
+       int rrderlen;
+       int r = 0;
+
+       rr = CMS_ReceiptRequest_new();
+       if (!rr)
+               goto merr;
+       if (id)
+               {
+               if (!ASN1_STRING_set(rr->signedContentIdentifier, id, idlen))
+                       goto merr;
+               }
+       else
+               {
+               if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
+                       goto merr;
+               if (RAND_pseudo_bytes(rr->signedContentIdentifier->data, 32) 
+                                       <= 0)
+                       goto err;
+               }
+
+       tmpto = rr->receiptsTo;
+       rr->receiptsTo = receiptsTo;
+
+       if (receiptList)
+               {
+               rr->receiptsFrom->type = 1;
+               rr->receiptsFrom->d.receiptList = receiptList;
+               }
+       else
+               {
+               rr->receiptsFrom->type = 0;
+               rr->receiptsFrom->d.allOrFirstTier = allorfirst;
+               }
+
+       rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
+
+       r = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
+                                       V_ASN1_SEQUENCE, rrder, rrderlen);
+
+       merr:
+       CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
+
+       err:
+       if (rr)
+               {
+               rr->receiptsTo = tmpto;
+               rr->receiptsFrom->type = 0;
+               CMS_ReceiptRequest_free(rr);
+               }
+       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;
+       }
+
+
+
index 0956721..5111617 100644 (file)
@@ -383,7 +383,7 @@ struct CMS_ReceiptRequest_st
        {
        ASN1_OCTET_STRING *signedContentIdentifier;
        CMS_ReceiptsFrom *receiptsFrom;
-       GENERAL_NAMES *receiptsTo;
+       STACK_OF(GENERAL_NAMES) *receiptsTo;
        };
 
 
@@ -393,7 +393,7 @@ struct CMS_ReceiptsFrom_st
        union
                {
                long allOrFirstTier;
-               GENERAL_NAMES *receiptList;
+               STACK_OF(GENERAL_NAMES) *receiptList;
                } d;
        };
 #endif
index 955275b..c00b478 100644 (file)
@@ -810,6 +810,28 @@ STACK_OF(type) \
 #define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
 #define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st))
 
+#define sk_GENERAL_NAMES_new(st) SKM_sk_new(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_new_null() SKM_sk_new_null(GENERAL_NAMES)
+#define sk_GENERAL_NAMES_free(st) SKM_sk_free(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_num(st) SKM_sk_num(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_value(st, i) SKM_sk_value(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_set(st, i, val) SKM_sk_set(GENERAL_NAMES, (st), (i), (val))
+#define sk_GENERAL_NAMES_zero(st) SKM_sk_zero(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_push(st, val) SKM_sk_push(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_unshift(st, val) SKM_sk_unshift(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find(st, val) SKM_sk_find(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_delete(st, i) SKM_sk_delete(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAMES, (st), (ptr))
+#define sk_GENERAL_NAMES_insert(st, val, i) SKM_sk_insert(GENERAL_NAMES, (st), (val), (i))
+#define sk_GENERAL_NAMES_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAMES, (st), (cmp))
+#define sk_GENERAL_NAMES_dup(st) SKM_sk_dup(GENERAL_NAMES, st)
+#define sk_GENERAL_NAMES_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAMES, (st), (free_func))
+#define sk_GENERAL_NAMES_shift(st) SKM_sk_shift(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_pop(st) SKM_sk_pop(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_sort(st) SKM_sk_sort(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAMES, (st))
+
 #define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
 #define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
 #define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st))
index 363f2d3..2a80586 100644 (file)
@@ -158,3 +158,95 @@ int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
        result = ASN1_TYPE_cmp(a->value, b->value);
        return result;
        }
+
+void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
+       {
+       switch(type)
+               {
+       case GEN_X400:
+       case GEN_EDIPARTY:
+               a->d.other = value;
+               break;
+
+       case GEN_OTHERNAME:
+               a->d.otherName = value;
+               break;
+
+       case GEN_EMAIL:
+       case GEN_DNS:
+       case GEN_URI:
+               a->d.ia5 = value;
+               break;
+
+       case GEN_DIRNAME:
+               a->d.dirn = value;
+               break;
+
+       case GEN_IPADD:
+               a->d.ip = value;
+               break;
+       
+       case GEN_RID:
+               a->d.rid = value;
+               break;
+               }
+       a->type = type;
+       }
+
+void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
+       {
+       if (ptype)
+               *ptype = a->type;
+       switch(a->type)
+               {
+       case GEN_X400:
+       case GEN_EDIPARTY:
+               return a->d.other;
+
+       case GEN_OTHERNAME:
+               return a->d.otherName;
+
+       case GEN_EMAIL:
+       case GEN_DNS:
+       case GEN_URI:
+               return a->d.ia5;
+
+       case GEN_DIRNAME:
+               return a->d.dirn;
+
+       case GEN_IPADD:
+               return a->d.ip;
+       
+       case GEN_RID:
+               return a->d.rid;
+
+       default:
+               return NULL;
+               }
+       }
+
+int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+                               ASN1_OBJECT *oid, ASN1_TYPE *value)
+       {
+       OTHERNAME *oth;
+       oth = OTHERNAME_new();
+       if (!oth)
+               return 0;
+       oth->type_id = oid;
+       oth->value = value;
+       GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
+       return 1;
+       }
+
+int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, 
+                               ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
+       {
+       if (gen->type != GEN_OTHERNAME)
+               return 0;
+       if (poid)
+               *poid = gen->d.otherName->type_id;
+       if (pvalue)
+               *pvalue = gen->d.otherName->value;
+       return 1;
+       }
+