LIBS=../../libcrypto
$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c evp_utils.c \
mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \
- pmeth_lib.c signature.c p_lib.c pmeth_gn.c exchange.c \
+ skeymgmt_meth.c \
+ pmeth_lib.c signature.c p_lib.c s_lib.c pmeth_gn.c exchange.c \
evp_rand.c asymcipher.c kem.c dh_support.c ec_support.c pmeth_check.c
SOURCE[../../libcrypto]=$COMMON\
if (enc) {
if (ctx->cipher->einit == NULL) {
+ /*
+ * We still should be able to set the IV using the new API
+ * if the key is not specified and old API is not available
+ */
+ if (key == NULL && ctx->cipher->einit_skey != NULL) {
+ return ctx->cipher->einit_skey(ctx->algctx, NULL,
+ iv,
+ iv == NULL ? 0
+ : EVP_CIPHER_CTX_get_iv_length(ctx),
+ params);
+ }
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
}
if (ctx->cipher->dinit == NULL) {
+ /*
+ * We still should be able to set the IV using the new API
+ * if the key is not specified and old API is not available
+ */
+ if (key == NULL && ctx->cipher->dinit_skey != NULL) {
+ return ctx->cipher->dinit_skey(ctx->algctx, NULL,
+ iv,
+ iv == NULL ? 0
+ : EVP_CIPHER_CTX_get_iv_length(ctx),
+ params);
+ }
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
return 1;
}
+/*
+ * This function is basically evp_cipher_init_internal without ENGINE support.
+ * They should be combined when engines are not supported any longer.
+ */
+static int evp_cipher_init_skey_internal(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher,
+ const EVP_SKEY *skey,
+ const unsigned char *iv, size_t iv_len,
+ int enc, const OSSL_PARAM params[])
+{
+ int ret;
+
+ /*
+ * enc == 1 means we are encrypting.
+ * enc == 0 means we are decrypting.
+ * enc == -1 means, use the previously initialised value for encrypt/decrypt
+ */
+ if (enc == -1)
+ enc = ctx->encrypt;
+ else
+ ctx->encrypt = enc != 0;
+
+ if (cipher == NULL && ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ /*
+ * If there are engines involved then we throw an error
+ */
+ if (ctx->engine != NULL
+ || (cipher != NULL && cipher->origin == EVP_ORIG_METH)
+ || (cipher == NULL && ctx->cipher != NULL
+ && ctx->cipher->origin == EVP_ORIG_METH)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ /*
+ * Ensure a context left lying around from last time is cleared
+ * (legacy code)
+ */
+ if (cipher != NULL && ctx->cipher != NULL) {
+ if (ctx->cipher->cleanup != NULL && !ctx->cipher->cleanup(ctx))
+ return 0;
+ OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
+ ctx->cipher_data = NULL;
+ }
+
+ /* Ensure a context left lying around from last time is cleared */
+ if (cipher != NULL && ctx->cipher != NULL) {
+ unsigned long flags = ctx->flags;
+
+ EVP_CIPHER_CTX_reset(ctx);
+ /* Restore encrypt and flags */
+ ctx->encrypt = enc;
+ ctx->flags = flags;
+ }
+
+ if (cipher == NULL)
+ cipher = ctx->cipher;
+
+ if (cipher->prov == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ if (cipher != ctx->fetched_cipher) {
+ if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ EVP_CIPHER_free(ctx->fetched_cipher);
+ /* Coverity false positive, the reference counting is confusing it */
+ /* coverity[use_after_free] */
+ ctx->fetched_cipher = (EVP_CIPHER *)cipher;
+ }
+ ctx->cipher = cipher;
+ if (ctx->algctx == NULL) {
+ ctx->algctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
+ if (ctx->algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ }
+
+ if (skey != NULL && skey->skeymgmt != NULL
+ && ctx->cipher->prov != skey->skeymgmt->prov) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
+ /*
+ * If this ctx was already set up for no padding then we need to tell
+ * the new cipher about it.
+ */
+ if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
+ return 0;
+ }
+
+ if (iv == NULL)
+ iv_len = 0;
+
+ /* We have a data managed via key management, using the new callbacks */
+ if (enc) {
+ if (ctx->cipher->einit_skey == NULL) {
+ /* Attempt fallback for providers that do not support SKEYs */
+ const unsigned char *keydata;
+ size_t keylen;
+
+ if (!EVP_SKEY_get_raw_key(skey, &keydata, &keylen)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ ret = ctx->cipher->einit(ctx->algctx, keydata, keylen,
+ iv, iv_len, params);
+ } else {
+ ret = ctx->cipher->einit_skey(ctx->algctx, skey->keydata,
+ iv, iv_len, params);
+ }
+ } else {
+ if (ctx->cipher->dinit_skey == NULL) {
+ /* Attempt fallback for providers that do not support SKEYs */
+ const unsigned char *keydata;
+ size_t keylen;
+
+ if (!EVP_SKEY_get_raw_key(skey, &keydata, &keylen)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ ret = ctx->cipher->dinit(ctx->algctx, keydata, keylen,
+ iv, iv_len, params);
+ } else {
+ ret = ctx->cipher->dinit_skey(ctx->algctx, skey->keydata,
+ iv, iv_len, params);
+ }
+ }
+
+ return ret;
+}
+
+int EVP_CipherInit_SKEY(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ EVP_SKEY *skey, const unsigned char *iv, size_t iv_len,
+ int enc, const OSSL_PARAM params[])
+{
+ return evp_cipher_init_skey_internal(ctx, cipher, skey, iv, iv_len, enc, params);
+}
+
int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv,
int enc, const OSSL_PARAM params[])
{
const OSSL_DISPATCH *fns = algodef->implementation;
EVP_CIPHER *cipher = NULL;
- int fnciphcnt = 0, fnpipecnt = 0, fnctxcnt = 0;
+ int fnciphcnt = 0, encinit = 0, decinit = 0, fnpipecnt = 0, fnctxcnt = 0;
if ((cipher = evp_cipher_new()) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
if (cipher->einit != NULL)
break;
cipher->einit = OSSL_FUNC_cipher_encrypt_init(fns);
- fnciphcnt++;
+ encinit = 1;
break;
case OSSL_FUNC_CIPHER_DECRYPT_INIT:
if (cipher->dinit != NULL)
break;
cipher->dinit = OSSL_FUNC_cipher_decrypt_init(fns);
- fnciphcnt++;
+ decinit = 1;
+ break;
+ case OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT:
+ if (cipher->einit_skey != NULL)
+ break;
+ cipher->einit_skey = OSSL_FUNC_cipher_encrypt_skey_init(fns);
+ encinit = 1;
+ break;
+ case OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT:
+ if (cipher->dinit_skey != NULL)
+ break;
+ cipher->dinit_skey = OSSL_FUNC_cipher_decrypt_skey_init(fns);
+ decinit = 1;
break;
case OSSL_FUNC_CIPHER_UPDATE:
if (cipher->cupdate != NULL)
break;
}
}
+ fnciphcnt += encinit + decinit;
if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
|| (fnciphcnt == 0 && cipher->ccipher == NULL && fnpipecnt == 0)
|| (fnpipecnt != 0 && (fnpipecnt < 3 || cipher->p_cupdate == NULL
OSSL_FUNC_signature_query_key_types_fn *query_key_types;
} /* EVP_SIGNATURE */;
+struct evp_skeymgmt_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+
+ /* Import and export routines */
+ OSSL_FUNC_skeymgmt_imp_settable_params_fn *imp_params;
+ OSSL_FUNC_skeymgmt_import_fn *import;
+ OSSL_FUNC_skeymgmt_export_fn *export;
+
+ /* Key generation */
+ OSSL_FUNC_skeymgmt_gen_settable_params_fn *gen_params;
+ OSSL_FUNC_skeymgmt_generate_fn *generate;
+
+ /* Key identifier */
+ OSSL_FUNC_skeymgmt_get_key_id_fn *get_key_id;
+
+ /* destructor */
+ OSSL_FUNC_skeymgmt_free_fn *free;
+} /* EVP_SKEYMGMT */;
+
struct evp_asym_cipher_st {
int name_id;
char *type_name;
void (*fn)(const char *name, void *data),
void *data);
int evp_cipher_cache_constants(EVP_CIPHER *cipher);
+
+EVP_SKEY *evp_skey_alloc(void);
--- /dev/null
+/*
+ * 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 <string.h>
+#include <openssl/params.h>
+#include <openssl/param_build.h>
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+
+#include "internal/provider.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+int EVP_SKEY_export(const EVP_SKEY *skey, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ if (skey == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (skey->skeymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ return evp_skeymgmt_export(skey->skeymgmt, skey->keydata, selection, export_cb, export_cbarg);
+}
+
+EVP_SKEY *evp_skey_alloc(void)
+{
+ EVP_SKEY *skey = OPENSSL_zalloc(sizeof(EVP_SKEY));
+
+ if (!CRYPTO_NEW_REF(&skey->references, 1))
+ goto err;
+
+ skey->lock = CRYPTO_THREAD_lock_new();
+ if (skey->lock == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
+ goto err;
+ }
+ return skey;
+
+ err:
+ CRYPTO_FREE_REF(&skey->references);
+ CRYPTO_THREAD_lock_free(skey->lock);
+ OPENSSL_free(skey);
+ return NULL;
+}
+
+EVP_SKEY *EVP_SKEY_import(OSSL_LIB_CTX *libctx, const char *skeymgmtname, const char *propquery,
+ int selection, const OSSL_PARAM *params)
+{
+ EVP_SKEYMGMT *skeymgmt = NULL;
+ EVP_SKEY *skey = evp_skey_alloc();
+
+ if (skey == NULL)
+ return NULL;
+
+ skeymgmt = EVP_SKEYMGMT_fetch(libctx, skeymgmtname, propquery);
+ if (skeymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_FETCH_FAILED);
+ goto err;
+ }
+ skey->skeymgmt = skeymgmt;
+
+ skey->keydata = evp_skeymgmt_import(skey->skeymgmt, selection, params);
+ if (skey->keydata == NULL)
+ goto err;
+
+ return skey;
+
+ err:
+ EVP_SKEYMGMT_free(skeymgmt);
+ EVP_SKEY_free(skey);
+ return NULL;
+}
+
+EVP_SKEY *EVP_SKEY_generate(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
+ const char *propquery, const OSSL_PARAM *params)
+{
+ EVP_SKEYMGMT *skeymgmt = NULL;
+ EVP_SKEY *skey = evp_skey_alloc();
+
+ if (skey == NULL)
+ return NULL;
+
+ skeymgmt = EVP_SKEYMGMT_fetch(libctx, skeymgmtname, propquery);
+ if (skeymgmt == NULL) {
+ /*
+ * if the specific key_type is unkown, attempt to use the generic
+ * key management
+ */
+ skeymgmt = EVP_SKEYMGMT_fetch(libctx, OSSL_SKEY_TYPE_GENERIC, propquery);
+ if (skeymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_FETCH_FAILED);
+ goto err;
+ }
+ }
+ skey->skeymgmt = skeymgmt;
+
+ skey->keydata = evp_skeymgmt_generate(skey->skeymgmt, params);
+ if (skey->keydata == NULL)
+ goto err;
+
+ return skey;
+
+ err:
+ EVP_SKEYMGMT_free(skeymgmt);
+ EVP_SKEY_free(skey);
+ return NULL;
+}
+
+struct raw_key_details_st {
+ const void **key;
+ size_t *len;
+};
+
+static int get_secret_key(const OSSL_PARAM params[], void *arg)
+{
+ const OSSL_PARAM *p = NULL;
+ struct raw_key_details_st *raw_key = arg;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES)) != NULL)
+ return OSSL_PARAM_get_octet_string_ptr(p, raw_key->key, raw_key->len);
+
+ return 0;
+}
+
+int EVP_SKEY_get_raw_key(const EVP_SKEY *skey, const unsigned char **key,
+ size_t *len)
+{
+ struct raw_key_details_st raw_key;
+
+ if (skey == NULL || key == NULL || len == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ raw_key.key = (const void **)key;
+ raw_key.len = len;
+
+ return evp_skeymgmt_export(skey->skeymgmt, skey->keydata,
+ OSSL_SKEYMGMT_SELECT_SECRET_KEY,
+ get_secret_key, &raw_key);
+}
+
+EVP_SKEY *EVP_SKEY_import_raw_key(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
+ unsigned char *key, size_t keylen,
+ const char *propquery)
+{
+ OSSL_PARAM params[2];
+
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
+ (void *)key, keylen);
+ params[1] = OSSL_PARAM_construct_end();
+
+ return EVP_SKEY_import(libctx, skeymgmtname, propquery,
+ OSSL_SKEYMGMT_SELECT_SECRET_KEY, params);
+}
+
+int EVP_SKEY_up_ref(EVP_SKEY *skey)
+{
+ int i;
+
+ if (CRYPTO_UP_REF(&skey->references, &i) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("EVP_SKEY", i, skey);
+ REF_ASSERT_ISNT(i < 2);
+ return i > 1 ? 1 : 0;
+}
+
+void EVP_SKEY_free(EVP_SKEY *skey)
+{
+ int i;
+
+ if (skey == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&skey->references, &i);
+ REF_PRINT_COUNT("EVP_SKEY", i, skey);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+ if (skey->keydata && skey->skeymgmt)
+ evp_skeymgmt_freedata(skey->skeymgmt, skey->keydata);
+
+ EVP_SKEYMGMT_free(skey->skeymgmt);
+
+ CRYPTO_THREAD_lock_free(skey->lock);
+ CRYPTO_FREE_REF(&skey->references);
+ OPENSSL_free(skey);
+}
+
+const char *EVP_SKEY_get0_key_id(const EVP_SKEY *skey)
+{
+ if (skey == NULL)
+ return NULL;
+
+ if (skey->skeymgmt->get_key_id)
+ return skey->skeymgmt->get_key_id(skey->keydata);
+
+ return NULL;
+}
+
+const char *EVP_SKEY_get0_skeymgmt_name(const EVP_SKEY *skey)
+{
+ if (skey == NULL)
+ return NULL;
+
+ return skey->skeymgmt->type_name;
+
+}
+
+const char *EVP_SKEY_get0_provider_name(const EVP_SKEY *skey)
+{
+ if (skey == NULL)
+ return NULL;
+
+ return ossl_provider_name(skey->skeymgmt->prov);
+}
--- /dev/null
+/*
+ * 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 <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "internal/core.h"
+#include "internal/provider.h"
+#include "internal/refcount.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+void *evp_skeymgmt_generate(const EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[])
+{
+ void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt));
+
+ return (skeymgmt->generate != NULL) ? skeymgmt->generate(provctx, params) : NULL;
+}
+
+void *evp_skeymgmt_import(const EVP_SKEYMGMT *skeymgmt, int selection, const OSSL_PARAM params[])
+{
+ void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt));
+
+ /* This is mandatory, no need to check for its presence */
+ return skeymgmt->import(provctx, selection, params);
+}
+
+int evp_skeymgmt_export(const EVP_SKEYMGMT *skeymgmt, void *keydata,
+ int selection, OSSL_CALLBACK *param_cb, void *cbarg)
+{
+ /* This is mandatory, no need to check for its presence */
+ return skeymgmt->export(keydata, selection, param_cb, cbarg);
+}
+
+void evp_skeymgmt_freedata(const EVP_SKEYMGMT *skeymgmt, void *keydata)
+{
+ /* This is mandatory, no need to check for its presence */
+ skeymgmt->free(keydata);
+}
+
+static void *skeymgmt_new(void)
+{
+ EVP_SKEYMGMT *skeymgmt = NULL;
+
+ if ((skeymgmt = OPENSSL_zalloc(sizeof(*skeymgmt))) == NULL)
+ return NULL;
+ if (!CRYPTO_NEW_REF(&skeymgmt->refcnt, 1)) {
+ EVP_SKEYMGMT_free(skeymgmt);
+ return NULL;
+ }
+ return skeymgmt;
+}
+
+static void *skeymgmt_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_SKEYMGMT *skeymgmt = NULL;
+
+ if ((skeymgmt = skeymgmt_new()) == NULL)
+ return NULL;
+
+ skeymgmt->name_id = name_id;
+ if ((skeymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ EVP_SKEYMGMT_free(skeymgmt);
+ return NULL;
+ }
+ skeymgmt->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_SKEYMGMT_FREE:
+ if (skeymgmt->free == NULL)
+ skeymgmt->free = OSSL_FUNC_skeymgmt_free(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_IMPORT:
+ if (skeymgmt->import == NULL)
+ skeymgmt->import = OSSL_FUNC_skeymgmt_import(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_EXPORT:
+ if (skeymgmt->export == NULL)
+ skeymgmt->export = OSSL_FUNC_skeymgmt_export(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_GENERATE:
+ if (skeymgmt->generate == NULL)
+ skeymgmt->generate = OSSL_FUNC_skeymgmt_generate(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_GET_KEY_ID:
+ if (skeymgmt->get_key_id == NULL)
+ skeymgmt->get_key_id = OSSL_FUNC_skeymgmt_get_key_id(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS:
+ if (skeymgmt->imp_params == NULL)
+ skeymgmt->imp_params = OSSL_FUNC_skeymgmt_imp_settable_params(fns);
+ break;
+ case OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS:
+ if (skeymgmt->gen_params == NULL)
+ skeymgmt->gen_params = OSSL_FUNC_skeymgmt_gen_settable_params(fns);
+ break;
+ }
+ }
+
+ /* Check that the provider is sensible */
+ if (skeymgmt->free == NULL
+ || skeymgmt->import == NULL
+ || skeymgmt->export == NULL) {
+ EVP_SKEYMGMT_free(skeymgmt);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ skeymgmt->prov = prov;
+ ossl_provider_up_ref(prov);
+
+ return skeymgmt;
+}
+
+EVP_SKEYMGMT *EVP_SKEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_SKEYMGMT, algorithm, properties,
+ skeymgmt_from_algorithm,
+ (int (*)(void *))EVP_SKEYMGMT_up_ref,
+ (void (*)(void *))EVP_SKEYMGMT_free);
+}
+
+int EVP_SKEYMGMT_up_ref(EVP_SKEYMGMT *skeymgmt)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&skeymgmt->refcnt, &ref);
+ return 1;
+}
+
+void EVP_SKEYMGMT_free(EVP_SKEYMGMT *skeymgmt)
+{
+ int ref = 0;
+
+ if (skeymgmt == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&skeymgmt->refcnt, &ref);
+ if (ref > 0)
+ return;
+ OPENSSL_free(skeymgmt->type_name);
+ ossl_provider_free(skeymgmt->prov);
+ CRYPTO_FREE_REF(&skeymgmt->refcnt);
+ OPENSSL_free(skeymgmt);
+}
+
+const OSSL_PROVIDER *EVP_SKEYMGMT_get0_provider(const EVP_SKEYMGMT *skeymgmt)
+{
+ return (skeymgmt != NULL) ? skeymgmt->prov : NULL;
+}
+
+const char *EVP_SKEYMGMT_get0_description(const EVP_SKEYMGMT *skeymgmt)
+{
+ return (skeymgmt != NULL) ? skeymgmt->description : NULL;
+}
+
+const char *EVP_SKEYMGMT_get0_name(const EVP_SKEYMGMT *skeymgmt)
+{
+ return (skeymgmt != NULL) ? skeymgmt->type_name : NULL;
+}
+
+int EVP_SKEYMGMT_is_a(const EVP_SKEYMGMT *skeymgmt, const char *name)
+{
+ return skeymgmt != NULL
+ && evp_is_a(skeymgmt->prov, skeymgmt->name_id, NULL, name);
+}
+
+void EVP_SKEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_SKEYMGMT *skeymgmt, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
+ (void (*)(void *, void *))fn, arg,
+ skeymgmt_from_algorithm,
+ (int (*)(void *))EVP_SKEYMGMT_up_ref,
+ (void (*)(void *))EVP_SKEYMGMT_free);
+}
+
+int EVP_SKEYMGMT_names_do_all(const EVP_SKEYMGMT *skeymgmt,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (skeymgmt == NULL)
+ return 0;
+
+ if (skeymgmt->prov != NULL)
+ return evp_names_do_all(skeymgmt->prov, skeymgmt->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PARAM *EVP_SKEYMGMT_get0_gen_settable_params(const EVP_SKEYMGMT *skeymgmt)
+{
+ void *provctx = NULL;
+
+ if (skeymgmt == NULL)
+ return 0;
+
+ provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt));
+
+ return (skeymgmt->gen_params != NULL) ? skeymgmt->gen_params(provctx) : NULL;
+}
+
+const OSSL_PARAM *EVP_SKEYMGMT_get0_imp_settable_params(const EVP_SKEYMGMT *skeymgmt)
+{
+ void *provctx = NULL;
+
+ if (skeymgmt == NULL)
+ return 0;
+
+ provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt));
+
+ return (skeymgmt->imp_params != NULL) ? skeymgmt->imp_params(provctx) : NULL;
+}
OSSL_FUNC_cipher_gettable_params_fn *gettable_params;
OSSL_FUNC_cipher_gettable_ctx_params_fn *gettable_ctx_params;
OSSL_FUNC_cipher_settable_ctx_params_fn *settable_ctx_params;
-} /* EVP_CIPHER */ ;
+ OSSL_FUNC_cipher_encrypt_skey_init_fn *einit_skey;
+ OSSL_FUNC_cipher_decrypt_skey_init_fn *dinit_skey;
+} /* EVP_CIPHER */;
/* Macros to code block cipher wrappers */
# define EVP_PKEY_CTX_IS_KEM_OP(ctx) \
(((ctx)->operation & EVP_PKEY_OP_TYPE_KEM) != 0)
+struct evp_skey_st {
+ /* == Common attributes == */
+ CRYPTO_REF_COUNT references;
+ CRYPTO_RWLOCK *lock;
+
+ void *keydata; /* Alg-specific key data */
+ EVP_SKEYMGMT *skeymgmt; /* Import, export, manage */
+}; /* EVP_SKEY */
+
void openssl_add_all_ciphers_int(void);
void openssl_add_all_digests_int(void);
void evp_cleanup_int(void);
const char *name,
const char *properties);
+/*
+ * SKEYMGMT provider interface functions
+ */
+void evp_skeymgmt_freedata(const EVP_SKEYMGMT *keymgmt, void *keyddata);
+void *evp_skeymgmt_import(const EVP_SKEYMGMT *skeymgmt, int selection, const OSSL_PARAM params[]);
+int evp_skeymgmt_export(const EVP_SKEYMGMT *skeymgmt, void *keydata,
+ int selection, OSSL_CALLBACK *param_cb, void *cbarg);
+void *evp_skeymgmt_generate(const EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[]);
/* Pulling defines out of C source files */
# define EVP_RC4_KEY_SIZE 16
# define OSSL_OP_SIGNATURE 12
# define OSSL_OP_ASYM_CIPHER 13
# define OSSL_OP_KEM 14
+# define OSSL_OP_SKEYMGMT 15
/* New section for non-EVP operations */
# define OSSL_OP_ENCODER 20
# define OSSL_OP_DECODER 21
# define OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT 16
# define OSSL_FUNC_CIPHER_PIPELINE_UPDATE 17
# define OSSL_FUNC_CIPHER_PIPELINE_FINAL 18
+# define OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT 19
+# define OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT 20
OSSL_CORE_MAKE_FUNC(void *, cipher_newctx, (void *provctx))
OSSL_CORE_MAKE_FUNC(int, cipher_encrypt_init, (void *cctx,
(void *cctx, void *provctx))
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, cipher_gettable_ctx_params,
(void *cctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, cipher_encrypt_skey_init, (void *cctx,
+ void *skeydata,
+ const unsigned char *iv,
+ size_t ivlen,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, cipher_decrypt_skey_init, (void *cctx,
+ void *skeydata,
+ const unsigned char *iv,
+ size_t ivlen,
+ const OSSL_PARAM params[]))
/* MACs */
(void *ctx))
OSSL_CORE_MAKE_FUNC(const char **, signature_query_key_types, (void))
+/*-
+ * Symmetric key management
+ *
+ * The Key Management takes care of provider side of symmetric key objects, and
+ * includes essentially everything that manipulates the keys themselves and
+ * their parameters.
+ *
+ * The key objects are commonly referred to as |keydata|, and it MUST be able
+ * to contain parameters if the key has any, and the secret key.
+ *
+ * Key objects are created with OSSL_FUNC_skeymgmt_import() (there is no
+ * dedicated memory allocation function), exported with
+ * OSSL_FUNC_skeymgmt_export() and destroyed with OSSL_FUNC_keymgmt_free().
+ *
+ */
+
+/* Key data subset selection - individual bits */
+# define OSSL_SKEYMGMT_SELECT_PARAMETERS 0x01
+# define OSSL_SKEYMGMT_SELECT_SECRET_KEY 0x02
+
+/* Key data subset selection - combinations */
+# define OSSL_SKEYMGMT_SELECT_ALL \
+ (OSSL_SKEYMGMT_SELECT_PARAMETERS | OSSL_SKEYMGMT_SELECT_SECRET_KEY)
+
+# define OSSL_FUNC_SKEYMGMT_FREE 1
+# define OSSL_FUNC_SKEYMGMT_IMPORT 2
+# define OSSL_FUNC_SKEYMGMT_EXPORT 3
+# define OSSL_FUNC_SKEYMGMT_GENERATE 4
+# define OSSL_FUNC_SKEYMGMT_GET_KEY_ID 5
+# define OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS 6
+# define OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS 7
+
+OSSL_CORE_MAKE_FUNC(void, skeymgmt_free, (void *keydata))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
+ skeymgmt_imp_settable_params, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void *, skeymgmt_import, (void *provctx, int selection,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, skeymgmt_export,
+ (void *keydata, int selection,
+ OSSL_CALLBACK *param_cb, void *cbarg))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
+ skeymgmt_gen_settable_params, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void *, skeymgmt_generate, (void *provctx,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const char *, skeymgmt_get_key_id, (void *keydata))
+
/* Asymmetric Ciphers */
# define OSSL_FUNC_ASYM_CIPHER_NEWCTX 1
# define OSSL_PKEY_EC_GROUP_CHECK_NAMED "named"
# define OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST "named-nist"
+/* PROV_SKEY well known key types */
+# define OSSL_SKEY_TYPE_GENERIC "GENERIC-SECRET"
+# define OSSL_SKEY_TYPE_AES "AES"
+
/* OSSL_KEM_PARAM_OPERATION values */
#define OSSL_KEM_PARAM_OPERATION_RSASVE "RSASVE"
#define OSSL_KEM_PARAM_OPERATION_DHKEM "DHKEM"
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv, int enc);
+__owur int EVP_CipherInit_SKEY(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ EVP_SKEY *skey, const unsigned char *iv, size_t iv_len,
+ int enc, const OSSL_PARAM params[]);
__owur int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv,
int enc, const OSSL_PARAM params[]);
const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt);
const OSSL_PARAM *EVP_KEYMGMT_gen_gettable_params(const EVP_KEYMGMT *keymgmt);
+EVP_SKEYMGMT *EVP_SKEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_SKEYMGMT_up_ref(EVP_SKEYMGMT *keymgmt);
+void EVP_SKEYMGMT_free(EVP_SKEYMGMT *keymgmt);
+const OSSL_PROVIDER *EVP_SKEYMGMT_get0_provider(const EVP_SKEYMGMT *keymgmt);
+const char *EVP_SKEYMGMT_get0_name(const EVP_SKEYMGMT *keymgmt);
+const char *EVP_SKEYMGMT_get0_description(const EVP_SKEYMGMT *keymgmt);
+int EVP_SKEYMGMT_is_a(const EVP_SKEYMGMT *keymgmt, const char *name);
+void EVP_SKEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_SKEYMGMT *keymgmt, void *arg),
+ void *arg);
+int EVP_SKEYMGMT_names_do_all(const EVP_SKEYMGMT *keymgmt,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *EVP_SKEYMGMT_get0_gen_settable_params(const EVP_SKEYMGMT *skeymgmt);
+const OSSL_PARAM *EVP_SKEYMGMT_get0_imp_settable_params(const EVP_SKEYMGMT *skeymgmt);
+
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx);
const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx);
+EVP_SKEY *EVP_SKEY_import(OSSL_LIB_CTX *libctx, const char *skeymgmtname, const char *propquery,
+ int selection, const OSSL_PARAM *params);
+EVP_SKEY *EVP_SKEY_generate(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
+ const char *propquery, const OSSL_PARAM *params);
+EVP_SKEY *EVP_SKEY_import_raw_key(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
+ unsigned char *key, size_t keylen,
+ const char *propquery);
+int EVP_SKEY_get_raw_key(const EVP_SKEY *skey, const unsigned char **key,
+ size_t *len);
+const char *EVP_SKEY_get0_key_id(const EVP_SKEY *skey);
+int EVP_SKEY_export(const EVP_SKEY *skey, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+int EVP_SKEY_up_ref(EVP_SKEY *skey);
+void EVP_SKEY_free(EVP_SKEY *skey);
+const char *EVP_SKEY_get0_skeymgmt_name(const EVP_SKEY *skey);
+const char *EVP_SKEY_get0_provider_name(const EVP_SKEY *skey);
+
# ifdef __cplusplus
}
# endif
typedef struct evp_mac_st EVP_MAC;
typedef struct evp_mac_ctx_st EVP_MAC_CTX;
typedef struct evp_pkey_st EVP_PKEY;
+typedef struct evp_skey_st EVP_SKEY;
typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
typedef struct evp_signature_st EVP_SIGNATURE;
+typedef struct evp_skeymgmt_st EVP_SKEYMGMT;
+
typedef struct evp_asym_cipher_st EVP_ASYM_CIPHER;
typedef struct evp_kem_st EVP_KEM;
OSSL_ALLOWED_ATTRIBUTES_SYNTAX_free ? 3_5_0 EXIST::FUNCTION:
OSSL_ALLOWED_ATTRIBUTES_SYNTAX_new ? 3_5_0 EXIST::FUNCTION:
OSSL_ALLOWED_ATTRIBUTES_SYNTAX_it ? 3_5_0 EXIST::FUNCTION:
+EVP_CipherInit_SKEY ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_import ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_generate ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_import_raw_key ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_get_raw_key ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_export ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_up_ref ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEY_free ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_fetch ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_up_ref ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_free ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_get0_provider ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_get0_name ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_get0_description ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_is_a ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_do_all_provided ? 3_5_0 EXIST::FUNCTION:
+EVP_SKEYMGMT_names_do_all ? 3_5_0 EXIST::FUNCTION:
OSSL_PROVIDER_add_conf_parameter ? 3_5_0 EXIST::FUNCTION:
OSSL_PROVIDER_get_conf_parameters ? 3_5_0 EXIST::FUNCTION:
OSSL_PROVIDER_conf_get_bool ? 3_5_0 EXIST::FUNCTION:
'LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA' => "max_early_data",
'LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING' => "block_padding",
'LIBSSL_RECORD_LAYER_PARAM_HS_PADDING' => "hs_padding",
+
+# Symmetric Key parametes
+ 'SKEY_PARAM_RAW_BYTES' => "raw-bytes",
+ 'SKEY_PARAM_KEY_LENGTH' => "key-length",
);
# Generate string based macros for public consumption