/*
* Copyright 2022-2023 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/evp.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/proverr.h>
#include "internal/nelem.h"
#include "testutil.h"
#define TEST_KEM_ENCAP 0
#define TEST_KEM_DECAP 1
#define TEST_KEM_ENCAP_DECAP 2
#define TEST_TYPE_AUTH 0
#define TEST_TYPE_NOAUTH 1
#define TEST_TYPE_AUTH_NOAUTH 2
#define TEST_KEYTYPE_P256 0
#define TEST_KEYTYPE_X25519 1
#define TEST_KEYTYPES_P256_X25519 2
static OSSL_LIB_CTX *libctx = NULL;
static OSSL_PROVIDER *nullprov = NULL;
static OSSL_PROVIDER *libprov = NULL;
static OSSL_PARAM opparam[2];
static EVP_PKEY *rkey[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
static EVP_PKEY_CTX *rctx[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
#include "dhkem_test.inc"
/* Perform encapsulate KAT's */
static int test_dhkem_encapsulate(int tstid)
{
int ret = 0;
EVP_PKEY *rpub = NULL, *spriv = NULL;
const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
TEST_note("Test %s %s Decapsulate", t->curve,
t->spriv != NULL ? "Auth" : "");
if (!TEST_ptr(rpub = new_raw_public_key(t->curve, t->rpub, t->rpublen)))
goto err;
if (t->spriv != NULL) {
if (!TEST_ptr(spriv = new_raw_private_key(t->curve,
t->spriv, t->sprivlen,
t->spub, t->spublen)))
goto err;
}
ret = do_encap(t, rpub, spriv);
err:
EVP_PKEY_free(spriv);
EVP_PKEY_free(rpub);
return ret;
}
/* Perform decapsulate KAT's */
static int test_dhkem_decapsulate(int tstid)
{
int ret = 0;
EVP_PKEY *rpriv = NULL, *spub = NULL;
const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
TEST_note("Test %s %s Decapsulate", t->curve, t->spub != NULL ? "Auth" : "");
if (!TEST_ptr(rpriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
t->rpub, t->rpublen)))
goto err;
if (t->spub != NULL) {
if (!TEST_ptr(spub = new_raw_public_key(t->curve, t->spub, t->spublen)))
goto err;
}
ret = do_decap(t, rpriv, spub);
err:
EVP_PKEY_free(spub);
EVP_PKEY_free(rpriv);
return ret;
}
/* Test that there are settables and they have correct data types */
static int test_settables(int tstid)
{
EVP_PKEY_CTX *ctx = rctx[tstid];
const OSSL_PARAM *settableparams;
const OSSL_PARAM *p;
return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
&& TEST_ptr(settableparams = EVP_PKEY_CTX_settable_params(ctx))
&& TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
OSSL_KEM_PARAM_OPERATION))
&& TEST_uint_eq(p->data_type, OSSL_PARAM_UTF8_STRING)
&& TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
OSSL_KEM_PARAM_IKME))
&& TEST_uint_eq(p->data_type, OSSL_PARAM_OCTET_STRING);
}
/* Test initing multiple times passes */
static int test_init_multiple(int tstid)
{
EVP_PKEY_CTX *ctx = rctx[tstid];
return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
&& TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
&& TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
&& TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1);
}
/* Fail is various bad inputs are passed to the derivekey (keygen) operation */
static int test_ec_dhkem_derivekey_fail(void)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
OSSL_PARAM params[3];
EVP_PKEY_CTX *genctx = NULL;
const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[0];
BIGNUM *priv = NULL;
/* Check non nist curve fails */
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
"secp256k1", 0);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
(char *)t->ikm, t->ikmlen);
params[2] = OSSL_PARAM_construct_end();
if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
|| !TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
|| !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params),