--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+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_printf(bio_err, "%s: out of memory\n", prog);
+ 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 {
+ const char *key_name = EVP_SKEY_get0_key_id(skey);
+
+ BIO_printf(bio_out, "An opaque key identified by %s is created\n",
+ key_name ? key_name : "<unknown>");
+ 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));
+ ret = 0;
+ }
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Key generation is the only supported operation 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;
+}
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
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 \
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 \
--- /dev/null
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-skeyutl - opaque symmetric keys routines
+
+=head1 SYNOPSIS
+
+B<openssl> B<skeyutl>
+[B<-help>]
+[B<-cipher> I<cipher>]
+[B<-skeymgmt> I<skeymgmt>]
+[B<-skeyopt> I<opt>:I<value>]
+[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 internally without any option to get the raw byte representation.
+
+This tool is designed for managing opaque symmetric keys.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-cipher> I<cipher>
+
+The cipher to generate the key for.
+
+=item B<-skeymgmt> I<skeymgmt>
+
+Some providers may support opaque symmetric keys objects. To use them, we need
+to know the I<skeymgmt>. If not specified, the name of the cipher will be used.
+
+To find out the name of the suitable symmetric key management,
+please refer to the output of the C<openssl list -skey-managers> command.
+
+=item B<-skeyopt> I<opt>:I<value>
+
+To obtain an existing opaque symmetric key or to generate a new one, key
+options are specified as opt:value. These options can't be used together with
+any options implying raw key either directly or indirectly.
+
+=item B<-genkey>
+
+Generate a new opaque key object.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl-enc(1)>, L<EVP_SKEY(3)>
+
+=head1 HISTORY
+
+The B<skeyutl> 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<https://www.openssl.org/source/license.html>.
+
+=cut