From 20b2f29ba1a080176623746a32406f58e54313b4 Mon Sep 17 00:00:00 2001 From: inoguchi <> Date: Mon, 18 Nov 2019 11:34:41 +0000 Subject: Add -keyopt opiton to openssl(1) cms subcommand This provides rsa_padding_mode:oaep for cms -encrypt, and rsa_padding_mode:pss for cms -sign. ok jsing@ --- src/usr.bin/openssl/cms.c | 136 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 8 deletions(-) diff --git a/src/usr.bin/openssl/cms.c b/src/usr.bin/openssl/cms.c index b36c08b209..71e52fe52c 100644 --- a/src/usr.bin/openssl/cms.c +++ b/src/usr.bin/openssl/cms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms.c,v 1.13 2019/11/04 15:34:27 jsing Exp $ */ +/* $OpenBSD: cms.c,v 1.14 2019/11/18 11:34:41 inoguchi Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -74,6 +74,8 @@ static void receipt_request_print(BIO *out, CMS_ContentInfo *cms); static CMS_ReceiptRequest *make_receipt_request( STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) *rr_from); +static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, + STACK_OF(OPENSSL_STRING) *param); #define SMIME_OP 0x10 #define SMIME_IP 0x20 @@ -97,6 +99,14 @@ static CMS_ReceiptRequest *make_receipt_request( int verify_err = 0; +typedef struct cms_key_param_st cms_key_param; + +struct cms_key_param_st { + int idx; + STACK_OF(OPENSSL_STRING) *param; + cms_key_param *next; +}; + int cms_main(int argc, char **argv) { @@ -132,6 +142,8 @@ cms_main(int argc, char **argv) unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; size_t secret_keylen = 0, secret_keyidlen = 0; + cms_key_param *key_first = NULL, *key_param = NULL; + ASN1_OBJECT *econtent_type = NULL; X509_VERIFY_PARAM *vpm = NULL; @@ -351,7 +363,19 @@ cms_main(int argc, char **argv) } else if (!strcmp(*args, "-recip")) { if (!args[1]) goto argerr; - recipfile = *++args; + if (operation == SMIME_ENCRYPT) { + if (encerts == NULL && + (encerts = sk_X509_new_null()) == NULL) + goto end; + cert = load_cert(bio_err, *++args, FORMAT_PEM, + NULL, "recipient certificate file"); + if (cert == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + } else { + recipfile = *++args; + } } else if (!strcmp(*args, "-certsout")) { if (!args[1]) goto argerr; @@ -389,6 +413,38 @@ cms_main(int argc, char **argv) if (!args[1]) goto argerr; keyform = str2fmt(*++args); + } else if (!strcmp (*args, "-keyopt")) { + int keyidx = -1; + if (!args[1]) + goto argerr; + if (operation == SMIME_ENCRYPT) { + if (encerts != NULL) + keyidx += sk_X509_num(encerts); + } else { + if (keyfile != NULL || signerfile != NULL) + keyidx++; + if (skkeys != NULL) + keyidx += sk_OPENSSL_STRING_num(skkeys); + } + if (keyidx < 0) { + BIO_printf(bio_err, "No key specified\n"); + goto argerr; + } + if (key_param == NULL || key_param->idx != keyidx) { + cms_key_param *nparam; + if ((nparam = malloc(sizeof(cms_key_param))) == NULL) + goto end; + nparam->idx = keyidx; + if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + nparam->next = NULL; + if (key_first == NULL) + key_first = nparam; + else + key_param->next = nparam; + key_param = nparam; + } + sk_OPENSSL_STRING_push(key_param->param, *++args); } else if (!strcmp(*args, "-rctform")) { if (!args[1]) goto argerr; @@ -474,7 +530,7 @@ cms_main(int argc, char **argv) badarg = 1; } } else if (operation == SMIME_ENCRYPT) { - if (!*args && !secret_key && !pwri_pass) { + if (!*args && !secret_key && !pwri_pass && !encerts) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); badarg = 1; @@ -524,6 +580,7 @@ cms_main(int argc, char **argv) BIO_printf(bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); BIO_printf(bio_err, "-inkey file input private key (if not signer or recipient)\n"); BIO_printf(bio_err, "-keyform arg input private key format (PEM)\n"); + BIO_printf (bio_err, "-keyopt nm:v set public key parameters\n"); BIO_printf(bio_err, "-out file output file\n"); BIO_printf(bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); BIO_printf(bio_err, "-content file supply or override content for detached signature\n"); @@ -578,7 +635,7 @@ cms_main(int argc, char **argv) BIO_printf(bio_err, "No secret key id\n"); goto end; } - if (*args) + if (*args && !encerts) encerts = sk_X509_new_null(); while (*args) { if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, @@ -722,10 +779,33 @@ cms_main(int argc, char **argv) } else if (operation == SMIME_COMPRESS) { cms = CMS_compress(in, -1, flags); } else if (operation == SMIME_ENCRYPT) { + int i; flags |= CMS_PARTIAL; - cms = CMS_encrypt(encerts, in, cipher, flags); - if (!cms) + cms = CMS_encrypt(NULL, in, cipher, flags); + if (cms == NULL) goto end; + for (i = 0; i < sk_X509_num(encerts); i++) { + CMS_RecipientInfo *ri; + cms_key_param *kparam; + int tflags = flags; + X509 *x = sk_X509_value(encerts, i); + for (kparam = key_first; kparam; kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + ri = CMS_add1_recipient_cert(cms, x, tflags); + if (ri == NULL) + goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } + } + if (secret_key) { if (!CMS_add0_recipient_key(cms, NID_undef, secret_key, secret_keylen, secret_keyid, secret_keyidlen, @@ -797,8 +877,11 @@ cms_main(int argc, char **argv) flags |= CMS_REUSE_DIGEST; for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { CMS_SignerInfo *si; + cms_key_param *kparam; + int tflags = flags; signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); + signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, "signer certificate"); if (!signer) @@ -807,9 +890,21 @@ cms_main(int argc, char **argv) "signing key file"); if (!key) goto end; - si = CMS_add1_signer(cms, signer, key, sign_md, flags); - if (!si) + for (kparam = key_first; kparam; kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + si = CMS_add1_signer(cms, signer, key, sign_md, tflags); + if (si == NULL) goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + pctx = CMS_SignerInfo_get0_pkey_ctx(si); + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } if (rr && !CMS_add1_ReceiptRequest(si, rr)) goto end; X509_free(signer); @@ -952,6 +1047,13 @@ cms_main(int argc, char **argv) CMS_ReceiptRequest_free(rr); sk_OPENSSL_STRING_free(rr_to); sk_OPENSSL_STRING_free(rr_from); + for (key_param = key_first; key_param;) { + cms_key_param *tparam; + sk_OPENSSL_STRING_free(key_param->param); + tparam = key_param->next; + free(key_param); + key_param = tparam; + } X509_STORE_free(store); X509_free(cert); X509_free(recip); @@ -1133,4 +1235,22 @@ make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, return NULL; } +static int +cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param) +{ + char *keyopt; + int i; + if (sk_OPENSSL_STRING_num(param) <= 0) + return 1; + for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) { + keyopt = sk_OPENSSL_STRING_value(param, i); + if (pkey_ctrl_string(pctx, keyopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt); + ERR_print_errors(bio_err); + return 0; + } + } + return 1; +} + #endif -- cgit v1.2.3-55-g6feb