1 /* 2 * Copyright 2022-2024 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/rand.h> 13 #include <openssl/hpke.h> 14 #include "testutil.h" 15 16 /* a size to use for stack buffers */ 17 #define OSSL_HPKE_TSTSIZE 512 18 19 static OSSL_LIB_CTX *testctx = NULL; 20 static OSSL_PROVIDER *nullprov = NULL; 21 static OSSL_PROVIDER *deflprov = NULL; 22 static char *testpropq = "provider=default"; 23 static int verbose = 0; 24 25 typedef struct { 26 int mode; 27 OSSL_HPKE_SUITE suite; 28 const unsigned char *ikmE; 29 size_t ikmElen; 30 const unsigned char *expected_pkEm; 31 size_t expected_pkEmlen; 32 const unsigned char *ikmR; 33 size_t ikmRlen; 34 const unsigned char *expected_pkRm; 35 size_t expected_pkRmlen; 36 const unsigned char *expected_skRm; 37 size_t expected_skRmlen; 38 const unsigned char *expected_secret; 39 size_t expected_secretlen; 40 const unsigned char *ksinfo; 41 size_t ksinfolen; 42 const unsigned char *ikmAuth; 43 size_t ikmAuthlen; 44 const unsigned char *psk; 45 size_t psklen; 46 const char *pskid; /* want terminating NUL here */ 47 } TEST_BASEDATA; 48 49 typedef struct { 50 int seq; 51 const unsigned char *pt; 52 size_t ptlen; 53 const unsigned char *aad; 54 size_t aadlen; 55 const unsigned char *expected_ct; 56 size_t expected_ctlen; 57 } TEST_AEADDATA; 58 59 typedef struct { 60 const unsigned char *context; 61 size_t contextlen; 62 const unsigned char *expected_secret; 63 size_t expected_secretlen; 64 } TEST_EXPORTDATA; 65 66 /** 67 * @brief Test that an EVP_PKEY encoded public key matches the supplied buffer 68 * @param pkey is the EVP_PKEY we want to check 69 * @param pub is the expected public key buffer 70 * @param publen is the length of the above 71 * @return 1 for good, 0 for bad 72 */ 73 static int cmpkey(const EVP_PKEY *pkey, 74 const unsigned char *pub, size_t publen) 75 { 76 unsigned char pubbuf[256]; 77 size_t pubbuflen = 0; 78 int erv = 0; 79 80 if (!TEST_true(publen <= sizeof(pubbuf))) 81 return 0; 82 erv = EVP_PKEY_get_octet_string_param(pkey, 83 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, 84 pubbuf, sizeof(pubbuf), &pubbuflen); 85 if (!TEST_true(erv)) 86 return 0; 87 if (pub != NULL && !TEST_mem_eq(pubbuf, pubbuflen, pub, publen)) 88 return 0; 89 return 1; 90 } 91 92 static int do_testhpke(const TEST_BASEDATA *base, 93 const TEST_AEADDATA *aead, size_t aeadsz, 94 const TEST_EXPORTDATA *export, size_t exportsz) 95 { 96 OSSL_LIB_CTX *libctx = testctx; 97 const char *propq = testpropq; 98 OSSL_HPKE_CTX *sealctx = NULL, *openctx = NULL; 99 unsigned char ct[256]; 100 unsigned char enc[256]; 101 unsigned char ptout[256]; 102 size_t ptoutlen = sizeof(ptout); 103 size_t enclen = sizeof(enc); 104 size_t ctlen = sizeof(ct); 105 unsigned char pub[OSSL_HPKE_TSTSIZE]; 106 size_t publen = sizeof(pub); 107 EVP_PKEY *privE = NULL; 108 unsigned char authpub[OSSL_HPKE_TSTSIZE]; 109 size_t authpublen = sizeof(authpub); 110 EVP_PKEY *authpriv = NULL; 111 unsigned char rpub[OSSL_HPKE_TSTSIZE]; 112 size_t rpublen = sizeof(pub); 113 EVP_PKEY *privR = NULL; 114 int ret = 0; 115 size_t i; 116 uint64_t lastseq = 0; 117 118 if (!TEST_true(OSSL_HPKE_keygen(base->suite, pub, &publen, &privE, 119 base->ikmE, base->ikmElen, libctx, propq))) 120 goto end; 121 if (!TEST_true(cmpkey(privE, base->expected_pkEm, base->expected_pkEmlen))) 122 goto end; 123 if (!TEST_ptr(sealctx = OSSL_HPKE_CTX_new(base->mode, base->suite, 124 OSSL_HPKE_ROLE_SENDER, 125 libctx, propq))) 126 goto end; 127 if (!TEST_true(OSSL_HPKE_CTX_set1_ikme(sealctx, base->ikmE, base->ikmElen))) 128 goto end; 129 if (base->mode == OSSL_HPKE_MODE_AUTH 130 || base->mode == OSSL_HPKE_MODE_PSKAUTH) { 131 if (!TEST_true(base->ikmAuth != NULL && base->ikmAuthlen > 0)) 132 goto end; 133 if (!TEST_true(OSSL_HPKE_keygen(base->suite, 134 authpub, &authpublen, &authpriv, 135 base->ikmAuth, base->ikmAuthlen, 136 libctx, propq))) 137 goto end; 138 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(sealctx, authpriv))) 139 goto end; 140 } 141 if (!TEST_true(OSSL_HPKE_keygen(base->suite, rpub, &rpublen, &privR, 142 base->ikmR, base->ikmRlen, libctx, propq))) 143 goto end; 144 if (!TEST_true(cmpkey(privR, base->expected_pkRm, base->expected_pkRmlen))) 145 goto end; 146 if (base->mode == OSSL_HPKE_MODE_PSK 147 || base->mode == OSSL_HPKE_MODE_PSKAUTH) { 148 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(sealctx, base->pskid, 149 base->psk, base->psklen))) 150 goto end; 151 } 152 if (!TEST_true(OSSL_HPKE_encap(sealctx, enc, &enclen, 153 rpub, rpublen, 154 base->ksinfo, base->ksinfolen))) 155 goto end; 156 if (!TEST_true(cmpkey(privE, enc, enclen))) 157 goto end; 158 for (i = 0; i < aeadsz; ++i) { 159 ctlen = sizeof(ct); 160 memset(ct, 0, ctlen); 161 if (!TEST_true(OSSL_HPKE_seal(sealctx, ct, &ctlen, 162 aead[i].aad, aead[i].aadlen, 163 aead[i].pt, aead[i].ptlen))) 164 goto end; 165 if (!TEST_mem_eq(ct, ctlen, aead[i].expected_ct, 166 aead[i].expected_ctlen)) 167 goto end; 168 if (!TEST_true(OSSL_HPKE_CTX_get_seq(sealctx, &lastseq))) 169 goto end; 170 if (lastseq != (uint64_t)(i + 1)) 171 goto end; 172 } 173 if (!TEST_ptr(openctx = OSSL_HPKE_CTX_new(base->mode, base->suite, 174 OSSL_HPKE_ROLE_RECEIVER, 175 libctx, propq))) 176 goto end; 177 if (base->mode == OSSL_HPKE_MODE_PSK 178 || base->mode == OSSL_HPKE_MODE_PSKAUTH) { 179 if (!TEST_true(base->pskid != NULL && base->psk != NULL 180 && base->psklen > 0)) 181 goto end; 182 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(openctx, base->pskid, 183 base->psk, base->psklen))) 184 goto end; 185 } 186 if (base->mode == OSSL_HPKE_MODE_AUTH 187 || base->mode == OSSL_HPKE_MODE_PSKAUTH) { 188 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(openctx, 189 authpub, authpublen))) 190 goto end; 191 } 192 if (!TEST_true(OSSL_HPKE_decap(openctx, enc, enclen, privR, 193 base->ksinfo, base->ksinfolen))) 194 goto end; 195 for (i = 0; i < aeadsz; ++i) { 196 ptoutlen = sizeof(ptout); 197 memset(ptout, 0, ptoutlen); 198 if (!TEST_true(OSSL_HPKE_open(openctx, ptout, &ptoutlen, 199 aead[i].aad, aead[i].aadlen, 200 aead[i].expected_ct, 201 aead[i].expected_ctlen))) 202 goto end; 203 if (!TEST_mem_eq(aead[i].pt, aead[i].ptlen, ptout, ptoutlen)) 204 goto end; 205 /* check the sequence is being incremented as expected */ 206 if (!TEST_true(OSSL_HPKE_CTX_get_seq(openctx, &lastseq))) 207 goto end; 208 if (lastseq != (uint64_t)(i + 1)) 209 goto end; 210 } 211 /* check exporters */ 212 for (i = 0; i < exportsz; ++i) { 213 size_t len = export[i].expected_secretlen; 214 unsigned char eval[OSSL_HPKE_TSTSIZE]; 215 216 if (len > sizeof(eval)) 217 goto end; 218 /* export with too long label should fail */ 219 if (!TEST_false(OSSL_HPKE_export(sealctx, eval, len, 220 export[i].context, -1))) 221 goto end; 222 /* good export call */ 223 if (!TEST_true(OSSL_HPKE_export(sealctx, eval, len, 224 export[i].context, 225 export[i].contextlen))) 226 goto end; 227 if (!TEST_mem_eq(eval, len, export[i].expected_secret, 228 export[i].expected_secretlen)) 229 goto end; 230 231 /* check seal fails if export only mode */ 232 if (aeadsz == 0) { 233 234 if (!TEST_false(OSSL_HPKE_seal(sealctx, ct, &ctlen, 235 NULL, 0, ptout, ptoutlen))) 236 goto end; 237 } 238 } 239 ret = 1; 240 end: 241 OSSL_HPKE_CTX_free(sealctx); 242 OSSL_HPKE_CTX_free(openctx); 243 EVP_PKEY_free(privE); 244 EVP_PKEY_free(privR); 245 EVP_PKEY_free(authpriv); 246 return ret; 247 } 248 249 static const unsigned char pt[] = { 250 0x42, 0x65, 0x61, 0x75, 0x74, 0x79, 0x20, 0x69, 251 0x73, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x2c, 252 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, 0x62, 253 0x65, 0x61, 0x75, 0x74, 0x79 254 }; 255 static const unsigned char ksinfo[] = { 256 0x4f, 0x64, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61, 257 0x20, 0x47, 0x72, 0x65, 0x63, 0x69, 0x61, 0x6e, 258 0x20, 0x55, 0x72, 0x6e 259 }; 260 #ifndef OPENSSL_NO_ECX 261 /* 262 * static const char *pskid = "Ennyn Durin aran Moria"; 263 */ 264 static const unsigned char pskid[] = { 265 0x45, 0x6e, 0x6e, 0x79, 0x6e, 0x20, 0x44, 0x75, 266 0x72, 0x69, 0x6e, 0x20, 0x61, 0x72, 0x61, 0x6e, 267 0x20, 0x4d, 0x6f, 0x72, 0x69, 0x61, 0x00 268 }; 269 static const unsigned char psk[] = { 270 0x02, 0x47, 0xfd, 0x33, 0xb9, 0x13, 0x76, 0x0f, 271 0xa1, 0xfa, 0x51, 0xe1, 0x89, 0x2d, 0x9f, 0x30, 272 0x7f, 0xbe, 0x65, 0xeb, 0x17, 0x1e, 0x81, 0x32, 273 0xc2, 0xaf, 0x18, 0x55, 0x5a, 0x73, 0x8b, 0x82 274 }; 275 276 /* these need to be "outside" the function below to keep check-ansi CI happy */ 277 static const unsigned char first_ikme[] = { 278 0x78, 0x62, 0x8c, 0x35, 0x4e, 0x46, 0xf3, 0xe1, 279 0x69, 0xbd, 0x23, 0x1b, 0xe7, 0xb2, 0xff, 0x1c, 280 0x77, 0xaa, 0x30, 0x24, 0x60, 0xa2, 0x6d, 0xbf, 281 0xa1, 0x55, 0x15, 0x68, 0x4c, 0x00, 0x13, 0x0b 282 }; 283 static const unsigned char first_ikmr[] = { 284 0xd4, 0xa0, 0x9d, 0x09, 0xf5, 0x75, 0xfe, 0xf4, 285 0x25, 0x90, 0x5d, 0x2a, 0xb3, 0x96, 0xc1, 0x44, 286 0x91, 0x41, 0x46, 0x3f, 0x69, 0x8f, 0x8e, 0xfd, 287 0xb7, 0xac, 0xcf, 0xaf, 0xf8, 0x99, 0x50, 0x98 288 }; 289 static const unsigned char first_ikmepub[] = { 290 0x0a, 291 0xd0, 292 0x95, 293 0x0d, 294 0x9f, 295 0xb9, 296 0x58, 297 0x8e, 298 0x59, 299 0x69, 300 0x0b, 301 0x74, 302 0xf1, 303 0x23, 304 0x7e, 305 0xcd, 306 0xf1, 307 0xd7, 308 0x75, 309 0xcd, 310 0x60, 311 0xbe, 312 0x2e, 313 0xca, 314 0x57, 315 0xaf, 316 0x5a, 317 0x4b, 318 0x04, 319 0x71, 320 0xc9, 321 0x1b, 322 }; 323 static const unsigned char first_ikmrpub[] = { 324 0x9f, 0xed, 0x7e, 0x8c, 0x17, 0x38, 0x75, 0x60, 325 0xe9, 0x2c, 0xc6, 0x46, 0x2a, 0x68, 0x04, 0x96, 326 0x57, 0x24, 0x6a, 0x09, 0xbf, 0xa8, 0xad, 0xe7, 327 0xae, 0xfe, 0x58, 0x96, 0x72, 0x01, 0x63, 0x66 328 }; 329 static const unsigned char first_ikmrpriv[] = { 330 0xc5, 0xeb, 0x01, 0xeb, 0x45, 0x7f, 0xe6, 0xc6, 331 0xf5, 0x75, 0x77, 0xc5, 0x41, 0x3b, 0x93, 0x15, 332 0x50, 0xa1, 0x62, 0xc7, 0x1a, 0x03, 0xac, 0x8d, 333 0x19, 0x6b, 0xab, 0xbd, 0x4e, 0x5c, 0xe0, 0xfd 334 }; 335 static const unsigned char first_expected_shared_secret[] = { 336 0x72, 0x76, 0x99, 0xf0, 0x09, 0xff, 0xe3, 0xc0, 337 0x76, 0x31, 0x50, 0x19, 0xc6, 0x96, 0x48, 0x36, 338 0x6b, 0x69, 0x17, 0x14, 0x39, 0xbd, 0x7d, 0xd0, 339 0x80, 0x77, 0x43, 0xbd, 0xe7, 0x69, 0x86, 0xcd 340 }; 341 static const unsigned char first_aad0[] = { 342 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30 343 }; 344 static const unsigned char first_ct0[] = { 345 0xe5, 0x2c, 0x6f, 0xed, 0x7f, 0x75, 0x8d, 0x0c, 346 0xf7, 0x14, 0x56, 0x89, 0xf2, 0x1b, 0xc1, 0xbe, 347 0x6e, 0xc9, 0xea, 0x09, 0x7f, 0xef, 0x4e, 0x95, 348 0x94, 0x40, 0x01, 0x2f, 0x4f, 0xeb, 0x73, 0xfb, 349 0x61, 0x1b, 0x94, 0x61, 0x99, 0xe6, 0x81, 0xf4, 350 0xcf, 0xc3, 0x4d, 0xb8, 0xea 351 }; 352 static const unsigned char first_aad1[] = { 353 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31 354 }; 355 static const unsigned char first_ct1[] = { 356 0x49, 0xf3, 0xb1, 0x9b, 0x28, 0xa9, 0xea, 0x9f, 357 0x43, 0xe8, 0xc7, 0x12, 0x04, 0xc0, 0x0d, 0x4a, 358 0x49, 0x0e, 0xe7, 0xf6, 0x13, 0x87, 0xb6, 0x71, 359 0x9d, 0xb7, 0x65, 0xe9, 0x48, 0x12, 0x3b, 0x45, 360 0xb6, 0x16, 0x33, 0xef, 0x05, 0x9b, 0xa2, 0x2c, 361 0xd6, 0x24, 0x37, 0xc8, 0xba 362 }; 363 static const unsigned char first_aad2[] = { 364 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x32 365 }; 366 static const unsigned char first_ct2[] = { 367 0x25, 0x7c, 0xa6, 0xa0, 0x84, 0x73, 0xdc, 0x85, 368 0x1f, 0xde, 0x45, 0xaf, 0xd5, 0x98, 0xcc, 0x83, 369 0xe3, 0x26, 0xdd, 0xd0, 0xab, 0xe1, 0xef, 0x23, 370 0xba, 0xa3, 0xba, 0xa4, 0xdd, 0x8c, 0xde, 0x99, 371 0xfc, 0xe2, 0xc1, 0xe8, 0xce, 0x68, 0x7b, 0x0b, 372 0x47, 0xea, 0xd1, 0xad, 0xc9 373 }; 374 static const unsigned char first_export1[] = { 375 0xdf, 0xf1, 0x7a, 0xf3, 0x54, 0xc8, 0xb4, 0x16, 376 0x73, 0x56, 0x7d, 0xb6, 0x25, 0x9f, 0xd6, 0x02, 377 0x99, 0x67, 0xb4, 0xe1, 0xaa, 0xd1, 0x30, 0x23, 378 0xc2, 0xae, 0x5d, 0xf8, 0xf4, 0xf4, 0x3b, 0xf6 379 }; 380 static const unsigned char first_context2[] = { 0x00 }; 381 static const unsigned char first_export2[] = { 382 0x6a, 0x84, 0x72, 0x61, 0xd8, 0x20, 0x7f, 0xe5, 383 0x96, 0xbe, 0xfb, 0x52, 0x92, 0x84, 0x63, 0x88, 384 0x1a, 0xb4, 0x93, 0xda, 0x34, 0x5b, 0x10, 0xe1, 385 0xdc, 0xc6, 0x45, 0xe3, 0xb9, 0x4e, 0x2d, 0x95 386 }; 387 static const unsigned char first_context3[] = { 388 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 389 0x65, 0x78, 0x74 390 }; 391 static const unsigned char first_export3[] = { 392 0x8a, 0xff, 0x52, 0xb4, 0x5a, 0x1b, 0xe3, 0xa7, 393 0x34, 0xbc, 0x7a, 0x41, 0xe2, 0x0b, 0x4e, 0x05, 394 0x5a, 0xd4, 0xc4, 0xd2, 0x21, 0x04, 0xb0, 0xc2, 395 0x02, 0x85, 0xa7, 0xc4, 0x30, 0x24, 0x01, 0xcd 396 }; 397 398 static int x25519kdfsha256_hkdfsha256_aes128gcm_psk_test(void) 399 { 400 const TEST_BASEDATA pskdata = { 401 /* "X25519", NULL, "SHA256", "SHA256", "AES-128-GCM", */ 402 OSSL_HPKE_MODE_PSK, 403 { OSSL_HPKE_KEM_ID_X25519, 404 OSSL_HPKE_KDF_ID_HKDF_SHA256, 405 OSSL_HPKE_AEAD_ID_AES_GCM_128 }, 406 first_ikme, sizeof(first_ikme), 407 first_ikmepub, sizeof(first_ikmepub), 408 first_ikmr, sizeof(first_ikmr), 409 first_ikmrpub, sizeof(first_ikmrpub), 410 first_ikmrpriv, sizeof(first_ikmrpriv), 411 first_expected_shared_secret, sizeof(first_expected_shared_secret), 412 ksinfo, sizeof(ksinfo), 413 NULL, 0, /* No Auth */ 414 psk, sizeof(psk), (char *)pskid 415 }; 416 const TEST_AEADDATA aeaddata[] = { 417 { 0, 418 pt, sizeof(pt), 419 first_aad0, sizeof(first_aad0), 420 first_ct0, sizeof(first_ct0) }, 421 { 1, 422 pt, sizeof(pt), 423 first_aad1, sizeof(first_aad1), 424 first_ct1, sizeof(first_ct1) }, 425 { 2, 426 pt, sizeof(pt), 427 first_aad2, sizeof(first_aad2), 428 first_ct2, sizeof(first_ct2) } 429 }; 430 const TEST_EXPORTDATA exportdata[] = { 431 { NULL, 0, first_export1, sizeof(first_export1) }, 432 { first_context2, sizeof(first_context2), 433 first_export2, sizeof(first_export2) }, 434 { first_context3, sizeof(first_context3), 435 first_export3, sizeof(first_export3) }, 436 }; 437 return do_testhpke(&pskdata, aeaddata, OSSL_NELEM(aeaddata), 438 exportdata, OSSL_NELEM(exportdata)); 439 } 440 441 static const unsigned char second_ikme[] = { 442 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43, 443 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13, 444 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2, 445 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34 446 }; 447 static const unsigned char second_ikmepub[] = { 448 0x37, 449 0xfd, 450 0xa3, 451 0x56, 452 0x7b, 453 0xdb, 454 0xd6, 455 0x28, 456 0xe8, 457 0x86, 458 0x68, 459 0xc3, 460 0xc8, 461 0xd7, 462 0xe9, 463 0x7d, 464 0x1d, 465 0x12, 466 0x53, 467 0xb6, 468 0xd4, 469 0xea, 470 0x6d, 471 0x44, 472 0xc1, 473 0x50, 474 0xf7, 475 0x41, 476 0xf1, 477 0xbf, 478 0x44, 479 0x31, 480 }; 481 static const unsigned char second_ikmr[] = { 482 0x6d, 0xb9, 0xdf, 0x30, 0xaa, 0x07, 0xdd, 0x42, 483 0xee, 0x5e, 0x81, 0x81, 0xaf, 0xdb, 0x97, 0x7e, 484 0x53, 0x8f, 0x5e, 0x1f, 0xec, 0x8a, 0x06, 0x22, 485 0x3f, 0x33, 0xf7, 0x01, 0x3e, 0x52, 0x50, 0x37 486 }; 487 static const unsigned char second_ikmrpub[] = { 488 0x39, 0x48, 0xcf, 0xe0, 0xad, 0x1d, 0xdb, 0x69, 489 0x5d, 0x78, 0x0e, 0x59, 0x07, 0x71, 0x95, 0xda, 490 0x6c, 0x56, 0x50, 0x6b, 0x02, 0x73, 0x29, 0x79, 491 0x4a, 0xb0, 0x2b, 0xca, 0x80, 0x81, 0x5c, 0x4d 492 }; 493 static const unsigned char second_ikmrpriv[] = { 494 0x46, 0x12, 0xc5, 0x50, 0x26, 0x3f, 0xc8, 0xad, 495 0x58, 0x37, 0x5d, 0xf3, 0xf5, 0x57, 0xaa, 0xc5, 496 0x31, 0xd2, 0x68, 0x50, 0x90, 0x3e, 0x55, 0xa9, 497 0xf2, 0x3f, 0x21, 0xd8, 0x53, 0x4e, 0x8a, 0xc8 498 }; 499 static const unsigned char second_expected_shared_secret[] = { 500 0xfe, 0x0e, 0x18, 0xc9, 0xf0, 0x24, 0xce, 0x43, 501 0x79, 0x9a, 0xe3, 0x93, 0xc7, 0xe8, 0xfe, 0x8f, 502 0xce, 0x9d, 0x21, 0x88, 0x75, 0xe8, 0x22, 0x7b, 503 0x01, 0x87, 0xc0, 0x4e, 0x7d, 0x2e, 0xa1, 0xfc 504 }; 505 static const unsigned char second_aead0[] = { 506 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30 507 }; 508 static const unsigned char second_ct0[] = { 509 0xf9, 0x38, 0x55, 0x8b, 0x5d, 0x72, 0xf1, 0xa2, 510 0x38, 0x10, 0xb4, 0xbe, 0x2a, 0xb4, 0xf8, 0x43, 511 0x31, 0xac, 0xc0, 0x2f, 0xc9, 0x7b, 0xab, 0xc5, 512 0x3a, 0x52, 0xae, 0x82, 0x18, 0xa3, 0x55, 0xa9, 513 0x6d, 0x87, 0x70, 0xac, 0x83, 0xd0, 0x7b, 0xea, 514 0x87, 0xe1, 0x3c, 0x51, 0x2a 515 }; 516 static const unsigned char second_aead1[] = { 517 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31 518 }; 519 static const unsigned char second_ct1[] = { 520 0xaf, 0x2d, 0x7e, 0x9a, 0xc9, 0xae, 0x7e, 0x27, 521 0x0f, 0x46, 0xba, 0x1f, 0x97, 0x5b, 0xe5, 0x3c, 522 0x09, 0xf8, 0xd8, 0x75, 0xbd, 0xc8, 0x53, 0x54, 523 0x58, 0xc2, 0x49, 0x4e, 0x8a, 0x6e, 0xab, 0x25, 524 0x1c, 0x03, 0xd0, 0xc2, 0x2a, 0x56, 0xb8, 0xca, 525 0x42, 0xc2, 0x06, 0x3b, 0x84 526 }; 527 static const unsigned char second_export1[] = { 528 0x38, 0x53, 0xfe, 0x2b, 0x40, 0x35, 0x19, 0x5a, 529 0x57, 0x3f, 0xfc, 0x53, 0x85, 0x6e, 0x77, 0x05, 530 0x8e, 0x15, 0xd9, 0xea, 0x06, 0x4d, 0xe3, 0xe5, 531 0x9f, 0x49, 0x61, 0xd0, 0x09, 0x52, 0x50, 0xee 532 }; 533 static const unsigned char second_context2[] = { 0x00 }; 534 static const unsigned char second_export2[] = { 535 0x2e, 0x8f, 0x0b, 0x54, 0x67, 0x3c, 0x70, 0x29, 536 0x64, 0x9d, 0x4e, 0xb9, 0xd5, 0xe3, 0x3b, 0xf1, 537 0x87, 0x2c, 0xf7, 0x6d, 0x62, 0x3f, 0xf1, 0x64, 538 0xac, 0x18, 0x5d, 0xa9, 0xe8, 0x8c, 0x21, 0xa5 539 }; 540 static const unsigned char second_context3[] = { 541 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 542 0x65, 0x78, 0x74 543 }; 544 static const unsigned char second_export3[] = { 545 0xe9, 0xe4, 0x30, 0x65, 0x10, 0x2c, 0x38, 0x36, 546 0x40, 0x1b, 0xed, 0x8c, 0x3c, 0x3c, 0x75, 0xae, 547 0x46, 0xbe, 0x16, 0x39, 0x86, 0x93, 0x91, 0xd6, 548 0x2c, 0x61, 0xf1, 0xec, 0x7a, 0xf5, 0x49, 0x31 549 }; 550 551 static int x25519kdfsha256_hkdfsha256_aes128gcm_base_test(void) 552 { 553 const TEST_BASEDATA basedata = { 554 OSSL_HPKE_MODE_BASE, 555 { OSSL_HPKE_KEM_ID_X25519, 556 OSSL_HPKE_KDF_ID_HKDF_SHA256, 557 OSSL_HPKE_AEAD_ID_AES_GCM_128 }, 558 second_ikme, sizeof(second_ikme), 559 second_ikmepub, sizeof(second_ikmepub), 560 second_ikmr, sizeof(second_ikmr), 561 second_ikmrpub, sizeof(second_ikmrpub), 562 second_ikmrpriv, sizeof(second_ikmrpriv), 563 second_expected_shared_secret, sizeof(second_expected_shared_secret), 564 ksinfo, sizeof(ksinfo), 565 NULL, 0, /* no auth ikm */ 566 NULL, 0, NULL /* no psk */ 567 }; 568 const TEST_AEADDATA aeaddata[] = { 569 { 0, 570 pt, sizeof(pt), 571 second_aead0, sizeof(second_aead0), 572 second_ct0, sizeof(second_ct0) }, 573 { 1, 574 pt, sizeof(pt), 575 second_aead1, sizeof(second_aead1), 576 second_ct1, sizeof(second_ct1) } 577 }; 578 const TEST_EXPORTDATA exportdata[] = { 579 { NULL, 0, second_export1, sizeof(second_export1) }, 580 { second_context2, sizeof(second_context2), 581 second_export2, sizeof(second_export2) }, 582 { second_context3, sizeof(second_context3), 583 second_export3, sizeof(second_export3) }, 584 }; 585 return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata), 586 exportdata, OSSL_NELEM(exportdata)); 587 } 588 #endif 589 590 static const unsigned char third_ikme[] = { 591 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d, 592 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f, 593 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f, 594 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e 595 }; 596 static const unsigned char third_ikmepub[] = { 597 0x04, 598 0xa9, 599 0x27, 600 0x19, 601 0xc6, 602 0x19, 603 0x5d, 604 0x50, 605 0x85, 606 0x10, 607 0x4f, 608 0x46, 609 0x9a, 610 0x8b, 611 0x98, 612 0x14, 613 0xd5, 614 0x83, 615 0x8f, 616 0xf7, 617 0x2b, 618 0x60, 619 0x50, 620 0x1e, 621 0x2c, 622 0x44, 623 0x66, 624 0xe5, 625 0xe6, 626 0x7b, 627 0x32, 628 0x5a, 629 0xc9, 630 0x85, 631 0x36, 632 0xd7, 633 0xb6, 634 0x1a, 635 0x1a, 636 0xf4, 637 0xb7, 638 0x8e, 639 0x5b, 640 0x7f, 641 0x95, 642 0x1c, 643 0x09, 644 0x00, 645 0xbe, 646 0x86, 647 0x3c, 648 0x40, 649 0x3c, 650 0xe6, 651 0x5c, 652 0x9b, 653 0xfc, 654 0xb9, 655 0x38, 656 0x26, 657 0x57, 658 0x22, 659 0x2d, 660 0x18, 661 0xc4, 662 }; 663 static const unsigned char third_ikmr[] = { 664 0x66, 0x8b, 0x37, 0x17, 0x1f, 0x10, 0x72, 0xf3, 665 0xcf, 0x12, 0xea, 0x8a, 0x23, 0x6a, 0x45, 0xdf, 666 0x23, 0xfc, 0x13, 0xb8, 0x2a, 0xf3, 0x60, 0x9a, 667 0xd1, 0xe3, 0x54, 0xf6, 0xef, 0x81, 0x75, 0x50 668 }; 669 static const unsigned char third_ikmrpub[] = { 670 0x04, 0xfe, 0x8c, 0x19, 0xce, 0x09, 0x05, 0x19, 671 0x1e, 0xbc, 0x29, 0x8a, 0x92, 0x45, 0x79, 0x25, 672 0x31, 0xf2, 0x6f, 0x0c, 0xec, 0xe2, 0x46, 0x06, 673 0x39, 0xe8, 0xbc, 0x39, 0xcb, 0x7f, 0x70, 0x6a, 674 0x82, 0x6a, 0x77, 0x9b, 0x4c, 0xf9, 0x69, 0xb8, 675 0xa0, 0xe5, 0x39, 0xc7, 0xf6, 0x2f, 0xb3, 0xd3, 676 0x0a, 0xd6, 0xaa, 0x8f, 0x80, 0xe3, 0x0f, 0x1d, 677 0x12, 0x8a, 0xaf, 0xd6, 0x8a, 0x2c, 0xe7, 0x2e, 678 0xa0 679 }; 680 static const unsigned char third_ikmrpriv[] = { 681 0xf3, 0xce, 0x7f, 0xda, 0xe5, 0x7e, 0x1a, 0x31, 682 0x0d, 0x87, 0xf1, 0xeb, 0xbd, 0xe6, 0xf3, 0x28, 683 0xbe, 0x0a, 0x99, 0xcd, 0xbc, 0xad, 0xf4, 0xd6, 684 0x58, 0x9c, 0xf2, 0x9d, 0xe4, 0xb8, 0xff, 0xd2 685 }; 686 static const unsigned char third_expected_shared_secret[] = { 687 0xc0, 0xd2, 0x6a, 0xea, 0xb5, 0x36, 0x60, 0x9a, 688 0x57, 0x2b, 0x07, 0x69, 0x5d, 0x93, 0x3b, 0x58, 689 0x9d, 0xcf, 0x36, 0x3f, 0xf9, 0xd9, 0x3c, 0x93, 690 0xad, 0xea, 0x53, 0x7a, 0xea, 0xbb, 0x8c, 0xb8 691 }; 692 static const unsigned char third_aead0[] = { 693 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30 694 }; 695 static const unsigned char third_ct0[] = { 696 0x5a, 0xd5, 0x90, 0xbb, 0x8b, 0xaa, 0x57, 0x7f, 697 0x86, 0x19, 0xdb, 0x35, 0xa3, 0x63, 0x11, 0x22, 698 0x6a, 0x89, 0x6e, 0x73, 0x42, 0xa6, 0xd8, 0x36, 699 0xd8, 0xb7, 0xbc, 0xd2, 0xf2, 0x0b, 0x6c, 0x7f, 700 0x90, 0x76, 0xac, 0x23, 0x2e, 0x3a, 0xb2, 0x52, 701 0x3f, 0x39, 0x51, 0x34, 0x34 702 }; 703 static const unsigned char third_aead1[] = { 704 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31 705 }; 706 static const unsigned char third_ct1[] = { 707 0xfa, 0x6f, 0x03, 0x7b, 0x47, 0xfc, 0x21, 0x82, 708 0x6b, 0x61, 0x01, 0x72, 0xca, 0x96, 0x37, 0xe8, 709 0x2d, 0x6e, 0x58, 0x01, 0xeb, 0x31, 0xcb, 0xd3, 710 0x74, 0x82, 0x71, 0xaf, 0xfd, 0x4e, 0xcb, 0x06, 711 0x64, 0x6e, 0x03, 0x29, 0xcb, 0xdf, 0x3c, 0x3c, 712 0xd6, 0x55, 0xb2, 0x8e, 0x82 713 }; 714 static const unsigned char third_export1[] = { 715 0x5e, 0x9b, 0xc3, 0xd2, 0x36, 0xe1, 0x91, 0x1d, 716 0x95, 0xe6, 0x5b, 0x57, 0x6a, 0x8a, 0x86, 0xd4, 717 0x78, 0xfb, 0x82, 0x7e, 0x8b, 0xdf, 0xe7, 0x7b, 718 0x74, 0x1b, 0x28, 0x98, 0x90, 0x49, 0x0d, 0x4d 719 }; 720 static const unsigned char third_context2[] = { 0x00 }; 721 static const unsigned char third_export2[] = { 722 0x6c, 0xff, 0x87, 0x65, 0x89, 0x31, 0xbd, 0xa8, 723 0x3d, 0xc8, 0x57, 0xe6, 0x35, 0x3e, 0xfe, 0x49, 724 0x87, 0xa2, 0x01, 0xb8, 0x49, 0x65, 0x8d, 0x9b, 725 0x04, 0x7a, 0xab, 0x4c, 0xf2, 0x16, 0xe7, 0x96 726 }; 727 static const unsigned char third_context3[] = { 728 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 729 0x65, 0x78, 0x74 730 }; 731 static const unsigned char third_export3[] = { 732 0xd8, 0xf1, 0xea, 0x79, 0x42, 0xad, 0xbb, 0xa7, 733 0x41, 0x2c, 0x6d, 0x43, 0x1c, 0x62, 0xd0, 0x13, 734 0x71, 0xea, 0x47, 0x6b, 0x82, 0x3e, 0xb6, 0x97, 735 0xe1, 0xf6, 0xe6, 0xca, 0xe1, 0xda, 0xb8, 0x5a 736 }; 737 738 static int P256kdfsha256_hkdfsha256_aes128gcm_base_test(void) 739 { 740 const TEST_BASEDATA basedata = { 741 OSSL_HPKE_MODE_BASE, 742 { OSSL_HPKE_KEM_ID_P256, 743 OSSL_HPKE_KDF_ID_HKDF_SHA256, 744 OSSL_HPKE_AEAD_ID_AES_GCM_128 }, 745 third_ikme, sizeof(third_ikme), 746 third_ikmepub, sizeof(third_ikmepub), 747 third_ikmr, sizeof(third_ikmr), 748 third_ikmrpub, sizeof(third_ikmrpub), 749 third_ikmrpriv, sizeof(third_ikmrpriv), 750 third_expected_shared_secret, sizeof(third_expected_shared_secret), 751 ksinfo, sizeof(ksinfo), 752 NULL, 0, /* no auth */ 753 NULL, 0, NULL /* PSK stuff */ 754 }; 755 const TEST_AEADDATA aeaddata[] = { 756 { 0, 757 pt, sizeof(pt), 758 third_aead0, sizeof(third_aead0), 759 third_ct0, sizeof(third_ct0) }, 760 { 1, 761 pt, sizeof(pt), 762 third_aead1, sizeof(third_aead1), 763 third_ct1, sizeof(third_ct1) } 764 }; 765 const TEST_EXPORTDATA exportdata[] = { 766 { NULL, 0, third_export1, sizeof(third_export1) }, 767 { third_context2, sizeof(third_context2), 768 third_export2, sizeof(third_export2) }, 769 { third_context3, sizeof(third_context3), 770 third_export3, sizeof(third_export3) }, 771 }; 772 return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata), 773 exportdata, OSSL_NELEM(exportdata)); 774 } 775 776 #ifndef OPENSSL_NO_ECX 777 static const unsigned char fourth_ikme[] = { 778 0x55, 0xbc, 0x24, 0x5e, 0xe4, 0xef, 0xda, 0x25, 779 0xd3, 0x8f, 0x2d, 0x54, 0xd5, 0xbb, 0x66, 0x65, 780 0x29, 0x1b, 0x99, 0xf8, 0x10, 0x8a, 0x8c, 0x4b, 781 0x68, 0x6c, 0x2b, 0x14, 0x89, 0x3e, 0xa5, 0xd9 782 }; 783 static const unsigned char fourth_ikmepub[] = { 784 0xe5, 0xe8, 0xf9, 0xbf, 0xff, 0x6c, 0x2f, 0x29, 785 0x79, 0x1f, 0xc3, 0x51, 0xd2, 0xc2, 0x5c, 0xe1, 786 0x29, 0x9a, 0xa5, 0xea, 0xca, 0x78, 0xa7, 0x57, 787 0xc0, 0xb4, 0xfb, 0x4b, 0xcd, 0x83, 0x09, 0x18 788 }; 789 static const unsigned char fourth_ikmr[] = { 790 0x68, 0x3a, 0xe0, 0xda, 0x1d, 0x22, 0x18, 0x1e, 791 0x74, 0xed, 0x2e, 0x50, 0x3e, 0xbf, 0x82, 0x84, 792 0x0d, 0xeb, 0x1d, 0x5e, 0x87, 0x2c, 0xad, 0xe2, 793 0x0f, 0x4b, 0x45, 0x8d, 0x99, 0x78, 0x3e, 0x31 794 }; 795 static const unsigned char fourth_ikmrpub[] = { 796 0x19, 0x41, 0x41, 0xca, 0x6c, 0x3c, 0x3b, 0xeb, 797 0x47, 0x92, 0xcd, 0x97, 0xba, 0x0e, 0xa1, 0xfa, 798 0xff, 0x09, 0xd9, 0x84, 0x35, 0x01, 0x23, 0x45, 799 0x76, 0x6e, 0xe3, 0x3a, 0xae, 0x2d, 0x76, 0x64 800 }; 801 static const unsigned char fourth_ikmrpriv[] = { 802 0x33, 0xd1, 0x96, 0xc8, 0x30, 0xa1, 0x2f, 0x9a, 803 0xc6, 0x5d, 0x6e, 0x56, 0x5a, 0x59, 0x0d, 0x80, 804 0xf0, 0x4e, 0xe9, 0xb1, 0x9c, 0x83, 0xc8, 0x7f, 805 0x2c, 0x17, 0x0d, 0x97, 0x2a, 0x81, 0x28, 0x48 806 }; 807 static const unsigned char fourth_expected_shared_secret[] = { 808 0xe8, 0x17, 0x16, 0xce, 0x8f, 0x73, 0x14, 0x1d, 809 0x4f, 0x25, 0xee, 0x90, 0x98, 0xef, 0xc9, 0x68, 810 0xc9, 0x1e, 0x5b, 0x8c, 0xe5, 0x2f, 0xff, 0xf5, 811 0x9d, 0x64, 0x03, 0x9e, 0x82, 0x91, 0x8b, 0x66 812 }; 813 static const unsigned char fourth_export1[] = { 814 0x7a, 0x36, 0x22, 0x1b, 0xd5, 0x6d, 0x50, 0xfb, 815 0x51, 0xee, 0x65, 0xed, 0xfd, 0x98, 0xd0, 0x6a, 816 0x23, 0xc4, 0xdc, 0x87, 0x08, 0x5a, 0xa5, 0x86, 817 0x6c, 0xb7, 0x08, 0x72, 0x44, 0xbd, 0x2a, 0x36 818 }; 819 static const unsigned char fourth_context2[] = { 0x00 }; 820 static const unsigned char fourth_export2[] = { 821 0xd5, 0x53, 0x5b, 0x87, 0x09, 0x9c, 0x6c, 0x3c, 822 0xe8, 0x0d, 0xc1, 0x12, 0xa2, 0x67, 0x1c, 0x6e, 823 0xc8, 0xe8, 0x11, 0xa2, 0xf2, 0x84, 0xf9, 0x48, 824 0xce, 0xc6, 0xdd, 0x17, 0x08, 0xee, 0x33, 0xf0 825 }; 826 static const unsigned char fourth_context3[] = { 827 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 828 0x65, 0x78, 0x74 829 }; 830 static const unsigned char fourth_export3[] = { 831 0xff, 0xaa, 0xbc, 0x85, 0xa7, 0x76, 0x13, 0x6c, 832 0xa0, 0xc3, 0x78, 0xe5, 0xd0, 0x84, 0xc9, 0x14, 833 0x0a, 0xb5, 0x52, 0xb7, 0x8f, 0x03, 0x9d, 0x2e, 834 0x87, 0x75, 0xf2, 0x6e, 0xff, 0xf4, 0xc7, 0x0e 835 }; 836 837 static int export_only_test(void) 838 { 839 /* based on RFC9180 A.7 */ 840 const TEST_BASEDATA basedata = { 841 OSSL_HPKE_MODE_BASE, 842 { OSSL_HPKE_KEM_ID_X25519, 843 OSSL_HPKE_KDF_ID_HKDF_SHA256, 844 OSSL_HPKE_AEAD_ID_EXPORTONLY }, 845 fourth_ikme, sizeof(fourth_ikme), 846 fourth_ikmepub, sizeof(fourth_ikmepub), 847 fourth_ikmr, sizeof(fourth_ikmr), 848 fourth_ikmrpub, sizeof(fourth_ikmrpub), 849 fourth_ikmrpriv, sizeof(fourth_ikmrpriv), 850 fourth_expected_shared_secret, sizeof(fourth_expected_shared_secret), 851 ksinfo, sizeof(ksinfo), 852 NULL, 0, /* no auth */ 853 NULL, 0, NULL /* PSK stuff */ 854 }; 855 const TEST_EXPORTDATA exportdata[] = { 856 { NULL, 0, fourth_export1, sizeof(fourth_export1) }, 857 { fourth_context2, sizeof(fourth_context2), 858 fourth_export2, sizeof(fourth_export2) }, 859 { fourth_context3, sizeof(fourth_context3), 860 fourth_export3, sizeof(fourth_export3) }, 861 }; 862 return do_testhpke(&basedata, NULL, 0, 863 exportdata, OSSL_NELEM(exportdata)); 864 } 865 #endif 866 867 /* 868 * Randomly toss a coin 869 */ 870 #define COIN_IS_HEADS (test_random() % 2) 871 872 /* tables of HPKE modes and suite values */ 873 static int hpke_mode_list[] = { 874 OSSL_HPKE_MODE_BASE, 875 OSSL_HPKE_MODE_PSK, 876 OSSL_HPKE_MODE_AUTH, 877 OSSL_HPKE_MODE_PSKAUTH 878 }; 879 static uint16_t hpke_kem_list[] = { 880 OSSL_HPKE_KEM_ID_P256, 881 OSSL_HPKE_KEM_ID_P384, 882 OSSL_HPKE_KEM_ID_P521, 883 #ifndef OPENSSL_NO_ECX 884 OSSL_HPKE_KEM_ID_X25519, 885 OSSL_HPKE_KEM_ID_X448 886 #endif 887 }; 888 static uint16_t hpke_kdf_list[] = { 889 OSSL_HPKE_KDF_ID_HKDF_SHA256, 890 OSSL_HPKE_KDF_ID_HKDF_SHA384, 891 OSSL_HPKE_KDF_ID_HKDF_SHA512 892 }; 893 static uint16_t hpke_aead_list[] = { 894 OSSL_HPKE_AEAD_ID_AES_GCM_128, 895 OSSL_HPKE_AEAD_ID_AES_GCM_256, 896 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) 897 OSSL_HPKE_AEAD_ID_CHACHA_POLY1305 898 #endif 899 }; 900 901 /* 902 * Strings that can be used with names or IANA codepoints. 903 * Note that the initial entries from these lists should 904 * match the lists above, i.e. kem_str_list[0] and 905 * hpke_kem_list[0] should refer to the same KEM. We use 906 * that for verbose output via TEST_note() below. 907 * Subsequent entries are only used for tests of 908 * OSSL_HPKE_str2suite() 909 */ 910 static const char *mode_str_list[] = { 911 "base", "psk", "auth", "pskauth" 912 }; 913 static const char *kem_str_list[] = { 914 #ifndef OPENSSL_NO_ECX 915 "P-256", "P-384", "P-521", "x25519", "x448", 916 "0x10", "0x11", "0x12", "0x20", "0x21", 917 "16", "17", "18", "32", "33" 918 #else 919 "P-256", "P-384", "P-521", 920 "0x10", "0x11", "0x12", 921 "16", "17", "18" 922 #endif 923 }; 924 static const char *kdf_str_list[] = { 925 "hkdf-sha256", "hkdf-sha384", "hkdf-sha512", 926 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03", 927 "1", "2", "3" 928 }; 929 static const char *aead_str_list[] = { 930 "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "exporter", 931 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03", 932 "1", "2", "3", 933 "0xff", "255" 934 }; 935 /* table of bogus strings that better not work */ 936 static const char *bogus_suite_strs[] = { 937 "3,33,3", 938 "bogus,bogus,bogus", 939 "bogus,33,3,1,bogus", 940 "bogus,33,3,1", 941 "bogus,bogus", 942 "bogus", 943 /* one bad token */ 944 "0x10,0x01,bogus", 945 "0x10,bogus,0x01", 946 "bogus,0x02,0x01", 947 /* in reverse order */ 948 "aes-256-gcm,hkdf-sha512,x25519", 949 /* surplus separators */ 950 ",,0x10,0x01,0x02", 951 "0x10,,0x01,0x02", 952 "0x10,0x01,,0x02", 953 /* embedded NUL chars */ 954 "0x10,\00x01,,0x02", 955 "0x10,\0" 956 "0x01,0x02", 957 "0x10\0,0x01,0x02", 958 "0x10,0x01\0,0x02", 959 "0x10,0x01,\0" 960 "0x02", 961 /* embedded whitespace */ 962 " aes-256-gcm,hkdf-sha512,x25519", 963 "aes-256-gcm, hkdf-sha512,x25519", 964 "aes-256-gcm ,hkdf-sha512,x25519", 965 "aes-256-gcm,hkdf-sha512, x25519", 966 "aes-256-gcm,hkdf-sha512 ,x25519", 967 "aes-256-gcm,hkdf-sha512,x25519 ", 968 /* good value followed by extra stuff */ 969 "0x10,0x01,0x02,", 970 "0x10,0x01,0x02,,,", 971 "0x10,0x01,0x01,0x02", 972 "0x10,0x01,0x01,blah", 973 "0x10,0x01,0x01 0x02", 974 /* too few but good tokens */ 975 "0x10,0x01", 976 "0x10", 977 /* empty things */ 978 NULL, 979 "", 980 ",", 981 ",," 982 }; 983 984 /** 985 * @brief round-trips, generating keys, encrypt and decrypt 986 * 987 * This iterates over all mode and ciphersuite options trying 988 * a key gen, encrypt and decrypt for each. The aad, info, and 989 * seq inputs are randomly set or omitted each time. EVP and 990 * non-EVP key generation are randomly selected. 991 * 992 * @return 1 for success, other otherwise 993 */ 994 static int test_hpke_modes_suites(void) 995 { 996 int overallresult = 1; 997 size_t mind = 0; /* index into hpke_mode_list */ 998 size_t kemind = 0; /* index into hpke_kem_list */ 999 size_t kdfind = 0; /* index into hpke_kdf_list */ 1000 size_t aeadind = 0; /* index into hpke_aead_list */ 1001 1002 /* iterate over the different modes */ 1003 for (mind = 0; mind < OSSL_NELEM(hpke_mode_list); mind++) { 1004 int hpke_mode = hpke_mode_list[mind]; 1005 size_t aadlen = OSSL_HPKE_TSTSIZE; 1006 unsigned char aad[OSSL_HPKE_TSTSIZE]; 1007 unsigned char *aadp = NULL; 1008 size_t infolen = 32; 1009 unsigned char info[32]; 1010 unsigned char *infop = NULL; 1011 unsigned char lpsk[32]; 1012 unsigned char *pskp = NULL; 1013 char lpskid[32]; 1014 size_t psklen = 32; 1015 char *pskidp = NULL; 1016 EVP_PKEY *privp = NULL; 1017 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1018 size_t plainlen = OSSL_HPKE_TSTSIZE; 1019 unsigned char plain[OSSL_HPKE_TSTSIZE]; 1020 OSSL_HPKE_CTX *rctx = NULL; 1021 OSSL_HPKE_CTX *ctx = NULL; 1022 1023 memset(plain, 0x00, OSSL_HPKE_TSTSIZE); 1024 strcpy((char *)plain, "a message not in a bottle"); 1025 plainlen = strlen((char *)plain); 1026 /* 1027 * Randomly try with/without info, aad, seq. Given mode and suite 1028 * combos, and this being run even a few times, we'll exercise many 1029 * code paths fairly quickly. We don't really care what the values 1030 * are but it'll be easier to debug if they're known, so we set 'em. 1031 */ 1032 if (COIN_IS_HEADS) { 1033 aadp = aad; 1034 memset(aad, 'a', aadlen); 1035 } else { 1036 aadlen = 0; 1037 } 1038 if (COIN_IS_HEADS) { 1039 infop = info; 1040 memset(info, 'i', infolen); 1041 } else { 1042 infolen = 0; 1043 } 1044 if (hpke_mode == OSSL_HPKE_MODE_PSK 1045 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1046 pskp = lpsk; 1047 memset(lpsk, 'P', psklen); 1048 pskidp = lpskid; 1049 memset(lpskid, 'I', psklen - 1); 1050 lpskid[psklen - 1] = '\0'; 1051 } else { 1052 psklen = 0; 1053 } 1054 for (kemind = 0; /* iterate over the kems, kdfs and aeads */ 1055 overallresult == 1 && kemind < OSSL_NELEM(hpke_kem_list); 1056 kemind++) { 1057 uint16_t kem_id = hpke_kem_list[kemind]; 1058 size_t authpublen = OSSL_HPKE_TSTSIZE; 1059 unsigned char authpub[OSSL_HPKE_TSTSIZE]; 1060 unsigned char *authpubp = NULL; 1061 EVP_PKEY *authpriv = NULL; 1062 1063 hpke_suite.kem_id = kem_id; 1064 if (hpke_mode == OSSL_HPKE_MODE_AUTH 1065 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1066 if (TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, 1067 &authpriv, NULL, 0, 1068 testctx, NULL)) 1069 != 1) { 1070 overallresult = 0; 1071 } 1072 authpubp = authpub; 1073 } else { 1074 authpublen = 0; 1075 } 1076 for (kdfind = 0; 1077 overallresult == 1 && kdfind < OSSL_NELEM(hpke_kdf_list); 1078 kdfind++) { 1079 uint16_t kdf_id = hpke_kdf_list[kdfind]; 1080 1081 hpke_suite.kdf_id = kdf_id; 1082 for (aeadind = 0; 1083 overallresult == 1 1084 && aeadind < OSSL_NELEM(hpke_aead_list); 1085 aeadind++) { 1086 uint16_t aead_id = hpke_aead_list[aeadind]; 1087 size_t publen = OSSL_HPKE_TSTSIZE; 1088 unsigned char pub[OSSL_HPKE_TSTSIZE]; 1089 size_t senderpublen = OSSL_HPKE_TSTSIZE; 1090 unsigned char senderpub[OSSL_HPKE_TSTSIZE]; 1091 size_t cipherlen = OSSL_HPKE_TSTSIZE; 1092 unsigned char cipher[OSSL_HPKE_TSTSIZE]; 1093 size_t clearlen = OSSL_HPKE_TSTSIZE; 1094 unsigned char clear[OSSL_HPKE_TSTSIZE]; 1095 1096 hpke_suite.aead_id = aead_id; 1097 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, 1098 pub, &publen, &privp, 1099 NULL, 0, testctx, NULL))) 1100 overallresult = 0; 1101 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1102 OSSL_HPKE_ROLE_SENDER, 1103 testctx, NULL))) 1104 overallresult = 0; 1105 if (hpke_mode == OSSL_HPKE_MODE_PSK 1106 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1107 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(ctx, pskidp, 1108 pskp, psklen))) 1109 overallresult = 0; 1110 } 1111 if (hpke_mode == OSSL_HPKE_MODE_AUTH 1112 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1113 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx, 1114 authpriv))) 1115 overallresult = 0; 1116 } 1117 if (!TEST_true(OSSL_HPKE_encap(ctx, senderpub, 1118 &senderpublen, 1119 pub, publen, 1120 infop, infolen))) 1121 overallresult = 0; 1122 /* throw in a call with a too-short cipherlen */ 1123 cipherlen = 15; 1124 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, 1125 aadp, aadlen, 1126 plain, plainlen))) 1127 overallresult = 0; 1128 /* fix back real cipherlen */ 1129 cipherlen = OSSL_HPKE_TSTSIZE; 1130 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, 1131 aadp, aadlen, 1132 plain, plainlen))) 1133 overallresult = 0; 1134 OSSL_HPKE_CTX_free(ctx); 1135 memset(clear, 0, clearlen); 1136 rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1137 OSSL_HPKE_ROLE_RECEIVER, 1138 testctx, NULL); 1139 if (!TEST_ptr(rctx)) 1140 overallresult = 0; 1141 if (hpke_mode == OSSL_HPKE_MODE_PSK 1142 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1143 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(rctx, pskidp, 1144 pskp, psklen))) 1145 overallresult = 0; 1146 } 1147 if (hpke_mode == OSSL_HPKE_MODE_AUTH 1148 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { 1149 /* check a borked p256 key */ 1150 if (hpke_suite.kem_id == OSSL_HPKE_KEM_ID_P256) { 1151 /* set to fail decode of authpub this time */ 1152 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(rctx, 1153 authpub, 1154 10))) 1155 overallresult = 0; 1156 } 1157 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx, 1158 authpubp, 1159 authpublen))) 1160 overallresult = 0; 1161 } 1162 if (!TEST_true(OSSL_HPKE_decap(rctx, senderpub, 1163 senderpublen, privp, 1164 infop, infolen))) 1165 overallresult = 0; 1166 /* throw in a call with a too-short clearlen */ 1167 clearlen = 15; 1168 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, 1169 aadp, aadlen, cipher, 1170 cipherlen))) 1171 overallresult = 0; 1172 /* fix up real clearlen again */ 1173 clearlen = OSSL_HPKE_TSTSIZE; 1174 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, 1175 aadp, aadlen, cipher, 1176 cipherlen))) 1177 overallresult = 0; 1178 OSSL_HPKE_CTX_free(rctx); 1179 EVP_PKEY_free(privp); 1180 privp = NULL; 1181 /* check output */ 1182 if (!TEST_mem_eq(clear, clearlen, plain, plainlen)) { 1183 overallresult = 0; 1184 } 1185 if (verbose || overallresult != 1) { 1186 const char *res = NULL; 1187 1188 res = (overallresult == 1 ? "worked" : "failed"); 1189 TEST_note("HPKE %s for mode: %s/0x%02x, " 1190 "kem: %s/0x%02x, kdf: %s/0x%02x, " 1191 "aead: %s/0x%02x", 1192 res, 1193 mode_str_list[mind], (int)mind, 1194 kem_str_list[kemind], kem_id, 1195 kdf_str_list[kdfind], kdf_id, 1196 aead_str_list[aeadind], aead_id); 1197 } 1198 } 1199 } 1200 EVP_PKEY_free(authpriv); 1201 } 1202 } 1203 return overallresult; 1204 } 1205 1206 /** 1207 * @brief check roundtrip for export 1208 * @return 1 for success, other otherwise 1209 */ 1210 static int test_hpke_export(void) 1211 { 1212 int erv = 0; 1213 EVP_PKEY *privp = NULL; 1214 unsigned char pub[OSSL_HPKE_TSTSIZE]; 1215 size_t publen = sizeof(pub); 1216 int hpke_mode = OSSL_HPKE_MODE_BASE; 1217 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1218 OSSL_HPKE_CTX *ctx = NULL; 1219 OSSL_HPKE_CTX *rctx = NULL; 1220 unsigned char exp[32]; 1221 unsigned char exp2[32]; 1222 unsigned char rexp[32]; 1223 unsigned char rexp2[32]; 1224 unsigned char plain[] = "quick brown fox"; 1225 size_t plainlen = sizeof(plain); 1226 unsigned char enc[OSSL_HPKE_TSTSIZE]; 1227 size_t enclen = sizeof(enc); 1228 unsigned char cipher[OSSL_HPKE_TSTSIZE]; 1229 size_t cipherlen = sizeof(cipher); 1230 unsigned char clear[OSSL_HPKE_TSTSIZE]; 1231 size_t clearlen = sizeof(clear); 1232 char *estr = "foo"; 1233 1234 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1235 NULL, 0, testctx, NULL))) 1236 goto end; 1237 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1238 OSSL_HPKE_ROLE_SENDER, 1239 testctx, NULL))) 1240 goto end; 1241 /* a few error cases 1st */ 1242 if (!TEST_false(OSSL_HPKE_export(NULL, exp, sizeof(exp), 1243 (unsigned char *)estr, strlen(estr)))) 1244 goto end; 1245 /* ctx before encap should fail too */ 1246 if (!TEST_false(OSSL_HPKE_export(ctx, exp, sizeof(exp), 1247 (unsigned char *)estr, strlen(estr)))) 1248 goto end; 1249 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 1250 goto end; 1251 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 1252 plain, plainlen))) 1253 goto end; 1254 /* now for real */ 1255 if (!TEST_true(OSSL_HPKE_export(ctx, exp, sizeof(exp), 1256 (unsigned char *)estr, strlen(estr)))) 1257 goto end; 1258 /* check a 2nd call with same input gives same output */ 1259 if (!TEST_true(OSSL_HPKE_export(ctx, exp2, sizeof(exp2), 1260 (unsigned char *)estr, strlen(estr)))) 1261 goto end; 1262 if (!TEST_mem_eq(exp, sizeof(exp), exp2, sizeof(exp2))) 1263 goto end; 1264 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1265 OSSL_HPKE_ROLE_RECEIVER, 1266 testctx, NULL))) 1267 goto end; 1268 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 1269 goto end; 1270 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1271 cipher, cipherlen))) 1272 goto end; 1273 if (!TEST_true(OSSL_HPKE_export(rctx, rexp, sizeof(rexp), 1274 (unsigned char *)estr, strlen(estr)))) 1275 goto end; 1276 /* check a 2nd call with same input gives same output */ 1277 if (!TEST_true(OSSL_HPKE_export(rctx, rexp2, sizeof(rexp2), 1278 (unsigned char *)estr, strlen(estr)))) 1279 goto end; 1280 if (!TEST_mem_eq(rexp, sizeof(rexp), rexp2, sizeof(rexp2))) 1281 goto end; 1282 if (!TEST_mem_eq(exp, sizeof(exp), rexp, sizeof(rexp))) 1283 goto end; 1284 erv = 1; 1285 end: 1286 OSSL_HPKE_CTX_free(ctx); 1287 OSSL_HPKE_CTX_free(rctx); 1288 EVP_PKEY_free(privp); 1289 return erv; 1290 } 1291 1292 /** 1293 * @brief Check mapping from strings to HPKE suites 1294 * @return 1 for success, other otherwise 1295 */ 1296 static int test_hpke_suite_strs(void) 1297 { 1298 int overallresult = 1; 1299 int kemind = 0; 1300 int kdfind = 0; 1301 int aeadind = 0; 1302 int sind = 0; 1303 char sstr[128]; 1304 OSSL_HPKE_SUITE stirred; 1305 char giant[2048]; 1306 1307 for (kemind = 0; kemind != OSSL_NELEM(kem_str_list); kemind++) { 1308 for (kdfind = 0; kdfind != OSSL_NELEM(kdf_str_list); kdfind++) { 1309 for (aeadind = 0; aeadind != OSSL_NELEM(aead_str_list); aeadind++) { 1310 BIO_snprintf(sstr, 128, "%s,%s,%s", kem_str_list[kemind], 1311 kdf_str_list[kdfind], aead_str_list[aeadind]); 1312 if (TEST_true(OSSL_HPKE_str2suite(sstr, &stirred)) != 1) { 1313 if (verbose) 1314 TEST_note("Unexpected str2suite fail for :%s", 1315 bogus_suite_strs[sind]); 1316 overallresult = 0; 1317 } 1318 } 1319 } 1320 } 1321 for (sind = 0; sind != OSSL_NELEM(bogus_suite_strs); sind++) { 1322 if (TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs[sind], 1323 &stirred)) 1324 != 1) { 1325 if (verbose) 1326 TEST_note("OSSL_HPKE_str2suite didn't fail for bogus[%d]:%s", 1327 sind, bogus_suite_strs[sind]); 1328 overallresult = 0; 1329 } 1330 } 1331 /* check a few errors */ 1332 if (!TEST_false(OSSL_HPKE_str2suite("", &stirred))) 1333 overallresult = 0; 1334 if (!TEST_false(OSSL_HPKE_str2suite(NULL, &stirred))) 1335 overallresult = 0; 1336 if (!TEST_false(OSSL_HPKE_str2suite("", NULL))) 1337 overallresult = 0; 1338 memset(giant, 'A', sizeof(giant) - 1); 1339 giant[sizeof(giant) - 1] = '\0'; 1340 if (!TEST_false(OSSL_HPKE_str2suite(giant, &stirred))) 1341 overallresult = 0; 1342 1343 return overallresult; 1344 } 1345 1346 /** 1347 * @brief try the various GREASEy APIs 1348 * @return 1 for success, other otherwise 1349 */ 1350 static int test_hpke_grease(void) 1351 { 1352 int overallresult = 1; 1353 OSSL_HPKE_SUITE g_suite; 1354 unsigned char g_pub[OSSL_HPKE_TSTSIZE]; 1355 size_t g_pub_len = OSSL_HPKE_TSTSIZE; 1356 unsigned char g_cipher[OSSL_HPKE_TSTSIZE]; 1357 size_t g_cipher_len = 266; 1358 size_t clearlen = 128; 1359 size_t expanded = 0; 1360 size_t enclen = 0; 1361 size_t ikmelen = 0; 1362 1363 memset(&g_suite, 0, sizeof(OSSL_HPKE_SUITE)); 1364 /* GREASEing */ 1365 /* check too short for public value */ 1366 g_pub_len = 10; 1367 if (TEST_false(OSSL_HPKE_get_grease_value(NULL, &g_suite, 1368 g_pub, &g_pub_len, 1369 g_cipher, g_cipher_len, 1370 testctx, NULL)) 1371 != 1) { 1372 overallresult = 0; 1373 } 1374 /* reset to work */ 1375 g_pub_len = OSSL_HPKE_TSTSIZE; 1376 if (TEST_true(OSSL_HPKE_get_grease_value(NULL, &g_suite, 1377 g_pub, &g_pub_len, 1378 g_cipher, g_cipher_len, 1379 testctx, NULL)) 1380 != 1) { 1381 overallresult = 0; 1382 } 1383 /* expansion */ 1384 expanded = OSSL_HPKE_get_ciphertext_size(g_suite, clearlen); 1385 if (!TEST_size_t_gt(expanded, clearlen)) { 1386 overallresult = 0; 1387 } 1388 enclen = OSSL_HPKE_get_public_encap_size(g_suite); 1389 if (!TEST_size_t_ne(enclen, 0)) 1390 overallresult = 0; 1391 /* not really GREASE but we'll check ikmelen thing */ 1392 ikmelen = OSSL_HPKE_get_recommended_ikmelen(g_suite); 1393 if (!TEST_size_t_ne(ikmelen, 0)) 1394 overallresult = 0; 1395 1396 return overallresult; 1397 } 1398 1399 /* 1400 * Make a set of calls with odd parameters 1401 */ 1402 static int test_hpke_oddcalls(void) 1403 { 1404 int erv = 0; 1405 EVP_PKEY *privp = NULL; 1406 unsigned char pub[OSSL_HPKE_TSTSIZE]; 1407 size_t publen = sizeof(pub); 1408 int hpke_mode = OSSL_HPKE_MODE_BASE; 1409 int bad_mode = 0xbad; 1410 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1411 OSSL_HPKE_SUITE bad_suite = { 0xbad, 0xbad, 0xbad }; 1412 OSSL_HPKE_CTX *ctx = NULL; 1413 OSSL_HPKE_CTX *rctx = NULL; 1414 unsigned char plain[] = "quick brown fox"; 1415 size_t plainlen = sizeof(plain); 1416 unsigned char enc[OSSL_HPKE_TSTSIZE], smallenc[10]; 1417 size_t enclen = sizeof(enc), smallenclen = sizeof(smallenc); 1418 unsigned char cipher[OSSL_HPKE_TSTSIZE]; 1419 size_t cipherlen = sizeof(cipher); 1420 unsigned char clear[OSSL_HPKE_TSTSIZE]; 1421 size_t clearlen = sizeof(clear); 1422 unsigned char fake_ikm[OSSL_HPKE_TSTSIZE]; 1423 char *badpropq = "yeah, this won't work"; 1424 uint64_t lseq = 0; 1425 char giant_pskid[OSSL_HPKE_MAX_PARMLEN + 10]; 1426 unsigned char info[OSSL_HPKE_TSTSIZE]; 1427 1428 /* many of the calls below are designed to get better test coverage */ 1429 1430 /* NULL ctx calls */ 1431 OSSL_HPKE_CTX_free(NULL); 1432 if (!TEST_false(OSSL_HPKE_CTX_set_seq(NULL, 1))) 1433 goto end; 1434 if (!TEST_false(OSSL_HPKE_CTX_get_seq(NULL, &lseq))) 1435 goto end; 1436 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(NULL, pub, publen))) 1437 goto end; 1438 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(NULL, privp))) 1439 goto end; 1440 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(NULL, NULL, 0))) 1441 goto end; 1442 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(NULL, NULL, NULL, 0))) 1443 goto end; 1444 1445 /* bad suite calls */ 1446 hpke_suite.aead_id = 0xbad; 1447 if (!TEST_false(OSSL_HPKE_suite_check(hpke_suite))) 1448 goto end; 1449 hpke_suite.aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128; 1450 if (!TEST_false(OSSL_HPKE_suite_check(bad_suite))) 1451 goto end; 1452 if (!TEST_false(OSSL_HPKE_get_recommended_ikmelen(bad_suite))) 1453 goto end; 1454 if (!TEST_false(OSSL_HPKE_get_public_encap_size(bad_suite))) 1455 goto end; 1456 if (!TEST_false(OSSL_HPKE_get_ciphertext_size(bad_suite, 0))) 1457 goto end; 1458 if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp, 1459 NULL, 0, testctx, badpropq))) 1460 goto end; 1461 if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp, 1462 NULL, 0, testctx, NULL))) 1463 goto end; 1464 1465 /* dodgy keygen calls */ 1466 /* no pub */ 1467 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, NULL, &publen, &privp, 1468 NULL, 0, testctx, NULL))) 1469 goto end; 1470 /* ikmlen but NULL ikm */ 1471 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1472 NULL, 80, testctx, NULL))) 1473 goto end; 1474 /* zero ikmlen but ikm */ 1475 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1476 fake_ikm, 0, testctx, NULL))) 1477 goto end; 1478 /* GIANT ikmlen */ 1479 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1480 fake_ikm, -1, testctx, NULL))) 1481 goto end; 1482 /* short publen */ 1483 publen = 10; 1484 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1485 NULL, 0, testctx, NULL))) 1486 goto end; 1487 publen = sizeof(pub); 1488 1489 /* encap/decap with NULLs */ 1490 if (!TEST_false(OSSL_HPKE_encap(NULL, NULL, NULL, NULL, 0, NULL, 0))) 1491 goto end; 1492 if (!TEST_false(OSSL_HPKE_decap(NULL, NULL, 0, NULL, NULL, 0))) 1493 goto end; 1494 1495 /* 1496 * run through a sender/recipient set of calls but with 1497 * failing calls interspersed whenever possible 1498 */ 1499 /* good keygen */ 1500 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1501 NULL, 0, testctx, NULL))) 1502 goto end; 1503 1504 /* a psk context with no psk => encap fail */ 1505 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite, 1506 OSSL_HPKE_ROLE_SENDER, 1507 testctx, NULL))) 1508 goto end; 1509 /* set bad length psk */ 1510 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo", 1511 (unsigned char *)"bar", -1))) 1512 goto end; 1513 /* set bad length pskid */ 1514 memset(giant_pskid, 'A', sizeof(giant_pskid) - 1); 1515 giant_pskid[sizeof(giant_pskid) - 1] = '\0'; 1516 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, giant_pskid, 1517 (unsigned char *)"bar", 3))) 1518 goto end; 1519 /* still no psk really set so encap fails */ 1520 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 1521 goto end; 1522 OSSL_HPKE_CTX_free(ctx); 1523 1524 /* bad suite */ 1525 if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(hpke_mode, bad_suite, 1526 OSSL_HPKE_ROLE_SENDER, 1527 testctx, NULL))) 1528 goto end; 1529 /* bad mode */ 1530 if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(bad_mode, hpke_suite, 1531 OSSL_HPKE_ROLE_SENDER, 1532 testctx, NULL))) 1533 goto end; 1534 /* make good ctx */ 1535 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1536 OSSL_HPKE_ROLE_SENDER, 1537 testctx, NULL))) 1538 goto end; 1539 /* too long ikm */ 1540 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, -1))) 1541 goto end; 1542 /* zero length ikm */ 1543 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, 0))) 1544 goto end; 1545 /* NULL authpub */ 1546 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(ctx, NULL, 0))) 1547 goto end; 1548 /* NULL auth priv */ 1549 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, NULL))) 1550 goto end; 1551 /* priv good, but mode is bad */ 1552 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, privp))) 1553 goto end; 1554 /* bad mode for psk */ 1555 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo", 1556 (unsigned char *)"bar", 3))) 1557 goto end; 1558 /* seal before encap */ 1559 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 1560 plain, plainlen))) 1561 goto end; 1562 /* encap with dodgy public */ 1563 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, NULL, 0))) 1564 goto end; 1565 /* encap with too big info */ 1566 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, info, -1))) 1567 goto end; 1568 /* encap with NULL info & non-zero infolen */ 1569 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, NULL, 1))) 1570 goto end; 1571 /* encap with non-NULL info & zero infolen */ 1572 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, info, 0))) 1573 goto end; 1574 /* encap with too small enc */ 1575 if (!TEST_false(OSSL_HPKE_encap(ctx, smallenc, &smallenclen, pub, 1, NULL, 0))) 1576 goto end; 1577 /* good encap */ 1578 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 1579 goto end; 1580 /* second encap fail */ 1581 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 1582 goto end; 1583 plainlen = 0; 1584 /* should fail for no plaintext */ 1585 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 1586 plain, plainlen))) 1587 goto end; 1588 plainlen = sizeof(plain); 1589 /* working seal */ 1590 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 1591 plain, plainlen))) 1592 goto end; 1593 1594 /* receiver side */ 1595 /* decap fail with psk mode but no psk set */ 1596 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite, 1597 OSSL_HPKE_ROLE_RECEIVER, 1598 testctx, NULL))) 1599 goto end; 1600 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 1601 goto end; 1602 /* done with PSK mode */ 1603 OSSL_HPKE_CTX_free(rctx); 1604 1605 /* back good calls for base mode */ 1606 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1607 OSSL_HPKE_ROLE_RECEIVER, 1608 testctx, NULL))) 1609 goto end; 1610 /* open before decap */ 1611 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1612 cipher, cipherlen))) 1613 goto end; 1614 /* decap with info too long */ 1615 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, info, -1))) 1616 goto end; 1617 /* good decap */ 1618 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 1619 goto end; 1620 /* second decap fail */ 1621 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 1622 goto end; 1623 /* no space for recovered clear */ 1624 clearlen = 0; 1625 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1626 cipher, cipherlen))) 1627 goto end; 1628 clearlen = OSSL_HPKE_TSTSIZE; 1629 /* seq wrap around test */ 1630 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, -1))) 1631 goto end; 1632 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1633 cipher, cipherlen))) 1634 goto end; 1635 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0))) 1636 goto end; 1637 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1638 cipher, cipherlen))) 1639 goto end; 1640 if (!TEST_mem_eq(plain, plainlen, clear, clearlen)) 1641 goto end; 1642 erv = 1; 1643 end: 1644 OSSL_HPKE_CTX_free(ctx); 1645 OSSL_HPKE_CTX_free(rctx); 1646 EVP_PKEY_free(privp); 1647 return erv; 1648 } 1649 1650 #ifndef OPENSSL_NO_ECX 1651 /* from RFC 9180 Appendix A.1.1 */ 1652 static const unsigned char ikm25519[] = { 1653 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43, 1654 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13, 1655 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2, 1656 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34 1657 }; 1658 static const unsigned char pub25519[] = { 1659 0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28, 1660 0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d, 1661 0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44, 1662 0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31 1663 }; 1664 #endif 1665 1666 /* from RFC9180 Appendix A.3.1 */ 1667 static const unsigned char ikmp256[] = { 1668 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d, 1669 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f, 1670 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f, 1671 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e 1672 }; 1673 static const unsigned char pubp256[] = { 1674 0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50, 1675 0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14, 1676 0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e, 1677 0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a, 1678 0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4, 1679 0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00, 1680 0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b, 1681 0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18, 1682 0xc4 1683 }; 1684 1685 /* 1686 * A test vector that exercises the counter iteration 1687 * for p256. This was contributed by Ilari L. on the 1688 * CFRG list, see the mail archive: 1689 * https://mailarchive.ietf.org/arch/msg/cfrg/4zwl_y5YN6OU9oeWZOMHNOlOa2w/ 1690 */ 1691 static const unsigned char ikmiter[] = { 1692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1695 0x00, 0x00, 0x00, 0x03, 0x01, 0x38, 0xb5, 0xec 1696 }; 1697 static const unsigned char pubiter[] = { 1698 0x04, 0x7d, 0x0c, 0x87, 0xff, 0xd5, 0xd1, 0x45, 1699 0x54, 0xa7, 0x51, 0xdf, 0xa3, 0x99, 0x26, 0xa9, 1700 0xe3, 0x0e, 0x7c, 0x3c, 0x65, 0x62, 0x4f, 0x4b, 1701 0x5f, 0xb3, 0xad, 0x7a, 0xa4, 0xda, 0xc2, 0x4a, 1702 0xd8, 0xf5, 0xbe, 0xd0, 0xe8, 0x6e, 0xb8, 0x84, 1703 0x1c, 0xe4, 0x89, 0x2e, 0x0f, 0xc3, 0x87, 0xbb, 1704 0xdb, 0xfe, 0x16, 0x0d, 0x58, 0x9c, 0x89, 0x2d, 1705 0xd4, 0xb1, 0x46, 0x4a, 0xc3, 0x51, 0xc5, 0x6f, 1706 0xb6 1707 }; 1708 1709 /* from RFC9180 Appendix A.6.1 */ 1710 static const unsigned char ikmp521[] = { 1711 0x7f, 0x06, 0xab, 0x82, 0x15, 0x10, 0x5f, 0xc4, 1712 0x6a, 0xce, 0xeb, 0x2e, 0x3d, 0xc5, 0x02, 0x8b, 1713 0x44, 0x36, 0x4f, 0x96, 0x04, 0x26, 0xeb, 0x0d, 1714 0x8e, 0x40, 0x26, 0xc2, 0xf8, 0xb5, 0xd7, 0xe7, 1715 0xa9, 0x86, 0x68, 0x8f, 0x15, 0x91, 0xab, 0xf5, 1716 0xab, 0x75, 0x3c, 0x35, 0x7a, 0x5d, 0x6f, 0x04, 1717 0x40, 0x41, 0x4b, 0x4e, 0xd4, 0xed, 0xe7, 0x13, 1718 0x17, 0x77, 0x2a, 0xc9, 0x8d, 0x92, 0x39, 0xf7, 1719 0x09, 0x04 1720 }; 1721 static const unsigned char pubp521[] = { 1722 0x04, 0x01, 0x38, 0xb3, 0x85, 0xca, 0x16, 0xbb, 1723 0x0d, 0x5f, 0xa0, 0xc0, 0x66, 0x5f, 0xbb, 0xd7, 1724 0xe6, 0x9e, 0x3e, 0xe2, 0x9f, 0x63, 0x99, 0x1d, 1725 0x3e, 0x9b, 0x5f, 0xa7, 0x40, 0xaa, 0xb8, 0x90, 1726 0x0a, 0xae, 0xed, 0x46, 0xed, 0x73, 0xa4, 0x90, 1727 0x55, 0x75, 0x84, 0x25, 0xa0, 0xce, 0x36, 0x50, 1728 0x7c, 0x54, 0xb2, 0x9c, 0xc5, 0xb8, 0x5a, 0x5c, 1729 0xee, 0x6b, 0xae, 0x0c, 0xf1, 0xc2, 0x1f, 0x27, 1730 0x31, 0xec, 0xe2, 0x01, 0x3d, 0xc3, 0xfb, 0x7c, 1731 0x8d, 0x21, 0x65, 0x4b, 0xb1, 0x61, 0xb4, 0x63, 1732 0x96, 0x2c, 0xa1, 0x9e, 0x8c, 0x65, 0x4f, 0xf2, 1733 0x4c, 0x94, 0xdd, 0x28, 0x98, 0xde, 0x12, 0x05, 1734 0x1f, 0x1e, 0xd0, 0x69, 0x22, 0x37, 0xfb, 0x02, 1735 0xb2, 0xf8, 0xd1, 0xdc, 0x1c, 0x73, 0xe9, 0xb3, 1736 0x66, 0xb5, 0x29, 0xeb, 0x43, 0x6e, 0x98, 0xa9, 1737 0x96, 0xee, 0x52, 0x2a, 0xef, 0x86, 0x3d, 0xd5, 1738 0x73, 0x9d, 0x2f, 0x29, 0xb0 1739 }; 1740 1741 static int test_hpke_random_suites(void) 1742 { 1743 OSSL_HPKE_SUITE def_suite = OSSL_HPKE_SUITE_DEFAULT; 1744 OSSL_HPKE_SUITE suite = OSSL_HPKE_SUITE_DEFAULT; 1745 OSSL_HPKE_SUITE suite2 = { 0xff01, 0xff02, 0xff03 }; 1746 unsigned char enc[200]; 1747 size_t enclen = sizeof(enc); 1748 unsigned char ct[500]; 1749 size_t ctlen = sizeof(ct); 1750 1751 /* test with NULL/0 inputs */ 1752 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL, NULL, 1753 NULL, NULL, NULL, 0, 1754 testctx, NULL))) 1755 return 0; 1756 enclen = 10; 1757 if (!TEST_false(OSSL_HPKE_get_grease_value(&def_suite, &suite2, 1758 enc, &enclen, ct, ctlen, 1759 testctx, NULL))) 1760 return 0; 1761 1762 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */ 1763 /* test with a should-be-good suite */ 1764 if (!TEST_true(OSSL_HPKE_get_grease_value(&def_suite, &suite2, 1765 enc, &enclen, ct, ctlen, 1766 testctx, NULL))) 1767 return 0; 1768 /* no suggested suite */ 1769 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */ 1770 if (!TEST_true(OSSL_HPKE_get_grease_value(NULL, &suite2, 1771 enc, &enclen, 1772 ct, ctlen, 1773 testctx, NULL))) 1774 return 0; 1775 /* suggested suite with P-521, just to be sure we hit long values */ 1776 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */ 1777 suite.kem_id = OSSL_HPKE_KEM_ID_P521; 1778 if (!TEST_true(OSSL_HPKE_get_grease_value(&suite, &suite2, 1779 enc, &enclen, ct, ctlen, 1780 testctx, NULL))) 1781 return 0; 1782 enclen = sizeof(enc); 1783 ctlen = 2; /* too-short cttext (can't fit an aead tag) */ 1784 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL, &suite2, 1785 enc, &enclen, ct, ctlen, 1786 testctx, NULL))) 1787 return 0; 1788 1789 ctlen = sizeof(ct); 1790 enclen = sizeof(enc); 1791 1792 suite.kem_id = OSSL_HPKE_KEM_ID_X25519; /* back to default */ 1793 suite.aead_id = 0x1234; /* bad aead */ 1794 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2, 1795 enc, &enclen, ct, ctlen, 1796 testctx, NULL))) 1797 return 0; 1798 enclen = sizeof(enc); 1799 suite.aead_id = def_suite.aead_id; /* good aead */ 1800 suite.kdf_id = 0x3451; /* bad kdf */ 1801 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2, 1802 enc, &enclen, ct, ctlen, 1803 testctx, NULL))) 1804 return 0; 1805 enclen = sizeof(enc); 1806 suite.kdf_id = def_suite.kdf_id; /* good kdf */ 1807 suite.kem_id = 0x4517; /* bad kem */ 1808 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2, 1809 enc, &enclen, ct, ctlen, 1810 testctx, NULL))) 1811 return 0; 1812 return 1; 1813 } 1814 1815 /* 1816 * @brief generate a key pair from initial key material (ikm) and check public 1817 * @param kem_id the KEM to use (RFC9180 code point) 1818 * @ikm is the initial key material buffer 1819 * @ikmlen is the length of ikm 1820 * @pub is the public key buffer 1821 * @publen is the length of the public key 1822 * @return 1 for good, other otherwise 1823 * 1824 * This calls OSSL_HPKE_keygen specifying only the IKM, then 1825 * compares the key pair values with the already-known values 1826 * that were input. 1827 */ 1828 static int test_hpke_one_ikm_gen(uint16_t kem_id, 1829 const unsigned char *ikm, size_t ikmlen, 1830 const unsigned char *pub, size_t publen) 1831 { 1832 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1833 unsigned char lpub[OSSL_HPKE_TSTSIZE]; 1834 size_t lpublen = OSSL_HPKE_TSTSIZE; 1835 EVP_PKEY *sk = NULL; 1836 1837 hpke_suite.kem_id = kem_id; 1838 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, lpub, &lpublen, &sk, 1839 ikm, ikmlen, testctx, NULL))) 1840 return 0; 1841 if (!TEST_ptr(sk)) 1842 return 0; 1843 EVP_PKEY_free(sk); 1844 if (!TEST_mem_eq(pub, publen, lpub, lpublen)) 1845 return 0; 1846 return 1; 1847 } 1848 1849 /* 1850 * @brief test some uses of IKM produce the expected public keys 1851 */ 1852 static int test_hpke_ikms(void) 1853 { 1854 int res = 1; 1855 1856 #ifndef OPENSSL_NO_ECX 1857 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_X25519, 1858 ikm25519, sizeof(ikm25519), 1859 pub25519, sizeof(pub25519)); 1860 if (res != 1) 1861 return res; 1862 #endif 1863 1864 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P521, 1865 ikmp521, sizeof(ikmp521), 1866 pubp521, sizeof(pubp521)); 1867 if (res != 1) 1868 return res; 1869 1870 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256, 1871 ikmp256, sizeof(ikmp256), 1872 pubp256, sizeof(pubp256)); 1873 if (res != 1) 1874 return res; 1875 1876 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256, 1877 ikmiter, sizeof(ikmiter), 1878 pubiter, sizeof(pubiter)); 1879 if (res != 1) 1880 return res; 1881 1882 return res; 1883 } 1884 1885 /* 1886 * Test that use of a compressed format auth public key works 1887 * We'll do a typical round-trip for auth mode but provide the 1888 * auth public key in compressed form. That should work. 1889 */ 1890 static int test_hpke_compressed(void) 1891 { 1892 int erv = 0; 1893 EVP_PKEY *privp = NULL; 1894 unsigned char pub[OSSL_HPKE_TSTSIZE]; 1895 size_t publen = sizeof(pub); 1896 EVP_PKEY *authpriv = NULL; 1897 unsigned char authpub[OSSL_HPKE_TSTSIZE]; 1898 size_t authpublen = sizeof(authpub); 1899 int hpke_mode = OSSL_HPKE_MODE_AUTH; 1900 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1901 OSSL_HPKE_CTX *ctx = NULL; 1902 OSSL_HPKE_CTX *rctx = NULL; 1903 unsigned char plain[] = "quick brown fox"; 1904 size_t plainlen = sizeof(plain); 1905 unsigned char enc[OSSL_HPKE_TSTSIZE]; 1906 size_t enclen = sizeof(enc); 1907 unsigned char cipher[OSSL_HPKE_TSTSIZE]; 1908 size_t cipherlen = sizeof(cipher); 1909 unsigned char clear[OSSL_HPKE_TSTSIZE]; 1910 size_t clearlen = sizeof(clear); 1911 1912 hpke_suite.kem_id = OSSL_HPKE_KEM_ID_P256; 1913 1914 /* generate auth key pair */ 1915 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, &authpriv, 1916 NULL, 0, testctx, NULL))) 1917 goto end; 1918 /* now get the compressed form public key */ 1919 if (!TEST_true(EVP_PKEY_set_utf8_string_param(authpriv, 1920 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, 1921 OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED))) 1922 goto end; 1923 if (!TEST_true(EVP_PKEY_get_octet_string_param(authpriv, 1924 OSSL_PKEY_PARAM_PUB_KEY, 1925 authpub, 1926 sizeof(authpub), 1927 &authpublen))) 1928 goto end; 1929 1930 /* sender side as usual */ 1931 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1932 NULL, 0, testctx, NULL))) 1933 goto end; 1934 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1935 OSSL_HPKE_ROLE_SENDER, 1936 testctx, NULL))) 1937 goto end; 1938 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx, authpriv))) 1939 goto end; 1940 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 1941 goto end; 1942 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 1943 plain, plainlen))) 1944 goto end; 1945 1946 /* receiver side providing compressed form of auth public */ 1947 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1948 OSSL_HPKE_ROLE_RECEIVER, 1949 testctx, NULL))) 1950 goto end; 1951 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx, authpub, authpublen))) 1952 goto end; 1953 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 1954 goto end; 1955 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 1956 cipher, cipherlen))) 1957 goto end; 1958 erv = 1; 1959 1960 end: 1961 EVP_PKEY_free(privp); 1962 EVP_PKEY_free(authpriv); 1963 OSSL_HPKE_CTX_free(ctx); 1964 OSSL_HPKE_CTX_free(rctx); 1965 return erv; 1966 } 1967 1968 /* 1969 * Test that nonce reuse calls are prevented as we expect 1970 */ 1971 static int test_hpke_noncereuse(void) 1972 { 1973 int erv = 0; 1974 EVP_PKEY *privp = NULL; 1975 unsigned char pub[OSSL_HPKE_TSTSIZE]; 1976 size_t publen = sizeof(pub); 1977 int hpke_mode = OSSL_HPKE_MODE_BASE; 1978 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; 1979 OSSL_HPKE_CTX *ctx = NULL; 1980 OSSL_HPKE_CTX *rctx = NULL; 1981 unsigned char plain[] = "quick brown fox"; 1982 size_t plainlen = sizeof(plain); 1983 unsigned char enc[OSSL_HPKE_TSTSIZE]; 1984 size_t enclen = sizeof(enc); 1985 unsigned char cipher[OSSL_HPKE_TSTSIZE]; 1986 size_t cipherlen = sizeof(cipher); 1987 unsigned char clear[OSSL_HPKE_TSTSIZE]; 1988 size_t clearlen = sizeof(clear); 1989 uint64_t seq = 0xbad1dea; 1990 1991 /* sender side is not allowed set seq once some crypto done */ 1992 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp, 1993 NULL, 0, testctx, NULL))) 1994 goto end; 1995 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 1996 OSSL_HPKE_ROLE_SENDER, 1997 testctx, NULL))) 1998 goto end; 1999 /* set seq will fail before any crypto done */ 2000 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq))) 2001 goto end; 2002 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0))) 2003 goto end; 2004 /* set seq will also fail after some crypto done */ 2005 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq + 1))) 2006 goto end; 2007 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0, 2008 plain, plainlen))) 2009 goto end; 2010 2011 /* receiver side is allowed control seq */ 2012 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, 2013 OSSL_HPKE_ROLE_RECEIVER, 2014 testctx, NULL))) 2015 goto end; 2016 /* set seq will work before any crypto done */ 2017 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq))) 2018 goto end; 2019 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0))) 2020 goto end; 2021 /* set seq will work for receivers even after crypto done */ 2022 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq))) 2023 goto end; 2024 /* but that value isn't good so decap will fail */ 2025 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 2026 cipher, cipherlen))) 2027 goto end; 2028 /* reset seq to correct value and _open() should work */ 2029 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0))) 2030 goto end; 2031 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0, 2032 cipher, cipherlen))) 2033 goto end; 2034 erv = 1; 2035 2036 end: 2037 EVP_PKEY_free(privp); 2038 OSSL_HPKE_CTX_free(ctx); 2039 OSSL_HPKE_CTX_free(rctx); 2040 return erv; 2041 } 2042 2043 typedef enum OPTION_choice { 2044 OPT_ERR = -1, 2045 OPT_EOF = 0, 2046 OPT_VERBOSE, 2047 OPT_TEST_ENUM 2048 } OPTION_CHOICE; 2049 2050 const OPTIONS *test_get_options(void) 2051 { 2052 static const OPTIONS test_options[] = { 2053 OPT_TEST_OPTIONS_DEFAULT_USAGE, 2054 { "v", OPT_VERBOSE, '-', "Enable verbose mode" }, 2055 { OPT_HELP_STR, 1, '-', "Run HPKE tests\n" }, 2056 { NULL } 2057 }; 2058 return test_options; 2059 } 2060 2061 int setup_tests(void) 2062 { 2063 OPTION_CHOICE o; 2064 2065 while ((o = opt_next()) != OPT_EOF) { 2066 switch (o) { 2067 case OPT_VERBOSE: 2068 verbose = 1; /* Print progress dots */ 2069 break; 2070 case OPT_TEST_CASES: 2071 break; 2072 default: 2073 return 0; 2074 } 2075 } 2076 2077 if (!test_get_libctx(&testctx, &nullprov, NULL, &deflprov, "default")) 2078 return 0; 2079 #ifndef OPENSSL_NO_ECX 2080 ADD_TEST(export_only_test); 2081 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_base_test); 2082 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_psk_test); 2083 #endif 2084 ADD_TEST(P256kdfsha256_hkdfsha256_aes128gcm_base_test); 2085 ADD_TEST(test_hpke_export); 2086 ADD_TEST(test_hpke_modes_suites); 2087 ADD_TEST(test_hpke_suite_strs); 2088 ADD_TEST(test_hpke_grease); 2089 ADD_TEST(test_hpke_ikms); 2090 ADD_TEST(test_hpke_random_suites); 2091 ADD_TEST(test_hpke_oddcalls); 2092 ADD_TEST(test_hpke_compressed); 2093 ADD_TEST(test_hpke_noncereuse); 2094 return 1; 2095 } 2096 2097 void cleanup_tests(void) 2098 { 2099 OSSL_PROVIDER_unload(deflprov); 2100 OSSL_PROVIDER_unload(nullprov); 2101 OSSL_LIB_CTX_free(testctx); 2102 } 2103