From 094fe66d9fdb70bb424de822bbed1eddb8f0194a Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 10 Jul 2000 18:33:05 +0000 Subject: [PATCH] Fix some typose in the i2d/d2i functions that call the i2c/c2i (they were not using the content length for the headers). Fix ASN1 long form tag encoding. This never worked but it was never tested since it is only used for tags > 30. New options to smime program to allow the PKCS#7 format to be specified and the content supplied externally. --- CHANGES | 10 ++++++++ apps/apps.c | 2 ++ apps/apps.h | 1 + apps/smime.c | 58 +++++++++++++++++++++++++++++++++++++----- crypto/asn1/a_bitstr.c | 2 +- crypto/asn1/a_int.c | 2 +- crypto/asn1/asn1_lib.c | 13 ++++++---- 7 files changed, 75 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index f3a7021e2..3f8faa985 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,16 @@ Changes between 0.9.5a and 0.9.6 [xx XXX 2000] + *) New options to smime application. -inform and -outform + allow alternative formats for the S/MIME message including + PEM and DER. The -content option allows the content to be + specified separately. This should allow things like Netscape + form signing output easier to verify. + [Steve Henson] + + *) Fix the ASN1 encoding of tags using the 'long form'. + [Steve Henson] + *) New ASN1 functions, i2c_* and c2i_* for INTEGER and BIT STRING types. These convert content octets to and from the underlying type. The actual tag and length octets are diff --git a/apps/apps.c b/apps/apps.c index b3a396905..0781c4bf9 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -164,6 +164,8 @@ int str2fmt(char *s) return(FORMAT_PEM); else if ((*s == 'N') || (*s == 'n')) return(FORMAT_NETSCAPE); + else if ((*s == 'S') || (*s == 's')) + return(FORMAT_SMIME); else if ((*s == '1') || (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0) || (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0)) diff --git a/apps/apps.h b/apps/apps.h index 6b89b7975..df939e0f4 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -158,6 +158,7 @@ STACK_OF(X509) *load_certs(BIO *err, char *file, int format); #define FORMAT_PEM 3 #define FORMAT_NETSCAPE 4 #define FORMAT_PKCS12 5 +#define FORMAT_SMIME 6 #define NETSCAPE_CERT_HDR "certificate" diff --git a/apps/smime.c b/apps/smime.c index bb8ecd7cf..ebc0eb6af 100644 --- a/apps/smime.c +++ b/apps/smime.c @@ -87,7 +87,7 @@ int MAIN(int argc, char **argv) char *inmode = "r", *outmode = "w"; char *infile = NULL, *outfile = NULL; char *signerfile = NULL, *recipfile = NULL; - char *certfile = NULL, *keyfile = NULL; + char *certfile = NULL, *keyfile = NULL, *contfile=NULL; EVP_CIPHER *cipher = NULL; PKCS7 *p7 = NULL; X509_STORE *store = NULL; @@ -102,6 +102,7 @@ int MAIN(int argc, char **argv) char *passargin = NULL, *passin = NULL; char *inrand = NULL; int need_rand = 0; + int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; args = argv + 1; ret = 1; @@ -205,11 +206,26 @@ int MAIN(int argc, char **argv) args++; infile = *args; } else badarg = 1; + } else if (!strcmp (*args, "-inform")) { + if (args[1]) { + args++; + informat = str2fmt(*args); + } else badarg = 1; + } else if (!strcmp (*args, "-outform")) { + if (args[1]) { + args++; + outformat = str2fmt(*args); + } else badarg = 1; } else if (!strcmp (*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; + } else if (!strcmp (*args, "-content")) { + if (args[1]) { + args++; + contfile = *args; + } else badarg = 1; } else badarg = 1; args++; } @@ -292,9 +308,12 @@ int MAIN(int argc, char **argv) if(operation != SMIME_SIGN) flags &= ~PKCS7_DETACHED; - if(flags & PKCS7_BINARY) { - if(operation & SMIME_OP) inmode = "rb"; - else outmode = "rb"; + if(operation & SMIME_OP) { + if(flags & PKCS7_BINARY) inmode = "rb"; + if(outformat == FORMAT_ASN1) outmode = "wb"; + } else { + if(flags & PKCS7_BINARY) outmode = "wb"; + if(informat == FORMAT_ASN1) inmode = "rb"; } if(operation == SMIME_ENCRYPT) { @@ -383,10 +402,28 @@ int MAIN(int argc, char **argv) p7 = PKCS7_sign(signer, key, other, in, flags); BIO_reset(in); } else { - if(!(p7 = SMIME_read_PKCS7(in, &indata))) { + if(informat == FORMAT_SMIME) + p7 = SMIME_read_PKCS7(in, &indata); + else if(informat == FORMAT_PEM) + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); + else if(informat == FORMAT_ASN1) + p7 = d2i_PKCS7_bio(in, NULL); + else { + BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); + goto end; + } + + if(!p7) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } + if(contfile) { + BIO_free(indata); + if(!(indata = BIO_new_file(contfile, "rb"))) { + BIO_printf(bio_err, "Can't read content file %s\n", contfile); + goto end; + } + } } if(!p7) { @@ -422,7 +459,16 @@ int MAIN(int argc, char **argv) if(to) BIO_printf(out, "To: %s\n", to); if(from) BIO_printf(out, "From: %s\n", from); if(subject) BIO_printf(out, "Subject: %s\n", subject); - SMIME_write_PKCS7(out, p7, in, flags); + if(outformat == FORMAT_SMIME) + SMIME_write_PKCS7(out, p7, in, flags); + else if(outformat == FORMAT_PEM) + PEM_write_bio_PKCS7(out,p7); + else if(outformat == FORMAT_ASN1) + i2d_PKCS7_bio(out,p7); + else { + BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); + goto end; + } } ret = 0; end: diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c index 35fe01d27..c0501e1ea 100644 --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -75,7 +75,7 @@ int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) len = i2c_ASN1_BIT_STRING(a, NULL); ret=ASN1_object_size(0,len,V_ASN1_BIT_STRING); if(pp) { - ASN1_put_object(pp,0,ret,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL); + ASN1_put_object(pp,0,len,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL); i2c_ASN1_BIT_STRING(a, pp); } return ret; diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index 721592bf1..45927ffd6 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -80,7 +80,7 @@ int i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) len = i2c_ASN1_INTEGER(a, NULL); ret=ASN1_object_size(0,len,V_ASN1_INTEGER); if(pp) { - ASN1_put_object(pp,0,ret,V_ASN1_INTEGER,V_ASN1_UNIVERSAL); + ASN1_put_object(pp,0,len,V_ASN1_INTEGER,V_ASN1_UNIVERSAL); i2c_ASN1_INTEGER(a, pp); } return ret; diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 11f8654c3..77447a524 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -181,7 +181,7 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int xclass) { unsigned char *p= *pp; - int i; + int i, ttag; i=(constructed)?V_ASN1_CONSTRUCTED:0; i|=(xclass&V_ASN1_PRIVATE); @@ -190,12 +190,15 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, else { *(p++)=i|V_ASN1_PRIMITIVE_TAG; - while (tag > 0x7f) + for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7; + ttag = i; + while(i-- > 0) { - *(p++)=(tag&0x7f)|0x80; - tag>>=7; + p[i] = tag & 0x7f; + if(i != (ttag - 1)) p[i] |= 0x80; + tag >>= 7; } - *(p++)=(tag&0x7f); + p += ttag; } if ((constructed == 2) && (length == 0)) *(p++)=0x80; /* der_put_length would output 0 instead */