From 52c517ac0d0ed1e2e71c12020706bce1c17bc9f0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 23 Jan 2025 12:36:43 +0100 Subject: [PATCH] skeyutl command line utility --- apps/build.info | 2 +- apps/skeyutl.c | 136 ++++++++++++++++++++++++++++++++ doc/build.info | 8 ++ doc/man1/build.info | 1 + doc/man1/openssl-skeyutl.pod.in | 77 ++++++++++++++++++ 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 apps/skeyutl.c create mode 100644 doc/man1/openssl-skeyutl.pod.in diff --git a/apps/build.info b/apps/build.info index 020d129f8cacc..e9565c45ee6d4 100644 --- a/apps/build.info +++ b/apps/build.info @@ -16,7 +16,7 @@ $OPENSSLSRC=\ enc.c errstr.c \ genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \ pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \ - s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \ + s_client.c s_server.c s_time.c sess_id.c skeyutl.c smime.c speed.c \ spkac.c verify.c version.c x509.c rehash.c storeutl.c \ list.c info.c fipsinstall.c pkcs12.c IF[{- !$disabled{'ec'} -}] diff --git a/apps/skeyutl.c b/apps/skeyutl.c new file mode 100644 index 0000000000000..9a35edcced7ca --- /dev/null +++ b/apps/skeyutl.c @@ -0,0 +1,136 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_PROV_ENUM, + OPT_CIPHER, + OPT_SKEYOPT, OPT_SKEYMGMT, OPT_GENKEY +} OPTION_CHOICE; + +const OPTIONS skeyutl_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"skeyopt", OPT_SKEYOPT, 's', "Key options as opt:value for opaque keys handling"}, + {"skeymgmt", OPT_SKEYMGMT, 's', "Symmetric key management name for opaque keys handling"}, + {"genkey", OPT_GENKEY, '-', "Generate an opaque symmetric key"}, + {"cipher", OPT_CIPHER, 's', "The cipher to generate key for"}, + OPT_PROV_OPTIONS, + {NULL} +}; + +int skeyutl_main(int argc, char **argv) +{ + EVP_CIPHER *cipher = NULL; + int ret = 1; + OPTION_CHOICE o; + int genkey = 0; + char *prog, *ciphername = NULL; + STACK_OF(OPENSSL_STRING) *skeyopts = NULL; + const char *skeymgmt = NULL; + EVP_SKEY *skey = NULL; + EVP_SKEYMGMT *mgmt = NULL; + + prog = opt_init(argc, argv, skeyutl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(skeyutl_options); + ret = 0; + goto end; + case OPT_GENKEY: + genkey = 1; + break; + case OPT_CIPHER: + ciphername = opt_arg(); + break; + case OPT_SKEYOPT: + if ((skeyopts == NULL && + (skeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || + sk_OPENSSL_STRING_push(skeyopts, opt_arg()) == 0) { + BIO_puts(bio_err, "out of memory\n"); + goto end; + } + break; + case OPT_SKEYMGMT: + skeymgmt = opt_arg(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; + } + } + + /* Get the cipher name, either from progname (if set) or flag. */ + if (!opt_cipher_any(ciphername, &cipher)) + goto opthelp; + + if (cipher == NULL && skeymgmt == NULL) { + BIO_printf(bio_err, "Either -skeymgmt -or -cipher option should be specified\n"); + goto end; + } + + if (genkey) { + OSSL_PARAM *params = NULL; + + mgmt = EVP_SKEYMGMT_fetch(app_get0_libctx(), + skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher), + app_get0_propq()); + if (mgmt == NULL) + goto end; + params = app_params_new_from_opts(skeyopts, + EVP_SKEYMGMT_get0_gen_settable_params(mgmt)); + + skey = EVP_SKEY_generate(app_get0_libctx(), + skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher), + app_get0_propq(), params); + OSSL_PARAM_free(params); + if (skey == NULL) { + BIO_printf(bio_err, "Error creating opaque key for skeymgmt %s\n", + skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher)); + ERR_print_errors(bio_err); + } else { + char *key_name = EVP_SKEY_get1_key_id(skey); + + BIO_printf(bio_out, "An opaque key identified by %s is created\n", + key_name ? key_name : ""); + BIO_printf(bio_out, "Provider: %s\n", EVP_SKEY_get0_provider_name(skey)); + BIO_printf(bio_out, "Key management: %s\n", EVP_SKEY_get0_skeymgmt_name(skey)); + OPENSSL_free(skey); + ret = 0; + } + goto end; + } else { + BIO_printf(bio_err, "Key generation is the only supported option as of now\n"); + } + + end: + ERR_print_errors(bio_err); + sk_OPENSSL_STRING_free(skeyopts); + EVP_SKEYMGMT_free(mgmt); + EVP_SKEY_free(skey); + EVP_CIPHER_free(cipher); + return ret; +} diff --git a/doc/build.info b/doc/build.info index 4622924e15890..2c037613d5034 100644 --- a/doc/build.info +++ b/doc/build.info @@ -280,6 +280,12 @@ DEPEND[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod GENERATE[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod DEPEND[man1/openssl-sess_id.pod]{pod}=man1/openssl-sess_id.pod.in GENERATE[man1/openssl-sess_id.pod]=man1/openssl-sess_id.pod.in +DEPEND[html/man1/openssl-skeyutl.html]=man1/openssl-skeyutl.pod +GENERATE[html/man1/openssl-skeyutl.html]=man1/openssl-skeyutl.pod +DEPEND[man/man1/openssl-skeyutl.1]=man1/openssl-skeyutl.pod +GENERATE[man/man1/openssl-skeyutl.1]=man1/openssl-skeyutl.pod +DEPEND[man1/openssl-skeyutl.pod]{pod}=man1/openssl-skeyutl.pod.in +GENERATE[man1/openssl-skeyutl.pod]=man1/openssl-skeyutl.pod.in DEPEND[html/man1/openssl-smime.html]=man1/openssl-smime.pod GENERATE[html/man1/openssl-smime.html]=man1/openssl-smime.pod DEPEND[man/man1/openssl-smime.1]=man1/openssl-smime.pod @@ -395,6 +401,7 @@ html/man1/openssl-s_client.html \ html/man1/openssl-s_server.html \ html/man1/openssl-s_time.html \ html/man1/openssl-sess_id.html \ +html/man1/openssl-skeyutl.html \ html/man1/openssl-smime.html \ html/man1/openssl-speed.html \ html/man1/openssl-spkac.html \ @@ -455,6 +462,7 @@ man/man1/openssl-s_client.1 \ man/man1/openssl-s_server.1 \ man/man1/openssl-s_time.1 \ man/man1/openssl-sess_id.1 \ +man/man1/openssl-skeyutl.1 \ man/man1/openssl-smime.1 \ man/man1/openssl-speed.1 \ man/man1/openssl-spkac.1 \ diff --git a/doc/man1/build.info b/doc/man1/build.info index b796fce42fdd9..ee6f243e20b31 100644 --- a/doc/man1/build.info +++ b/doc/man1/build.info @@ -44,6 +44,7 @@ DEPEND[openssl-rsa.pod]=../perlvars.pm DEPEND[openssl-rsautl.pod]=../perlvars.pm DEPEND[openssl-s_client.pod]=../perlvars.pm DEPEND[openssl-sess_id.pod]=../perlvars.pm +DEPEND[openssl-skeyutl.pod]=../perlvars.pm DEPEND[openssl-smime.pod]=../perlvars.pm DEPEND[openssl-speed.pod]=../perlvars.pm DEPEND[openssl-spkac.pod]=../perlvars.pm diff --git a/doc/man1/openssl-skeyutl.pod.in b/doc/man1/openssl-skeyutl.pod.in new file mode 100644 index 0000000000000..8fa1fd64f3004 --- /dev/null +++ b/doc/man1/openssl-skeyutl.pod.in @@ -0,0 +1,77 @@ +=pod +{- OpenSSL::safe::output_do_not_edit_headers(); -} + +=head1 NAME + +openssl-skeyutl - opaque symmetric keys routines + +=head1 SYNOPSIS + +B B +[B<-help>] +[B<-cipher> I] +[B<-skeymgmt> I] +[B<-skeyopt> I:I] +[B<-genkey>] +{- $OpenSSL::safe::opt_provider_synopsis -} + +=head1 DESCRIPTION + +Not all cipher implementations support keys as raw bytes. E.g. PKCS#11 tokens +can store them inside without any option to get the raw byte representation. + +This tool is designed for managing opaque symmetic keys. + +=head1 OPTIONS + +=over 4 + +=item B<-help> + +Print out a usage message. + +=item B<-cipher> I + +The cipher to generate the key for. + +=item B<-skeymgmt> I + +Some providers may support opaque symmetric keys objects. To use them, the +particular we need to know the I. If not specified, the name of the +cipher will be used. + +To find out the name of the suitable symmetric key management, +please refer C command output. + +=item B<-skeyopt> I:I + +To obtain the existing opaque symmetric key or generate the new one, key +options are specified as opt:value. These options can't be used together with +any options implying raw key directly or indirectly. + +=item B<-genkey> + +Generate a new opaque key object. + +{- $OpenSSL::safe::opt_provider_item -} + +=back + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +The B command was added in OpenSSL 3.5. + +=head1 COPYRIGHT + +Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut