]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
skeyutl command line utility
authorDmitry Belyavskiy <beldmit@gmail.com>
Thu, 23 Jan 2025 11:36:43 +0000 (12:36 +0100)
committerDmitry Belyavskiy <beldmit@gmail.com>
Sat, 15 Feb 2025 17:51:31 +0000 (18:51 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26753)

apps/build.info
apps/skeyutl.c [new file with mode: 0644]
doc/build.info
doc/man1/build.info
doc/man1/openssl-skeyutl.pod.in [new file with mode: 0644]

index 020d129f8cacca8f57df3f91c875f88c8b9356aa..e9565c45ee6d42e95f7f2801982eeefdbe081717 100644 (file)
@@ -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 (file)
index 0000000..bc744f7
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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;
+}
index 2748d0e04967622a11371f54b6e0549badae27eb..414831d303780359a8670ece23ad506534acd8a9 100644 (file)
@@ -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 \
index b796fce42fdd900ef6ed6f37954fa551e15cd176..ee6f243e20b3183ecfcac21958fa5de775b1ff99 100644 (file)
@@ -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 (file)
index 0000000..c8f1ba1
--- /dev/null
@@ -0,0 +1,76 @@
+=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