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 d15e203f9cb4be67f68892b63266c3890b35cd6d..ddc3d5ec17554cb51b686cfad2b2decb90ae8c7d 100644 (file)
@@ -258,6 +258,8 @@ int MAIN(int argc, char **argv)
                                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") 
index 54a704a969ead5e66680da2e712aed00ae3101dc..120889350ce9b11aca4720b04ccf294f356010a9 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 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);
@@ -554,14 +554,30 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                }
        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)
                        {
-                       eol = strip_eol(linebuf, &len);
+                       eol = strip_eol(linebuf, &len, flags);
                        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);
-                       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);
@@ -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 */
-                       next_eol = strip_eol(linebuf, &len);
+                       next_eol = strip_eol(linebuf, &len, 0);
                        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;
 }
 
-static int strip_eol(char *linebuf, int *plen)
+static int strip_eol(char *linebuf, int *plen, int flags)
        {
        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;
+               else if (is_eol && flags & SMIME_ASCIICRLF && c < 33)
+                       continue;
                else if (c != '\r')
                        break;
                }
index 4b36a69c4f2981a690535b737f60d8758774dce5..0d1649ab21853154af5a23df8889fd457c692864 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_ASCIICRLF                  0x80000
 
 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
 
index 8f1aa38ccc5b3bd56ab755ba72f8084fa980320d..e907b279eaac9dd93a906d2646dc2a5e6d155ee8 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 && !(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 */
 
@@ -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;
+       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))
                {
index e4d443193c43a35506dc4940e874373cd37b8774..267a64685aa81e1c35908cb1e9d5386692ac3563 100644 (file)
@@ -276,6 +276,9 @@ DECLARE_PKCS12_STACK_OF(PKCS7)
 #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,
index 29720a87f9fa5e560d848d105c714a6625fd58b4..cfdc4cb13452b333be540542f054bf3dc8263637 100644 (file)
@@ -43,6 +43,7 @@ B<openssl> B<cms>
 [B<-noattr>]
 [B<-nosmimecap>]
 [B<-binary>]
+[B<-asciicrlf>]
 [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.
 
+=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