Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <openssl/evp.h>
     11 #include <openssl/core_names.h>
     12 #include <openssl/param_build.h>
     13 #include <openssl/proverr.h>
     14 #include "internal/nelem.h"
     15 #include "testutil.h"
     16 
     17 #define TEST_KEM_ENCAP 0
     18 #define TEST_KEM_DECAP 1
     19 #define TEST_KEM_ENCAP_DECAP 2
     20 
     21 #define TEST_TYPE_AUTH 0
     22 #define TEST_TYPE_NOAUTH 1
     23 #define TEST_TYPE_AUTH_NOAUTH 2
     24 
     25 #define TEST_KEYTYPE_P256 0
     26 #define TEST_KEYTYPE_X25519 1
     27 #define TEST_KEYTYPES_P256_X25519 2
     28 
     29 static OSSL_LIB_CTX *libctx = NULL;
     30 static OSSL_PROVIDER *nullprov = NULL;
     31 static OSSL_PROVIDER *libprov = NULL;
     32 static OSSL_PARAM opparam[2];
     33 static EVP_PKEY *rkey[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
     34 static EVP_PKEY_CTX *rctx[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
     35 
     36 #include "dhkem_test.inc"
     37 
     38 /* Perform encapsulate KAT's */
     39 static int test_dhkem_encapsulate(int tstid)
     40 {
     41     int ret = 0;
     42     EVP_PKEY *rpub = NULL, *spriv = NULL;
     43     const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
     44 
     45     TEST_note("Test %s %s Decapsulate", t->curve,
     46         t->spriv != NULL ? "Auth" : "");
     47 
     48     if (!TEST_ptr(rpub = new_raw_public_key(t->curve, t->rpub, t->rpublen)))
     49         goto err;
     50 
     51     if (t->spriv != NULL) {
     52         if (!TEST_ptr(spriv = new_raw_private_key(t->curve,
     53                           t->spriv, t->sprivlen,
     54                           t->spub, t->spublen)))
     55             goto err;
     56     }
     57     ret = do_encap(t, rpub, spriv);
     58 err:
     59     EVP_PKEY_free(spriv);
     60     EVP_PKEY_free(rpub);
     61     return ret;
     62 }
     63 
     64 /* Perform decapsulate KAT's */
     65 static int test_dhkem_decapsulate(int tstid)
     66 {
     67     int ret = 0;
     68     EVP_PKEY *rpriv = NULL, *spub = NULL;
     69     const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
     70 
     71     TEST_note("Test %s %s Decapsulate", t->curve, t->spub != NULL ? "Auth" : "");
     72 
     73     if (!TEST_ptr(rpriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
     74                       t->rpub, t->rpublen)))
     75         goto err;
     76     if (t->spub != NULL) {
     77         if (!TEST_ptr(spub = new_raw_public_key(t->curve, t->spub, t->spublen)))
     78             goto err;
     79     }
     80     ret = do_decap(t, rpriv, spub);
     81 err:
     82     EVP_PKEY_free(spub);
     83     EVP_PKEY_free(rpriv);
     84     return ret;
     85 }
     86 
     87 /* Test that there are settables and they have correct data types */
     88 static int test_settables(int tstid)
     89 {
     90     EVP_PKEY_CTX *ctx = rctx[tstid];
     91     const OSSL_PARAM *settableparams;
     92     const OSSL_PARAM *p;
     93 
     94     return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
     95         && TEST_ptr(settableparams = EVP_PKEY_CTX_settable_params(ctx))
     96         && TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
     97                         OSSL_KEM_PARAM_OPERATION))
     98         && TEST_uint_eq(p->data_type, OSSL_PARAM_UTF8_STRING)
     99         && TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
    100                         OSSL_KEM_PARAM_IKME))
    101         && TEST_uint_eq(p->data_type, OSSL_PARAM_OCTET_STRING);
    102 }
    103 
    104 /* Test initing multiple times passes */
    105 static int test_init_multiple(int tstid)
    106 {
    107     EVP_PKEY_CTX *ctx = rctx[tstid];
    108 
    109     return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
    110         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
    111         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
    112         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1);
    113 }
    114 
    115 /* Fail is various bad inputs are passed to the derivekey (keygen) operation */
    116 static int test_ec_dhkem_derivekey_fail(void)
    117 {
    118     int ret = 0;
    119     EVP_PKEY *pkey = NULL;
    120     OSSL_PARAM params[3];
    121     EVP_PKEY_CTX *genctx = NULL;
    122     const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[0];
    123     BIGNUM *priv = NULL;
    124 
    125     /* Check non nist curve fails */
    126     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
    127         "secp256k1", 0);
    128     params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
    129         (char *)t->ikm, t->ikmlen);
    130     params[2] = OSSL_PARAM_construct_end();
    131 
    132     if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
    133         || !TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
    134         || !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
    135         || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
    136         goto err;
    137 
    138     /* Fail if curve is not one of P-256, P-384 or P-521 */
    139     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
    140         "P-224", 0);
    141     params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
    142         (char *)t->ikm, t->ikmlen);
    143     params[2] = OSSL_PARAM_construct_end();
    144     if (!TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
    145         || !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
    146         || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
    147         goto err;
    148 
    149     /* Fail if ikm len is too small*/
    150     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
    151         "P-256", 0);
    152     params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
    153         (char *)t->ikm, t->ikmlen - 1);
    154     params[2] = OSSL_PARAM_construct_end();
    155     if (!TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
    156         || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
    157         goto err;
    158 
    159     ret = 1;
    160 err:
    161     BN_free(priv);
    162     EVP_PKEY_free(pkey);
    163     EVP_PKEY_CTX_free(genctx);
    164     return ret;
    165 }
    166 
    167 /* Succeed even if the operation parameter is not set */
    168 static int test_no_operation_set(int tstid)
    169 {
    170     EVP_PKEY_CTX *ctx = rctx[tstid];
    171     const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
    172     size_t len = 0;
    173 
    174     return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
    175         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &len, NULL, NULL), 1)
    176         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
    177         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, &len,
    178                            t->expected_enc,
    179                            t->expected_enclen),
    180             1);
    181 }
    182 
    183 /* Fail if the ikm is too small */
    184 static int test_ikm_small(int tstid)
    185 {
    186     unsigned char tmp[16] = { 0 };
    187     unsigned char secret[256];
    188     unsigned char enc[256];
    189     size_t secretlen = sizeof(secret);
    190     size_t enclen = sizeof(enc);
    191     OSSL_PARAM params[3];
    192     EVP_PKEY_CTX *ctx = rctx[tstid];
    193 
    194     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
    195         OSSL_KEM_PARAM_OPERATION_DHKEM,
    196         0);
    197     params[1] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
    198         tmp, sizeof(tmp));
    199     params[2] = OSSL_PARAM_construct_end();
    200 
    201     return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, params), 1)
    202         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
    203                            secret, &secretlen),
    204             0);
    205 }
    206 
    207 /* Fail if buffers lengths are too small to hold returned data */
    208 static int test_input_size_small(int tstid)
    209 {
    210     int ret = 0;
    211     unsigned char sec[256];
    212     unsigned char enc[256];
    213     size_t seclen = sizeof(sec);
    214     size_t enclen = sizeof(enc);
    215     EVP_PKEY_CTX *ctx = rctx[tstid];
    216 
    217     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
    218         || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &enclen,
    219                             NULL, &seclen),
    220             1))
    221         goto err;
    222 
    223     /* buffer too small for enc */
    224     enclen--;
    225     if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen),
    226             0))
    227         goto err;
    228     enclen++;
    229     /* buffer too small for secret */
    230     seclen--;
    231     if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen), 0))
    232         goto err;
    233     seclen++;
    234     if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
    235         goto err;
    236     /* buffer too small for decapsulate secret */
    237     seclen--;
    238     if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0))
    239         goto err;
    240     seclen++;
    241     /* incorrect enclen passed to decap  */
    242     enclen--;
    243     ret = TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0);
    244 err:
    245     return ret;
    246 }
    247 
    248 /* Fail if the auth key has a different curve */
    249 static int test_ec_auth_key_curve_mismatch(void)
    250 {
    251     int ret = 0;
    252     EVP_PKEY *auth = NULL;
    253 
    254     if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-521")))
    255         return 0;
    256 
    257     ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[0], auth, opparam), 0);
    258     EVP_PKEY_free(auth);
    259     return ret;
    260 }
    261 
    262 /* Fail if the auth key has a different key type to the recipient */
    263 static int test_auth_key_type_mismatch(int tstid)
    264 {
    265     int id1 = tstid;
    266     int id2 = !tstid;
    267 
    268     return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[id1],
    269                            rkey[id2], opparam),
    270         0);
    271 }
    272 
    273 static int test_ec_invalid_private_key(void)
    274 {
    275     int ret = 0;
    276     EVP_PKEY *priv = NULL;
    277     EVP_PKEY_CTX *ctx = NULL;
    278     const TEST_ENCAPDATA *t = &ec_encapdata[0];
    279     static const unsigned char order[] = {
    280         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
    281         0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
    282         0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
    283     };
    284 
    285     ret = TEST_ptr(priv = new_raw_private_key("P-256", order, sizeof(order),
    286                        t->rpub, t->rpublen))
    287         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
    288         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0);
    289     EVP_PKEY_free(priv);
    290     EVP_PKEY_CTX_free(ctx);
    291     return ret;
    292 }
    293 
    294 static int test_ec_public_key_infinity(void)
    295 {
    296     int ret = 0;
    297     EVP_PKEY *key = NULL;
    298     EVP_PKEY_CTX *keyctx = NULL;
    299     unsigned char s[256];
    300     unsigned char e[256];
    301     size_t slen = sizeof(s);
    302     size_t elen = sizeof(e);
    303     unsigned char tmp[1] = { 0 }; /* The encoding for an EC point at infinity */
    304     EVP_PKEY_CTX *ctx = rctx[0];
    305     const TEST_ENCAPDATA *t = &ec_encapdata[0];
    306 
    307     ret = TEST_ptr(key = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
    308                        tmp, sizeof(tmp)))
    309         && TEST_ptr(keyctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
    310         /* Fail if the recipient public key is invalid */
    311         && TEST_int_eq(EVP_PKEY_encapsulate_init(keyctx, opparam), 1)
    312         && TEST_int_eq(EVP_PKEY_encapsulate(keyctx, e, &elen, s, &slen), 0)
    313         /* Fail the decap if the recipient public key is invalid */
    314         && TEST_int_eq(EVP_PKEY_decapsulate_init(keyctx, opparam), 1)
    315         && TEST_int_eq(EVP_PKEY_decapsulate(keyctx, s, &slen,
    316                            t->expected_enc,
    317                            t->expected_enclen),
    318             0)
    319         /* Fail if the auth key has a bad public key */
    320         && TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, key, opparam), 1)
    321         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, e, &elen, s, &slen), 0);
    322 
    323     EVP_PKEY_free(key);
    324     EVP_PKEY_CTX_free(keyctx);
    325     return ret;
    326 }
    327 
    328 /* Test incorrectly passing NULL values fail */
    329 static int test_null_params(int tstid)
    330 {
    331     EVP_PKEY_CTX *ctx = rctx[tstid];
    332     const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
    333 
    334     /* auth_encap/decap init must be passed a non NULL value */
    335     return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, NULL, opparam), 0)
    336         && TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, NULL, opparam), 0)
    337         /* Check decap fails if NULL params are passed */
    338         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
    339         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, NULL,
    340                            t->expected_enc,
    341                            t->expected_enclen),
    342             0)
    343         /* Check encap fails if NULL params are passed */
    344         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
    345         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, NULL,
    346                            NULL, NULL),
    347             0);
    348 }
    349 
    350 static int test_set_params(int tstid)
    351 {
    352     int ret = 0;
    353     EVP_PKEY_CTX *ctx = rctx[tstid];
    354     OSSL_PARAM badparams[4];
    355     int val = 1;
    356 
    357     /* wrong data type for operation param */
    358     badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_OPERATION, &val);
    359     badparams[1] = OSSL_PARAM_construct_end();
    360     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
    361         goto err;
    362     /* unknown string used for the operation param */
    363     badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
    364         "unknown_op", 0);
    365     badparams[1] = OSSL_PARAM_construct_end();
    366     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
    367         goto err;
    368 
    369     /* NULL string set for the operation param */
    370     badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
    371         NULL, 0);
    372     badparams[1] = OSSL_PARAM_construct_end();
    373     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
    374         goto err;
    375 
    376     /* wrong data type for ikme param */
    377     badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_IKME, &val);
    378     badparams[1] = OSSL_PARAM_construct_end();
    379     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
    380         goto err;
    381 
    382     /* Setting the ikme to NULL is allowed */
    383     badparams[0] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME, NULL, 0);
    384     badparams[1] = OSSL_PARAM_construct_end();
    385     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1))
    386         goto err;
    387 
    388     /* Test that unknown params are ignored */
    389     badparams[0] = OSSL_PARAM_construct_int("unknownparam", &val);
    390     badparams[1] = OSSL_PARAM_construct_end();
    391     ret = TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1);
    392 err:
    393     return ret;
    394 }
    395 
    396 /*
    397  * ECX keys autogen the public key if a private key is loaded,
    398  * So this test passes for ECX, but fails for EC
    399  */
    400 static int test_nopublic(int tstid)
    401 {
    402     int ret = 0;
    403     EVP_PKEY_CTX *ctx = NULL;
    404     EVP_PKEY *priv = NULL;
    405     int encap = ((tstid & 1) == 0);
    406     int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
    407     const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
    408     int expected = (keytype == TEST_KEYTYPE_X25519);
    409 
    410     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
    411     if (!TEST_ptr(priv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
    412                       NULL, 0)))
    413         goto err;
    414     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL)))
    415         goto err;
    416 
    417     if (encap) {
    418         if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), expected))
    419             goto err;
    420     } else {
    421         if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), expected))
    422             goto err;
    423     }
    424     if (expected == 0
    425         && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NOT_A_PUBLIC_KEY))
    426         goto err;
    427     ret = 1;
    428 err:
    429     EVP_PKEY_free(priv);
    430     EVP_PKEY_CTX_free(ctx);
    431     return ret;
    432 }
    433 
    434 /* Test that not setting the auth public key fails the auth encap/decap init */
    435 static int test_noauthpublic(int tstid)
    436 {
    437     int ret = 0;
    438     EVP_PKEY *auth = NULL;
    439     int encap = ((tstid & 1) == 0);
    440     int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
    441     const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
    442     EVP_PKEY_CTX *ctx = rctx[keytype];
    443     int expected = (keytype == TEST_KEYTYPE_X25519);
    444 
    445     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
    446     if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv,
    447                       t->rprivlen, NULL, expected)))
    448         goto err;
    449 
    450     if (encap) {
    451         if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
    452                              opparam),
    453                 expected))
    454             goto err;
    455     } else {
    456         if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth,
    457                              opparam),
    458                 expected))
    459             goto err;
    460     }
    461     if (expected == 0
    462         && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
    463             PROV_R_NOT_A_PUBLIC_KEY))
    464         goto err;
    465     ret = 1;
    466 err:
    467     EVP_PKEY_free(auth);
    468     return ret;
    469 }
    470 
    471 /* EC specific tests */
    472 
    473 /* Perform EC DHKEM KATs */
    474 static int test_ec_dhkem_derivekey(int tstid)
    475 {
    476     int ret = 0;
    477     EVP_PKEY *pkey = NULL;
    478     OSSL_PARAM params[3];
    479     EVP_PKEY_CTX *genctx = NULL;
    480     const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[tstid];
    481     unsigned char pubkey[133];
    482     unsigned char privkey[66];
    483     size_t pubkeylen = 0, privkeylen = 0;
    484     BIGNUM *priv = NULL;
    485 
    486     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
    487         (char *)t->curvename, 0);
    488     params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
    489         (char *)t->ikm, t->ikmlen);
    490     params[2] = OSSL_PARAM_construct_end();
    491 
    492     ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
    493         && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
    494         && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
    495         && TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 1)
    496         && TEST_true(EVP_PKEY_get_octet_string_param(pkey,
    497             OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
    498             pubkey, sizeof(pubkey), &pubkeylen))
    499         && TEST_true(EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
    500             &priv))
    501         && TEST_int_gt(privkeylen = BN_bn2bin(priv, privkey), 0)
    502         && TEST_int_le(privkeylen, sizeof(privkey))
    503         && TEST_mem_eq(privkey, privkeylen, t->priv, t->privlen)
    504         && TEST_mem_eq(pubkey, pubkeylen, t->pub, t->publen);
    505 
    506     BN_free(priv);
    507     EVP_PKEY_free(pkey);
    508     EVP_PKEY_CTX_free(genctx);
    509     return ret;
    510 }
    511 
    512 /*
    513  * Test that encapsulation uses a random seed if the ikm is not specified,
    514  * and verify that the shared secret matches the decapsulate result.
    515  */
    516 static int test_ec_noikme(int tstid)
    517 {
    518     int ret = 0, auth = 0;
    519     EVP_PKEY_CTX *ctx = NULL;
    520     EVP_PKEY *recip = NULL;
    521     EVP_PKEY *sender_auth = NULL;
    522     unsigned char sender_secret[256];
    523     unsigned char recip_secret[256];
    524     unsigned char sender_pub[256];
    525     size_t sender_secretlen = sizeof(sender_secret);
    526     size_t recip_secretlen = sizeof(recip_secret);
    527     size_t sender_publen = sizeof(sender_pub);
    528     const char *curve;
    529     int sz = OSSL_NELEM(dhkem_supported_curves);
    530     const char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
    531 
    532     if (tstid >= sz) {
    533         auth = 1;
    534         tstid -= sz;
    535     }
    536     curve = dhkem_supported_curves[tstid];
    537     TEST_note("testing encap/decap of curve %s%s\n", curve,
    538         auth ? " with auth" : "");
    539 
    540     if (curve[0] == 'X') {
    541         if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, curve))
    542             || (auth
    543                 && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
    544                                  curve))))
    545             goto err;
    546     } else {
    547         if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
    548             || (auth
    549                 && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
    550                                  "EC", curve))))
    551             goto err;
    552     }
    553 
    554     ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recip, NULL))
    555         && (sender_auth == NULL
    556             || TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, sender_auth,
    557                                NULL),
    558                 1))
    559         && (sender_auth != NULL
    560             || TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1))
    561         && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
    562         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, sender_pub, &sender_publen,
    563                            sender_secret, &sender_secretlen),
    564             1)
    565         && (sender_auth == NULL
    566             || TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, sender_auth,
    567                                NULL),
    568                 1))
    569         && (sender_auth != NULL
    570             || TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1))
    571         && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
    572         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, recip_secret, &recip_secretlen,
    573                            sender_pub, sender_publen),
    574             1)
    575         && TEST_mem_eq(recip_secret, recip_secretlen,
    576             sender_secret, sender_secretlen);
    577 err:
    578     EVP_PKEY_CTX_free(ctx);
    579     EVP_PKEY_free(sender_auth);
    580     EVP_PKEY_free(recip);
    581     return ret;
    582 }
    583 
    584 /* Test encap/decap init fail if the curve is invalid */
    585 static int do_ec_curve_failtest(const char *curve)
    586 {
    587     int ret;
    588     EVP_PKEY *key = NULL;
    589     EVP_PKEY_CTX *ctx = NULL;
    590 
    591     ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
    592         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
    593         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
    594         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
    595     EVP_PKEY_free(key);
    596     EVP_PKEY_CTX_free(ctx);
    597     return ret;
    598 }
    599 
    600 static int test_ec_curve_nonnist(void)
    601 {
    602     return do_ec_curve_failtest("secp256k1");
    603 }
    604 
    605 static int test_ec_curve_unsupported(void)
    606 {
    607     return do_ec_curve_failtest("P-224");
    608 }
    609 
    610 /* Test that passing a bad recipient public EC key fails during encap/decap */
    611 static int test_ec_badpublic(int tstid)
    612 {
    613     int ret = 0;
    614     EVP_PKEY *recippriv = NULL;
    615     EVP_PKEY_CTX *ctx = NULL;
    616     unsigned char secret[256];
    617     unsigned char pub[256];
    618     size_t secretlen = sizeof(secret);
    619     int encap = ((tstid & 1) == 0);
    620     const TEST_ENCAPDATA *t = &ec_encapdata[0];
    621 
    622     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
    623     /* Set the recipient public key to the point at infinity */
    624     pub[0] = 0;
    625     if (!TEST_ptr(recippriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
    626                       pub, 1)))
    627         goto err;
    628 
    629     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recippriv, NULL)))
    630         goto err;
    631 
    632     if (encap) {
    633         unsigned char enc[256];
    634         size_t enclen = sizeof(enc);
    635 
    636         if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1))
    637             goto err;
    638         if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
    639                              secret, &secretlen),
    640                 0))
    641             goto err;
    642     } else {
    643         if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
    644             goto err;
    645         if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
    646                              t->expected_enc,
    647                              t->expected_enclen),
    648                 0))
    649             goto err;
    650     }
    651     if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
    652         goto err;
    653     ret = 1;
    654 err:
    655     EVP_PKEY_free(recippriv);
    656     EVP_PKEY_CTX_free(ctx);
    657     return ret;
    658 }
    659 
    660 static int test_ec_badauth(int tstid)
    661 {
    662     int ret = 0;
    663     EVP_PKEY *auth = NULL;
    664     unsigned char enc[256];
    665     unsigned char secret[256];
    666     unsigned char pub[256];
    667     size_t enclen = sizeof(enc);
    668     size_t secretlen = sizeof(secret);
    669     int encap = ((tstid & 1) == 0);
    670     const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
    671     EVP_PKEY_CTX *ctx = rctx[TEST_KEYTYPE_P256];
    672 
    673     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
    674     /* Set the auth public key to the point at infinity */
    675     pub[0] = 0;
    676     if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
    677                       pub, 1)))
    678         goto err;
    679     if (encap) {
    680         if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
    681                              opparam),
    682                 1)
    683             || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
    684                                 secret, &secretlen),
    685                 0))
    686             goto err;
    687     } else {
    688         if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth, opparam), 1)
    689             || !TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
    690                                 t->expected_enc,
    691                                 t->expected_enclen),
    692                 0))
    693             goto err;
    694     }
    695     if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
    696         goto err;
    697     ret = 1;
    698 err:
    699     EVP_PKEY_free(auth);
    700     return ret;
    701 }
    702 
    703 static int test_ec_invalid_decap_enc_buffer(void)
    704 {
    705     const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
    706     unsigned char enc[256];
    707     unsigned char secret[256];
    708     size_t secretlen = sizeof(secret);
    709     EVP_PKEY_CTX *ctx = rctx[0];
    710 
    711     memcpy(enc, t->expected_enc, t->expected_enclen);
    712     enc[0] = 0xFF;
    713 
    714     return TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
    715         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
    716                            enc, t->expected_enclen),
    717             0);
    718 }
    719 
    720 #ifndef OPENSSL_NO_ECX
    721 /* ECX specific tests */
    722 
    723 /* Perform ECX DHKEM KATs */
    724 static int test_ecx_dhkem_derivekey(int tstid)
    725 {
    726     int ret;
    727     OSSL_PARAM params[2];
    728     EVP_PKEY_CTX *genctx;
    729     EVP_PKEY *pkey = NULL;
    730     unsigned char pubkey[64];
    731     unsigned char privkey[64];
    732     unsigned char masked_priv[64];
    733     size_t pubkeylen = 0, privkeylen = 0;
    734     const TEST_DERIVEKEY_DATA *t = &ecx_derivekey_data[tstid];
    735 
    736     memcpy(masked_priv, t->priv, t->privlen);
    737     if (OPENSSL_strcasecmp(t->curvename, "X25519") == 0) {
    738         /*
    739          * The RFC test vector seems incorrect since it is not in serialized form,
    740          * So manually do the conversion here for now.
    741          */
    742         masked_priv[0] &= 248;
    743         masked_priv[t->privlen - 1] &= 127;
    744         masked_priv[t->privlen - 1] |= 64;
    745     } else {
    746         masked_priv[0] &= 252;
    747         masked_priv[t->privlen - 1] |= 128;
    748     }
    749 
    750     params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
    751         (char *)t->ikm, t->ikmlen);
    752     params[1] = OSSL_PARAM_construct_end();
    753 
    754     ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, t->curvename, NULL))
    755         && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
    756         && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
    757         && TEST_int_eq(EVP_PKEY_keygen(genctx, &pkey), 1)
    758         && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
    759                            OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
    760                            pubkey, sizeof(pubkey), &pubkeylen),
    761             1)
    762         && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
    763                            OSSL_PKEY_PARAM_PRIV_KEY,
    764                            privkey, sizeof(privkey), &privkeylen),
    765             1)
    766         && TEST_mem_eq(t->pub, t->publen, pubkey, pubkeylen)
    767         && TEST_mem_eq(masked_priv, t->privlen, privkey, privkeylen);
    768 
    769     EVP_PKEY_free(pkey);
    770     EVP_PKEY_CTX_free(genctx);
    771     return ret;
    772 }
    773 
    774 /* Fail if the auth key has a different curve */
    775 static int test_ecx_auth_key_curve_mismatch(void)
    776 {
    777     int ret = 0;
    778     EVP_PKEY *auth = NULL;
    779 
    780     if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "X448")))
    781         return 0;
    782 
    783     ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[TEST_KEYTYPE_X25519],
    784                           auth, opparam),
    785         0);
    786     EVP_PKEY_free(auth);
    787     return ret;
    788 }
    789 
    790 /* Fail if ED448 is used for DHKEM */
    791 static int test_ed_curve_unsupported(void)
    792 {
    793     int ret;
    794     EVP_PKEY *key = NULL;
    795     EVP_PKEY_CTX *ctx = NULL;
    796 
    797     ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "ED448"))
    798         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
    799         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
    800         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
    801     EVP_PKEY_free(key);
    802     EVP_PKEY_CTX_free(ctx);
    803     return ret;
    804 }
    805 #endif
    806 
    807 int setup_tests(void)
    808 {
    809     const char *prov_name = "default";
    810     char *config_file = NULL;
    811     char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
    812 
    813     if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
    814         return 0;
    815     opparam[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
    816         op, 0);
    817     opparam[1] = OSSL_PARAM_construct_end();
    818 
    819     /* Create P256 and X25519 keys and ctxs */
    820     if (!TEST_ptr(rkey[TEST_KEYTYPE_P256] = EVP_PKEY_Q_keygen(libctx, NULL,
    821                       "EC", "P-256")))
    822         goto err;
    823 #ifndef OPENSSL_NO_ECX
    824     if (!TEST_ptr(rkey[TEST_KEYTYPE_X25519] = EVP_PKEY_Q_keygen(libctx, NULL,
    825                       "X25519")))
    826         goto err;
    827 #endif
    828     if (!TEST_ptr(rctx[TEST_KEYTYPE_P256] = EVP_PKEY_CTX_new_from_pkey(libctx,
    829                       rkey[TEST_KEYTYPE_P256], NULL)))
    830         goto err;
    831 #ifndef OPENSSL_NO_ECX
    832     if (!TEST_ptr(rctx[TEST_KEYTYPE_X25519] = EVP_PKEY_CTX_new_from_pkey(libctx,
    833                       rkey[TEST_KEYTYPE_X25519], NULL)))
    834         goto err;
    835 #endif
    836 
    837     ADD_ALL_TESTS(test_dhkem_encapsulate, OSSL_NELEM(ec_encapdata));
    838     ADD_ALL_TESTS(test_dhkem_decapsulate, OSSL_NELEM(ec_encapdata));
    839 #ifndef OPENSSL_NO_ECX
    840     ADD_ALL_TESTS(test_settables, TEST_KEYTYPES_P256_X25519);
    841     ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPES_P256_X25519);
    842 
    843     ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPES_P256_X25519);
    844     ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPES_P256_X25519);
    845     ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPES_P256_X25519);
    846     ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPES_P256_X25519);
    847     ADD_ALL_TESTS(test_null_params, TEST_KEYTYPES_P256_X25519);
    848     ADD_ALL_TESTS(test_set_params, TEST_KEYTYPES_P256_X25519);
    849     ADD_ALL_TESTS(test_nopublic,
    850         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
    851     ADD_ALL_TESTS(test_noauthpublic,
    852         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
    853 #else
    854     ADD_ALL_TESTS(test_settables, TEST_KEYTYPE_P256);
    855     ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPE_P256);
    856 
    857     ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPE_P256);
    858     ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPE_P256);
    859     ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPE_P256);
    860     ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPE_P256);
    861     ADD_ALL_TESTS(test_null_params, TEST_KEYTYPE_P256);
    862     ADD_ALL_TESTS(test_set_params, TEST_KEYTYPE_P256);
    863     ADD_ALL_TESTS(test_nopublic,
    864         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
    865     ADD_ALL_TESTS(test_noauthpublic,
    866         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
    867 #endif
    868     /* EC Specific tests */
    869     ADD_ALL_TESTS(test_ec_dhkem_derivekey, OSSL_NELEM(ec_derivekey_data));
    870     ADD_ALL_TESTS(test_ec_noikme,
    871         TEST_TYPE_AUTH_NOAUTH * OSSL_NELEM(dhkem_supported_curves));
    872     ADD_TEST(test_ec_auth_key_curve_mismatch);
    873     ADD_TEST(test_ec_invalid_private_key);
    874     ADD_TEST(test_ec_dhkem_derivekey_fail);
    875     ADD_TEST(test_ec_curve_nonnist);
    876     ADD_TEST(test_ec_curve_unsupported);
    877     ADD_TEST(test_ec_invalid_decap_enc_buffer);
    878     ADD_TEST(test_ec_public_key_infinity);
    879     ADD_ALL_TESTS(test_ec_badpublic, TEST_KEM_ENCAP_DECAP);
    880     ADD_ALL_TESTS(test_ec_badauth, TEST_KEM_ENCAP_DECAP);
    881 
    882     /* ECX specific tests */
    883 #ifndef OPENSSL_NO_ECX
    884     ADD_ALL_TESTS(test_ecx_dhkem_derivekey, OSSL_NELEM(ecx_derivekey_data));
    885     ADD_TEST(test_ecx_auth_key_curve_mismatch);
    886     ADD_TEST(test_ed_curve_unsupported);
    887 #endif
    888     return 1;
    889 err:
    890     return 0;
    891 }
    892 
    893 void cleanup_tests(void)
    894 {
    895     EVP_PKEY_free(rkey[1]);
    896     EVP_PKEY_free(rkey[0]);
    897     EVP_PKEY_CTX_free(rctx[1]);
    898     EVP_PKEY_CTX_free(rctx[0]);
    899     OSSL_PROVIDER_unload(libprov);
    900     OSSL_LIB_CTX_free(libctx);
    901     OSSL_PROVIDER_unload(nullprov);
    902 }
    903