diff options
27 files changed, 1677 insertions, 10 deletions
diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 36fac11683..7f1459a15c 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -2,7 +2,7 @@ LIBS=../../libcrypto $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \ mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \ m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c exchange.c \ - pmeth_check.c evp_rand.c asymcipher.c + pmeth_check.c evp_rand.c asymcipher.c kem.c SOURCE[../../libcrypto]=$COMMON\ encode.c evp_key.c evp_cnf.c \ diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index e7f7643d83..3268aa4109 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -181,6 +181,25 @@ struct evp_asym_cipher_st { OSSL_FUNC_asym_cipher_settable_ctx_params_fn *settable_ctx_params; } /* EVP_ASYM_CIPHER */; +struct evp_kem_st { + int name_id; + OSSL_PROVIDER *prov; + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; + + OSSL_FUNC_kem_newctx_fn *newctx; + OSSL_FUNC_kem_encapsulate_init_fn *encapsulate_init; + OSSL_FUNC_kem_encapsulate_fn *encapsulate; + OSSL_FUNC_kem_decapsulate_init_fn *decapsulate_init; + OSSL_FUNC_kem_decapsulate_fn *decapsulate; + OSSL_FUNC_kem_freectx_fn *freectx; + OSSL_FUNC_kem_dupctx_fn *dupctx; + OSSL_FUNC_kem_get_ctx_params_fn *get_ctx_params; + OSSL_FUNC_kem_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_FUNC_kem_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_kem_settable_ctx_params_fn *settable_ctx_params; +} /* EVP_KEM */; + int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c new file mode 100644 index 0000000000..6f0424075a --- /dev/null +++ b/crypto/evp/kem.c @@ -0,0 +1,359 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <stdlib.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include "internal/cryptlib.h" +#include "crypto/evp.h" +#include "internal/provider.h" +#include "evp_local.h" + +static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation) +{ + int ret = 0; + EVP_KEM *kem = NULL; + EVP_KEYMGMT *tmp_keymgmt = NULL; + void *provkey = NULL; + const char *supported_kem = NULL; + + if (ctx == NULL || ctx->keytype == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = operation; + + /* + * Ensure that the key is provided, either natively, or as a cached export. + */ + tmp_keymgmt = ctx->keymgmt; + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (provkey == NULL + || !EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + EVP_KEYMGMT_free(ctx->keymgmt); + ctx->keymgmt = tmp_keymgmt; + + if (ctx->keymgmt->query_operation_name != NULL) + supported_kem = ctx->keymgmt->query_operation_name(OSSL_OP_KEM); + + /* + * If we didn't get a supported kem, assume there is one with the + * same name as the key type. + */ + if (supported_kem == NULL) + supported_kem = ctx->keytype; + + kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery); + if (kem == NULL + || (EVP_KEYMGMT_provider(ctx->keymgmt) != EVP_KEM_provider(kem))) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + + ctx->op.encap.kem = kem; + ctx->op.encap.kemprovctx = kem->newctx(ossl_provider_ctx(kem->prov)); + if (ctx->op.encap.kemprovctx == NULL) { + /* The provider key can stay in the cache */ + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + + switch (operation) { + case EVP_PKEY_OP_ENCAPSULATE: + if (kem->encapsulate_init == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = kem->encapsulate_init(ctx->op.encap.kemprovctx, provkey); + break; + case EVP_PKEY_OP_DECAPSULATE: + if (kem->decapsulate_init == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = kem->decapsulate_init(ctx->op.encap.kemprovctx, provkey); + break; + default: + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + + if (ret > 0) + return 1; + err: + if (ret <= 0) { + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = EVP_PKEY_OP_UNDEFINED; + } + return ret; +} + +int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx) +{ + return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE); +} + +int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + unsigned char *secret, size_t *secretlen) +{ + if (ctx == NULL) + return 0; + + if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) { + EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.encap.kemprovctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (out != NULL && secret == NULL) + return 0; + + return ctx->op.encap.kem->encapsulate(ctx->op.encap.kemprovctx, + out, outlen, secret, secretlen); +} + +int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx) +{ + return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE); +} + +int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, + unsigned char *secret, size_t *secretlen, + const unsigned char *in, size_t inlen) +{ + if (ctx == NULL + || (in == NULL || inlen == 0) + || (secret == NULL && secretlen == NULL)) + return 0; + + if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) { + EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.encap.kemprovctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + return ctx->op.encap.kem->decapsulate(ctx->op.encap.kemprovctx, + secret, secretlen, in, inlen); +} + +static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov) +{ + EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM)); + + if (kem == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + kem->lock = CRYPTO_THREAD_lock_new(); + if (kem->lock == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(kem); + return NULL; + } + kem->prov = prov; + ossl_provider_up_ref(prov); + kem->refcnt = 1; + + return kem; +} + +static void *evp_kem_from_dispatch(int name_id, const OSSL_DISPATCH *fns, + OSSL_PROVIDER *prov) +{ + EVP_KEM *kem = NULL; + int ctxfncnt = 0, encfncnt = 0, decfncnt = 0; + int gparamfncnt = 0, sparamfncnt = 0; + + if ((kem = evp_kem_new(prov)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + goto err; + } + + kem->name_id = name_id; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_KEM_NEWCTX: + if (kem->newctx != NULL) + break; + kem->newctx = OSSL_FUNC_kem_newctx(fns); + ctxfncnt++; + break; + case OSSL_FUNC_KEM_ENCAPSULATE_INIT: + if (kem->encapsulate_init != NULL) + break; + kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns); + encfncnt++; + break; + case OSSL_FUNC_KEM_ENCAPSULATE: + if (kem->encapsulate != NULL) + break; + kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns); + encfncnt++; + break; + case OSSL_FUNC_KEM_DECAPSULATE_INIT: + if (kem->decapsulate_init != NULL) + break; + kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns); + decfncnt++; + break; + case OSSL_FUNC_KEM_DECAPSULATE: + if (kem->decapsulate != NULL) + break; + kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns); + decfncnt++; + break; + case OSSL_FUNC_KEM_FREECTX: + if (kem->freectx != NULL) + break; + kem->freectx = OSSL_FUNC_kem_freectx(fns); + ctxfncnt++; + break; + case OSSL_FUNC_KEM_DUPCTX: + if (kem->dupctx != NULL) + break; + kem->dupctx = OSSL_FUNC_kem_dupctx(fns); + break; + case OSSL_FUNC_KEM_GET_CTX_PARAMS: + if (kem->get_ctx_params != NULL) + break; + kem->get_ctx_params + = OSSL_FUNC_kem_get_ctx_params(fns); + gparamfncnt++; + break; + case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS: + if (kem->gettable_ctx_params != NULL) + break; + kem->gettable_ctx_params + = OSSL_FUNC_kem_gettable_ctx_params(fns); + gparamfncnt++; + break; + case OSSL_FUNC_KEM_SET_CTX_PARAMS: + if (kem->set_ctx_params != NULL) + break; + kem->set_ctx_params + = OSSL_FUNC_kem_set_ctx_params(fns); + sparamfncnt++; + break; + case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS: + if (kem->settable_ctx_params != NULL) + break; + kem->settable_ctx_params + = OSSL_FUNC_kem_settable_ctx_params(fns); + sparamfncnt++; + break; + } + } + if (ctxfncnt != 2 + || (encfncnt != 0 && encfncnt != 2) + || (decfncnt != 0 && decfncnt != 2) + || (encfncnt != 2 && decfncnt != 2) + || (gparamfncnt != 0 && gparamfncnt != 2) + || (sparamfncnt != 0 && sparamfncnt != 2)) { + /* + * In order to be a consistent set of functions we must have at least + * a set of context functions (newctx and freectx) as well as a pair of + * "kem" functions: (encapsulate_init, encapsulate) or + * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are + * optional, but if one of them is present then the other one must also + * be present. The same applies to get_ctx_params and + * gettable_ctx_params. The dupctx function is optional. + */ + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); + goto err; + } + + return kem; + err: + EVP_KEM_free(kem); + return NULL; +} + +void EVP_KEM_free(EVP_KEM *kem) +{ + if (kem != NULL) { + int i; + + CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock); + if (i > 0) + return; + ossl_provider_free(kem->prov); + CRYPTO_THREAD_lock_free(kem->lock); + OPENSSL_free(kem); + } +} + +int EVP_KEM_up_ref(EVP_KEM *kem) +{ + int ref = 0; + + CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock); + return 1; +} + +OSSL_PROVIDER *EVP_KEM_provider(const EVP_KEM *kem) +{ + return kem->prov; +} + +EVP_KEM *EVP_KEM_fetch(OPENSSL_CTX *ctx, const char *algorithm, + const char *properties) +{ + return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties, + evp_kem_from_dispatch, + (int (*)(void *))EVP_KEM_up_ref, + (void (*)(void *))EVP_KEM_free); +} + +int EVP_KEM_is_a(const EVP_KEM *kem, const char *name) +{ + return evp_is_a(kem->prov, kem->name_id, NULL, name); +} + +int EVP_KEM_number(const EVP_KEM *kem) +{ + return kem->name_id; +} + +void EVP_KEM_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(EVP_KEM *kem, void *arg), + void *arg) +{ + evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg, + evp_kem_from_dispatch, + (void (*)(void *))EVP_KEM_free); +} + + +void EVP_KEM_names_do_all(const EVP_KEM *kem, + void (*fn)(const char *name, void *data), + void *data) +{ + if (kem->prov != NULL) + evp_names_do_all(kem->prov, kem->name_id, fn, data); +} diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 38f42eca7d..fcd7266975 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -148,7 +148,9 @@ static int evp_pkey_ctx_state(EVP_PKEY_CTX *ctx) || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) && ctx->op.ciph.ciphprovctx != NULL) || (EVP_PKEY_CTX_IS_GEN_OP(ctx) - && ctx->op.keymgmt.genctx != NULL)) + && ctx->op.keymgmt.genctx != NULL) + || (EVP_PKEY_CTX_IS_KEM_OP(ctx) + && ctx->op.encap.kemprovctx != NULL)) return EVP_PKEY_STATE_PROVIDER; return EVP_PKEY_STATE_LEGACY; @@ -396,7 +398,14 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) EVP_KEYEXCH_free(ctx->op.kex.exchange); ctx->op.kex.exchprovctx = NULL; ctx->op.kex.exchange = NULL; - } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { + } else if (EVP_PKEY_CTX_IS_KEM_OP(ctx)) { + if (ctx->op.encap.kemprovctx != NULL && ctx->op.encap.kem != NULL) + ctx->op.encap.kem->freectx(ctx->op.encap.kemprovctx); + EVP_KEM_free(ctx->op.encap.kem); + ctx->op.encap.kemprovctx = NULL; + ctx->op.encap.kem = NULL; + } + else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { if (ctx->op.ciph.ciphprovctx != NULL && ctx->op.ciph.cipher != NULL) ctx->op.ciph.cipher->freectx(ctx->op.ciph.ciphprovctx); EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher); @@ -559,6 +568,26 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) } return rctx; } + } else if (EVP_PKEY_CTX_IS_KEM_OP(pctx)) { + if (pctx->op.encap.kem != NULL) { + rctx->op.encap.kem = pctx->op.encap.kem; + if (!EVP_KEM_up_ref(rctx->op.encap.kem)) { + OPENSSL_free(rctx); + return NULL; + } + } + if (pctx->op.encap.kemprovctx != NULL) { + if (!ossl_assert(pctx->op.encap.kem != NULL)) + return NULL; + rctx->op.encap.kemprovctx + = pctx->op.encap.kem->dupctx(pctx->op.encap.kemprovctx); + if (rctx->op.encap.kemprovctx == NULL) { + EVP_KEM_free(rctx->op.encap.kem); + OPENSSL_free(rctx); + return NULL; + } + return rctx; + } } rctx->pmeth = pctx->pmeth; @@ -659,6 +688,12 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) && ctx->keymgmt->gen_set_params != NULL) return evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx, params); + if (EVP_PKEY_CTX_IS_KEM_OP(ctx) + && ctx->op.encap.kemprovctx != NULL + && ctx->op.encap.kem != NULL + && ctx->op.encap.kem->set_ctx_params != NULL) + return ctx->op.encap.kem->set_ctx_params(ctx->op.encap.kemprovctx, + params); return 0; } @@ -682,6 +717,12 @@ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) && ctx->op.ciph.cipher->get_ctx_params != NULL) return ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.ciphprovctx, params); + if (EVP_PKEY_CTX_IS_KEM_OP(ctx) + && ctx->op.encap.kemprovctx != NULL + && ctx->op.encap.kem != NULL + && ctx->op.encap.kem->get_ctx_params != NULL) + return ctx->op.encap.kem->get_ctx_params(ctx->op.encap.kemprovctx, + params); return 0; } @@ -710,6 +751,12 @@ const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx) EVP_ASYM_CIPHER_provider(ctx->op.ciph.cipher)); return ctx->op.ciph.cipher->gettable_ctx_params(provctx); } + if (EVP_PKEY_CTX_IS_KEM_OP(ctx) + && ctx->op.encap.kem != NULL + && ctx->op.encap.kem->gettable_ctx_params != NULL) { + provctx = ossl_provider_ctx(EVP_KEM_provider(ctx->op.encap.kem)); + return ctx->op.encap.kem->gettable_ctx_params(provctx); + } return NULL; } @@ -740,7 +787,12 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) if (EVP_PKEY_CTX_IS_GEN_OP(ctx) && ctx->keymgmt != NULL) return EVP_KEYMGMT_gen_settable_params(ctx->keymgmt); - + if (EVP_PKEY_CTX_IS_KEM_OP(ctx) + && ctx->op.encap.kem != NULL + && ctx->op.encap.kem->settable_ctx_params != NULL) { + provctx = ossl_provider_ctx(EVP_KEM_provider(ctx->op.encap.kem)); + return ctx->op.encap.kem->settable_ctx_params(provctx); + } return NULL; } @@ -1096,6 +1148,24 @@ int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key, key, keylen); } +int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op) +{ + OSSL_PARAM params[2], *p = params; + + if (ctx == NULL || op == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE); + return 0; + } + if (!EVP_PKEY_CTX_IS_KEM_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION, + (char *)op, 0); + *p = OSSL_PARAM_construct_end(); + return EVP_PKEY_CTX_set_params(ctx, params); +} + int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len) { OSSL_PARAM params[2], *p = params; diff --git a/doc/man3/EVP_KEM_free.pod b/doc/man3/EVP_KEM_free.pod new file mode 100644 index 0000000000..0e3ca12ae3 --- /dev/null +++ b/doc/man3/EVP_KEM_free.pod @@ -0,0 +1,82 @@ +=pod + +=head1 NAME + +EVP_KEM_fetch, EVP_KEM_free, EVP_KEM_up_ref, +EVP_KEM_number, EVP_KEM_is_a, EVP_KEM_provider, +EVP_KEM_do_all_provided, EVP_KEM_names_do_all +- Functions to manage EVP_KEM algorithm objects + +=head1 SYNOPSIS + + #include <openssl/evp.h> + + EVP_KEM *EVP_KEM_fetch(OPENSSL_CTX *ctx, const char *algorithm, + const char *properties); + void EVP_KEM_free(EVP_KEM *kem); + int EVP_KEM_up_ref(EVP_KEM *kem); + int EVP_KEM_number(const EVP_KEM *kem); + int EVP_KEM_is_a(const EVP_KEM *kem, const char *name); + OSSL_PROVIDER *EVP_KEM_provider(const EVP_KEM *kem); + void EVP_KEM_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(EVP_KEM *kem, void *arg), void *arg); + void EVP_KEM_names_do_all(const EVP_KEM *kem, + void (*fn)(const char *name, void *data), void *data); + +=head1 DESCRIPTION + +EVP_KEM_fetch() fetches the implementation for the given B<algorithm> from any +provider offering it, within the criteria given by the B<properties> and in the +scope of the given library context B<ctx> (see L<OPENSSL_CTX(3)>). The algorithm +will be one offering functions for performing asymmetric kem related tasks such +as key encapsulation and decapsulation. +See L<provider(7)/Fetching algorithms> for further information. + +The returned value must eventually be freed with EVP_KEM_free(). + +EVP_KEM_free() decrements the reference count for the B<EVP_KEM> structure. +Typically this structure will have been obtained from an earlier call to +EVP_KEM_fetch(). If the reference count drops to 0 then the structure is freed. + +EVP_KEM_up_ref() increments the reference count for an B<EVP_KEM> structure. + +EVP_KEM_is_a() returns 1 if I<kem> is an implementation of an +algorithm that's identifiable with I<name>, otherwise 0. + +EVP_KEM_provider() returns the provider that I<kem> was fetched from. + +EVP_KEM_do_all_provided() traverses all EVP_KEMs implemented by all activated +providers in the given library context I<libctx>, and for each of the +implementations, calls the given function I<fn> with the implementation method +and the given I<arg> as argument. + +EVP_KEM_number() returns the internal dynamic number assigned to I<kem>. + +EVP_KEM_names_do_all() traverses all names for I<kem>, and calls I<fn> with +each name and I<data>. + +=head1 RETURN VALUES + +EVP_KEM_fetch() returns a pointer to an B<EVP_KEM> for success or B<NULL> for +failure. + +EVP_KEM_up_ref() returns 1 for success or 0 otherwise. + +=head1 SEE ALSO + +L<provider(7)/Fetching algorithms>, L<OSSL_PROVIDER(3)> + +=head1 HISTORY + +The functions described here were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 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 +L<https://www.openssl.org/source/license.html>. + +=cut diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index 794ad2053a..e5c187d950 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -67,7 +67,8 @@ EVP_PKEY_CTX_set_ecdh_kdf_outlen, EVP_PKEY_CTX_get_ecdh_kdf_outlen, EVP_PKEY_CTX_set0_ecdh_kdf_ukm, EVP_PKEY_CTX_get0_ecdh_kdf_ukm, -EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len +EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len, +EVP_PKEY_CTX_set_kem_op - algorithm specific control operations =head1 SYNOPSIS @@ -91,6 +92,8 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name); int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen); + int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op); + #include <openssl/rsa.h> int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad); @@ -606,6 +609,12 @@ memory for further calls to EVP_PKEY_CTX_get1_id(). EVP_PKEY_CTX_get1_id() returns the previously set ID value to caller in I<id>. The caller should allocate adequate memory space for the I<id> before calling EVP_PKEY_CTX_get1_id(). +EVP_PKEY_CTX_set_kem_op() sets the KEM operation to run. This can be set after +EVP_PKEY_encapsulate_init() or EVP_PKEY_decapsulate_init() to select the +kem operation. RSA is the only key type that supports encapsulation currently, +and as there is no default operation for the RSA type, this function must be +called before EVP_PKEY_encapsulate() or EVP_PKEY_decapsulate(). + =head1 RETURN VALUES All other functions described on this page return a positive value for success @@ -623,6 +632,8 @@ L<EVP_PKEY_verify(3)>, L<EVP_PKEY_verify_recover(3)>, L<EVP_PKEY_derive(3)>, L<EVP_PKEY_keygen(3)> +L<EVP_PKEY_encapsulate(3)> +L<EVP_PKEY_decapsulate(3)> =head1 HISTORY diff --git a/doc/man3/EVP_PKEY_decapsulate.pod b/doc/man3/EVP_PKEY_decapsulate.pod new file mode 100644 index 0000000000..7dd47a1e58 --- /dev/null +++ b/doc/man3/EVP_PKEY_decapsulate.pod @@ -0,0 +1,99 @@ +=pod + +=head1 NAME + +EVP_PKEY_decapsulate_init, EVP_PKEY_decapsulate +- Key decapsulation using a private key algorithm + +=head1 SYNOPSIS + + #include <openssl/evp.h> + + int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, + unsigned char *secret, size_t *secretlen, + const unsigned char *wrapped, size_t wrappedlen); + +=head1 DESCRIPTION + +The EVP_PKEY_decapsulate_init() function initializes a private key algorithm +context I<ctx> for a decapsulation operation. + +The EVP_PKEY_decapsulate() function performs a private key decapsulation +operation using I<ctx>. The data to be decapsulated is specified using the +I<wrapped> and I<wrappedlen> parameters. +If I<secret> is I<NULL> then the maximum size of the output secret buffer +is written to the I<*secretlen> parameter. If I<secret> is not B<NULL> and the +call is successful then the decapsulated secret data is written to I<secret> and +the amount of data written to I<secretlen>. + +=head1 NOTES + +After the call to EVP_PKEY_decapsulate_init() algorithm specific parameters +for the operation may be set using L<EVP_PKEY_CTX_set_params(3)>. There are no +settable parameters currently. + +=head1 RETURN VALUES + +EVP_PKEY_decapsulate_init() and EVP_PKEY_decapsulate() return 1 for +success and 0 or a negative value for failure. In particular a return value of -2 +indicates the operation is not supported by the private key algorithm. + +=head1 EXAMPLES + +Decapsulate data using RSA: + + #include <openssl/evp.h> + + /* + * NB: assumes rsa_priv_key is an RSA private key, + * and that in, inlen are already set up to contain encapsulated data. + */ + + EVP_PKEY_CTX *ctx = NULL; + size_t secretlen = 0; + unsigned char *secret = NULL;; + + ctx = EVP_PKEY_CTX_new_from_pkey(libctx, rsa_priv_key, NULL); + if (ctx = NULL) + /* Error */ + if (EVP_PKEY_decapsulate_init(ctx) <= 0) + /* Error */ + + /* Set the mode - only 'RSASVE' is currently supported */ + if (EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE") <= 0) + /* Error */ + + /* Determine buffer length */ + if (EVP_PKEY_decapsulate(ctx, NULL, &secretlen, in, inlen) <= 0) + /* Error */ + + secret = OPENSSL_malloc(secretlen); + if (secret == NULL) + /* malloc failure */ + + /* Decapsulated secret data is secretlen bytes long */ + if (EVP_PKEY_decapsulaterctx, secret, &secretlen, in, inlen) <= 0) + /* Error */ + + +=head1 SEE ALSO + +L<EVP_PKEY_CTX_new(3)>, +L<EVP_PKEY_encapsulate(3)>, +L<EVP_KEM-RSA(7)>, + +=head1 HISTORY + +These functions were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 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 +L<https://www.openssl.org/source/license.html>. + +=cut diff --git a/doc/man3/EVP_PKEY_encapsulate.pod b/doc/man3/EVP_PKEY_encapsulate.pod new file mode 100644 index 0000000000..0e911f71cf --- /dev/null +++ b/doc/man3/EVP_PKEY_encapsulate.pod @@ -0,0 +1,101 @@ +=pod + +=head1 NAME + +EVP_PKEY_encapsulate_init, EVP_PKEY_encapsulate +- Key encapsulation using a public key algorithm + +=head1 SYNOPSIS + + #include <openssl/evp.h> + + int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + unsigned char *genkey, size_t *genkeylen); + +=head1 DESCRIPTION + +The EVP_PKEY_encapsulate_init() function initializes a public key algorithm +context I<ctx> for an encapsulation operation. + +The EVP_PKEY_encapsulate() function performs a public key encapsulation +operation using I<ct |