diff options
Diffstat (limited to 'apps/cms.c')
-rw-r--r-- | apps/cms.c | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/apps/cms.c b/apps/cms.c index dce227ef2db5..919d306ff687 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -66,10 +66,11 @@ typedef enum OPTION_choice { OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN, OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT, OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY, - OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, + OPT_DIGEST, OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT, OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS, - OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID, + OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_NO_SIGNING_TIME, + OPT_BINARY, OPT_KEYID, OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, @@ -106,6 +107,7 @@ const OPTIONS cms_options[] = { "Generate a signed receipt for a message"}, {"verify_receipt", OPT_VERIFY_RECEIPT, '<', "Verify receipts; exit if receipt signatures do not verify"}, + {"digest", OPT_DIGEST, 's', "Sign a pre-computed digest in hex notation"}, {"digest_create", OPT_DIGEST_CREATE, '-', "Create a CMS \"DigestedData\" object"}, {"digest_verify", OPT_DIGEST_VERIFY, '-', @@ -174,7 +176,10 @@ const OPTIONS cms_options[] = { OPT_SECTION("Signing"), {"md", OPT_MD, 's', "Digest algorithm to use"}, {"signer", OPT_SIGNER, 's', "Signer certificate input file"}, - {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"certfile", OPT_CERTFILE, '<', + "Extra signer and intermediate CA certificates to include when signing"}, + {OPT_MORE_STR, 0, 0, + "or to use as preferred signer certs and for chain building when verifying"}, {"cades", OPT_CADES, '-', "Include signingCertificate attribute (CAdES-BES)"}, {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, @@ -182,6 +187,8 @@ const OPTIONS cms_options[] = { "Don't include signer's certificate when signing"}, {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"no_signing_time", OPT_NO_SIGNING_TIME, '-', + "Omit the signing time attribute"}, {"receipt_request_all", OPT_RR_ALL, '-', "When signing, create a receipt request for all recipients"}, {"receipt_request_first", OPT_RR_FIRST, '-', @@ -293,6 +300,9 @@ int cms_main(int argc, char **argv) const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL; char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL; int noCAfile = 0, noCApath = 0, noCAstore = 0; + char *digesthex = NULL; + unsigned char *digestbin = NULL; + long digestlen = 0; char *infile = NULL, *outfile = NULL, *rctfile = NULL; char *passinarg = NULL, *passin = NULL, *signerfile = NULL; char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL; @@ -314,6 +324,7 @@ int cms_main(int argc, char **argv) if (encerts == NULL || vpm == NULL) goto end; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, cms_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -366,6 +377,9 @@ int cms_main(int argc, char **argv) case OPT_DIGEST_CREATE: operation = SMIME_DIGEST_CREATE; break; + case OPT_DIGEST: + digesthex = opt_arg(); + break; case OPT_DIGEST_VERIFY: operation = SMIME_DIGEST_VERIFY; break; @@ -418,6 +432,9 @@ int cms_main(int argc, char **argv) case OPT_NOSMIMECAP: flags |= CMS_NOSMIMECAP; break; + case OPT_NO_SIGNING_TIME: + flags |= CMS_NO_SIGNING_TIME; + break; case OPT_BINARY: flags |= CMS_BINARY; break; @@ -705,17 +722,14 @@ int cms_main(int argc, char **argv) if (!opt_md(digestname, &sign_md)) goto end; } - if (ciphername != NULL) { - if (!opt_cipher_any(ciphername, &cipher)) - goto end; - } + if (!opt_cipher_any(ciphername, &cipher)) + goto end; if (wrapname != NULL) { if (!opt_cipher_any(wrapname, &wrap_cipher)) goto end; } /* Remaining args are files to process. */ - argc = opt_num_rest(); argv = opt_rest(); if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) { @@ -822,15 +836,8 @@ int cms_main(int argc, char **argv) } if (operation == SMIME_ENCRYPT) { - if (!cipher) { -#ifndef OPENSSL_NO_DES - cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); -#else - BIO_printf(bio_err, "No cipher selected\n"); - goto end; -#endif - } - + if (!cipher) + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); if (secret_key && !secret_keyid) { BIO_printf(bio_err, "No secret key id\n"); goto end; @@ -894,10 +901,31 @@ int cms_main(int argc, char **argv) goto end; } - in = bio_open_default(infile, 'r', - binary_files ? FORMAT_BINARY : informat); - if (in == NULL) - goto end; + if (digesthex != NULL) { + if (operation != SMIME_SIGN) { + BIO_printf(bio_err, + "Cannot use -digest for non-signing operation\n"); + goto end; + } + if (infile != NULL + || (flags & CMS_DETACHED) == 0 + || (flags & CMS_STREAM) != 0) { + BIO_printf(bio_err, + "Cannot use -digest when -in, -nodetach or streaming is used\n"); + goto end; + } + digestbin = OPENSSL_hexstr2buf(digesthex, &digestlen); + if (digestbin == NULL) { + BIO_printf(bio_err, + "Invalid hex value after -digest\n"); + goto end; + } + } else { + in = bio_open_default(infile, 'r', + binary_files ? FORMAT_BINARY : informat); + if (in == NULL) + goto end; + } if (operation & SMIME_IP) { cms = load_content_info(informat, in, flags, &indata, "SMIME"); @@ -919,7 +947,7 @@ int cms_main(int argc, char **argv) ret = 5; goto end; } - sk_X509_pop_free(allcerts, X509_free); + OSSL_STACK_OF_X509_free(allcerts); } } @@ -983,7 +1011,7 @@ int cms_main(int argc, char **argv) goto end; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (kparam != NULL) { + if (pctx != NULL && kparam != NULL) { if (!cms_set_pkey_param(pctx, kparam->param)) goto end; } @@ -998,7 +1026,8 @@ int cms_main(int argc, char **argv) && wrap_cipher != NULL) { EVP_CIPHER_CTX *wctx; wctx = CMS_RecipientInfo_kari_get0_ctx(ri); - EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL); + if (EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL) != 1) + goto end; } } @@ -1053,12 +1082,12 @@ int cms_main(int argc, char **argv) } else if (operation & SMIME_SIGNERS) { int i; /* - * If detached data content we enable streaming if S/MIME output - * format. + * If detached data content and not signing pre-computed digest, we + * enable streaming if S/MIME output format. */ if (operation == SMIME_SIGN) { - if (flags & CMS_DETACHED) { + if ((flags & CMS_DETACHED) != 0 && digestbin == NULL) { if (outformat == FORMAT_SMIME) flags |= CMS_STREAM; } @@ -1119,7 +1148,12 @@ int cms_main(int argc, char **argv) key = NULL; } /* If not streaming or resigning finalize structure */ - if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) { + if (operation == SMIME_SIGN && digestbin != NULL + && (flags & CMS_STREAM) == 0) { + /* Use pre-computed digest instead of content */ + if (!CMS_final_digest(cms, digestbin, digestlen, NULL, flags)) + goto end; + } else if (operation == SMIME_SIGN && (flags & CMS_STREAM) == 0) { if (!CMS_final(cms, in, NULL, flags)) goto end; } @@ -1254,8 +1288,8 @@ int cms_main(int argc, char **argv) end: if (ret) ERR_print_errors(bio_err); - sk_X509_pop_free(encerts, X509_free); - sk_X509_pop_free(other, X509_free); + OSSL_STACK_OF_X509_free(encerts); + OSSL_STACK_OF_X509_free(other); X509_VERIFY_PARAM_free(vpm); sk_OPENSSL_STRING_free(sksigners); sk_OPENSSL_STRING_free(skkeys); @@ -1289,6 +1323,7 @@ int cms_main(int argc, char **argv) BIO_free(in); BIO_free(indata); BIO_free_all(out); + OPENSSL_free(digestbin); OPENSSL_free(passin); NCONF_free(conf); return ret; |