Add suppot for ASCII with CRLF canonicalisation.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 12 Feb 2014 15:15:55 +0000 (15:15 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 13 Feb 2014 14:35:56 +0000 (14:35 +0000)
apps/cms.c
crypto/asn1/asn_mime.c
crypto/cms/cms.h
crypto/cms/cms_smime.c
crypto/pkcs7/pkcs7.h
doc/apps/cms.pod

index d15e203..ddc3d5e 100644 (file)
@@ -258,6 +258,8 @@ int MAIN(int argc, char **argv)
                                flags |= CMS_DEBUG_DECRYPT;
                else if (!strcmp (*args, "-text")) 
                                flags |= CMS_TEXT;
                                flags |= CMS_DEBUG_DECRYPT;
                else if (!strcmp (*args, "-text")) 
                                flags |= CMS_TEXT;
+               else if (!strcmp (*args, "-asciicrlf")) 
+                               flags |= CMS_ASCIICRLF;
                else if (!strcmp (*args, "-nointern")) 
                                flags |= CMS_NOINTERN;
                else if (!strcmp (*args, "-noverify") 
                else if (!strcmp (*args, "-nointern")) 
                                flags |= CMS_NOINTERN;
                else if (!strcmp (*args, "-noverify") 
index 54a704a..1208893 100644 (file)
@@ -102,7 +102,7 @@ static int mime_param_cmp(const MIME_PARAM * const *a,
 static void mime_param_free(MIME_PARAM *param);
 static int mime_bound_check(char *line, int linelen, char *bound, int blen);
 static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
 static void mime_param_free(MIME_PARAM *param);
 static int mime_bound_check(char *line, int linelen, char *bound, int blen);
 static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
-static int strip_eol(char *linebuf, int *plen);
+static int strip_eol(char *linebuf, int *plen, int flags);
 static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
 static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
 static void mime_hdr_free(MIME_HEADER *hdr);
 static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
 static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
 static void mime_hdr_free(MIME_HEADER *hdr);
@@ -554,14 +554,30 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                }
        else
                {
                }
        else
                {
+               int eolcnt = 0;
                if(flags & SMIME_TEXT)
                        BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
                while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
                        {
                if(flags & SMIME_TEXT)
                        BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
                while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
                        {
-                       eol = strip_eol(linebuf, &len);
+                       eol = strip_eol(linebuf, &len, flags);
                        if (len)
                        if (len)
+                               {
+                               /* Not EOF: write out all CRLF */
+                               if (flags & SMIME_ASCIICRLF)
+                                       {
+                                       int i;
+                                       for(i = 0; i < eolcnt; i++)
+                                               BIO_write(out, "\r\n", 2);
+                                       eolcnt = 0;
+                                       }
                                BIO_write(out, linebuf, len);
                                BIO_write(out, linebuf, len);
-                       if(eol) BIO_write(out, "\r\n", 2);
+                               if(eol)
+                                       BIO_write(out, "\r\n", 2);
+                               }
+                       else if (flags & SMIME_ASCIICRLF)
+                               eolcnt++;       
+                       else if(eol)
+                               BIO_write(out, "\r\n", 2);
                        }
                }
        (void)BIO_flush(out);
                        }
                }
        (void)BIO_flush(out);
@@ -630,7 +646,7 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
                        return 1;
                } else if(part) {
                        /* Strip CR+LF from linebuf */
                        return 1;
                } else if(part) {
                        /* Strip CR+LF from linebuf */
-                       next_eol = strip_eol(linebuf, &len);
+                       next_eol = strip_eol(linebuf, &len, 0);
                        if(first) {
                                first = 0;
                                if(bpart) sk_BIO_push(parts, bpart);
                        if(first) {
                                first = 0;
                                if(bpart) sk_BIO_push(parts, bpart);
@@ -932,7 +948,7 @@ static int mime_bound_check(char *line, int linelen, char *bound, int blen)
        return 0;
 }
 
        return 0;
 }
 
-static int strip_eol(char *linebuf, int *plen)
+static int strip_eol(char *linebuf, int *plen, int flags)
        {
        int len = *plen;
        char *p, c;
        {
        int len = *plen;
        char *p, c;
@@ -943,6 +959,8 @@ static int strip_eol(char *linebuf, int *plen)
                c = *p;
                if (c == '\n')
                        is_eol = 1;
                c = *p;
                if (c == '\n')
                        is_eol = 1;
+               else if (is_eol && flags & SMIME_ASCIICRLF && c < 33)
+                       continue;
                else if (c != '\r')
                        break;
                }
                else if (c != '\r')
                        break;
                }
index 4b36a69..0d1649a 100644 (file)
@@ -117,6 +117,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 #define CMS_USE_KEYID                  0x10000
 #define CMS_DEBUG_DECRYPT              0x20000
 #define CMS_KEY_PARAM                  0x40000
 #define CMS_USE_KEYID                  0x10000
 #define CMS_DEBUG_DECRYPT              0x20000
 #define CMS_KEY_PARAM                  0x40000
+#define CMS_ASCIICRLF                  0x80000
 
 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
 
 
 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
 
index 8f1aa38..e907b27 100644 (file)
@@ -334,6 +334,12 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 
        if (!dcont && !check_content(cms))
                return 0;
 
        if (!dcont && !check_content(cms))
                return 0;
+       if (dcont && !(flags & CMS_BINARY))
+               {
+               const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
+               if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
+                       flags |= CMS_ASCIICRLF;
+               }
 
        /* Attempt to find all signer certificates */
 
 
        /* Attempt to find all signer certificates */
 
@@ -519,6 +525,8 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
        cms = CMS_ContentInfo_new();
        if (!cms || !CMS_SignedData_init(cms))
                goto merr;
        cms = CMS_ContentInfo_new();
        if (!cms || !CMS_SignedData_init(cms))
                goto merr;
+       if (flags & CMS_ASCIICRLF && !CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
+               goto err;
 
        if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
                {
 
        if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
                {
index e4d4431..267a646 100644 (file)
@@ -276,6 +276,9 @@ DECLARE_PKCS12_STACK_OF(PKCS7)
 #define SMIME_BINARY   PKCS7_BINARY
 #define SMIME_NOATTR   PKCS7_NOATTR
 
 #define SMIME_BINARY   PKCS7_BINARY
 #define SMIME_NOATTR   PKCS7_NOATTR
 
+/* CRLF ASCII canonicalisation */
+#define SMIME_ASCIICRLF                0x80000
+
 DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
 
 int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type,
 DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
 
 int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type,
index 29720a8..cfdc4cb 100644 (file)
@@ -43,6 +43,7 @@ B<openssl> B<cms>
 [B<-noattr>]
 [B<-nosmimecap>]
 [B<-binary>]
 [B<-noattr>]
 [B<-nosmimecap>]
 [B<-binary>]
+[B<-asciicrlf>]
 [B<-nodetach>]
 [B<-certfile file>]
 [B<-certsout file>]
 [B<-nodetach>]
 [B<-certfile file>]
 [B<-certsout file>]
@@ -291,6 +292,15 @@ effectively using CR and LF as end of line: as required by the S/MIME
 specification. When this option is present no translation occurs. This
 is useful when handling binary data which may not be in MIME format.
 
 specification. When this option is present no translation occurs. This
 is useful when handling binary data which may not be in MIME format.
 
+=item B<-asciicrlf>
+
+when signing use ASCII CRLF format canonicalisation. This strips trailing
+whitespace from all lines, deletes trailing blank lines at EOF and sets
+the encapsulated content type. This option is normally used with detached
+content and an output signature format of DER. This option is not normally
+needed when verifying as it is enabled automatically if the encapsulated
+content format is detected.
+
 =item B<-nodetach>
 
 when signing a message use opaque signing: this form is more resistant
 =item B<-nodetach>
 
 when signing a message use opaque signing: this form is more resistant