123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883 |
- /*
- * 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), 1)
- || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey),0))
- goto err;
- /* Fail if curve is not one of P-256, P-384 or P-521 */
- params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
- "P-224", 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_int_eq(EVP_PKEY_keygen_init(genctx), 1)
- || !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
- || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
- goto err;
- /* Fail if ikm len is too small*/
- params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
- "P-256", 0);
- params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
- (char *)t->ikm, t->ikmlen - 1);
- params[2] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
- || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
- goto err;
- ret = 1;
- err:
- BN_free(priv);
- EVP_PKEY_free(pkey);
- EVP_PKEY_CTX_free(genctx);
- return ret;
- }
- /* Fail if the operation parameter is not set */
- static int test_no_operation_set(int tstid)
- {
- EVP_PKEY_CTX *ctx = rctx[tstid];
- const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
- size_t len = 0;
- return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &len, NULL, NULL), -2)
- && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, &len,
- t->expected_enc,
- t->expected_enclen), -2);
- }
- /* Fail if the ikm is too small */
- static int test_ikm_small(int tstid)
- {
- unsigned char tmp[16] = { 0 };
- unsigned char secret[256];
- unsigned char enc[256];
- size_t secretlen = sizeof(secret);
- size_t enclen = sizeof(enc);
- OSSL_PARAM params[3];
- EVP_PKEY_CTX *ctx = rctx[tstid];
- params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
- OSSL_KEM_PARAM_OPERATION_DHKEM,
- 0);
- params[1] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
- tmp, sizeof(tmp));
- params[2] = OSSL_PARAM_construct_end();
- return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, params), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
- secret, &secretlen), 0);
- }
- /* Fail if buffers lengths are too small to hold returned data */
- static int test_input_size_small(int tstid)
- {
- int ret = 0;
- unsigned char sec[256];
- unsigned char enc[256];
- size_t seclen = sizeof(sec);
- size_t enclen = sizeof(enc);
- EVP_PKEY_CTX *ctx = rctx[tstid];
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
- || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &enclen,
- NULL, &seclen), 1))
- goto err;
- /* buffer too small for enc */
- enclen--;
- if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen),
- 0))
- goto err;
- enclen++;
- /* buffer too small for secret */
- seclen--;
- if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen), 0))
- goto err;
- seclen++;
- if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
- goto err;
- /* buffer too small for decapsulate secret */
- seclen--;
- if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0))
- goto err;
- seclen++;
- /* incorrect enclen passed to decap */
- enclen--;
- ret = TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0);
- err:
- return ret;
- }
- /* Fail if the auth key has a different curve */
- static int test_ec_auth_key_curve_mismatch(void)
- {
- int ret = 0;
- EVP_PKEY *auth = NULL;
- if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-521")))
- return 0;
- ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[0], auth, opparam), 0);
- EVP_PKEY_free(auth);
- return ret;
- }
- /* Fail if the auth key has a different key type to the recipient */
- static int test_auth_key_type_mismatch(int tstid)
- {
- int id1 = tstid;
- int id2 = !tstid;
- return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[id1],
- rkey[id2], opparam), 0);
- }
- static int test_ec_invalid_private_key(void)
- {
- int ret = 0;
- EVP_PKEY *priv = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- const TEST_ENCAPDATA *t = &ec_encapdata[0];
- static const unsigned char order[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
- 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
- };
- ret = TEST_ptr(priv = new_raw_private_key("P-256", order, sizeof(order),
- t->rpub, t->rpublen))
- && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
- && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0);
- EVP_PKEY_free(priv);
- EVP_PKEY_CTX_free(ctx);
- return ret;
- }
- static int test_ec_public_key_infinity(void)
- {
- int ret = 0;
- EVP_PKEY *key = NULL;
- EVP_PKEY_CTX *keyctx = NULL;
- unsigned char s[256];
- unsigned char e[256];
- size_t slen = sizeof(s);
- size_t elen = sizeof(e);
- unsigned char tmp[1] = { 0 }; /* The encoding for an EC point at infinity */
- EVP_PKEY_CTX *ctx = rctx[0];
- const TEST_ENCAPDATA *t = &ec_encapdata[0];
- ret = TEST_ptr(key = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
- tmp, sizeof(tmp)))
- && TEST_ptr(keyctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
- /* Fail if the recipient public key is invalid */
- && TEST_int_eq(EVP_PKEY_encapsulate_init(keyctx, opparam), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(keyctx, e, &elen, s, &slen), 0)
- /* Fail the decap if the recipient public key is invalid */
- && TEST_int_eq(EVP_PKEY_decapsulate_init(keyctx, opparam), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(keyctx, s, &slen,
- t->expected_enc,
- t->expected_enclen), 0)
- /* Fail if the auth key has a bad public key */
- && TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, key, opparam), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(ctx, e, &elen, s, &slen), 0);
- EVP_PKEY_free(key);
- EVP_PKEY_CTX_free(keyctx);
- return ret;
- }
- /* Test incorrectly passing NULL values fail */
- static int test_null_params(int tstid)
- {
- EVP_PKEY_CTX *ctx = rctx[tstid];
- const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
- /* auth_encap/decap init must be passed a non NULL value */
- return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, NULL, opparam), 0)
- && TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, NULL, opparam), 0)
- /* Check decap fails if NULL params are passed */
- && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, NULL,
- t->expected_enc,
- t->expected_enclen), 0)
- /* Check encap fails if NULL params are passed */
- && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, NULL,
- NULL, NULL), 0);
- }
- static int test_set_params(int tstid)
- {
- int ret = 0;
- EVP_PKEY_CTX *ctx = rctx[tstid];
- OSSL_PARAM badparams[4];
- int val = 1;
- /* wrong data type for operation param */
- badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_OPERATION, &val);
- badparams[1] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
- goto err;
- /* unknown string used for the operation param */
- badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
- "unknown_op", 0);
- badparams[1] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
- goto err;
- /* NULL string set for the operation param */
- badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
- NULL, 0);
- badparams[1] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
- goto err;
- /* wrong data type for ikme param */
- badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_IKME, &val);
- badparams[1] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
- goto err;
- /* Setting the ikme to NULL is allowed */
- badparams[0] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME, NULL, 0);
- badparams[1] = OSSL_PARAM_construct_end();
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1))
- goto err;
- /* Test that unknown params are ignored */
- badparams[0] = OSSL_PARAM_construct_int("unknownparam", &val);
- badparams[1] = OSSL_PARAM_construct_end();
- ret = TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1);
- err:
- return ret;
- }
- /*
- * ECX keys autogen the public key if a private key is loaded,
- * So this test passes for ECX, but fails for EC
- */
- static int test_nopublic(int tstid)
- {
- int ret = 0;
- EVP_PKEY_CTX *ctx = NULL;
- EVP_PKEY *priv = NULL;
- int encap = ((tstid & 1) == 0);
- int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
- const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
- int expected = (keytype == TEST_KEYTYPE_X25519);
- TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
- if (!TEST_ptr(priv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
- NULL, 0)))
- goto err;
- if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL)))
- goto err;
- if (encap) {
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), expected))
- goto err;
- } else {
- if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), expected))
- goto err;
- }
- if (expected == 0
- && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NOT_A_PUBLIC_KEY))
- goto err;
- ret = 1;
- err:
- EVP_PKEY_free(priv);
- EVP_PKEY_CTX_free(ctx);
- return ret;
- }
- /* Test that not setting the auth public key fails the auth encap/decap init */
- static int test_noauthpublic(int tstid)
- {
- int ret = 0;
- EVP_PKEY *auth = NULL;
- int encap = ((tstid & 1) == 0);
- int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
- const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
- EVP_PKEY_CTX *ctx = rctx[keytype];
- int expected = (keytype == TEST_KEYTYPE_X25519);
- TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
- if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv,
- t->rprivlen, NULL, expected)))
- goto err;
- if (encap) {
- if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
- opparam), expected))
- goto err;
- } else {
- if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth,
- opparam), expected))
- goto err;
- }
- if (expected == 0
- && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
- PROV_R_NOT_A_PUBLIC_KEY))
- goto err;
- ret = 1;
- err:
- EVP_PKEY_free(auth);
- return ret;
- }
- /* EC specific tests */
- /* Perform EC DHKEM KATs */
- static int test_ec_dhkem_derivekey(int tstid)
- {
- int ret = 0;
- EVP_PKEY *pkey = NULL;
- OSSL_PARAM params[3];
- EVP_PKEY_CTX *genctx = NULL;
- const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[tstid];
- unsigned char pubkey[133];
- unsigned char privkey[66];
- size_t pubkeylen = 0, privkeylen = 0;
- BIGNUM *priv = NULL;
- params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
- (char *)t->curvename, 0);
- params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
- (char *)t->ikm, t->ikmlen);
- params[2] = OSSL_PARAM_construct_end();
- ret = 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), 1)
- && TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 1)
- && TEST_true(EVP_PKEY_get_octet_string_param(pkey,
- OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
- pubkey, sizeof(pubkey), &pubkeylen))
- && TEST_true(EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
- &priv))
- && TEST_int_gt(privkeylen = BN_bn2bin(priv, privkey), 0)
- && TEST_int_le(privkeylen, sizeof(privkey))
- && TEST_mem_eq(privkey, privkeylen, t->priv, t->privlen)
- && TEST_mem_eq(pubkey, pubkeylen, t->pub, t->publen);
- BN_free(priv);
- EVP_PKEY_free(pkey);
- EVP_PKEY_CTX_free(genctx);
- return ret;
- }
- /*
- * Test that encapsulation uses a random seed if the ikm is not specified,
- * and verify that the shared secret matches the decapsulate result.
- */
- static int test_ec_noikme(int tstid)
- {
- int ret = 0, auth = 0;
- EVP_PKEY_CTX *ctx = NULL;
- EVP_PKEY *recip = NULL;
- EVP_PKEY *sender_auth = NULL;
- unsigned char sender_secret[256];
- unsigned char recip_secret[256];
- unsigned char sender_pub[256];
- size_t sender_secretlen = sizeof(sender_secret);
- size_t recip_secretlen = sizeof(recip_secret);
- size_t sender_publen = sizeof(sender_pub);
- const char *curve;
- int sz = OSSL_NELEM(dhkem_supported_curves);
- const char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
- if (tstid >= sz) {
- auth = 1;
- tstid -= sz;
- }
- curve = dhkem_supported_curves[tstid];
- TEST_note("testing encap/decap of curve %s%s\n", curve,
- auth ? " with auth" : "");
- if (curve[0] == 'X') {
- if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, curve))
- || (auth
- && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
- curve))))
- goto err;
- } else {
- if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
- || (auth
- && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
- "EC", curve))))
- goto err;
- }
- ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recip, NULL))
- && (sender_auth == NULL
- || TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, sender_auth,
- NULL), 1))
- && (sender_auth != NULL
- || TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1))
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(ctx, sender_pub, &sender_publen,
- sender_secret, &sender_secretlen), 1)
- && (sender_auth == NULL
- || TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, sender_auth,
- NULL), 1))
- && (sender_auth != NULL
- || TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1))
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(ctx, recip_secret, &recip_secretlen,
- sender_pub, sender_publen), 1)
- && TEST_mem_eq(recip_secret, recip_secretlen,
- sender_secret, sender_secretlen);
- err:
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(sender_auth);
- EVP_PKEY_free(recip);
- return ret;
- }
- /* Test encap/decap init fail if the curve is invalid */
- static int do_ec_curve_failtest(const char *curve)
- {
- int ret;
- EVP_PKEY *key = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
- && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
- && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
- && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
- EVP_PKEY_free(key);
- EVP_PKEY_CTX_free(ctx);
- return ret;
- }
- static int test_ec_curve_nonnist(void)
- {
- return do_ec_curve_failtest("secp256k1");
- }
- static int test_ec_curve_unsupported(void)
- {
- return do_ec_curve_failtest("P-224");
- }
- /* Test that passing a bad recipient public EC key fails during encap/decap */
- static int test_ec_badpublic(int tstid)
- {
- int ret = 0;
- EVP_PKEY *recippriv = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- unsigned char secret[256];
- unsigned char pub[256];
- size_t secretlen = sizeof(secret);
- int encap = ((tstid & 1) == 0);
- const TEST_ENCAPDATA *t = &ec_encapdata[0];
- TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
- /* Set the recipient public key to the point at infinity */
- pub[0] = 0;
- if (!TEST_ptr(recippriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
- pub, 1)))
- goto err;
- if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recippriv, NULL)))
- goto err;
- if (encap) {
- unsigned char enc[256];
- size_t enclen = sizeof(enc);
- if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1))
- goto err;
- if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc , &enclen,
- secret, &secretlen), 0 ))
- goto err;
- } else {
- if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
- goto err;
- if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
- t->expected_enc,
- t->expected_enclen),
- 0))
- goto err;
- }
- if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
- goto err;
- ret = 1;
- err:
- EVP_PKEY_free(recippriv);
- EVP_PKEY_CTX_free(ctx);
- return ret;
- }
- static int test_ec_badauth(int tstid)
- {
- int ret = 0;
- EVP_PKEY *auth = NULL;
- unsigned char enc[256];
- unsigned char secret[256];
- unsigned char pub[256];
- size_t enclen = sizeof(enc);
- size_t secretlen = sizeof(secret);
- int encap = ((tstid & 1) == 0);
- const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
- EVP_PKEY_CTX *ctx = rctx[TEST_KEYTYPE_P256];
- TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
- /* Set the auth public key to the point at infinity */
- pub[0] = 0;
- if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
- pub, 1)))
- goto err;
- if (encap) {
- if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
- opparam), 1)
- || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
- secret, &secretlen), 0))
- goto err;
- } else {
- if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth, opparam), 1)
- || !TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
- t->expected_enc,
- t->expected_enclen), 0))
- goto err;
- }
- if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
- goto err;
- ret = 1;
- err:
- EVP_PKEY_free(auth);
- return ret;
- }
- static int test_ec_invalid_decap_enc_buffer(void)
- {
- const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
- unsigned char enc[256];
- unsigned char secret[256];
- size_t secretlen = sizeof(secret);
- EVP_PKEY_CTX *ctx = rctx[0];
- memcpy(enc, t->expected_enc, t->expected_enclen);
- enc[0] = 0xFF;
- return TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
- enc, t->expected_enclen), 0);
- }
- #ifndef OPENSSL_NO_ECX
- /* ECX specific tests */
- /* Perform ECX DHKEM KATs */
- static int test_ecx_dhkem_derivekey(int tstid)
- {
- int ret;
- OSSL_PARAM params[2];
- EVP_PKEY_CTX *genctx;
- EVP_PKEY *pkey = NULL;
- unsigned char pubkey[64];
- unsigned char privkey[64];
- unsigned char masked_priv[64];
- size_t pubkeylen = 0, privkeylen = 0;
- const TEST_DERIVEKEY_DATA *t = &ecx_derivekey_data[tstid];
- memcpy(masked_priv, t->priv, t->privlen);
- if (OPENSSL_strcasecmp(t->curvename, "X25519") == 0) {
- /*
- * The RFC test vector seems incorrect since it is not in serialized form,
- * So manually do the conversion here for now.
- */
- masked_priv[0] &= 248;
- masked_priv[t->privlen - 1] &= 127;
- masked_priv[t->privlen - 1] |= 64;
- } else {
- masked_priv[0] &= 252;
- masked_priv[t->privlen - 1] |= 128;
- }
- params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
- (char *)t->ikm, t->ikmlen);
- params[1] = OSSL_PARAM_construct_end();
- ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, t->curvename, NULL))
- && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
- && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
- && TEST_int_eq(EVP_PKEY_keygen(genctx, &pkey), 1)
- && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
- OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
- pubkey, sizeof(pubkey), &pubkeylen), 1)
- && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
- OSSL_PKEY_PARAM_PRIV_KEY,
- privkey, sizeof(privkey), &privkeylen), 1)
- && TEST_mem_eq(t->pub, t->publen, pubkey, pubkeylen)
- && TEST_mem_eq(masked_priv, t->privlen, privkey, privkeylen);
- EVP_PKEY_free(pkey);
- EVP_PKEY_CTX_free(genctx);
- return ret;
- }
- /* Fail if the auth key has a different curve */
- static int test_ecx_auth_key_curve_mismatch(void)
- {
- int ret = 0;
- EVP_PKEY *auth = NULL;
- if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "X448")))
- return 0;
- ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[TEST_KEYTYPE_X25519],
- auth, opparam), 0);
- EVP_PKEY_free(auth);
- return ret;
- }
- /* Fail if ED448 is used for DHKEM */
- static int test_ed_curve_unsupported(void)
- {
- int ret;
- EVP_PKEY *key = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "ED448"))
- && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
- && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
- && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
- EVP_PKEY_free(key);
- EVP_PKEY_CTX_free(ctx);
- return ret;
- }
- #endif
- int setup_tests(void)
- {
- const char *prov_name = "default";
- char *config_file = NULL;
- char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
- if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
- return 0;
- opparam[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
- op, 0);
- opparam[1] = OSSL_PARAM_construct_end();
- /* Create P256 and X25519 keys and ctxs */
- if (!TEST_ptr(rkey[TEST_KEYTYPE_P256] = EVP_PKEY_Q_keygen(libctx, NULL,
- "EC", "P-256")))
- goto err;
- #ifndef OPENSSL_NO_ECX
- if (!TEST_ptr(rkey[TEST_KEYTYPE_X25519] = EVP_PKEY_Q_keygen(libctx, NULL,
- "X25519")))
- goto err;
- #endif
- if (!TEST_ptr(rctx[TEST_KEYTYPE_P256] =
- EVP_PKEY_CTX_new_from_pkey(libctx,
- rkey[TEST_KEYTYPE_P256], NULL)))
- goto err;
- #ifndef OPENSSL_NO_ECX
- if (!TEST_ptr(rctx[TEST_KEYTYPE_X25519] =
- EVP_PKEY_CTX_new_from_pkey(libctx,
- rkey[TEST_KEYTYPE_X25519], NULL)))
- goto err;
- #endif
- ADD_ALL_TESTS(test_dhkem_encapsulate, OSSL_NELEM(ec_encapdata));
- ADD_ALL_TESTS(test_dhkem_decapsulate, OSSL_NELEM(ec_encapdata));
- #ifndef OPENSSL_NO_ECX
- ADD_ALL_TESTS(test_settables, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_null_params, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_set_params, TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_nopublic,
- TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
- ADD_ALL_TESTS(test_noauthpublic,
- TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
- #else
- ADD_ALL_TESTS(test_settables, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_null_params, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_set_params, TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_nopublic,
- TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
- ADD_ALL_TESTS(test_noauthpublic,
- TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
- #endif
- /* EC Specific tests */
- ADD_ALL_TESTS(test_ec_dhkem_derivekey, OSSL_NELEM(ec_derivekey_data));
- ADD_ALL_TESTS(test_ec_noikme,
- TEST_TYPE_AUTH_NOAUTH * OSSL_NELEM(dhkem_supported_curves));
- ADD_TEST(test_ec_auth_key_curve_mismatch);
- ADD_TEST(test_ec_invalid_private_key);
- ADD_TEST(test_ec_dhkem_derivekey_fail);
- ADD_TEST(test_ec_curve_nonnist);
- ADD_TEST(test_ec_curve_unsupported);
- ADD_TEST(test_ec_invalid_decap_enc_buffer);
- ADD_TEST(test_ec_public_key_infinity);
- ADD_ALL_TESTS(test_ec_badpublic, TEST_KEM_ENCAP_DECAP);
- ADD_ALL_TESTS(test_ec_badauth, TEST_KEM_ENCAP_DECAP);
- /* ECX specific tests */
- #ifndef OPENSSL_NO_ECX
- ADD_ALL_TESTS(test_ecx_dhkem_derivekey, OSSL_NELEM(ecx_derivekey_data));
- ADD_TEST(test_ecx_auth_key_curve_mismatch);
- ADD_TEST(test_ed_curve_unsupported);
- #endif
- return 1;
- err:
- return 0;
- }
- void cleanup_tests(void)
- {
- EVP_PKEY_free(rkey[1]);
- EVP_PKEY_free(rkey[0]);
- EVP_PKEY_CTX_free(rctx[1]);
- EVP_PKEY_CTX_free(rctx[0]);
- OSSL_PROVIDER_unload(libprov);
- OSSL_LIB_CTX_free(libctx);
- OSSL_PROVIDER_unload(nullprov);
- }
|