OPT_R_ENUM,
OPT_PROV_ENUM,
OPT_SKEYOPT,
- OPT_SKEYMGMT
+ OPT_SKEYMGMT,
+ OPT_SKEYURI,
+ OPT_PASSIN
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
#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" },
+ { "skeyuri", OPT_SKEYURI, 's', "Symmetric key object URI" },
+ { "storepass", OPT_PASSIN, 's', "Store pass phrase source when skeyuri is used (optional)" },
{ "", OPT_CIPHER, '-', "Any supported cipher" },
OPT_R_OPTIONS,
{ NULL }
};
+static EVP_SKEY *skey_from_params(const EVP_CIPHER *cipher, const char *skeymgmt,
+ STACK_OF(OPENSSL_STRING) *opts)
+{
+ EVP_SKEY *skey = NULL;
+ EVP_SKEYMGMT *mgmt = NULL;
+ OSSL_PARAM *params = NULL;
+
+ mgmt = EVP_SKEYMGMT_fetch(app_get0_libctx(),
+ skeymgmt != NULL ? skeymgmt : EVP_CIPHER_name(cipher),
+ app_get0_propq());
+ if (mgmt == NULL)
+ return NULL;
+
+ params = app_params_new_from_opts(opts, EVP_SKEYMGMT_get0_imp_settable_params(mgmt));
+ if (params == NULL) {
+ EVP_SKEYMGMT_free(mgmt);
+ return NULL;
+ }
+
+ skey = EVP_SKEY_import(app_get0_libctx(), EVP_SKEYMGMT_get0_name(mgmt),
+ app_get0_propq(), OSSL_SKEYMGMT_SELECT_ALL, params);
+ OSSL_PARAM_free(params);
+ EVP_SKEYMGMT_free(mgmt);
+
+ return skey;
+}
+
int enc_main(int argc, char **argv)
{
static char buf[128];
char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
char *infile = NULL, *outfile = NULL, *prog;
char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
+ char *storepassarg = NULL;
const char *ciphername = NULL;
char mbuf[sizeof(magic) - 1];
OPTION_CHOICE o;
BIO *bzstd = NULL;
STACK_OF(OPENSSL_STRING) *skeyopts = NULL;
const char *skeymgmt = NULL;
+ const char *skeyuri = NULL;
EVP_SKEY *skey = NULL;
- EVP_SKEYMGMT *mgmt = NULL;
/* first check the command name */
if (strcmp(argv[0], "base64") == 0)
case OPT_PASS:
passarg = opt_arg();
break;
+ case OPT_PASSIN:
+ storepassarg = opt_arg();
+ break;
case OPT_D:
enc = 0;
break;
case OPT_SKEYMGMT:
skeymgmt = opt_arg();
break;
+ case OPT_SKEYURI:
+ skeyuri = opt_arg();
+ break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
str = pass;
}
- if ((str == NULL) && (cipher != NULL) && (hkey == NULL) && (skeyopts == NULL)) {
+ if ((str == NULL) && (cipher != NULL) && (hkey == NULL)
+ && (skeyopts == NULL) && (skeyuri == NULL)) {
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
for (;;) {
* 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");
+ if (rawkey_set > 0 && (skeyopts != NULL || skeyuri != NULL)) {
+ BIO_printf(bio_err, "Either a raw key or the skeyopt/skeyuri args must be used.\n");
goto end;
}
(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;
+ char *storepass = NULL;
+ if (!app_passwd(storepassarg, NULL, &storepass, NULL)) {
+ BIO_printf(bio_err,
+ "Error getting store password from 'storepass' argument\n");
+ }
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 (skeyuri != NULL) {
+ skey = load_skey(skeyuri, FORMAT_UNDEF, 0, storepass, 0);
+ OPENSSL_free(storepass);
+ if (skey == NULL) {
+ BIO_printf(bio_err, "Error loading opaque key object from URI %s\n", skeyuri);
+ goto end;
+ }
+ } else {
+ skey = skey_from_params(cipher, skeymgmt, skeyopts);
+ if (skey == NULL) {
+ BIO_printf(bio_err, "Error creating opaque key object for skeymgmt %s\n",
+ skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher));
+ goto end;
+ }
}
if (!EVP_CipherInit_SKEY(ctx, cipher, skey,
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;
}
}
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);
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
- X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls);
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls.
+ EVP_SKEY **pskey);
+EVP_SKEY *load_skey(const char *uri, int format, int maybe_stdin,
+ const char *pass, int quiet);
X509_STORE *setup_verify(const char *CAfile, int noCAfile,
const char *CApath, int noCApath,
const char *CAstore, int noCAstore);
}
} else {
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
- NULL, NULL, NULL, &cert, NULL, NULL, NULL);
+ NULL, NULL, NULL, &cert, NULL, NULL, NULL, NULL);
}
return cert;
}
}
} else {
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, 0,
- NULL, NULL, NULL, NULL, NULL, &crl, NULL);
+ NULL, NULL, NULL, NULL, NULL, &crl, NULL, NULL);
}
return crl;
}
desc = "private key";
(void)load_key_certs_crls(uri, format, may_stdin, pass, desc, 0,
- &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
+ &pkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
return pkey;
}
desc = "public key";
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 1,
- NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
+ NULL, &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
if (pkey == NULL)
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
- &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
+ &pkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
return pkey;
}
desc = "key parameters";
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
suppress_decode_errors,
- NULL, NULL, ¶ms, NULL, NULL, NULL, NULL);
+ NULL, NULL, ¶ms, NULL, NULL, NULL, NULL, NULL);
if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0);
}
+EVP_SKEY *load_skey(const char *uri, int format, int may_stdin,
+ const char *pass, int quiet)
+{
+ EVP_SKEY *skey = NULL;
+
+ (void)load_key_certs_crls(uri, format, may_stdin, pass, NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, &skey);
+
+ return skey;
+}
+
void app_bail_out(char *fmt, ...)
{
va_list args;
}
pass_string = get_passwd(pass, desc);
ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, 0,
- NULL, NULL, NULL, pcert, pcerts, NULL, NULL);
+ NULL, NULL, NULL, pcert, pcerts, NULL, NULL, NULL);
clear_free(pass_string);
if (ret) {
if (desc == NULL)
desc = "certificates";
return load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc, 0,
- NULL, NULL, NULL, NULL, certs, NULL, NULL);
+ NULL, NULL, NULL, NULL, certs, NULL, NULL, NULL);
}
/*
if (desc == NULL)
desc = "CRLs";
return load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, crls);
+ NULL, NULL, NULL, NULL, NULL, NULL, crls, NULL);
}
static const char *format2string(int format)
SET_EXPECT(val); \
}
/* Provide (error msg) text for some of the credential types to be loaded. */
-#define FAIL_NAME \
- (ppkey != NULL ? "private key" : ppubkey != NULL ? "public key" \
- : pparams != NULL ? "key parameters" \
- : pcert != NULL ? "certificate" \
- : pcerts != NULL ? "certificates" \
- : pcrl != NULL ? "CRL" \
- : pcrls != NULL ? "CRLs" \
+#define FAIL_NAME \
+ (ppkey != NULL ? "private key" : ppubkey != NULL ? "public key" \
+ : pparams != NULL ? "key parameters" \
+ : pcert != NULL ? "certificate" \
+ : pcerts != NULL ? "certificates" \
+ : pcrl != NULL ? "CRL" \
+ : pcrls != NULL ? "CRLs" \
+ : pskey != NULL ? "symmetric key" : NULL \
: NULL)
/*
* Load those types of credentials for which the result pointer is not NULL.
* Reads from stdin if 'uri' is NULL and 'maybe_stdin' is nonzero.
* 'format' parameter may be FORMAT_PEM, FORMAT_ASN1, or 0 for no hint.
* desc may contain more detail on the credential(s) to be loaded for error msg
- * For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded.
+ * For non-NULL ppkey, pcert, pcrl, and pskey the first suitable value found is loaded.
* If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated.
* If pcerts is non-NULL then all available certificates are appended to *pcerts
* except any certificate assigned to *pcert.
* except any CRL assigned to *pcrl.
* On error, any contents of non-NULL credential pointers are freed.
*/
+
int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc, int quiet,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
- X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+ EVP_SKEY **pskey)
{
PW_CB_DATA uidata;
OSSL_STORE_CTX *ctx = NULL;
OSSL_LIB_CTX *libctx = app_get0_libctx();
const char *propq = app_get0_propq();
- int ncerts = 0, ncrls = 0, expect = -1;
+ int ncerts = 0, ncrls = 0, nskeys = 0, expect = -1;
const char *failed = FAIL_NAME;
const char *input_type;
OSSL_PARAM itp[2];
SET_EXPECT1(ppubkey, OSSL_STORE_INFO_PUBKEY);
SET_EXPECT1(pparams, OSSL_STORE_INFO_PARAMS);
SET_EXPECT1(pcert, OSSL_STORE_INFO_CERT);
+ SET_EXPECT1(pskey, OSSL_STORE_INFO_SKEY);
/*
* Up to here, the following holds.
- * If just one of the ppkey, ppubkey, pparams, and pcert function parameters
+ * If just one of the ppkey, ppubkey, pparams, pcert, and pskey function parameters
* is nonzero, expect > 0 indicates which type of credential is expected.
* If expect == 0, more than one of them is nonzero (multiple types expected).
*/
BIO_printf(bio_err, "Could not open file or uri for loading");
goto end;
}
+
/* expect == 0 means here multiple types of credentials are to be loaded */
if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) {
if (!quiet)
/* from here, failed != NULL only if actually an error has been detected */
while ((ppkey != NULL || ppubkey != NULL || pparams != NULL
- || pcert != NULL || pcerts != NULL || pcrl != NULL || pcrls != NULL)
+ || pcert != NULL || pcerts != NULL || pcrl != NULL || pcrls != NULL
+ || pskey != NULL)
&& !OSSL_STORE_eof(ctx)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int type, ok = 1;
}
ncrls += ok;
break;
+ case OSSL_STORE_INFO_SKEY:
+ if (pskey != NULL) {
+ ok = (*pskey = OSSL_STORE_INFO_get1_SKEY(info)) != NULL;
+ if (ok)
+ pskey = NULL;
+ }
+ nskeys += ok;
+ break;
default:
/* skip any other type; ok stays == 1 */
break;
pcerts = NULL;
if (ncrls > 0)
pcrls = NULL;
+ if (nskeys > 0)
+ pskey = NULL;
failed = FAIL_NAME;
if (failed != NULL && !quiet)
BIO_printf(bio_err, "Could not find");
OPT_SEARCHFOR_CERTS,
OPT_SEARCHFOR_KEYS,
OPT_SEARCHFOR_CRLS,
+ OPT_SEARCHFOR_SKEYS,
OPT_CRITERION_SUBJECT,
OPT_CRITERION_ISSUER,
OPT_CRITERION_SERIAL,
{ "certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only" },
{ "keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only" },
{ "crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only" },
+ { "skeys", OPT_SEARCHFOR_SKEYS, '-', "Search for symmetric keys only" },
{ "subject", OPT_CRITERION_SUBJECT, 's', "Search by subject" },
{ "issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name" },
{ "serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number" },
case OPT_SEARCHFOR_CERTS:
case OPT_SEARCHFOR_KEYS:
case OPT_SEARCHFOR_CRLS:
+ case OPT_SEARCHFOR_SKEYS:
if (expected != 0) {
BIO_printf(bio_err, "%s: only one search type can be given.\n",
prog);
{ OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT },
{ OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY },
{ OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL },
+ { OPT_SEARCHFOR_SKEYS, OSSL_STORE_INFO_SKEY },
};
size_t i;
if (!noout)
PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info));
break;
+ case OSSL_STORE_INFO_SKEY:
+ /* Currently there is no universal API allowing to print smth, so no output */
+ break;
default:
BIO_printf(bio_err, "!!! Unknown code\n");
ret++;
OSSL_STORE_R_NOT_A_NAME:103:not a name
OSSL_STORE_R_NOT_A_PRIVATE_KEY:102:not a private key
OSSL_STORE_R_NOT_A_PUBLIC_KEY:122:not a public key
+OSSL_STORE_R_NOT_A_SYMMETRIC_KEY:124:not a symmetric key
OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
OSSL_STORE_R_NO_LOADERS_FOUND:123:no loaders found
OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
"not a private key" },
{ ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PUBLIC_KEY),
"not a public key" },
+ { ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_SYMMETRIC_KEY),
+ "not a symmetric key" },
{ ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS),
"not parameters" },
{ ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NO_LOADERS_FOUND),
int ret = 1;
if (ctx == NULL
- || expected_type < 0 || expected_type > OSSL_STORE_INFO_CRL) {
+ || expected_type < 0 || expected_type > OSSL_STORE_INFO_SKEY) {
ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
return info;
}
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_SKEY(EVP_SKEY *skey)
+{
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_SKEY, skey);
+
+ if (info == NULL)
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
+ return info;
+}
+
/*
* Functions to try to extract data from an OSSL_STORE_INFO.
*/
return NULL;
}
+EVP_SKEY *OSSL_STORE_INFO_get0_SKEY(const OSSL_STORE_INFO *info)
+{
+ if (info->type == OSSL_STORE_INFO_SKEY)
+ return info->_.skey;
+ return NULL;
+}
+
+EVP_SKEY *OSSL_STORE_INFO_get1_SKEY(const OSSL_STORE_INFO *info)
+{
+ if (info->type == OSSL_STORE_INFO_SKEY) {
+ if (!EVP_SKEY_up_ref(info->_.skey))
+ return NULL;
+ return info->_.skey;
+ }
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_SYMMETRIC_KEY);
+ return NULL;
+}
+
/*
* Free the OSSL_STORE_INFO
*/
case OSSL_STORE_INFO_CRL:
X509_CRL_free(info->_.crl);
break;
+ case OSSL_STORE_INFO_SKEY:
+ EVP_SKEY_free(info->_.skey);
+ break;
}
OPENSSL_free(info);
}
EVP_PKEY *pkey; /* when type == OSSL_STORE_INFO_PKEY */
X509 *x509; /* when type == OSSL_STORE_INFO_CERT */
X509_CRL *crl; /* when type == OSSL_STORE_INFO_CRL */
+ EVP_SKEY *skey; /* when type == OSSL_STORE_INFO_SKEY */
} _;
};
DEFINE_STACK_OF(OSSL_STORE_INFO)
OSSL_LIB_CTX *, const char *);
static int try_pkcs12(struct extracted_param_data_st *, OSSL_STORE_INFO **,
OSSL_STORE_CTX *, OSSL_LIB_CTX *, const char *);
+static int try_skey(struct extracted_param_data_st *, OSSL_STORE_INFO **,
+ const OSSL_PROVIDER *, OSSL_LIB_CTX *, const char *);
int ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg)
{
if (*v == NULL && !try_pkcs12(&helper_data, v, ctx, libctx, propq))
goto err;
ERR_pop_to_mark();
+ ERR_set_mark();
+ if (*v == NULL && !try_skey(&helper_data, v, provider, libctx, propq))
+ goto err;
+ ERR_pop_to_mark();
if (*v == NULL) {
const char *hint = "";
return ok;
}
+
+static int try_skey(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
+ const OSSL_PROVIDER *provider, OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_SKEY *skey = NULL;
+ const char *skeymgmt_name = data->data_type == NULL
+ ? OSSL_SKEY_TYPE_GENERIC : data->data_type;
+ size_t keysize = 0;
+ unsigned char *keybytes = NULL;
+
+ if (data->object_type != OSSL_OBJECT_SKEY)
+ return 0;
+
+ if (data->octet_data != NULL) {
+ keysize = data->octet_data_size;
+ keybytes = (unsigned char *)data->octet_data;
+ skey = EVP_SKEY_import_raw_key(libctx, skeymgmt_name,
+ keybytes, keysize, propq);
+ } else if (data->ref != NULL) {
+ EVP_SKEYMGMT *skeymgmt = evp_skeymgmt_fetch_from_prov((OSSL_PROVIDER *)provider,
+ skeymgmt_name, propq);
+ OSSL_PARAM params[2];
+
+ /*
+ * We got an internal reference from a particular provider so we need the SKEYMGMT
+ * exactly from this provider
+ */
+ if (skeymgmt == NULL)
+ return 0;
+
+ keysize = data->ref_size;
+ keybytes = (unsigned char *)data->ref;
+ params[0] = OSSL_PARAM_construct_octet_ptr(OSSL_OBJECT_PARAM_REFERENCE,
+ (void **)&keybytes, keysize);
+ params[1] = OSSL_PARAM_construct_end();
+
+ skey = EVP_SKEY_import_SKEYMGMT(libctx, skeymgmt, OSSL_SKEYMGMT_SELECT_ALL, params);
+ }
+
+ if (skey != NULL)
+ *v = OSSL_STORE_INFO_new_SKEY(skey);
+ if (*v == NULL)
+ EVP_SKEY_free(skey);
+
+ return 1;
+}
"Public key", /* OSSL_STORE_INFO_PUBKEY */
"Pkey", /* OSSL_STORE_INFO_PKEY */
"Certificate", /* OSSL_STORE_INFO_CERT */
- "CRL" /* OSSL_STORE_INFO_CRL */
+ "CRL", /* OSSL_STORE_INFO_CRL */
+ "Symmetric key" /* OSSL_STORE_INFO_SKEY */
};
const char *OSSL_STORE_INFO_type_string(int type)
[B<-none>]
[B<-skeymgmt> I<skeymgmt>]
[B<-skeyopt> I<opt>:I<value>]
+[B<-skeyuri> I<uri>]
+[B<-storepass> I<arg>]
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
options are specified as opt:value. These options can't be used together with
any options implying raw key directly or indirectly.
+=item B<-skeyuri> I<uri>
+
+The URI identifying the symmetric key object to be used for encryption. This
+option can't be used together with any options implying raw key directly or
+indirectly. The B<-skeymgmt> option is ignored. If both B<-skeyuri> and
+B<-skeyopt> options are provided, B<-skeyuri> is ignored.
+
+=item B<-storepass> I<arg>
+
+The input URI password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
=head1 SEE ALSO
-L<openssl-list(1)>, L<EVP_SKEY(3)>
+L<openssl-list(1)>, L<EVP_SKEY(3)>, L<openssl-passphrase-options(1)>
=head1 HISTORY
The B<-engine> option was removed in OpenSSL 4.0.
+The B<-skeyuri> and B<-storepass> options were added in OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
[B<-certs>]
[B<-keys>]
[B<-crls>]
+[B<-skeys>]
[B<-subject> I<arg>]
[B<-issuer> I<arg>]
[B<-serial> I<arg>]
=item B<-crls>
-Only select the certificates, keys or CRLs from the given URI.
+=item B<-skeys>
+
+Only select the certificates, keys, CRLs or symmetric keys from the given URI.
However, if this URI would return a set of names (URIs), those are always
returned.
The B<-engine> option was removed in OpenSSL 4.0.
+The B<-skeys> option was added in OpenSSL 4.0
+
=head1 COPYRIGHT
-Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-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
OSSL_STORE_INFO_get0_NAME_description,
OSSL_STORE_INFO_get0_PARAMS, OSSL_STORE_INFO_get0_PUBKEY,
OSSL_STORE_INFO_get0_PKEY, OSSL_STORE_INFO_get0_CERT, OSSL_STORE_INFO_get0_CRL,
+OSSL_STORE_INFO_get0_SKEY,
OSSL_STORE_INFO_get1_NAME, OSSL_STORE_INFO_get1_NAME_description,
OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PUBKEY,
OSSL_STORE_INFO_get1_PKEY, OSSL_STORE_INFO_get1_CERT, OSSL_STORE_INFO_get1_CRL,
+OSSL_STORE_INFO_get1_SKEY,
OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free,
OSSL_STORE_INFO_new_NAME, OSSL_STORE_INFO_set0_NAME_description,
OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PUBKEY,
OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL,
-OSSL_STORE_INFO_new, OSSL_STORE_INFO_get0_data
+OSSL_STORE_INFO_new, OSSL_STORE_INFO_new_SKEY, OSSL_STORE_INFO_get0_data
- Functions to manipulate OSSL_STORE_INFO objects
=head1 SYNOPSIS
X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *store_info);
X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *store_info);
X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *store_info);
+ EVP_SKEY *OSSL_STORE_INFO_get0_SKEY(const OSSL_STORE_INFO *store_info);
+ EVP_SKEY *OSSL_STORE_INFO_get1_SKEY(const OSSL_STORE_INFO *store_info);
const char *OSSL_STORE_INFO_type_string(int type);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
+ OSSL_STORE_INFO *OSSL_STORE_INFO_new_SKEY(EVP_SKEY *skey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data);
void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info);
OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(),
OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PUBKEY(),
OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(),
-OSSL_STORE_INFO_get0_CRL()
+OSSL_STORE_INFO_get0_CRL(), OSSL_STORE_INFO_get0_SKEY()
all take a B<OSSL_STORE_INFO> and return the object it holds if the
B<OSSL_STORE_INFO> type (as returned by OSSL_STORE_INFO_get_type())
matches the function, otherwise NULL.
OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(),
OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PUBKEY(),
OSSL_STORE_INFO_get1_PKEY(), OSSL_STORE_INFO_get1_CERT() and
-OSSL_STORE_INFO_get1_CRL()
+OSSL_STORE_INFO_get1_CRL(), OSSL_STORE_INFO_get1_SKEY()
all take a B<OSSL_STORE_INFO> and return a duplicate the object it
holds if the B<OSSL_STORE_INFO> type (as returned by
OSSL_STORE_INFO_get_type()) matches the function, otherwise NULL.
OSSL_STORE_INFO_new_NAME() , OSSL_STORE_INFO_new_PARAMS(),
, OSSL_STORE_INFO_new_PUBKEY(), OSSL_STORE_INFO_new_PKEY(),
-OSSL_STORE_INFO_new_CERT() and OSSL_STORE_INFO_new_CRL()
+OSSL_STORE_INFO_new_CERT(), OSSL_STORE_INFO_new_CRL() and
+OSSL_STORE_INFO_new_SKEY()
create a B<OSSL_STORE_INFO> object to hold the given input object.
On success the input object is consumed.
A X.509 certificate revocation list.
+=item OSSL_STORE_INFO_SKEY
+
+A symmetric key object.
+
=back
=head1 RETURN VALUES
OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(),
OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
-OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all return
-a pointer to the OpenSSL object on success, NULL otherwise.
+OSSL_STORE_INFO_get0_CERT(), OSSL_STORE_INFO_get0_CRL() and
+OSSL_STORE_INFO_get0_SKEY() all return a pointer to the OpenSSL object on
+success, NULL otherwise.
OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(),
OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(),
-OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all return
-a pointer to a duplicate of the OpenSSL object on success, NULL otherwise.
+OSSL_STORE_INFO_get1_CERT(), OSSL_STORE_INFO_get1_CRL() and
+OSSL_STORE_INFO_get1_SKEY() all return a pointer to a duplicate of the OpenSSL
+object on success, NULL otherwise.
OSSL_STORE_INFO_type_string() returns a string on success, or NULL on
failure.
OSSL_STORE_INFO_new_NAME(), OSSL_STORE_INFO_new_PARAMS(),
-OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT() and
-OSSL_STORE_INFO_new_CRL() return a B<OSSL_STORE_INFO>
-pointer on success, or NULL on failure.
+OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT(),
+OSSL_STORE_INFO_new_CRL() and OSSL_STORE_INFO_new_SKEY() return a
+B<OSSL_STORE_INFO> pointer on success, or NULL on failure.
OSSL_STORE_INFO_set0_NAME_description() returns 1 on success, or 0 on
failure.
The OSSL_STORE_INFO_PUBKEY object type was added in OpenSSL 3.0.
+OSSL_STORE_INFO_get0_SKEY(), OSSL_STORE_INFO_get1_SKEY() and
+OSSL_STORE_INFO_new_SKEY() were added in OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
loaded in raw form in its entirety and passed to the available file
handlers as is, with no PEM name or headers.
+Store 'file' also supports load of symmetric keys from arbitrary files. As
+symmetric keys don't have any structure and encapsulation, the interpretation
+of a file as a symmetric key should be requested explicitly via
+L<OSSL_STORE_expect(3)>.
+
+When loading from a file, symmetric keys are limited to 2048 bytes in length.
+
Each file handler is expected to handle PEM and non-PEM content as
appropriate. Some may refuse non-PEM content for the sake of
determinism (for example, there are keys out in the wild that are
=head1 SEE ALSO
-L<ossl_store(7)>, L<passphrase-encoding(7)>
+L<ossl_store(7)>, L<passphrase-encoding(7)>, L<OSSL_STORE_expect(3)>
+
+=head1 HISTORY
+
+Support for reading symmetric keys from files was added in OpenSSL 4.0
=head1 COPYRIGHT
-Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-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
#define OSSL_OBJECT_PKEY 2 /* EVP_PKEY * */
#define OSSL_OBJECT_CERT 3 /* X509 * */
#define OSSL_OBJECT_CRL 4 /* X509_CRL * */
+#define OSSL_OBJECT_SKEY 5 /* EVP_SKEY * */
/*
* The rest of the associated OSSL_PARAM elements is described in core_names.h
#define OSSL_STORE_INFO_PKEY 4 /* EVP_PKEY * */
#define OSSL_STORE_INFO_CERT 5 /* X509 * */
#define OSSL_STORE_INFO_CRL 6 /* X509_CRL * */
+#define OSSL_STORE_INFO_SKEY 7 /* EVP_SKEY * */
/*
* Functions to generate OSSL_STORE_INFOs, one function for each type we
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_SKEY(EVP_SKEY *skey);
/*
* Functions to try to extract data from a OSSL_STORE_INFO.
X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info);
X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info);
X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info);
+EVP_SKEY *OSSL_STORE_INFO_get0_SKEY(const OSSL_STORE_INFO *info);
+EVP_SKEY *OSSL_STORE_INFO_get1_SKEY(const OSSL_STORE_INFO *info);
const char *OSSL_STORE_INFO_type_string(int type);
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
#define OSSL_STORE_R_NOT_A_NAME 103
#define OSSL_STORE_R_NOT_A_PRIVATE_KEY 102
#define OSSL_STORE_R_NOT_A_PUBLIC_KEY 122
+#define OSSL_STORE_R_NOT_A_SYMMETRIC_KEY 124
#define OSSL_STORE_R_NOT_PARAMETERS 104
#define OSSL_STORE_R_NO_LOADERS_FOUND 123
#define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114
goto err;
}
break;
+ case OSSL_STORE_INFO_SKEY: /* No input structure */
+ break;
default:
break;
}
continue;
}
+ /*
+ * As any sequence of bytes can be a secret key, we allow
+ * reading raw key from a file only when it is explicitly requested.
+ */
+ if ((ctx->expected_type != OSSL_STORE_INFO_SKEY)
+ && OPENSSL_strcasecmp(input_type, "raw") == 0) {
+ ossl_decoder_instance_free(to_obj_inst);
+ continue;
+ }
+
if (!ossl_decoder_ctx_add_decoder_inst(ctx->_.file.decoderctx,
to_obj_inst)) {
ossl_decoder_instance_free(to_obj_inst);
OSSL_DISPATCH_END \
}
+#define MAX_RAW_KEY_SIZE 2048
+
+static OSSL_FUNC_decoder_decode_fn raw2obj_decode;
+static int raw2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct any2obj_ctx_st *ctx = vctx;
+ BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
+ BUF_MEM *mem = NULL;
+ size_t len = 0, max_len = MAX_RAW_KEY_SIZE;
+ int ok = 0;
+
+ if (in == NULL)
+ goto err;
+
+ if ((mem = BUF_MEM_new()) == NULL
+ || BUF_MEM_grow(mem, max_len) == 0) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
+ goto err;
+ }
+
+ ok = BIO_read_ex(in, &mem->data[0], max_len, &len);
+ if (ok == 0) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
+ goto err;
+ }
+
+ if (len == 0) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_UNSUPPORTED);
+ goto err;
+ }
+
+ BIO_free(in);
+
+ if (BUF_MEM_grow(mem, len) != len) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
+ goto err;
+ }
+
+ /* any2obj_decode_final() frees |mem| for us */
+ return any2obj_decode_final(ctx, OSSL_OBJECT_SKEY, "raw", "SKEY",
+ mem, data_cb, data_cbarg);
+
+ err:
+ BIO_free(in);
+ BUF_MEM_free(mem);
+ return 0;
+}
+
MAKE_DECODER(der, OSSL_OBJECT_UNKNOWN);
MAKE_DECODER(msblob, OSSL_OBJECT_PKEY);
MAKE_DECODER(pvk, OSSL_OBJECT_PKEY);
+MAKE_DECODER(raw, OSSL_OBJECT_SKEY);
const OSSL_ALGORITHM ossl_any_to_obj_algorithm[] = {
{ "obj", "input=DER", der_to_obj_decoder_functions },
{ "obj", "input=MSBLOB", msblob_to_obj_decoder_functions },
{ "obj", "input=PVK", pvk_to_obj_decoder_functions },
+ { "obj", "input=RAW", raw_to_obj_decoder_functions },
{
NULL,
}
|rc2|rc4|seed)/x} @ciphers
if disabled("legacy");
-plan tests => 5 + (scalar @ciphers)*2;
+plan tests => 6 + (scalar @ciphers)*2;
SKIP: {
skip "Problems getting ciphers...", 1 + scalar(@ciphers)
&& compare_text($test,"salted.clear") == 0,
"Check that we can still use a salt length of 16 bytes for PKDF2");
+#./util/wrap.pl apps/openssl enc -aes128 -K 30313032303330343035303630373038 -iv 100f0e0d0c0b0a090807060504030201 -in 1.txt -out 2.enc
+#./util/wrap.pl apps/openssl enc -aes128 -skeyuri skeyfile.bin -iv 100f0e0d0c0b0a090807060504030201 -in 1.txt -out 1.enc
+ my $folder = "test/recipes/20-test_enc_data";
+ my $skeyuri = srctop_file($folder, "skeyfile.bin");
+ ok(run(app([$cmd, "enc", "-in", $test, "-aes128", "-K", "30313032303330343035303630373038",
+ "-iv", "100f0e0d0c0b0a090807060504030201",
+ "-out", "key_from_cmdline.enc"]))
+ && run(app([$cmd, "enc", "-in", $test, "-aes128", "-skeyuri", $skeyuri,
+ "-iv", "100f0e0d0c0b0a090807060504030201",
+ "-out", "key_from_uri.enc" ]))
+ && File::Compare::compare("key_from_cmdline.enc", "key_from_uri.enc") == 0,
+ "Check that key from URI gives an equal result comparing to the explicit one");
}
--- /dev/null
+0102030405060708
\ No newline at end of file
OSSL_AA_DIST_POINT_free ? 4_0_0 EXIST::FUNCTION:
OSSL_AA_DIST_POINT_new ? 4_0_0 EXIST::FUNCTION:
OSSL_AA_DIST_POINT_it ? 4_0_0 EXIST::FUNCTION:
+OSSL_STORE_INFO_new_SKEY ? 4_0_0 EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_SKEY ? 4_0_0 EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_SKEY ? 4_0_0 EXIST::FUNCTION:
OPENSSL_posix_to_tm ? 4_0_0 EXIST::FUNCTION:
OPENSSL_tm_to_posix ? 4_0_0 EXIST::FUNCTION:
OPENSSL_timegm ? 4_0_0 EXIST::FUNCTION: