]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Implementing store support for EVP_SKEY
authorDmitry Belyavskiy <beldmit@gmail.com>
Mon, 11 Aug 2025 09:55:06 +0000 (11:55 +0200)
committerNeil Horman <nhorman@openssl.org>
Wed, 10 Dec 2025 17:20:44 +0000 (12:20 -0500)
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Simo Sorce <simo@redhat.com>
(Merged from https://github.com/openssl/openssl/pull/28278)

22 files changed:
apps/enc.c
apps/include/apps.h
apps/lib/apps.c
apps/storeutl.c
crypto/err/openssl.txt
crypto/store/store_err.c
crypto/store/store_lib.c
crypto/store/store_local.h
crypto/store/store_result.c
crypto/store/store_strings.c
doc/man1/openssl-enc.pod.in
doc/man1/openssl-storeutl.pod.in
doc/man3/OSSL_STORE_INFO.pod
doc/man7/ossl_store-file.pod
include/openssl/core_object.h
include/openssl/store.h
include/openssl/storeerr.h
providers/implementations/storemgmt/file_store.c
providers/implementations/storemgmt/file_store_any2obj.c
test/recipes/20-test_enc.t
test/recipes/20-test_enc_data/skeyfile.bin [new file with mode: 0644]
util/libcrypto.num

index 69ac4bc60c899647ec2b27d7267a07116cccd5c8..fa8adc8970d866b2ba5f62c576e057103c51e7be 100644 (file)
@@ -75,7 +75,9 @@ typedef enum OPTION_choice {
     OPT_R_ENUM,
     OPT_PROV_ENUM,
     OPT_SKEYOPT,
-    OPT_SKEYMGMT
+    OPT_SKEYMGMT,
+    OPT_SKEYURI,
+    OPT_PASSIN
 } OPTION_CHOICE;
 
 const OPTIONS enc_options[] = {
@@ -130,6 +132,8 @@ 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,
@@ -137,6 +141,33 @@ const OPTIONS enc_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];
@@ -149,6 +180,7 @@ int enc_main(int argc, char **argv)
     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;
@@ -176,8 +208,8 @@ int enc_main(int argc, char **argv)
     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)
@@ -231,6 +263,9 @@ int enc_main(int argc, char **argv)
         case OPT_PASS:
             passarg = opt_arg();
             break;
+        case OPT_PASSIN:
+            storepassarg = opt_arg();
+            break;
         case OPT_D:
             enc = 0;
             break;
@@ -346,6 +381,9 @@ int enc_main(int argc, char **argv)
         case OPT_SKEYMGMT:
             skeymgmt = opt_arg();
             break;
+        case OPT_SKEYURI:
+            skeyuri = opt_arg();
+            break;
         case OPT_R_CASES:
             if (!opt_rand(o))
                 goto end;
@@ -427,7 +465,8 @@ int enc_main(int argc, char **argv)
         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 (;;) {
@@ -666,8 +705,8 @@ int enc_main(int argc, char **argv)
          * 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;
         }
 
@@ -689,31 +728,35 @@ int enc_main(int argc, char **argv)
                     (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,
@@ -721,7 +764,6 @@ int enc_main(int argc, char **argv)
                     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;
             }
         }
@@ -795,7 +837,6 @@ int enc_main(int argc, char **argv)
 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);
index ce87477924295896f7da772af71ed7604e141cf8..b4792a6f07c565036e89288c7db6fe0f8918c919 100644 (file)
@@ -156,7 +156,10 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     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);
index 5f6dcae84e19db08aab08822442b981325b4b3f9..2a36c4215abb7c09106d24c8bb1f101ebda1133e 100644 (file)
@@ -442,7 +442,7 @@ X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
         }
     } 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;
 }
@@ -464,7 +464,7 @@ X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
         }
     } 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;
 }
@@ -555,7 +555,7 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
         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;
 }
@@ -570,10 +570,10 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
         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;
 }
 
@@ -587,7 +587,7 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
         desc = "key parameters";
     (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
         suppress_decode_errors,
-        NULL, NULL, &params, NULL, NULL, NULL, NULL);
+        NULL, NULL, &params, 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,
@@ -605,6 +605,17 @@ EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
     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;
@@ -704,7 +715,7 @@ int load_cert_certs(const char *uri,
     }
     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) {
@@ -805,7 +816,7 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
     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);
 }
 
 /*
@@ -818,7 +829,7 @@ int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
     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)
@@ -845,20 +856,21 @@ 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.
@@ -867,18 +879,20 @@ static const char *format2string(int format)
  * 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];
@@ -898,9 +912,10 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     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).
      */
@@ -969,6 +984,7 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
             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)
@@ -980,7 +996,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     /* 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;
@@ -1047,6 +1064,14 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
             }
             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;
@@ -1069,6 +1094,8 @@ end:
             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");
index ebd430d89a66a34ed08d6cf34f0e72ccb6f7ae01..387cf54522b0e0189fbec7d4cdd6e287793bb4f3 100644 (file)
@@ -33,6 +33,7 @@ typedef enum OPTION_choice {
     OPT_SEARCHFOR_CERTS,
     OPT_SEARCHFOR_KEYS,
     OPT_SEARCHFOR_CRLS,
+    OPT_SEARCHFOR_SKEYS,
     OPT_CRITERION_SUBJECT,
     OPT_CRITERION_ISSUER,
     OPT_CRITERION_SERIAL,
@@ -53,6 +54,7 @@ const OPTIONS storeutl_options[] = {
     { "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" },
@@ -124,6 +126,7 @@ int storeutl_main(int argc, char *argv[])
         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);
@@ -137,6 +140,7 @@ int storeutl_main(int argc, char *argv[])
                     { 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;
 
@@ -476,6 +480,9 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
             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++;
index 8bd83215dd0731231be241e6b973725bd317fc2d..70e06a6a38aed05a9eeb6864c2eb2dcc1bd4042f 100644 (file)
@@ -898,6 +898,7 @@ OSSL_STORE_R_NOT_A_CRL:101:not a crl
 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
index ee35151cc34bb53065cf21a441880477df222731..afde022997b3ea310d4ea2a4baf742ef510891d8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -38,6 +38,8 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
         "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),
index 7c111541388cae206a6f1a98c40f78a73089e8a1..ea0ab3423baf85258d44adf43582ce9299339d2a 100644 (file)
@@ -295,7 +295,7 @@ int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
     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;
     }
@@ -690,6 +690,15 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
     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.
  */
@@ -825,6 +834,24 @@ X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *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
  */
@@ -851,6 +878,9 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *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);
     }
index a7ae850d1b9e1a6b9bd0851496c6b9fc0b4dafd3..dd7c107a50b70c9fdc64466e196e14605419e4f6 100644 (file)
@@ -37,6 +37,7 @@ struct ossl_store_info_st {
         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)
index 849e4f33fbe79fb70996c635890b934fd8693a77..1900b42dcc45fa098f76dcb3c35fc7e4406bd797 100644 (file)
@@ -83,6 +83,8 @@ static int try_crl(struct extracted_param_data_st *, 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)
 {
@@ -150,6 +152,10 @@ 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 = "";
@@ -665,3 +671,49 @@ static int try_pkcs12(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
 
     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;
+}
index 0d525b71c229b0f31e61b56533f4adb1538589a3..e8b17e5188edf5c911b57597d13415bbc38e5190 100644 (file)
@@ -17,7 +17,8 @@ static const char *const type_strings[] = {
     "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)
index 429ef9abcffa2641737083c6d28f999d888f299f..fd05d777c92ebc9d0efc9dc15fe8226f8186c284 100644 (file)
@@ -41,6 +41,8 @@ B<openssl> B<enc>|I<cipher>
 [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 -}
 
@@ -237,6 +239,18 @@ 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.
 
+=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 -}
@@ -485,7 +499,7 @@ certain parameters. So if, for example, you want to use RC2 with a
 
 =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
 
@@ -501,6 +515,8 @@ The B<-skeymgmt> and B<-skeyopt> options were added in OpenSSL 3.5.
 
 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.
index 38dd1df645f82fa715ad5f0af8b30e00e354781e..c2ae6251e6209debef917029fa9a5ca222e30f47 100644 (file)
@@ -21,6 +21,7 @@ B<openssl> B<storeutl>
 [B<-certs>]
 [B<-keys>]
 [B<-crls>]
+[B<-skeys>]
 [B<-subject> I<arg>]
 [B<-issuer> I<arg>]
 [B<-serial> I<arg>]
@@ -75,7 +76,9 @@ Fetch objects recursively when possible.
 
 =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.
 
@@ -138,9 +141,11 @@ This command was added in OpenSSL 1.1.1.
 
 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
index b8332855d4d04691f22fdd62aaf7088968aaffe1..1052749a4b3feea91f284ce5f70702f321b6c9a9 100644 (file)
@@ -6,14 +6,16 @@ OSSL_STORE_INFO, OSSL_STORE_INFO_get_type, 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_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
@@ -38,6 +40,8 @@ OSSL_STORE_INFO_new, OSSL_STORE_INFO_get0_data
  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);
 
@@ -50,6 +54,7 @@ OSSL_STORE_INFO_new, OSSL_STORE_INFO_get0_data
  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);
@@ -87,7 +92,7 @@ short string describing it.
 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.
@@ -95,7 +100,7 @@ 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.
@@ -105,7 +110,8 @@ If the argument is NULL, nothing is done.
 
 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.
 
@@ -181,6 +187,10 @@ An X.509 certificate.
 
 A X.509 certificate revocation list.
 
+=item OSSL_STORE_INFO_SKEY
+
+A symmetric key object.
+
 =back
 
 =head1 RETURN VALUES
@@ -191,21 +201,23 @@ There is no error value.
 
 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.
@@ -220,6 +232,9 @@ The OSSL_STORE API was added in OpenSSL 1.1.1.
 
 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.
index d4d163eabbe971bedb8a968d44e7b8c6e462a335..c44567270ff696b756937e876ef23fb57a81c3cf 100644 (file)
@@ -35,6 +35,13 @@ If the file isn't determined to be formatted as PEM, the content is
 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
@@ -57,11 +64,15 @@ See L<passphrase-encoding(7)> for more information.
 
 =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
index df0c79436d880ee96cca41d4a1d0271692879788..d6d46a914f697b58fd76256d0513ce46745c8e00 100644 (file)
@@ -29,6 +29,7 @@ extern "C" {
 #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
index 0658739ea354d9b4822af8f12d61226ac312efd8..5c25d0f8528ba3663d2e5830921b2fa11ac653ff 100644 (file)
@@ -160,6 +160,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
 #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
@@ -176,6 +177,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey);
 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.
@@ -196,6 +198,8 @@ X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *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);
 
index a61bee11125f972ca7925a859202b99c22261dee..fb58f0630e7c96fca9b7e4605b750434579d8551 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -32,6 +32,7 @@
 #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
index 77351dccc2c702d2ea845029cea8a84e0d94552f..8493bb44261f070331cb5d501da7368efd42cf77 100644 (file)
@@ -464,6 +464,8 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
                 goto err;
             }
             break;
+        case OSSL_STORE_INFO_SKEY: /* No input structure */
+            break;
         default:
             break;
         }
@@ -502,6 +504,16 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
                 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);
index fc7a98d1e878267228eb7d44389162992ebbf761..67de51d94a84a1f4a92ef251ab50c56623cc5c9d 100644 (file)
@@ -302,14 +302,66 @@ err:
         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,
     }
index 2b430b74fcb66f5ae5c807962c8fe410d08428fd..fe09dfdd4c93a12243c375571c4a6aa3d130e824 100644 (file)
@@ -41,7 +41,7 @@ my @ciphers =
                      |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)
@@ -90,4 +90,16 @@ plan tests => 5 + (scalar @ciphers)*2;
         && 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");
 }
diff --git a/test/recipes/20-test_enc_data/skeyfile.bin b/test/recipes/20-test_enc_data/skeyfile.bin
new file mode 100644 (file)
index 0000000..8fd8c47
--- /dev/null
@@ -0,0 +1 @@
+0102030405060708
\ No newline at end of file
index ee9be3c00e0cc2ff16019cf5cde2aea2c9242008..155ba0f93d18c816d00ee5071c0ea156649e9cc7 100644 (file)
@@ -5805,6 +5805,9 @@ i2d_OSSL_AA_DIST_POINT                  ? 4_0_0   EXIST::FUNCTION:
 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: