| /* |
| * Copyright 2025-2026 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_puts(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" |
| "Provider: %s\n" |
| "Key management: %s\n", |
| key_name ? key_name : "<unknown>", |
| EVP_SKEY_get0_provider_name(skey), |
| EVP_SKEY_get0_skeymgmt_name(skey)); |
| ret = 0; |
| } |
| goto end; |
| } else { |
| BIO_puts(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; |
| } |