aboutsummaryrefslogtreecommitdiff
path: root/apps/cms.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/cms.c')
-rw-r--r--apps/cms.c95
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;