Single pass processing to cleartext S/MIME signing.
authorDr. Stephen Henson <steve@openssl.org>
Sat, 15 Feb 2003 00:50:55 +0000 (00:50 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sat, 15 Feb 2003 00:50:55 +0000 (00:50 +0000)
CHANGES
apps/smime.c
crypto/pkcs7/pk7_mime.c
crypto/pkcs7/pk7_smime.c
crypto/pkcs7/pkcs7.h

diff --git a/CHANGES b/CHANGES
index 1bfbb2741f1141e15d3e061ff8f98941c5747b07..aab19157d64b02bd9d6dfd591bbbd74d2d1b228d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,17 @@
 
  Changes between 0.9.7a and 0.9.8  [xx XXX xxxx]
 
+  *) Support for single pass processing for S/MIME signing. This now
+     means that S/MIME signing can be done from a pipe, in addition
+     cleartext signing (multipart/signed type) is effectively streaming
+     and the signed data does not need to be all held in memory.
+
+     This is done with a new flag PKCS7_PARTSIGN. When this flag is set
+     PKCS7_sign() only initializes the PKCS7 structure and the actual signing
+     is done after the data is output (and digests calculated) in
+     SMIME_write_PKCS7().
+     [Steve Henson]
+
   *) Add full support for -rpath/-R, both in shared libraries and
      applications, at least on the platforms where it's known how
      to do it.
index cc248d377bb4a39b6b76a82e8f4317753f47f138..83daa71ca19d47f97a9153d2af9414773c83fa30 100644 (file)
@@ -1,9 +1,9 @@
 /* smime.c */
 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2003 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
@@ -478,8 +478,14 @@ int MAIN(int argc, char **argv)
        if(operation == SMIME_ENCRYPT) {
                p7 = PKCS7_encrypt(encerts, in, cipher, flags);
        } else if(operation == SMIME_SIGN) {
+               /* If detached data and SMIME output enable partial
+                * signing.
+                */
+               if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME))
+                       flags |= PKCS7_PARTSIGN;
                p7 = PKCS7_sign(signer, key, other, in, flags);
-               if (BIO_reset(in) != 0 && (flags & PKCS7_DETACHED)) {
+               /* Don't need to rewind for partial signing */
+               if (!(flags & PKCS7_PARTSIGN) && (BIO_reset(in) != 0)) {
                  BIO_printf(bio_err, "Can't rewind input file\n");
                  goto end;
                }
index 5100c84b881aafb504e4e3035f0533678e99a32e..51be7776876fbc5bb1fe926a64c692ad4a7ab7a3 100644 (file)
@@ -1,9 +1,9 @@
 /* pk7_mime.c */
 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2003 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
@@ -86,6 +86,7 @@ STACK_OF(MIME_PARAM) *params;         /* Zero or more parameters */
 DECLARE_STACK_OF(MIME_HEADER)
 IMPLEMENT_STACK_OF(MIME_HEADER)
 
+static int pkcs7_output_data(BIO *bio, BIO *data, PKCS7 *p7, int flags);
 static int B64_write_PKCS7(BIO *bio, PKCS7 *p7);
 static PKCS7 *B64_read_PKCS7(BIO *bio);
 static char * strip_ends(char *name);
@@ -150,7 +151,6 @@ static PKCS7 *B64_read_PKCS7(BIO *bio)
 
 int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 {
-       char linebuf[MAX_SMLEN];
        char bound[33], c;
        int i;
        if((flags & PKCS7_DETACHED) && data) {
@@ -171,9 +171,9 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
                BIO_printf(bio, "This is an S/MIME signed message\n\n");
                /* Now write out the first part */
                BIO_printf(bio, "------%s\r\n", bound);
-               if(flags & PKCS7_TEXT) BIO_printf(bio, "Content-Type: text/plain\n\n");
-               while((i = BIO_read(data, linebuf, MAX_SMLEN)) > 0) 
-                                               BIO_write(bio, linebuf, i);
+
+               pkcs7_output_data(bio, data, p7, flags);
+
                BIO_printf(bio, "\n------%s\n", bound);
 
                /* Headers for signature */
@@ -195,6 +195,47 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
        return 1;
 }
 
+/* Handle output of PKCS#7 data */
+
+
+static int pkcs7_output_data(BIO *out, BIO *data, PKCS7 *p7, int flags)
+       {
+       BIO *tmpbio, *p7bio;
+
+       if (!(flags & PKCS7_PARTSIGN))
+               {
+               SMIME_crlf_copy(data, out, flags);
+               return 1;
+               }
+
+       /* Partial sign operation */
+
+       /* Initialize sign operation */
+       p7bio = PKCS7_dataInit(p7, out);
+
+       /* Copy data across, computing digests etc */
+       SMIME_crlf_copy(data, p7bio, flags);
+
+       /* Must be detached */
+       PKCS7_set_detached(p7, 1);
+
+       /* Finalize signatures */
+       PKCS7_dataFinal(p7, p7bio);
+
+       /* Now remove any digests from output BIO */
+
+       while (1)
+               {
+               tmpbio = BIO_pop(p7bio);
+               if (tmpbio == out)
+                       break;
+               BIO_free(tmpbio);
+               }
+
+       return 1;
+
+       }
+
 /* SMIME reader: handle multipart/signed and opaque signing.
  * in multipart case the content is placed in a memory BIO
  * pointed to by "bcont". In opaque this is set to NULL
@@ -314,7 +355,8 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                                                BIO_write(out, linebuf, len);
                return 1;
        }
-       if(flags & PKCS7_TEXT) BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
+       if(flags & PKCS7_TEXT)
+               BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
        while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
                eol = 0;
                while(iscrlf(linebuf[len - 1])) {
index f0d071e2824a60b3305c918aac8f66a3cecd359b..b170fe285d48920be2a8bbc0c66717c830b2d2b5 100644 (file)
@@ -1,9 +1,9 @@
 /* pk7_smime.c */
 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2003 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
@@ -97,14 +97,6 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                        PKCS7_add_certificate(p7, sk_X509_value(certs, i));
        }
 
-       if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
-               PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
-               return NULL;
-       }
-
-
-       SMIME_crlf_copy(data, p7bio, flags);
-
        if(!(flags & PKCS7_NOATTR)) {
                PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
                                V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
@@ -133,6 +125,16 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                }
        }
 
+       if (flags & PKCS7_PARTSIGN)
+               return p7;
+
+       if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
+               PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
+               return NULL;
+       }
+
+       SMIME_crlf_copy(data, p7bio, flags);
+
        if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
 
         if (!PKCS7_dataFinal(p7,p7bio)) {
index 226fb64348148590e912c8a931ba990244e2a60a..a2956589ab12d026642fdd1f4fc1719ca7295637 100644 (file)
@@ -260,6 +260,7 @@ DECLARE_PKCS12_STACK_OF(PKCS7)
 #define PKCS7_BINARY           0x80
 #define PKCS7_NOATTR           0x100
 #define        PKCS7_NOSMIMECAP        0x200
+#define        PKCS7_PARTSIGN          0x400
 
 /* Flags: for compatibility with older code */