From 8a2b5bc8139146fce78897c1a6d75a3c8cc558ac Mon Sep 17 00:00:00 2001 From: Michael Baentsch <57787676+baentsch@users.noreply.github.com> Date: Sat, 3 Aug 2024 07:20:31 +0200 Subject: [PATCH] Update codeowners (#458) * prepare fixing #457 Signed-off-by: Michael Baentsch <57787676+baentsch@users.noreply.github.com> * refactor for proper code ownership tagging Signed-off-by: Michael Baentsch <57787676+baentsch@users.noreply.github.com> --------- Signed-off-by: Michael Baentsch <57787676+baentsch@users.noreply.github.com> --- .github/CODEOWNERS | 7 ++ CONTRIBUTING.md | 6 ++ README.md | 20 ++-- oqsprov/oqs_hyb_kem.c | 239 ++++++++++++++++++++++++++++++++++++++++++ oqsprov/oqs_kem.c | 230 +--------------------------------------- 5 files changed, 263 insertions(+), 239 deletions(-) create mode 100644 oqsprov/oqs_hyb_kem.c diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 47ce0da9..af0eb104 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,10 @@ # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners * @baentsch +/oqsprov/oqs_hyb_kem.c @bhess +/oqs-template/generate.yml @baentsch @bhess @feventura +/CMakeLists.txt @baentsch @thb-sb +/.circleci/config.yml @baentsch @thb-sb +/.github/workflows @baentsch @thb-sb +/oqsprov/oqs_sig.c @baentsch @feventura +/scripts/oqsprovider-pkcs12gen.sh @iyanmv diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea800111..da002df2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,6 +22,12 @@ All PRs should move to "Ready for Review" stage only if all CI tests pass (are g The OQS core team is happy to provide feedback also to Draft PRs in order to improve them before the final "Review" stage. +### CODEOWNERS + +This file is used to track which contributors are most well suited for reviewing +changes to specific sections, typically because they authored part or all of them. +Thus, any PR should revisit and possibly update this file suitably. + ### Coding style This project has adopted the [OpenSSL coding style](https://www.openssl.org/policies/technical/coding-style.html). diff --git a/README.md b/README.md index 6ba2bab9..8df044be 100644 --- a/README.md +++ b/README.md @@ -178,16 +178,16 @@ Team Contributors to the `oqsprovider` include: -- Michael Baentsch -- Christian Paquin -- Richard Levitte -- Basil Hess -- Julian Segeth -- Alex Zaslavsky -- Will Childs-Klein -- Thomas Bailleux -- Felipe Ventura -- Iyán Méndez Veiga +- Michael Baentsch (initial author and maintainer; responsible for all code except as listed per specific contributions below) +- Christian Paquin (original OpenSSL111 OQS integrator) +- Richard Levitte (OpenSSL provider wizard and initial `cmake` setup) +- Basil Hess (hybrid KEM integration & pqcrystals/mayo OID management) +- Julian Segeth (some memory management improvements) +- Alex Zaslavsky (improvements on OpenSSL integration) +- Will Childs-Klein (improvements on Kyber hybrid OIDs) +- Thomas Bailleux (many build, CI and usage improvements for different platforms) +- Felipe Ventura (composite sig integration and OID management) +- Iyán Méndez Veiga (PKCS#12 testing) History ------- diff --git a/oqsprov/oqs_hyb_kem.c b/oqsprov/oqs_hyb_kem.c new file mode 100644 index 00000000..98c87d1d --- /dev/null +++ b/oqsprov/oqs_hyb_kem.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: Apache-2.0 AND MIT + +/* + * OQS OpenSSL 3 provider + * + * Hybrid KEM code. + * + */ + +static OSSL_FUNC_kem_encapsulate_fn oqs_hyb_kem_encaps; +static OSSL_FUNC_kem_decapsulate_fn oqs_hyb_kem_decaps; + +/// EVP KEM functions + +static int oqs_evp_kem_encaps_keyslot(void *vpkemctx, unsigned char *ct, + size_t *ctlen, unsigned char *secret, + size_t *secretlen, int keyslot) +{ + int ret = OQS_SUCCESS, ret2 = 0; + + const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; + const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; + + size_t pubkey_kexlen = 0; + size_t kexDeriveLen = 0, pkeylen = 0; + unsigned char *pubkey_kex = pkemctx->kem->comp_pubkey[keyslot]; + + // Free at err: + EVP_PKEY_CTX *ctx = NULL, *kgctx = NULL; + ; + EVP_PKEY *pkey = NULL, *peerpk = NULL; + unsigned char *ctkex_encoded = NULL; + + pubkey_kexlen = evp_ctx->evp_info->length_public_key; + kexDeriveLen = evp_ctx->evp_info->kex_length_secret; + + *ctlen = pubkey_kexlen; + *secretlen = kexDeriveLen; + + if (ct == NULL || secret == NULL) { + OQS_KEM_PRINTF3("EVP KEM returning lengths %ld and %ld\n", *ctlen, + *secretlen); + return 1; + } + + peerpk = EVP_PKEY_new(); + ON_ERR_SET_GOTO(!peerpk, ret, -1, err); + + ret2 = EVP_PKEY_copy_parameters(peerpk, evp_ctx->keyParam); + ON_ERR_SET_GOTO(ret2 <= 0, ret, -1, err); + + ret2 = EVP_PKEY_set1_encoded_public_key(peerpk, pubkey_kex, pubkey_kexlen); + ON_ERR_SET_GOTO(ret2 <= 0, ret, -1, err); + + kgctx = EVP_PKEY_CTX_new(evp_ctx->keyParam, NULL); + ON_ERR_SET_GOTO(!kgctx, ret, -1, err); + + ret2 = EVP_PKEY_keygen_init(kgctx); + ON_ERR_SET_GOTO(ret2 != 1, ret, -1, err); + + ret2 = EVP_PKEY_keygen(kgctx, &pkey); + ON_ERR_SET_GOTO(ret2 != 1, ret, -1, err); + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + ON_ERR_SET_GOTO(!ctx, ret, -1, err); + + ret = EVP_PKEY_derive_init(ctx); + ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); + + ret = EVP_PKEY_derive_set_peer(ctx, peerpk); + ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); + + ret = EVP_PKEY_derive(ctx, secret, &kexDeriveLen); + ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); + + pkeylen = EVP_PKEY_get1_encoded_public_key(pkey, &ctkex_encoded); + ON_ERR_SET_GOTO(pkeylen <= 0 || !ctkex_encoded || pkeylen != pubkey_kexlen, + ret, -1, err); + + memcpy(ct, ctkex_encoded, pkeylen); + +err: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_CTX_free(kgctx); + EVP_PKEY_free(pkey); + EVP_PKEY_free(peerpk); + OPENSSL_free(ctkex_encoded); + return ret; +} + +static int oqs_evp_kem_decaps_keyslot(void *vpkemctx, unsigned char *secret, + size_t *secretlen, + const unsigned char *ct, size_t ctlen, + int keyslot) +{ + OQS_KEM_PRINTF("OQS KEM provider called: oqs_hyb_kem_decaps\n"); + + int ret = OQS_SUCCESS, ret2 = 0; + const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; + const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; + + size_t pubkey_kexlen = evp_ctx->evp_info->length_public_key; + size_t kexDeriveLen = evp_ctx->evp_info->kex_length_secret; + unsigned char *privkey_kex = pkemctx->kem->comp_privkey[keyslot]; + size_t privkey_kexlen = evp_ctx->evp_info->length_private_key; + + // Free at err: + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL, *peerpkey = NULL; + + *secretlen = kexDeriveLen; + if (secret == NULL) + return 1; + + if (evp_ctx->evp_info->raw_key_support) { + pkey = EVP_PKEY_new_raw_private_key(evp_ctx->evp_info->keytype, NULL, + privkey_kex, privkey_kexlen); + ON_ERR_SET_GOTO(!pkey, ret, -10, err); + } else { + pkey = d2i_AutoPrivateKey(&pkey, (const unsigned char **)&privkey_kex, + privkey_kexlen); + ON_ERR_SET_GOTO(!pkey, ret, -2, err); + } + + peerpkey = EVP_PKEY_new(); + ON_ERR_SET_GOTO(!peerpkey, ret, -3, err); + + ret2 = EVP_PKEY_copy_parameters(peerpkey, evp_ctx->keyParam); + ON_ERR_SET_GOTO(ret2 <= 0, ret, -4, err); + + ret2 = EVP_PKEY_set1_encoded_public_key(peerpkey, ct, pubkey_kexlen); + ON_ERR_SET_GOTO(ret2 <= 0 || !peerpkey, ret, -5, err); + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + ON_ERR_SET_GOTO(!ctx, ret, -6, err); + + ret = EVP_PKEY_derive_init(ctx); + ON_ERR_SET_GOTO(ret <= 0, ret, -7, err); + ret = EVP_PKEY_derive_set_peer(ctx, peerpkey); + ON_ERR_SET_GOTO(ret <= 0, ret, -8, err); + + ret = EVP_PKEY_derive(ctx, secret, &kexDeriveLen); + ON_ERR_SET_GOTO(ret <= 0, ret, -9, err); + +err: + EVP_PKEY_free(peerpkey); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +/// Hybrid KEM functions + +static int oqs_hyb_kem_encaps(void *vpkemctx, unsigned char *ct, size_t *ctlen, + unsigned char *secret, size_t *secretlen) +{ + int ret = OQS_SUCCESS; + const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; + size_t secretLen0 = 0, secretLen1 = 0; + size_t ctLen0 = 0, ctLen1 = 0; + unsigned char *ct0, *ct1, *secret0, *secret1; + + ret = oqs_evp_kem_encaps_keyslot(vpkemctx, NULL, &ctLen0, NULL, &secretLen0, + 0); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + ret = oqs_qs_kem_encaps_keyslot(vpkemctx, NULL, &ctLen1, NULL, &secretLen1, + 1); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + + *ctlen = ctLen0 + ctLen1; + *secretlen = secretLen0 + secretLen1; + + if (ct == NULL || secret == NULL) { + OQS_KEM_PRINTF3("HYB KEM returning lengths %ld and %ld\n", *ctlen, + *secretlen); + return 1; + } + + ct0 = ct; + ct1 = ct + ctLen0; + secret0 = secret; + secret1 = secret + secretLen0; + + ret = oqs_evp_kem_encaps_keyslot(vpkemctx, ct0, &ctLen0, secret0, + &secretLen0, 0); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + + ret = oqs_qs_kem_encaps_keyslot(vpkemctx, ct1, &ctLen1, secret1, + &secretLen1, 1); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + +err: + return ret; +} + +static int oqs_hyb_kem_decaps(void *vpkemctx, unsigned char *secret, + size_t *secretlen, const unsigned char *ct, + size_t ctlen) +{ + int ret = OQS_SUCCESS; + const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; + const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; + const OQS_KEM *qs_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_qs_ctx.kem; + + size_t secretLen0 = 0, secretLen1 = 0; + size_t ctLen0 = 0, ctLen1 = 0; + const unsigned char *ct0, *ct1; + unsigned char *secret0, *secret1; + + ret = oqs_evp_kem_decaps_keyslot(vpkemctx, NULL, &secretLen0, NULL, 0, 0); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + ret = oqs_qs_kem_decaps_keyslot(vpkemctx, NULL, &secretLen1, NULL, 0, 1); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + + *secretlen = secretLen0 + secretLen1; + + if (secret == NULL) + return 1; + + ctLen0 = evp_ctx->evp_info->length_public_key; + ctLen1 = qs_ctx->length_ciphertext; + + ON_ERR_SET_GOTO(ctLen0 + ctLen1 != ctlen, ret, OQS_ERROR, err); + + ct0 = ct; + ct1 = ct + ctLen0; + secret0 = secret; + secret1 = secret + secretLen0; + + ret = oqs_evp_kem_decaps_keyslot(vpkemctx, secret0, &secretLen0, ct0, + ctLen0, 0); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + ret = oqs_qs_kem_decaps_keyslot(vpkemctx, secret1, &secretLen1, ct1, ctLen1, + 1); + ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); + +err: + return ret; +} diff --git a/oqsprov/oqs_kem.c b/oqsprov/oqs_kem.c index a56150d4..a1e27b4d 100644 --- a/oqsprov/oqs_kem.c +++ b/oqsprov/oqs_kem.c @@ -37,9 +37,7 @@ static OSSL_FUNC_kem_newctx_fn oqs_kem_newctx; static OSSL_FUNC_kem_encapsulate_init_fn oqs_kem_encaps_init; static OSSL_FUNC_kem_encapsulate_fn oqs_qs_kem_encaps; -static OSSL_FUNC_kem_encapsulate_fn oqs_hyb_kem_encaps; static OSSL_FUNC_kem_decapsulate_fn oqs_qs_kem_decaps; -static OSSL_FUNC_kem_decapsulate_fn oqs_hyb_kem_decaps; static OSSL_FUNC_kem_freectx_fn oqs_kem_freectx; /* @@ -218,233 +216,7 @@ static int oqs_qs_kem_decaps(void *vpkemctx, unsigned char *out, size_t *outlen, return oqs_qs_kem_decaps_keyslot(vpkemctx, out, outlen, in, inlen, 0); } -/// EVP KEM functions - -static int oqs_evp_kem_encaps_keyslot(void *vpkemctx, unsigned char *ct, - size_t *ctlen, unsigned char *secret, - size_t *secretlen, int keyslot) -{ - int ret = OQS_SUCCESS, ret2 = 0; - - const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; - const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; - - size_t pubkey_kexlen = 0; - size_t kexDeriveLen = 0, pkeylen = 0; - unsigned char *pubkey_kex = pkemctx->kem->comp_pubkey[keyslot]; - - // Free at err: - EVP_PKEY_CTX *ctx = NULL, *kgctx = NULL; - ; - EVP_PKEY *pkey = NULL, *peerpk = NULL; - unsigned char *ctkex_encoded = NULL; - - pubkey_kexlen = evp_ctx->evp_info->length_public_key; - kexDeriveLen = evp_ctx->evp_info->kex_length_secret; - - *ctlen = pubkey_kexlen; - *secretlen = kexDeriveLen; - - if (ct == NULL || secret == NULL) { - OQS_KEM_PRINTF3("EVP KEM returning lengths %ld and %ld\n", *ctlen, - *secretlen); - return 1; - } - - peerpk = EVP_PKEY_new(); - ON_ERR_SET_GOTO(!peerpk, ret, -1, err); - - ret2 = EVP_PKEY_copy_parameters(peerpk, evp_ctx->keyParam); - ON_ERR_SET_GOTO(ret2 <= 0, ret, -1, err); - - ret2 = EVP_PKEY_set1_encoded_public_key(peerpk, pubkey_kex, pubkey_kexlen); - ON_ERR_SET_GOTO(ret2 <= 0, ret, -1, err); - - kgctx = EVP_PKEY_CTX_new(evp_ctx->keyParam, NULL); - ON_ERR_SET_GOTO(!kgctx, ret, -1, err); - - ret2 = EVP_PKEY_keygen_init(kgctx); - ON_ERR_SET_GOTO(ret2 != 1, ret, -1, err); - - ret2 = EVP_PKEY_keygen(kgctx, &pkey); - ON_ERR_SET_GOTO(ret2 != 1, ret, -1, err); - - ctx = EVP_PKEY_CTX_new(pkey, NULL); - ON_ERR_SET_GOTO(!ctx, ret, -1, err); - - ret = EVP_PKEY_derive_init(ctx); - ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); - - ret = EVP_PKEY_derive_set_peer(ctx, peerpk); - ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); - - ret = EVP_PKEY_derive(ctx, secret, &kexDeriveLen); - ON_ERR_SET_GOTO(ret <= 0, ret, -1, err); - - pkeylen = EVP_PKEY_get1_encoded_public_key(pkey, &ctkex_encoded); - ON_ERR_SET_GOTO(pkeylen <= 0 || !ctkex_encoded || pkeylen != pubkey_kexlen, - ret, -1, err); - - memcpy(ct, ctkex_encoded, pkeylen); - -err: - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_CTX_free(kgctx); - EVP_PKEY_free(pkey); - EVP_PKEY_free(peerpk); - OPENSSL_free(ctkex_encoded); - return ret; -} - -static int oqs_evp_kem_decaps_keyslot(void *vpkemctx, unsigned char *secret, - size_t *secretlen, - const unsigned char *ct, size_t ctlen, - int keyslot) -{ - OQS_KEM_PRINTF("OQS KEM provider called: oqs_hyb_kem_decaps\n"); - - int ret = OQS_SUCCESS, ret2 = 0; - const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; - const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; - - size_t pubkey_kexlen = evp_ctx->evp_info->length_public_key; - size_t kexDeriveLen = evp_ctx->evp_info->kex_length_secret; - unsigned char *privkey_kex = pkemctx->kem->comp_privkey[keyslot]; - size_t privkey_kexlen = evp_ctx->evp_info->length_private_key; - - // Free at err: - EVP_PKEY_CTX *ctx = NULL; - EVP_PKEY *pkey = NULL, *peerpkey = NULL; - - *secretlen = kexDeriveLen; - if (secret == NULL) - return 1; - - if (evp_ctx->evp_info->raw_key_support) { - pkey = EVP_PKEY_new_raw_private_key(evp_ctx->evp_info->keytype, NULL, - privkey_kex, privkey_kexlen); - ON_ERR_SET_GOTO(!pkey, ret, -10, err); - } else { - pkey = d2i_AutoPrivateKey(&pkey, (const unsigned char **)&privkey_kex, - privkey_kexlen); - ON_ERR_SET_GOTO(!pkey, ret, -2, err); - } - - peerpkey = EVP_PKEY_new(); - ON_ERR_SET_GOTO(!peerpkey, ret, -3, err); - - ret2 = EVP_PKEY_copy_parameters(peerpkey, evp_ctx->keyParam); - ON_ERR_SET_GOTO(ret2 <= 0, ret, -4, err); - - ret2 = EVP_PKEY_set1_encoded_public_key(peerpkey, ct, pubkey_kexlen); - ON_ERR_SET_GOTO(ret2 <= 0 || !peerpkey, ret, -5, err); - - ctx = EVP_PKEY_CTX_new(pkey, NULL); - ON_ERR_SET_GOTO(!ctx, ret, -6, err); - - ret = EVP_PKEY_derive_init(ctx); - ON_ERR_SET_GOTO(ret <= 0, ret, -7, err); - ret = EVP_PKEY_derive_set_peer(ctx, peerpkey); - ON_ERR_SET_GOTO(ret <= 0, ret, -8, err); - - ret = EVP_PKEY_derive(ctx, secret, &kexDeriveLen); - ON_ERR_SET_GOTO(ret <= 0, ret, -9, err); - -err: - EVP_PKEY_free(peerpkey); - EVP_PKEY_free(pkey); - EVP_PKEY_CTX_free(ctx); - return ret; -} - -/// Hybrid KEM functions - -static int oqs_hyb_kem_encaps(void *vpkemctx, unsigned char *ct, size_t *ctlen, - unsigned char *secret, size_t *secretlen) -{ - int ret = OQS_SUCCESS; - const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; - size_t secretLen0 = 0, secretLen1 = 0; - size_t ctLen0 = 0, ctLen1 = 0; - unsigned char *ct0, *ct1, *secret0, *secret1; - - ret = oqs_evp_kem_encaps_keyslot(vpkemctx, NULL, &ctLen0, NULL, &secretLen0, - 0); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - ret = oqs_qs_kem_encaps_keyslot(vpkemctx, NULL, &ctLen1, NULL, &secretLen1, - 1); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - - *ctlen = ctLen0 + ctLen1; - *secretlen = secretLen0 + secretLen1; - - if (ct == NULL || secret == NULL) { - OQS_KEM_PRINTF3("HYB KEM returning lengths %ld and %ld\n", *ctlen, - *secretlen); - return 1; - } - - ct0 = ct; - ct1 = ct + ctLen0; - secret0 = secret; - secret1 = secret + secretLen0; - - ret = oqs_evp_kem_encaps_keyslot(vpkemctx, ct0, &ctLen0, secret0, - &secretLen0, 0); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - - ret = oqs_qs_kem_encaps_keyslot(vpkemctx, ct1, &ctLen1, secret1, - &secretLen1, 1); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - -err: - return ret; -} - -static int oqs_hyb_kem_decaps(void *vpkemctx, unsigned char *secret, - size_t *secretlen, const unsigned char *ct, - size_t ctlen) -{ - int ret = OQS_SUCCESS; - const PROV_OQSKEM_CTX *pkemctx = (PROV_OQSKEM_CTX *)vpkemctx; - const OQSX_EVP_CTX *evp_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_evp_ctx; - const OQS_KEM *qs_ctx = pkemctx->kem->oqsx_provider_ctx.oqsx_qs_ctx.kem; - - size_t secretLen0 = 0, secretLen1 = 0; - size_t ctLen0 = 0, ctLen1 = 0; - const unsigned char *ct0, *ct1; - unsigned char *secret0, *secret1; - - ret = oqs_evp_kem_decaps_keyslot(vpkemctx, NULL, &secretLen0, NULL, 0, 0); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - ret = oqs_qs_kem_decaps_keyslot(vpkemctx, NULL, &secretLen1, NULL, 0, 1); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - - *secretlen = secretLen0 + secretLen1; - - if (secret == NULL) - return 1; - - ctLen0 = evp_ctx->evp_info->length_public_key; - ctLen1 = qs_ctx->length_ciphertext; - - ON_ERR_SET_GOTO(ctLen0 + ctLen1 != ctlen, ret, OQS_ERROR, err); - - ct0 = ct; - ct1 = ct + ctLen0; - secret0 = secret; - secret1 = secret + secretLen0; - - ret = oqs_evp_kem_decaps_keyslot(vpkemctx, secret0, &secretLen0, ct0, - ctLen0, 0); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - ret = oqs_qs_kem_decaps_keyslot(vpkemctx, secret1, &secretLen1, ct1, ctLen1, - 1); - ON_ERR_SET_GOTO(ret <= 0, ret, OQS_ERROR, err); - -err: - return ret; -} +#include "oqs_hyb_kem.c" #define MAKE_KEM_FUNCTIONS(alg) \ const OSSL_DISPATCH oqs_##alg##_kem_functions[] = { \