Loading CHANGES +5 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,11 @@ Changes between 0.9.8b and 0.9.9 [xx XXX xxxx] *) New -resign option to smime utility. This adds one or more signers to an existing PKCS#7 signedData structure. Also -md option to use an alternative message digest algorithm for signing. [Steve Henson] *) Tidy up PKCS#7 routines and add new functions to make it easier to create PKCS7 structures containing multiple signers. Update smime application to support multiple signers. Loading apps/smime.c +84 −65 Original line number Diff line number Diff line Loading @@ -73,11 +73,14 @@ static int save_certs(char *signerfile, STACK_OF(X509) *signers); static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_OP 0x10 #define SMIME_IP 0x20 #define SMIME_SIGNERS 0x40 #define SMIME_ENCRYPT (1 | SMIME_OP) #define SMIME_DECRYPT 2 #define SMIME_SIGN (3 | SMIME_OP) #define SMIME_VERIFY 4 #define SMIME_PK7OUT 5 #define SMIME_DECRYPT (2 | SMIME_IP) #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) #define SMIME_VERIFY (4 | SMIME_IP) #define SMIME_PK7OUT (5 | SMIME_OP) #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) int MAIN(int, char **); Loading Loading @@ -106,6 +109,7 @@ int MAIN(int argc, char **argv) char *passargin = NULL, *passin = NULL; char *inrand = NULL; int need_rand = 0; const EVP_MD *sign_md = NULL; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; int keyform = FORMAT_PEM; #ifndef OPENSSL_NO_ENGINE Loading Loading @@ -136,6 +140,8 @@ int MAIN(int argc, char **argv) operation = SMIME_DECRYPT; else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; else if (!strcmp (*args, "-resign")) operation = SMIME_RESIGN; else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; else if (!strcmp (*args, "-pk7out")) Loading Loading @@ -252,6 +258,18 @@ int MAIN(int argc, char **argv) goto argerr; recipfile = *++args; } else if (!strcmp (*args, "-md")) { if (!args[1]) goto argerr; sign_md = EVP_get_digestbyname(*++args); if (sign_md == NULL) { BIO_printf(bio_err, "Unknown digest %s\n", *args); goto argerr; } } else if (!strcmp (*args, "-inkey")) { if (!args[1]) Loading Loading @@ -335,13 +353,13 @@ int MAIN(int argc, char **argv) args++; } if ((operation != SMIME_SIGN) && (skkeys || sksigners)) if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto argerr; } if (operation == SMIME_SIGN) if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) Loading Loading @@ -468,13 +486,11 @@ int MAIN(int argc, char **argv) ret = 2; if (operation != SMIME_SIGN) if (!(operation & SMIME_SIGNERS)) flags &= ~PKCS7_DETACHED; if (operation & SMIME_OP) { if (flags & PKCS7_BINARY) inmode = "rb"; if (outformat == FORMAT_ASN1) outmode = "wb"; } Loading @@ -482,9 +498,18 @@ int MAIN(int argc, char **argv) { if (flags & PKCS7_BINARY) outmode = "wb"; } if (operation & SMIME_IP) { if (informat == FORMAT_ASN1) inmode = "rb"; } else { if (flags & PKCS7_BINARY) inmode = "rb"; } if (operation == SMIME_ENCRYPT) { Loading Loading @@ -514,26 +539,11 @@ int MAIN(int argc, char **argv) } } if (signerfile && (operation == SMIME_SIGN)) { if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, e, "signer certificate"))) { #if 0 /* An appropri message has already been printed */ BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); #endif goto end; } } if (certfile) { if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, e, "certificate file"))) { #if 0 /* An appropriate message has already been printed */ BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); #endif ERR_print_errors(bio_err); goto end; } Loading @@ -544,9 +554,6 @@ int MAIN(int argc, char **argv) if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, e, "recipient certificate file"))) { #if 0 /* An appropriate message has alrady been printed */ BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); #endif ERR_print_errors(bio_err); goto end; } Loading Loading @@ -584,6 +591,36 @@ int MAIN(int argc, char **argv) else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (operation & SMIME_IP) { 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 (outfile) { if (!(out = BIO_new_file(outfile, outmode))) Loading Loading @@ -618,16 +655,22 @@ int MAIN(int argc, char **argv) if (operation == SMIME_ENCRYPT) p7 = PKCS7_encrypt(encerts, in, cipher, flags); else if (operation == SMIME_SIGN) else if (operation & SMIME_SIGNERS) { int i; /* If detached data and SMIME output enable partial * signing. */ if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) if (operation == SMIME_SIGN) { if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) flags |= PKCS7_STREAM; flags |= PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, other, in, flags); } else flags |= PKCS7_REUSE_DIGEST; for (i = 0; i < sk_num(sksigners); i++) { signerfile = sk_value(sksigners, i); Loading @@ -641,15 +684,15 @@ int MAIN(int argc, char **argv) if (!key) goto end; if (!PKCS7_sign_add_signer(p7, signer, key, NULL, flags)) sign_md, flags)) goto end; X509_free(signer); signer = NULL; EVP_PKEY_free(key); key = NULL; } /* If not streaming finalize structure */ if (!(flags & PKCS7_STREAM)) /* If not streaming or resigning finalize structure */ if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { if (!PKCS7_final(p7, in, flags)) goto end; Loading @@ -660,35 +703,6 @@ int MAIN(int argc, char **argv) } } } else { 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) { Loading Loading @@ -736,7 +750,12 @@ int MAIN(int argc, char **argv) if (subject) BIO_printf(out, "Subject: %s\n", subject); if (outformat == FORMAT_SMIME) { if (operation == SMIME_RESIGN) SMIME_write_PKCS7(out, p7, indata, flags); else SMIME_write_PKCS7(out, p7, in, flags); } else if (outformat == FORMAT_PEM) PEM_write_bio_PKCS7(out,p7); else if (outformat == FORMAT_ASN1) Loading crypto/pkcs7/pk7_doit.c +0 −1 Original line number Diff line number Diff line Loading @@ -854,7 +854,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) EVP_MD_CTX_cleanup(&mctx); ASN1_STRING_set0(si->enc_digest, abuf, siglen); abuf = NULL; return 1; Loading crypto/pkcs7/pk7_mime.c +1 −1 Original line number Diff line number Diff line Loading @@ -204,7 +204,7 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) msg_type = "enveloped-data"; else if (PKCS7_type_is_signed(p7)) { /* If we have any signers it is signed-data othewise /* If we have any signers it is signed-data otherwise * certs-only. */ STACK_OF(PKCS7_SIGNER_INFO) *sinfos; Loading crypto/pkcs7/pk7_smime.c +45 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { Loading Loading @@ -198,6 +200,14 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, || !PKCS7_add_attrib_smimecap (si, smcap)) goto err; sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); smcap = NULL; } if (flags & PKCS7_REUSE_DIGEST) { if (!pkcs7_copy_existing_digest(p7, si)) goto err; if (!PKCS7_SIGNER_INFO_sign(si)) goto err; } } return si; Loading @@ -209,6 +219,41 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, return NULL; } /* Search for a digest matching SignerInfo digest type and if found * copy across. */ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) { int i; STACK_OF(PKCS7_SIGNER_INFO) *sinfos; PKCS7_SIGNER_INFO *sitmp; ASN1_OCTET_STRING *osdig = NULL; sinfos = PKCS7_get_signer_info(p7); for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i); if (si == sitmp) break; if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0) continue; if (!OBJ_cmp(si->digest_alg->algorithm, sitmp->digest_alg->algorithm)) { osdig = PKCS7_digest_from_attributes(sitmp->auth_attr); break; } } if (osdig) return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); return 0; } int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags) { Loading Loading
CHANGES +5 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,11 @@ Changes between 0.9.8b and 0.9.9 [xx XXX xxxx] *) New -resign option to smime utility. This adds one or more signers to an existing PKCS#7 signedData structure. Also -md option to use an alternative message digest algorithm for signing. [Steve Henson] *) Tidy up PKCS#7 routines and add new functions to make it easier to create PKCS7 structures containing multiple signers. Update smime application to support multiple signers. Loading
apps/smime.c +84 −65 Original line number Diff line number Diff line Loading @@ -73,11 +73,14 @@ static int save_certs(char *signerfile, STACK_OF(X509) *signers); static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_OP 0x10 #define SMIME_IP 0x20 #define SMIME_SIGNERS 0x40 #define SMIME_ENCRYPT (1 | SMIME_OP) #define SMIME_DECRYPT 2 #define SMIME_SIGN (3 | SMIME_OP) #define SMIME_VERIFY 4 #define SMIME_PK7OUT 5 #define SMIME_DECRYPT (2 | SMIME_IP) #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) #define SMIME_VERIFY (4 | SMIME_IP) #define SMIME_PK7OUT (5 | SMIME_OP) #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) int MAIN(int, char **); Loading Loading @@ -106,6 +109,7 @@ int MAIN(int argc, char **argv) char *passargin = NULL, *passin = NULL; char *inrand = NULL; int need_rand = 0; const EVP_MD *sign_md = NULL; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; int keyform = FORMAT_PEM; #ifndef OPENSSL_NO_ENGINE Loading Loading @@ -136,6 +140,8 @@ int MAIN(int argc, char **argv) operation = SMIME_DECRYPT; else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; else if (!strcmp (*args, "-resign")) operation = SMIME_RESIGN; else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; else if (!strcmp (*args, "-pk7out")) Loading Loading @@ -252,6 +258,18 @@ int MAIN(int argc, char **argv) goto argerr; recipfile = *++args; } else if (!strcmp (*args, "-md")) { if (!args[1]) goto argerr; sign_md = EVP_get_digestbyname(*++args); if (sign_md == NULL) { BIO_printf(bio_err, "Unknown digest %s\n", *args); goto argerr; } } else if (!strcmp (*args, "-inkey")) { if (!args[1]) Loading Loading @@ -335,13 +353,13 @@ int MAIN(int argc, char **argv) args++; } if ((operation != SMIME_SIGN) && (skkeys || sksigners)) if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto argerr; } if (operation == SMIME_SIGN) if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) Loading Loading @@ -468,13 +486,11 @@ int MAIN(int argc, char **argv) ret = 2; if (operation != SMIME_SIGN) if (!(operation & SMIME_SIGNERS)) flags &= ~PKCS7_DETACHED; if (operation & SMIME_OP) { if (flags & PKCS7_BINARY) inmode = "rb"; if (outformat == FORMAT_ASN1) outmode = "wb"; } Loading @@ -482,9 +498,18 @@ int MAIN(int argc, char **argv) { if (flags & PKCS7_BINARY) outmode = "wb"; } if (operation & SMIME_IP) { if (informat == FORMAT_ASN1) inmode = "rb"; } else { if (flags & PKCS7_BINARY) inmode = "rb"; } if (operation == SMIME_ENCRYPT) { Loading Loading @@ -514,26 +539,11 @@ int MAIN(int argc, char **argv) } } if (signerfile && (operation == SMIME_SIGN)) { if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, e, "signer certificate"))) { #if 0 /* An appropri message has already been printed */ BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); #endif goto end; } } if (certfile) { if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, e, "certificate file"))) { #if 0 /* An appropriate message has already been printed */ BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); #endif ERR_print_errors(bio_err); goto end; } Loading @@ -544,9 +554,6 @@ int MAIN(int argc, char **argv) if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, e, "recipient certificate file"))) { #if 0 /* An appropriate message has alrady been printed */ BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); #endif ERR_print_errors(bio_err); goto end; } Loading Loading @@ -584,6 +591,36 @@ int MAIN(int argc, char **argv) else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (operation & SMIME_IP) { 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 (outfile) { if (!(out = BIO_new_file(outfile, outmode))) Loading Loading @@ -618,16 +655,22 @@ int MAIN(int argc, char **argv) if (operation == SMIME_ENCRYPT) p7 = PKCS7_encrypt(encerts, in, cipher, flags); else if (operation == SMIME_SIGN) else if (operation & SMIME_SIGNERS) { int i; /* If detached data and SMIME output enable partial * signing. */ if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) if (operation == SMIME_SIGN) { if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) flags |= PKCS7_STREAM; flags |= PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, other, in, flags); } else flags |= PKCS7_REUSE_DIGEST; for (i = 0; i < sk_num(sksigners); i++) { signerfile = sk_value(sksigners, i); Loading @@ -641,15 +684,15 @@ int MAIN(int argc, char **argv) if (!key) goto end; if (!PKCS7_sign_add_signer(p7, signer, key, NULL, flags)) sign_md, flags)) goto end; X509_free(signer); signer = NULL; EVP_PKEY_free(key); key = NULL; } /* If not streaming finalize structure */ if (!(flags & PKCS7_STREAM)) /* If not streaming or resigning finalize structure */ if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { if (!PKCS7_final(p7, in, flags)) goto end; Loading @@ -660,35 +703,6 @@ int MAIN(int argc, char **argv) } } } else { 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) { Loading Loading @@ -736,7 +750,12 @@ int MAIN(int argc, char **argv) if (subject) BIO_printf(out, "Subject: %s\n", subject); if (outformat == FORMAT_SMIME) { if (operation == SMIME_RESIGN) SMIME_write_PKCS7(out, p7, indata, flags); else SMIME_write_PKCS7(out, p7, in, flags); } else if (outformat == FORMAT_PEM) PEM_write_bio_PKCS7(out,p7); else if (outformat == FORMAT_ASN1) Loading
crypto/pkcs7/pk7_doit.c +0 −1 Original line number Diff line number Diff line Loading @@ -854,7 +854,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) EVP_MD_CTX_cleanup(&mctx); ASN1_STRING_set0(si->enc_digest, abuf, siglen); abuf = NULL; return 1; Loading
crypto/pkcs7/pk7_mime.c +1 −1 Original line number Diff line number Diff line Loading @@ -204,7 +204,7 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) msg_type = "enveloped-data"; else if (PKCS7_type_is_signed(p7)) { /* If we have any signers it is signed-data othewise /* If we have any signers it is signed-data otherwise * certs-only. */ STACK_OF(PKCS7_SIGNER_INFO) *sinfos; Loading
crypto/pkcs7/pk7_smime.c +45 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { Loading Loading @@ -198,6 +200,14 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, || !PKCS7_add_attrib_smimecap (si, smcap)) goto err; sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); smcap = NULL; } if (flags & PKCS7_REUSE_DIGEST) { if (!pkcs7_copy_existing_digest(p7, si)) goto err; if (!PKCS7_SIGNER_INFO_sign(si)) goto err; } } return si; Loading @@ -209,6 +219,41 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, return NULL; } /* Search for a digest matching SignerInfo digest type and if found * copy across. */ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) { int i; STACK_OF(PKCS7_SIGNER_INFO) *sinfos; PKCS7_SIGNER_INFO *sitmp; ASN1_OCTET_STRING *osdig = NULL; sinfos = PKCS7_get_signer_info(p7); for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i); if (si == sitmp) break; if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0) continue; if (!OBJ_cmp(si->digest_alg->algorithm, sitmp->digest_alg->algorithm)) { osdig = PKCS7_digest_from_attributes(sitmp->auth_attr); break; } } if (osdig) return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); return 0; } int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags) { Loading