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