diff --git a/CHANGES b/CHANGES index f3a7021e2312e33a22c5a41e1c92ae95fd83e74e..3f8faa98569904ca8f8de7408a4d1656246175f8 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 b3a39690509c3141581e2deaff417ebecd187e26..0781c4bf939e9def64fbc8b758c759aa7d6d0421 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 6b89b797513c616e509aea960c745ab20595542c..df939e0f401715f65e3b3ee813cc0c503387cac7 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 bb8ecd7cf03de9e83f61aa6cde9c9ff87fe980e3..ebc0eb6af44c1c22842112a66d6183250d1d1e4e 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 35fe01d27e31fcbc4e9a10c613a1ce0c1cec42b4..c0501e1ea95c0d107f8110d6f5acdac7644b7edb 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 721592bf1c7bc0c837e7bda33e57f456cdfce599..45927ffd6e6ec81f4b6323001046c1a20285f29e 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 11f8654c36e4c56b7250827a36f23ab4896cb458..77447a5240959387c9a7dd634e5519a8b171798f 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 */