Support EVP_SKEY object for the `enc` command.
Support EVP_SKEYMGMT for the `list` command.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26753)
OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
- OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM
+ OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM,
+ OPT_SKEYOPT, OPT_SKEYMGMT
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
#ifndef OPENSSL_NO_ZLIB
{"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"},
#endif
+ {"skeyopt", OPT_SKEYOPT, 's', "Key options as opt:value for opaque symmetric key handling"},
+ {"skeymgmt", OPT_SKEYMGMT, 's', "Symmetric key management name for opaque symmetric key handling"},
{"", OPT_CIPHER, '-', "Any supported cipher"},
OPT_R_OPTIONS,
int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY;
int ret = 1, inl, nopad = 0;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+ int rawkey_set = 0;
unsigned char *buff = NULL, salt[EVP_MAX_IV_LENGTH];
int saltlen = 0;
int pbkdf2 = 0;
BIO *bbrot = NULL;
int do_zstd = 0;
BIO *bzstd = NULL;
+ STACK_OF(OPENSSL_STRING) *skeyopts = NULL;
+ const char *skeymgmt = NULL;
+ EVP_SKEY *skey = NULL;
+ EVP_SKEYMGMT *mgmt = NULL;
/* first check the command name */
if (strcmp(argv[0], "base64") == 0)
case OPT_NONE:
cipher = NULL;
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_R_CASES:
if (!opt_rand(o))
goto end;
str = pass;
}
- if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) {
+ if ((str == NULL) && (cipher != NULL) && (hkey == NULL) && (skeyopts == NULL)) {
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
for (;;) {
/* split and move data back to global buffer */
memcpy(key, tmpkeyiv, iklen);
memcpy(iv, tmpkeyiv+iklen, ivlen);
+ rawkey_set = 1;
} else {
BIO_printf(bio_err, "*** WARNING : "
"deprecated key derivation used.\n"
BIO_printf(bio_err, "EVP_BytesToKey failed\n");
goto end;
}
+ rawkey_set = 1;
}
/*
* zero the complete buffer or the string passed from the command
}
/* wiping secret data as we no longer need it */
cleanse(hkey);
+ rawkey_set = 1;
+ }
+
+ /*
+ * At this moment we know whether we trying to use raw bytes as the key
+ * or an opaque symmetric key. We do not allow both options simultaneously.
+ */
+ if (rawkey_set > 0 && skeyopts != NULL) {
+ BIO_printf(bio_err, "Either a raw key or the 'skeyopt' args must be used.\n");
+ goto end;
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)
if (wrap == 1)
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
- if (!EVP_CipherInit_ex(ctx, cipher, e, NULL, NULL, enc)) {
- BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_get0_name(cipher));
- ERR_print_errors(bio_err);
- goto end;
+ if (rawkey_set) {
+ if (!EVP_CipherInit_ex(ctx, cipher, e, key,
+ (hiv == NULL && wrap == 1 ? NULL : iv), enc)) {
+ BIO_printf(bio_err, "Error setting cipher %s\n",
+ EVP_CIPHER_get0_name(cipher));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+ OSSL_PARAM *params = NULL;
+
+ mgmt = EVP_SKEYMGMT_fetch(app_get0_libctx(),
+ skeymgmt != NULL ? skeymgmt : EVP_CIPHER_name(cipher),
+ app_get0_propq());
+ if (mgmt == NULL)
+ goto end;
+
+ params = app_params_new_from_opts(skeyopts,
+ EVP_SKEYMGMT_get0_imp_settable_params(mgmt));
+ if (params == NULL)
+ goto end;
+
+ skey = EVP_SKEY_import(app_get0_libctx(), EVP_SKEYMGMT_get0_name(mgmt),
+ app_get0_propq(), OSSL_SKEYMGMT_SELECT_ALL, params);
+ OSSL_PARAM_free(params);
+ if (skey == NULL) {
+ BIO_printf(bio_err, "Error creating opaque key object for skeymgmt %s\n",
+ skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (!EVP_CipherInit_SKEY(ctx, cipher, skey,
+ (hiv == NULL && wrap == 1 ? NULL : iv),
+ EVP_CIPHER_get_iv_length(cipher), enc, NULL)) {
+ BIO_printf(bio_err, "Error setting an opaque key for cipher %s\n",
+ EVP_CIPHER_get0_name(cipher));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
}
if (nopad)
EVP_CIPHER_CTX_set_padding(ctx, 0);
- if (!EVP_CipherInit_ex(ctx, NULL, NULL, key,
- (hiv == NULL && wrap == 1 ? NULL : iv), enc)) {
- BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_get0_name(cipher));
- ERR_print_errors(bio_err);
- goto end;
- }
-
if (debug) {
BIO_set_callback_ex(benc, BIO_debug_callback_ex);
BIO_set_callback_arg(benc, (char *)bio_err);
}
end:
ERR_print_errors(bio_err);
+ sk_OPENSSL_STRING_free(skeyopts);
+ EVP_SKEYMGMT_free(mgmt);
+ EVP_SKEY_free(skey);
OPENSSL_free(strbuf);
OPENSSL_free(buff);
BIO_free(in);
IS_FETCHABLE(kdf, EVP_KDF)
IS_FETCHABLE(rand, EVP_RAND)
IS_FETCHABLE(keymgmt, EVP_KEYMGMT)
+IS_FETCHABLE(skeymgmt, EVP_SKEYMGMT)
IS_FETCHABLE(signature, EVP_SIGNATURE)
IS_FETCHABLE(kem, EVP_KEM)
IS_FETCHABLE(asym_cipher, EVP_ASYM_CIPHER)
sk_EVP_KEYMGMT_pop_free(km_stack, EVP_KEYMGMT_free);
}
+DEFINE_STACK_OF(EVP_SKEYMGMT)
+static int skeymanager_cmp(const EVP_SKEYMGMT * const *a,
+ const EVP_SKEYMGMT * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(*b)));
+}
+
+static void collect_skeymanagers(EVP_SKEYMGMT *km, void *stack)
+{
+ STACK_OF(EVP_SKEYMGMT) *km_stack = stack;
+
+ if (is_skeymgmt_fetchable(km)
+ && sk_EVP_SKEYMGMT_push(km_stack, km) > 0)
+ EVP_SKEYMGMT_up_ref(km);
+}
+
+static void list_skeymanagers(void)
+{
+ int i;
+ STACK_OF(EVP_SKEYMGMT) *km_stack = sk_EVP_SKEYMGMT_new(skeymanager_cmp);
+
+ EVP_SKEYMGMT_do_all_provided(app_get0_libctx(), collect_skeymanagers,
+ km_stack);
+ sk_EVP_SKEYMGMT_sort(km_stack);
+
+ for (i = 0; i < sk_EVP_SKEYMGMT_num(km_stack); i++) {
+ EVP_SKEYMGMT *k = sk_EVP_SKEYMGMT_value(km_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_SKEYMGMT_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_SKEYMGMT_names_do_all(k, collect_names, names)) {
+ const char *desc = EVP_SKEYMGMT_get0_description(k);
+
+ BIO_printf(bio_out, " Name: ");
+ if (desc != NULL)
+ BIO_printf(bio_out, "%s", desc);
+ else
+ BIO_printf(bio_out, "%s", sk_OPENSSL_CSTRING_value(names, 0));
+ BIO_printf(bio_out, "\n");
+ BIO_printf(bio_out, " Type: Provider Algorithm\n");
+ BIO_printf(bio_out, " IDs: ");
+ print_names(bio_out, names);
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(k)));
+
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_SKEYMGMT_pop_free(km_stack, EVP_SKEYMGMT_free);
+}
+
DEFINE_STACK_OF(EVP_SIGNATURE)
static int signature_cmp(const EVP_SIGNATURE * const *a,
const EVP_SIGNATURE * const *b)
OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED,
OPT_KDF_ALGORITHMS, OPT_RANDOM_INSTANCES, OPT_RANDOM_GENERATORS,
OPT_ENCODERS, OPT_DECODERS, OPT_KEYMANAGERS, OPT_KEYEXCHANGE_ALGORITHMS,
+ OPT_SKEYMANAGERS,
OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS,
OPT_TLS_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS,
OPT_STORE_LOADERS, OPT_PROVIDER_INFO, OPT_OBJECTS,
{"encoders", OPT_ENCODERS, '-', "List of encoding methods" },
{"decoders", OPT_DECODERS, '-', "List of decoding methods" },
{"key-managers", OPT_KEYMANAGERS, '-', "List of key managers" },
+ {"skey-managers", OPT_SKEYMANAGERS, '-', "List of symmetric key managers" },
{"key-exchange-algorithms", OPT_KEYEXCHANGE_ALGORITHMS, '-',
"List of key exchange algorithms" },
{"kem-algorithms", OPT_KEM_ALGORITHMS, '-',
unsigned int encoder_algorithms:1;
unsigned int decoder_algorithms:1;
unsigned int keymanager_algorithms:1;
+ unsigned int skeymanager_algorithms:1;
unsigned int signature_algorithms:1;
unsigned int tls_signature_algorithms:1;
unsigned int keyexchange_algorithms:1;
case OPT_KEYMANAGERS:
todo.keymanager_algorithms = 1;
break;
+ case OPT_SKEYMANAGERS:
+ todo.skeymanager_algorithms = 1;
+ break;
case OPT_SIGNATURE_ALGORITHMS:
todo.signature_algorithms = 1;
break;
MAYBE_ADD_NL(list_decoders());
if (todo.keymanager_algorithms)
MAYBE_ADD_NL(list_keymanagers());
+ if (todo.skeymanager_algorithms)
+ MAYBE_ADD_NL(list_skeymanagers());
if (todo.signature_algorithms)
MAYBE_ADD_NL(list_signatures());
if (todo.tls_signature_algorithms)
[B<-v>]
[B<-debug>]
[B<-none>]
+[B<-skeymgmt> I<skeymgmt>]
+[B<-skeyopt> I<opt>:I<value>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
Use NULL cipher (no encryption or decryption of input).
+=item B<-skeymgmt> I<skeymgmt>
+
+Some providers may support opaque symmetric keys objects. To use them, we need
+to know the name of the B<EVP_SKEYMGMT> to be used. 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 generate a 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.
+
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
certain parameters. So if, for example, you want to use RC2 with a
76 bit key or RC4 with an 84 bit key you can't use this program.
+=head1 SEE ALSO
+
+L<openssl-list(1)>, L<EVP_SKEY(3)>
+
=head1 HISTORY
The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
The B<-saltlen> option was added in OpenSSL 3.2.
+The B<-skeymgmt> and B<-skeyopt> options were added in OpenSSL 3.5.
+
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
-}[B<-encoders>]
[B<-decoders>]
[B<-key-managers>]
+[B<-skey-managers>]
[B<-key-exchange-algorithms>]
[B<-kem-algorithms>]
[B<-tls-groups>]
=item Key managers
+=item Symmetric key managers
+
=item Message authentication code algorithms (MAC)
=item Random number generators (RNG, DRBG)
Display a list of key managers.
+=item B<-skey-managers>
+
+Display a list of symmetric key managers.
+
=item B<-key-exchange-algorithms>
Display a list of key exchange algorithms.
The B<-engines>, B<-digest-commands>, and B<-cipher-commands> options
were deprecated in OpenSSL 3.0.
+The B<-skey-managers> option was added in OpenSSL 3.5.
+
=head1 COPYRIGHT
Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.