2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/evp.h>
11 #include <openssl/core_names.h>
12 #include <openssl/rand.h>
13 #include <openssl/hpke.h>
16 /* a size to use for stack buffers */
17 #define OSSL_HPKE_TSTSIZE 512
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;
27 OSSL_HPKE_SUITE suite;
28 const unsigned char *ikmE;
30 const unsigned char *expected_pkEm;
31 size_t expected_pkEmlen;
32 const unsigned char *ikmR;
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;
42 const unsigned char *ikmAuth;
44 const unsigned char *psk;
46 const char *pskid; /* want terminating NUL here */
52 const unsigned char *pt;
54 const unsigned char *aad;
56 const unsigned char *expected_ct;
57 size_t expected_ctlen;
62 const unsigned char *context;
64 const unsigned char *expected_secret;
65 size_t expected_secretlen;
69 * @brief Test that an EVP_PKEY encoded public key matches the supplied buffer
70 * @param pkey is the EVP_PKEY we want to check
71 * @param pub is the expected public key buffer
72 * @param publen is the length of the above
73 * @return 1 for good, 0 for bad
75 static int cmpkey(const EVP_PKEY *pkey,
76 const unsigned char *pub, size_t publen)
78 unsigned char pubbuf[256];
82 if (!TEST_true(publen <= sizeof(pubbuf)))
84 erv = EVP_PKEY_get_octet_string_param(pkey,
85 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
86 pubbuf, sizeof(pubbuf), &pubbuflen);
89 if (pub != NULL && !TEST_mem_eq(pubbuf, pubbuflen, pub, publen))
94 static int do_testhpke(const TEST_BASEDATA *base,
95 const TEST_AEADDATA *aead, size_t aeadsz,
96 const TEST_EXPORTDATA *export, size_t exportsz)
98 OSSL_LIB_CTX *libctx = testctx;
99 const char *propq = testpropq;
100 OSSL_HPKE_CTX *sealctx = NULL, *openctx = NULL;
101 unsigned char ct[256];
102 unsigned char enc[256];
103 unsigned char ptout[256];
104 size_t ptoutlen = sizeof(ptout);
105 size_t enclen = sizeof(enc);
106 size_t ctlen = sizeof(ct);
107 unsigned char pub[OSSL_HPKE_TSTSIZE];
108 size_t publen = sizeof(pub);
109 EVP_PKEY *privE = NULL;
110 unsigned char authpub[OSSL_HPKE_TSTSIZE];
111 size_t authpublen = sizeof(authpub);
112 EVP_PKEY *authpriv = NULL;
113 unsigned char rpub[OSSL_HPKE_TSTSIZE];
114 size_t rpublen = sizeof(pub);
115 EVP_PKEY *privR = NULL;
118 uint64_t lastseq = 0;
120 if (!TEST_true(OSSL_HPKE_keygen(base->suite, pub, &publen, &privE,
121 base->ikmE, base->ikmElen, libctx, propq)))
123 if (!TEST_true(cmpkey(privE, base->expected_pkEm, base->expected_pkEmlen)))
125 if (!TEST_ptr(sealctx = OSSL_HPKE_CTX_new(base->mode, base->suite,
126 OSSL_HPKE_ROLE_SENDER,
129 if (!TEST_true(OSSL_HPKE_CTX_set1_ikme(sealctx, base->ikmE, base->ikmElen)))
131 if (base->mode == OSSL_HPKE_MODE_AUTH
132 || base->mode == OSSL_HPKE_MODE_PSKAUTH) {
133 if (!TEST_true(base->ikmAuth != NULL && base->ikmAuthlen > 0))
135 if (!TEST_true(OSSL_HPKE_keygen(base->suite,
136 authpub, &authpublen, &authpriv,
137 base->ikmAuth, base->ikmAuthlen,
140 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(sealctx, authpriv)))
143 if (!TEST_true(OSSL_HPKE_keygen(base->suite, rpub, &rpublen, &privR,
144 base->ikmR, base->ikmRlen, libctx, propq)))
146 if (!TEST_true(cmpkey(privR, base->expected_pkRm, base->expected_pkRmlen)))
148 if (base->mode == OSSL_HPKE_MODE_PSK
149 || base->mode == OSSL_HPKE_MODE_PSKAUTH) {
150 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(sealctx, base->pskid,
151 base->psk, base->psklen)))
154 if (!TEST_true(OSSL_HPKE_encap(sealctx, enc, &enclen,
156 base->ksinfo, base->ksinfolen)))
158 if (!TEST_true(cmpkey(privE, enc, enclen)))
160 for (i = 0; i < aeadsz; ++i) {
162 memset(ct, 0, ctlen);
163 if (!TEST_true(OSSL_HPKE_seal(sealctx, ct, &ctlen,
164 aead[i].aad, aead[i].aadlen,
165 aead[i].pt, aead[i].ptlen)))
167 if (!TEST_mem_eq(ct, ctlen, aead[i].expected_ct,
168 aead[i].expected_ctlen))
170 if (!TEST_true(OSSL_HPKE_CTX_get_seq(sealctx, &lastseq)))
172 if (lastseq != (uint64_t)(i + 1))
175 if (!TEST_ptr(openctx = OSSL_HPKE_CTX_new(base->mode, base->suite,
176 OSSL_HPKE_ROLE_RECEIVER,
179 if (base->mode == OSSL_HPKE_MODE_PSK
180 || base->mode == OSSL_HPKE_MODE_PSKAUTH) {
181 if (!TEST_true(base->pskid != NULL && base->psk != NULL
182 && base->psklen > 0))
184 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(openctx, base->pskid,
185 base->psk, base->psklen)))
188 if (base->mode == OSSL_HPKE_MODE_AUTH
189 || base->mode == OSSL_HPKE_MODE_PSKAUTH) {
190 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(openctx,
191 authpub, authpublen)))
194 if (!TEST_true(OSSL_HPKE_decap(openctx, enc, enclen, privR,
195 base->ksinfo, base->ksinfolen)))
197 for (i = 0; i < aeadsz; ++i) {
198 ptoutlen = sizeof(ptout);
199 memset(ptout, 0, ptoutlen);
200 if (!TEST_true(OSSL_HPKE_open(openctx, ptout, &ptoutlen,
201 aead[i].aad, aead[i].aadlen,
203 aead[i].expected_ctlen)))
205 if (!TEST_mem_eq(aead[i].pt, aead[i].ptlen, ptout, ptoutlen))
207 /* check the sequence is being incremented as expected */
208 if (!TEST_true(OSSL_HPKE_CTX_get_seq(openctx, &lastseq)))
210 if (lastseq != (uint64_t)(i + 1))
213 /* check exporters */
214 for (i = 0; i < exportsz; ++i) {
215 size_t len = export[i].expected_secretlen;
216 unsigned char eval[OSSL_HPKE_TSTSIZE];
218 if (len > sizeof(eval))
220 /* export with too long label should fail */
221 if (!TEST_false(OSSL_HPKE_export(sealctx, eval, len,
222 export[i].context, -1)))
224 /* good export call */
225 if (!TEST_true(OSSL_HPKE_export(sealctx, eval, len,
227 export[i].contextlen)))
229 if (!TEST_mem_eq(eval, len, export[i].expected_secret,
230 export[i].expected_secretlen))
233 /* check seal fails if export only mode */
236 if (!TEST_false(OSSL_HPKE_seal(sealctx, ct, &ctlen,
237 NULL, 0, ptout, ptoutlen)))
243 OSSL_HPKE_CTX_free(sealctx);
244 OSSL_HPKE_CTX_free(openctx);
245 EVP_PKEY_free(privE);
246 EVP_PKEY_free(privR);
247 EVP_PKEY_free(authpriv);
251 static const unsigned char pt[] = {
252 0x42, 0x65, 0x61, 0x75, 0x74, 0x79, 0x20, 0x69,
253 0x73, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x2c,
254 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, 0x62,
255 0x65, 0x61, 0x75, 0x74, 0x79
257 static const unsigned char ksinfo[] = {
258 0x4f, 0x64, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61,
259 0x20, 0x47, 0x72, 0x65, 0x63, 0x69, 0x61, 0x6e,
260 0x20, 0x55, 0x72, 0x6e
263 * static const char *pskid = "Ennyn Durin aran Moria";
265 static const unsigned char pskid[] = {
266 0x45, 0x6e, 0x6e, 0x79, 0x6e, 0x20, 0x44, 0x75,
267 0x72, 0x69, 0x6e, 0x20, 0x61, 0x72, 0x61, 0x6e,
268 0x20, 0x4d, 0x6f, 0x72, 0x69, 0x61, 0x00
270 static const unsigned char psk[] = {
271 0x02, 0x47, 0xfd, 0x33, 0xb9, 0x13, 0x76, 0x0f,
272 0xa1, 0xfa, 0x51, 0xe1, 0x89, 0x2d, 0x9f, 0x30,
273 0x7f, 0xbe, 0x65, 0xeb, 0x17, 0x1e, 0x81, 0x32,
274 0xc2, 0xaf, 0x18, 0x55, 0x5a, 0x73, 0x8b, 0x82
277 /* these need to be "outside" the function below to keep check-ansi CI happy */
278 static const unsigned char first_ikme[] = {
279 0x78, 0x62, 0x8c, 0x35, 0x4e, 0x46, 0xf3, 0xe1,
280 0x69, 0xbd, 0x23, 0x1b, 0xe7, 0xb2, 0xff, 0x1c,
281 0x77, 0xaa, 0x30, 0x24, 0x60, 0xa2, 0x6d, 0xbf,
282 0xa1, 0x55, 0x15, 0x68, 0x4c, 0x00, 0x13, 0x0b
284 static const unsigned char first_ikmr[] = {
285 0xd4, 0xa0, 0x9d, 0x09, 0xf5, 0x75, 0xfe, 0xf4,
286 0x25, 0x90, 0x5d, 0x2a, 0xb3, 0x96, 0xc1, 0x44,
287 0x91, 0x41, 0x46, 0x3f, 0x69, 0x8f, 0x8e, 0xfd,
288 0xb7, 0xac, 0xcf, 0xaf, 0xf8, 0x99, 0x50, 0x98
290 static const unsigned char first_ikmepub[] = {
291 0x0a, 0xd0, 0x95, 0x0d, 0x9f, 0xb9, 0x58, 0x8e,
292 0x59, 0x69, 0x0b, 0x74, 0xf1, 0x23, 0x7e, 0xcd,
293 0xf1, 0xd7, 0x75, 0xcd, 0x60, 0xbe, 0x2e, 0xca,
294 0x57, 0xaf, 0x5a, 0x4b, 0x04, 0x71, 0xc9, 0x1b,
296 static const unsigned char first_ikmrpub[] = {
297 0x9f, 0xed, 0x7e, 0x8c, 0x17, 0x38, 0x75, 0x60,
298 0xe9, 0x2c, 0xc6, 0x46, 0x2a, 0x68, 0x04, 0x96,
299 0x57, 0x24, 0x6a, 0x09, 0xbf, 0xa8, 0xad, 0xe7,
300 0xae, 0xfe, 0x58, 0x96, 0x72, 0x01, 0x63, 0x66
302 static const unsigned char first_ikmrpriv[] = {
303 0xc5, 0xeb, 0x01, 0xeb, 0x45, 0x7f, 0xe6, 0xc6,
304 0xf5, 0x75, 0x77, 0xc5, 0x41, 0x3b, 0x93, 0x15,
305 0x50, 0xa1, 0x62, 0xc7, 0x1a, 0x03, 0xac, 0x8d,
306 0x19, 0x6b, 0xab, 0xbd, 0x4e, 0x5c, 0xe0, 0xfd
308 static const unsigned char first_expected_shared_secret[] = {
309 0x72, 0x76, 0x99, 0xf0, 0x09, 0xff, 0xe3, 0xc0,
310 0x76, 0x31, 0x50, 0x19, 0xc6, 0x96, 0x48, 0x36,
311 0x6b, 0x69, 0x17, 0x14, 0x39, 0xbd, 0x7d, 0xd0,
312 0x80, 0x77, 0x43, 0xbd, 0xe7, 0x69, 0x86, 0xcd
314 static const unsigned char first_aad0[] = {
315 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
317 static const unsigned char first_ct0[] = {
318 0xe5, 0x2c, 0x6f, 0xed, 0x7f, 0x75, 0x8d, 0x0c,
319 0xf7, 0x14, 0x56, 0x89, 0xf2, 0x1b, 0xc1, 0xbe,
320 0x6e, 0xc9, 0xea, 0x09, 0x7f, 0xef, 0x4e, 0x95,
321 0x94, 0x40, 0x01, 0x2f, 0x4f, 0xeb, 0x73, 0xfb,
322 0x61, 0x1b, 0x94, 0x61, 0x99, 0xe6, 0x81, 0xf4,
323 0xcf, 0xc3, 0x4d, 0xb8, 0xea
325 static const unsigned char first_aad1[] = {
326 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
328 static const unsigned char first_ct1[] = {
329 0x49, 0xf3, 0xb1, 0x9b, 0x28, 0xa9, 0xea, 0x9f,
330 0x43, 0xe8, 0xc7, 0x12, 0x04, 0xc0, 0x0d, 0x4a,
331 0x49, 0x0e, 0xe7, 0xf6, 0x13, 0x87, 0xb6, 0x71,
332 0x9d, 0xb7, 0x65, 0xe9, 0x48, 0x12, 0x3b, 0x45,
333 0xb6, 0x16, 0x33, 0xef, 0x05, 0x9b, 0xa2, 0x2c,
334 0xd6, 0x24, 0x37, 0xc8, 0xba
336 static const unsigned char first_aad2[] = {
337 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x32
339 static const unsigned char first_ct2[] = {
340 0x25, 0x7c, 0xa6, 0xa0, 0x84, 0x73, 0xdc, 0x85,
341 0x1f, 0xde, 0x45, 0xaf, 0xd5, 0x98, 0xcc, 0x83,
342 0xe3, 0x26, 0xdd, 0xd0, 0xab, 0xe1, 0xef, 0x23,
343 0xba, 0xa3, 0xba, 0xa4, 0xdd, 0x8c, 0xde, 0x99,
344 0xfc, 0xe2, 0xc1, 0xe8, 0xce, 0x68, 0x7b, 0x0b,
345 0x47, 0xea, 0xd1, 0xad, 0xc9
347 static const unsigned char first_export1[] = {
348 0xdf, 0xf1, 0x7a, 0xf3, 0x54, 0xc8, 0xb4, 0x16,
349 0x73, 0x56, 0x7d, 0xb6, 0x25, 0x9f, 0xd6, 0x02,
350 0x99, 0x67, 0xb4, 0xe1, 0xaa, 0xd1, 0x30, 0x23,
351 0xc2, 0xae, 0x5d, 0xf8, 0xf4, 0xf4, 0x3b, 0xf6
353 static const unsigned char first_context2[] = { 0x00 };
354 static const unsigned char first_export2[] = {
355 0x6a, 0x84, 0x72, 0x61, 0xd8, 0x20, 0x7f, 0xe5,
356 0x96, 0xbe, 0xfb, 0x52, 0x92, 0x84, 0x63, 0x88,
357 0x1a, 0xb4, 0x93, 0xda, 0x34, 0x5b, 0x10, 0xe1,
358 0xdc, 0xc6, 0x45, 0xe3, 0xb9, 0x4e, 0x2d, 0x95
360 static const unsigned char first_context3[] = {
361 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
364 static const unsigned char first_export3[] = {
365 0x8a, 0xff, 0x52, 0xb4, 0x5a, 0x1b, 0xe3, 0xa7,
366 0x34, 0xbc, 0x7a, 0x41, 0xe2, 0x0b, 0x4e, 0x05,
367 0x5a, 0xd4, 0xc4, 0xd2, 0x21, 0x04, 0xb0, 0xc2,
368 0x02, 0x85, 0xa7, 0xc4, 0x30, 0x24, 0x01, 0xcd
371 static int x25519kdfsha256_hkdfsha256_aes128gcm_psk_test(void)
373 const TEST_BASEDATA pskdata = {
374 /* "X25519", NULL, "SHA256", "SHA256", "AES-128-GCM", */
377 OSSL_HPKE_KEM_ID_X25519,
378 OSSL_HPKE_KDF_ID_HKDF_SHA256,
379 OSSL_HPKE_AEAD_ID_AES_GCM_128
381 first_ikme, sizeof(first_ikme),
382 first_ikmepub, sizeof(first_ikmepub),
383 first_ikmr, sizeof(first_ikmr),
384 first_ikmrpub, sizeof(first_ikmrpub),
385 first_ikmrpriv, sizeof(first_ikmrpriv),
386 first_expected_shared_secret, sizeof(first_expected_shared_secret),
387 ksinfo, sizeof(ksinfo),
388 NULL, 0, /* No Auth */
389 psk, sizeof(psk), (char *) pskid
391 const TEST_AEADDATA aeaddata[] = {
395 first_aad0, sizeof(first_aad0),
396 first_ct0, sizeof(first_ct0)
401 first_aad1, sizeof(first_aad1),
402 first_ct1, sizeof(first_ct1)
407 first_aad2, sizeof(first_aad2),
408 first_ct2, sizeof(first_ct2)
411 const TEST_EXPORTDATA exportdata[] = {
412 { NULL, 0, first_export1, sizeof(first_export1) },
413 { first_context2, sizeof(first_context2),
414 first_export2, sizeof(first_export2) },
415 { first_context3, sizeof(first_context3),
416 first_export3, sizeof(first_export3) },
418 return do_testhpke(&pskdata, aeaddata, OSSL_NELEM(aeaddata),
419 exportdata, OSSL_NELEM(exportdata));
422 static const unsigned char second_ikme[] = {
423 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43,
424 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13,
425 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2,
426 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34
428 static const unsigned char second_ikmepub[] = {
429 0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28,
430 0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d,
431 0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44,
432 0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31,
434 static const unsigned char second_ikmr[] = {
435 0x6d, 0xb9, 0xdf, 0x30, 0xaa, 0x07, 0xdd, 0x42,
436 0xee, 0x5e, 0x81, 0x81, 0xaf, 0xdb, 0x97, 0x7e,
437 0x53, 0x8f, 0x5e, 0x1f, 0xec, 0x8a, 0x06, 0x22,
438 0x3f, 0x33, 0xf7, 0x01, 0x3e, 0x52, 0x50, 0x37
440 static const unsigned char second_ikmrpub[] = {
441 0x39, 0x48, 0xcf, 0xe0, 0xad, 0x1d, 0xdb, 0x69,
442 0x5d, 0x78, 0x0e, 0x59, 0x07, 0x71, 0x95, 0xda,
443 0x6c, 0x56, 0x50, 0x6b, 0x02, 0x73, 0x29, 0x79,
444 0x4a, 0xb0, 0x2b, 0xca, 0x80, 0x81, 0x5c, 0x4d
446 static const unsigned char second_ikmrpriv[] = {
447 0x46, 0x12, 0xc5, 0x50, 0x26, 0x3f, 0xc8, 0xad,
448 0x58, 0x37, 0x5d, 0xf3, 0xf5, 0x57, 0xaa, 0xc5,
449 0x31, 0xd2, 0x68, 0x50, 0x90, 0x3e, 0x55, 0xa9,
450 0xf2, 0x3f, 0x21, 0xd8, 0x53, 0x4e, 0x8a, 0xc8
452 static const unsigned char second_expected_shared_secret[] = {
453 0xfe, 0x0e, 0x18, 0xc9, 0xf0, 0x24, 0xce, 0x43,
454 0x79, 0x9a, 0xe3, 0x93, 0xc7, 0xe8, 0xfe, 0x8f,
455 0xce, 0x9d, 0x21, 0x88, 0x75, 0xe8, 0x22, 0x7b,
456 0x01, 0x87, 0xc0, 0x4e, 0x7d, 0x2e, 0xa1, 0xfc
458 static const unsigned char second_aead0[] = {
459 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
461 static const unsigned char second_ct0[] = {
462 0xf9, 0x38, 0x55, 0x8b, 0x5d, 0x72, 0xf1, 0xa2,
463 0x38, 0x10, 0xb4, 0xbe, 0x2a, 0xb4, 0xf8, 0x43,
464 0x31, 0xac, 0xc0, 0x2f, 0xc9, 0x7b, 0xab, 0xc5,
465 0x3a, 0x52, 0xae, 0x82, 0x18, 0xa3, 0x55, 0xa9,
466 0x6d, 0x87, 0x70, 0xac, 0x83, 0xd0, 0x7b, 0xea,
467 0x87, 0xe1, 0x3c, 0x51, 0x2a
469 static const unsigned char second_aead1[] = {
470 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
472 static const unsigned char second_ct1[] = {
473 0xaf, 0x2d, 0x7e, 0x9a, 0xc9, 0xae, 0x7e, 0x27,
474 0x0f, 0x46, 0xba, 0x1f, 0x97, 0x5b, 0xe5, 0x3c,
475 0x09, 0xf8, 0xd8, 0x75, 0xbd, 0xc8, 0x53, 0x54,
476 0x58, 0xc2, 0x49, 0x4e, 0x8a, 0x6e, 0xab, 0x25,
477 0x1c, 0x03, 0xd0, 0xc2, 0x2a, 0x56, 0xb8, 0xca,
478 0x42, 0xc2, 0x06, 0x3b, 0x84
480 static const unsigned char second_export1[] = {
481 0x38, 0x53, 0xfe, 0x2b, 0x40, 0x35, 0x19, 0x5a,
482 0x57, 0x3f, 0xfc, 0x53, 0x85, 0x6e, 0x77, 0x05,
483 0x8e, 0x15, 0xd9, 0xea, 0x06, 0x4d, 0xe3, 0xe5,
484 0x9f, 0x49, 0x61, 0xd0, 0x09, 0x52, 0x50, 0xee
486 static const unsigned char second_context2[] = { 0x00 };
487 static const unsigned char second_export2[] = {
488 0x2e, 0x8f, 0x0b, 0x54, 0x67, 0x3c, 0x70, 0x29,
489 0x64, 0x9d, 0x4e, 0xb9, 0xd5, 0xe3, 0x3b, 0xf1,
490 0x87, 0x2c, 0xf7, 0x6d, 0x62, 0x3f, 0xf1, 0x64,
491 0xac, 0x18, 0x5d, 0xa9, 0xe8, 0x8c, 0x21, 0xa5
493 static const unsigned char second_context3[] = {
494 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
497 static const unsigned char second_export3[] = {
498 0xe9, 0xe4, 0x30, 0x65, 0x10, 0x2c, 0x38, 0x36,
499 0x40, 0x1b, 0xed, 0x8c, 0x3c, 0x3c, 0x75, 0xae,
500 0x46, 0xbe, 0x16, 0x39, 0x86, 0x93, 0x91, 0xd6,
501 0x2c, 0x61, 0xf1, 0xec, 0x7a, 0xf5, 0x49, 0x31
504 static int x25519kdfsha256_hkdfsha256_aes128gcm_base_test(void)
506 const TEST_BASEDATA basedata = {
509 OSSL_HPKE_KEM_ID_X25519,
510 OSSL_HPKE_KDF_ID_HKDF_SHA256,
511 OSSL_HPKE_AEAD_ID_AES_GCM_128
513 second_ikme, sizeof(second_ikme),
514 second_ikmepub, sizeof(second_ikmepub),
515 second_ikmr, sizeof(second_ikmr),
516 second_ikmrpub, sizeof(second_ikmrpub),
517 second_ikmrpriv, sizeof(second_ikmrpriv),
518 second_expected_shared_secret, sizeof(second_expected_shared_secret),
519 ksinfo, sizeof(ksinfo),
520 NULL, 0, /* no auth ikm */
521 NULL, 0, NULL /* no psk */
523 const TEST_AEADDATA aeaddata[] = {
527 second_aead0, sizeof(second_aead0),
528 second_ct0, sizeof(second_ct0)
533 second_aead1, sizeof(second_aead1),
534 second_ct1, sizeof(second_ct1)
537 const TEST_EXPORTDATA exportdata[] = {
538 { NULL, 0, second_export1, sizeof(second_export1) },
539 { second_context2, sizeof(second_context2),
540 second_export2, sizeof(second_export2) },
541 { second_context3, sizeof(second_context3),
542 second_export3, sizeof(second_export3) },
544 return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata),
545 exportdata, OSSL_NELEM(exportdata));
548 static const unsigned char third_ikme[] = {
549 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d,
550 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f,
551 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f,
552 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e
554 static const unsigned char third_ikmepub[] = {
555 0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50,
556 0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14,
557 0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e,
558 0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a,
559 0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4,
560 0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00,
561 0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b,
562 0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18,
565 static const unsigned char third_ikmr[] = {
566 0x66, 0x8b, 0x37, 0x17, 0x1f, 0x10, 0x72, 0xf3,
567 0xcf, 0x12, 0xea, 0x8a, 0x23, 0x6a, 0x45, 0xdf,
568 0x23, 0xfc, 0x13, 0xb8, 0x2a, 0xf3, 0x60, 0x9a,
569 0xd1, 0xe3, 0x54, 0xf6, 0xef, 0x81, 0x75, 0x50
571 static const unsigned char third_ikmrpub[] = {
572 0x04, 0xfe, 0x8c, 0x19, 0xce, 0x09, 0x05, 0x19,
573 0x1e, 0xbc, 0x29, 0x8a, 0x92, 0x45, 0x79, 0x25,
574 0x31, 0xf2, 0x6f, 0x0c, 0xec, 0xe2, 0x46, 0x06,
575 0x39, 0xe8, 0xbc, 0x39, 0xcb, 0x7f, 0x70, 0x6a,
576 0x82, 0x6a, 0x77, 0x9b, 0x4c, 0xf9, 0x69, 0xb8,
577 0xa0, 0xe5, 0x39, 0xc7, 0xf6, 0x2f, 0xb3, 0xd3,
578 0x0a, 0xd6, 0xaa, 0x8f, 0x80, 0xe3, 0x0f, 0x1d,
579 0x12, 0x8a, 0xaf, 0xd6, 0x8a, 0x2c, 0xe7, 0x2e,
582 static const unsigned char third_ikmrpriv[] = {
583 0xf3, 0xce, 0x7f, 0xda, 0xe5, 0x7e, 0x1a, 0x31,
584 0x0d, 0x87, 0xf1, 0xeb, 0xbd, 0xe6, 0xf3, 0x28,
585 0xbe, 0x0a, 0x99, 0xcd, 0xbc, 0xad, 0xf4, 0xd6,
586 0x58, 0x9c, 0xf2, 0x9d, 0xe4, 0xb8, 0xff, 0xd2
588 static const unsigned char third_expected_shared_secret[] = {
589 0xc0, 0xd2, 0x6a, 0xea, 0xb5, 0x36, 0x60, 0x9a,
590 0x57, 0x2b, 0x07, 0x69, 0x5d, 0x93, 0x3b, 0x58,
591 0x9d, 0xcf, 0x36, 0x3f, 0xf9, 0xd9, 0x3c, 0x93,
592 0xad, 0xea, 0x53, 0x7a, 0xea, 0xbb, 0x8c, 0xb8
594 static const unsigned char third_aead0[] = {
595 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
597 static const unsigned char third_ct0[] = {
598 0x5a, 0xd5, 0x90, 0xbb, 0x8b, 0xaa, 0x57, 0x7f,
599 0x86, 0x19, 0xdb, 0x35, 0xa3, 0x63, 0x11, 0x22,
600 0x6a, 0x89, 0x6e, 0x73, 0x42, 0xa6, 0xd8, 0x36,
601 0xd8, 0xb7, 0xbc, 0xd2, 0xf2, 0x0b, 0x6c, 0x7f,
602 0x90, 0x76, 0xac, 0x23, 0x2e, 0x3a, 0xb2, 0x52,
603 0x3f, 0x39, 0x51, 0x34, 0x34
605 static const unsigned char third_aead1[] = {
606 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
608 static const unsigned char third_ct1[] = {
609 0xfa, 0x6f, 0x03, 0x7b, 0x47, 0xfc, 0x21, 0x82,
610 0x6b, 0x61, 0x01, 0x72, 0xca, 0x96, 0x37, 0xe8,
611 0x2d, 0x6e, 0x58, 0x01, 0xeb, 0x31, 0xcb, 0xd3,
612 0x74, 0x82, 0x71, 0xaf, 0xfd, 0x4e, 0xcb, 0x06,
613 0x64, 0x6e, 0x03, 0x29, 0xcb, 0xdf, 0x3c, 0x3c,
614 0xd6, 0x55, 0xb2, 0x8e, 0x82
616 static const unsigned char third_export1[] = {
617 0x5e, 0x9b, 0xc3, 0xd2, 0x36, 0xe1, 0x91, 0x1d,
618 0x95, 0xe6, 0x5b, 0x57, 0x6a, 0x8a, 0x86, 0xd4,
619 0x78, 0xfb, 0x82, 0x7e, 0x8b, 0xdf, 0xe7, 0x7b,
620 0x74, 0x1b, 0x28, 0x98, 0x90, 0x49, 0x0d, 0x4d
622 static const unsigned char third_context2[] = { 0x00 };
623 static const unsigned char third_export2[] = {
624 0x6c, 0xff, 0x87, 0x65, 0x89, 0x31, 0xbd, 0xa8,
625 0x3d, 0xc8, 0x57, 0xe6, 0x35, 0x3e, 0xfe, 0x49,
626 0x87, 0xa2, 0x01, 0xb8, 0x49, 0x65, 0x8d, 0x9b,
627 0x04, 0x7a, 0xab, 0x4c, 0xf2, 0x16, 0xe7, 0x96
629 static const unsigned char third_context3[] = {
630 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
633 static const unsigned char third_export3[] = {
634 0xd8, 0xf1, 0xea, 0x79, 0x42, 0xad, 0xbb, 0xa7,
635 0x41, 0x2c, 0x6d, 0x43, 0x1c, 0x62, 0xd0, 0x13,
636 0x71, 0xea, 0x47, 0x6b, 0x82, 0x3e, 0xb6, 0x97,
637 0xe1, 0xf6, 0xe6, 0xca, 0xe1, 0xda, 0xb8, 0x5a
640 static int P256kdfsha256_hkdfsha256_aes128gcm_base_test(void)
642 const TEST_BASEDATA basedata = {
645 OSSL_HPKE_KEM_ID_P256,
646 OSSL_HPKE_KDF_ID_HKDF_SHA256,
647 OSSL_HPKE_AEAD_ID_AES_GCM_128
649 third_ikme, sizeof(third_ikme),
650 third_ikmepub, sizeof(third_ikmepub),
651 third_ikmr, sizeof(third_ikmr),
652 third_ikmrpub, sizeof(third_ikmrpub),
653 third_ikmrpriv, sizeof(third_ikmrpriv),
654 third_expected_shared_secret, sizeof(third_expected_shared_secret),
655 ksinfo, sizeof(ksinfo),
656 NULL, 0, /* no auth */
657 NULL, 0, NULL /* PSK stuff */
659 const TEST_AEADDATA aeaddata[] = {
663 third_aead0, sizeof(third_aead0),
664 third_ct0, sizeof(third_ct0)
669 third_aead1, sizeof(third_aead1),
670 third_ct1, sizeof(third_ct1)
673 const TEST_EXPORTDATA exportdata[] = {
674 { NULL, 0, third_export1, sizeof(third_export1) },
675 { third_context2, sizeof(third_context2),
676 third_export2, sizeof(third_export2) },
677 { third_context3, sizeof(third_context3),
678 third_export3, sizeof(third_export3) },
680 return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata),
681 exportdata, OSSL_NELEM(exportdata));
684 static const unsigned char fourth_ikme[] = {
685 0x55, 0xbc, 0x24, 0x5e, 0xe4, 0xef, 0xda, 0x25,
686 0xd3, 0x8f, 0x2d, 0x54, 0xd5, 0xbb, 0x66, 0x65,
687 0x29, 0x1b, 0x99, 0xf8, 0x10, 0x8a, 0x8c, 0x4b,
688 0x68, 0x6c, 0x2b, 0x14, 0x89, 0x3e, 0xa5, 0xd9
690 static const unsigned char fourth_ikmepub[] = {
691 0xe5, 0xe8, 0xf9, 0xbf, 0xff, 0x6c, 0x2f, 0x29,
692 0x79, 0x1f, 0xc3, 0x51, 0xd2, 0xc2, 0x5c, 0xe1,
693 0x29, 0x9a, 0xa5, 0xea, 0xca, 0x78, 0xa7, 0x57,
694 0xc0, 0xb4, 0xfb, 0x4b, 0xcd, 0x83, 0x09, 0x18
696 static const unsigned char fourth_ikmr[] = {
697 0x68, 0x3a, 0xe0, 0xda, 0x1d, 0x22, 0x18, 0x1e,
698 0x74, 0xed, 0x2e, 0x50, 0x3e, 0xbf, 0x82, 0x84,
699 0x0d, 0xeb, 0x1d, 0x5e, 0x87, 0x2c, 0xad, 0xe2,
700 0x0f, 0x4b, 0x45, 0x8d, 0x99, 0x78, 0x3e, 0x31
702 static const unsigned char fourth_ikmrpub[] = {
703 0x19, 0x41, 0x41, 0xca, 0x6c, 0x3c, 0x3b, 0xeb,
704 0x47, 0x92, 0xcd, 0x97, 0xba, 0x0e, 0xa1, 0xfa,
705 0xff, 0x09, 0xd9, 0x84, 0x35, 0x01, 0x23, 0x45,
706 0x76, 0x6e, 0xe3, 0x3a, 0xae, 0x2d, 0x76, 0x64
708 static const unsigned char fourth_ikmrpriv[] = {
709 0x33, 0xd1, 0x96, 0xc8, 0x30, 0xa1, 0x2f, 0x9a,
710 0xc6, 0x5d, 0x6e, 0x56, 0x5a, 0x59, 0x0d, 0x80,
711 0xf0, 0x4e, 0xe9, 0xb1, 0x9c, 0x83, 0xc8, 0x7f,
712 0x2c, 0x17, 0x0d, 0x97, 0x2a, 0x81, 0x28, 0x48
714 static const unsigned char fourth_expected_shared_secret[] = {
715 0xe8, 0x17, 0x16, 0xce, 0x8f, 0x73, 0x14, 0x1d,
716 0x4f, 0x25, 0xee, 0x90, 0x98, 0xef, 0xc9, 0x68,
717 0xc9, 0x1e, 0x5b, 0x8c, 0xe5, 0x2f, 0xff, 0xf5,
718 0x9d, 0x64, 0x03, 0x9e, 0x82, 0x91, 0x8b, 0x66
720 static const unsigned char fourth_export1[] = {
721 0x7a, 0x36, 0x22, 0x1b, 0xd5, 0x6d, 0x50, 0xfb,
722 0x51, 0xee, 0x65, 0xed, 0xfd, 0x98, 0xd0, 0x6a,
723 0x23, 0xc4, 0xdc, 0x87, 0x08, 0x5a, 0xa5, 0x86,
724 0x6c, 0xb7, 0x08, 0x72, 0x44, 0xbd, 0x2a, 0x36
726 static const unsigned char fourth_context2[] = { 0x00 };
727 static const unsigned char fourth_export2[] = {
728 0xd5, 0x53, 0x5b, 0x87, 0x09, 0x9c, 0x6c, 0x3c,
729 0xe8, 0x0d, 0xc1, 0x12, 0xa2, 0x67, 0x1c, 0x6e,
730 0xc8, 0xe8, 0x11, 0xa2, 0xf2, 0x84, 0xf9, 0x48,
731 0xce, 0xc6, 0xdd, 0x17, 0x08, 0xee, 0x33, 0xf0
733 static const unsigned char fourth_context3[] = {
734 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
737 static const unsigned char fourth_export3[] = {
738 0xff, 0xaa, 0xbc, 0x85, 0xa7, 0x76, 0x13, 0x6c,
739 0xa0, 0xc3, 0x78, 0xe5, 0xd0, 0x84, 0xc9, 0x14,
740 0x0a, 0xb5, 0x52, 0xb7, 0x8f, 0x03, 0x9d, 0x2e,
741 0x87, 0x75, 0xf2, 0x6e, 0xff, 0xf4, 0xc7, 0x0e
744 static int export_only_test(void)
746 /* based on RFC9180 A.7 */
747 const TEST_BASEDATA basedata = {
750 OSSL_HPKE_KEM_ID_X25519,
751 OSSL_HPKE_KDF_ID_HKDF_SHA256,
752 OSSL_HPKE_AEAD_ID_EXPORTONLY
754 fourth_ikme, sizeof(fourth_ikme),
755 fourth_ikmepub, sizeof(fourth_ikmepub),
756 fourth_ikmr, sizeof(fourth_ikmr),
757 fourth_ikmrpub, sizeof(fourth_ikmrpub),
758 fourth_ikmrpriv, sizeof(fourth_ikmrpriv),
759 fourth_expected_shared_secret, sizeof(fourth_expected_shared_secret),
760 ksinfo, sizeof(ksinfo),
761 NULL, 0, /* no auth */
762 NULL, 0, NULL /* PSK stuff */
764 const TEST_EXPORTDATA exportdata[] = {
765 { NULL, 0, fourth_export1, sizeof(fourth_export1) },
766 { fourth_context2, sizeof(fourth_context2),
767 fourth_export2, sizeof(fourth_export2) },
768 { fourth_context3, sizeof(fourth_context3),
769 fourth_export3, sizeof(fourth_export3) },
771 return do_testhpke(&basedata, NULL, 0,
772 exportdata, OSSL_NELEM(exportdata));
776 * Randomly toss a coin
778 #define COIN_IS_HEADS (test_random() % 2)
780 /* tables of HPKE modes and suite values */
781 static int hpke_mode_list[] = {
785 OSSL_HPKE_MODE_PSKAUTH
787 static uint16_t hpke_kem_list[] = {
788 OSSL_HPKE_KEM_ID_P256,
789 OSSL_HPKE_KEM_ID_P384,
790 OSSL_HPKE_KEM_ID_P521,
791 OSSL_HPKE_KEM_ID_X25519,
792 OSSL_HPKE_KEM_ID_X448
794 static uint16_t hpke_kdf_list[] = {
795 OSSL_HPKE_KDF_ID_HKDF_SHA256,
796 OSSL_HPKE_KDF_ID_HKDF_SHA384,
797 OSSL_HPKE_KDF_ID_HKDF_SHA512
799 static uint16_t hpke_aead_list[] = {
800 OSSL_HPKE_AEAD_ID_AES_GCM_128,
801 OSSL_HPKE_AEAD_ID_AES_GCM_256,
802 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
803 OSSL_HPKE_AEAD_ID_CHACHA_POLY1305
808 * Strings that can be used with names or IANA codepoints.
809 * Note that the initial entries from these lists should
810 * match the lists above, i.e. kem_str_list[0] and
811 * hpke_kem_list[0] should refer to the same KEM. We use
812 * that for verbose output via TEST_note() below.
813 * Subsequent entries are only used for tests of
814 * OSSL_HPKE_str2suite()
816 static const char *mode_str_list[] = {
817 "base", "psk", "auth", "pskauth"
819 static const char *kem_str_list[] = {
820 "P-256", "P-384", "P-521", "x25519", "x448",
821 "0x10", "0x11", "0x12", "0x20", "0x21",
822 "16", "17", "18", "32", "33"
824 static const char *kdf_str_list[] = {
825 "hkdf-sha256", "hkdf-sha384", "hkdf-sha512",
826 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
829 static const char *aead_str_list[] = {
830 "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "exporter",
831 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
835 /* table of bogus strings that better not work */
836 static const char *bogus_suite_strs[] = {
839 "bogus,33,3,1,bogus",
847 /* in reverse order */
848 "aes-256-gcm,hkdf-sha512,x25519",
849 /* surplus separators */
853 /* embedded NUL chars */
855 "0x10,\0""0x01,0x02",
858 "0x10,0x01,\0""0x02",
859 /* embedded whitespace */
860 " aes-256-gcm,hkdf-sha512,x25519",
861 "aes-256-gcm, hkdf-sha512,x25519",
862 "aes-256-gcm ,hkdf-sha512,x25519",
863 "aes-256-gcm,hkdf-sha512, x25519",
864 "aes-256-gcm,hkdf-sha512 ,x25519",
865 "aes-256-gcm,hkdf-sha512,x25519 ",
866 /* good value followed by extra stuff */
869 "0x10,0x01,0x01,0x02",
870 "0x10,0x01,0x01,blah",
871 "0x10,0x01,0x01 0x02",
872 /* too few but good tokens */
883 * @brief round-trips, generating keys, encrypt and decrypt
885 * This iterates over all mode and ciphersuite options trying
886 * a key gen, encrypt and decrypt for each. The aad, info, and
887 * seq inputs are randomly set or omitted each time. EVP and
888 * non-EVP key generation are randomly selected.
890 * @return 1 for success, other otherwise
892 static int test_hpke_modes_suites(void)
894 int overallresult = 1;
895 size_t mind = 0; /* index into hpke_mode_list */
896 size_t kemind = 0; /* index into hpke_kem_list */
897 size_t kdfind = 0; /* index into hpke_kdf_list */
898 size_t aeadind = 0; /* index into hpke_aead_list */
900 /* iterate over the different modes */
901 for (mind = 0; mind < OSSL_NELEM(hpke_mode_list); mind++) {
902 int hpke_mode = hpke_mode_list[mind];
903 size_t aadlen = OSSL_HPKE_TSTSIZE;
904 unsigned char aad[OSSL_HPKE_TSTSIZE];
905 unsigned char *aadp = NULL;
907 unsigned char info[32];
908 unsigned char *infop = NULL;
909 unsigned char lpsk[32];
910 unsigned char *pskp = NULL;
914 EVP_PKEY *privp = NULL;
915 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
916 size_t plainlen = OSSL_HPKE_TSTSIZE;
917 unsigned char plain[OSSL_HPKE_TSTSIZE];
918 OSSL_HPKE_CTX *rctx = NULL;
919 OSSL_HPKE_CTX *ctx = NULL;
921 memset(plain, 0x00, OSSL_HPKE_TSTSIZE);
922 strcpy((char *)plain, "a message not in a bottle");
923 plainlen = strlen((char *)plain);
925 * Randomly try with/without info, aad, seq. Given mode and suite
926 * combos, and this being run even a few times, we'll exercise many
927 * code paths fairly quickly. We don't really care what the values
928 * are but it'll be easier to debug if they're known, so we set 'em.
932 memset(aad, 'a', aadlen);
938 memset(info, 'i', infolen);
942 if (hpke_mode == OSSL_HPKE_MODE_PSK
943 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
945 memset(lpsk, 'P', psklen);
947 memset(lpskid, 'I', psklen - 1);
948 lpskid[psklen - 1] = '\0';
952 for (kemind = 0; /* iterate over the kems, kdfs and aeads */
953 overallresult == 1 && kemind < OSSL_NELEM(hpke_kem_list);
955 uint16_t kem_id = hpke_kem_list[kemind];
956 size_t authpublen = OSSL_HPKE_TSTSIZE;
957 unsigned char authpub[OSSL_HPKE_TSTSIZE];
958 unsigned char *authpubp = NULL;
959 EVP_PKEY *authpriv = NULL;
961 hpke_suite.kem_id = kem_id;
962 if (hpke_mode == OSSL_HPKE_MODE_AUTH
963 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
964 if (TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen,
966 testctx, NULL)) != 1) {
974 overallresult == 1 && kdfind < OSSL_NELEM(hpke_kdf_list);
976 uint16_t kdf_id = hpke_kdf_list[kdfind];
978 hpke_suite.kdf_id = kdf_id;
981 && aeadind < OSSL_NELEM(hpke_aead_list);
983 uint16_t aead_id = hpke_aead_list[aeadind];
984 size_t publen = OSSL_HPKE_TSTSIZE;
985 unsigned char pub[OSSL_HPKE_TSTSIZE];
986 size_t senderpublen = OSSL_HPKE_TSTSIZE;
987 unsigned char senderpub[OSSL_HPKE_TSTSIZE];
988 size_t cipherlen = OSSL_HPKE_TSTSIZE;
989 unsigned char cipher[OSSL_HPKE_TSTSIZE];
990 size_t clearlen = OSSL_HPKE_TSTSIZE;
991 unsigned char clear[OSSL_HPKE_TSTSIZE];
993 hpke_suite.aead_id = aead_id;
994 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite,
995 pub, &publen, &privp,
996 NULL, 0, testctx, NULL)))
998 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
999 OSSL_HPKE_ROLE_SENDER,
1002 if (hpke_mode == OSSL_HPKE_MODE_PSK
1003 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
1004 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(ctx, pskidp,
1008 if (hpke_mode == OSSL_HPKE_MODE_AUTH
1009 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
1010 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx,
1014 if (!TEST_true(OSSL_HPKE_encap(ctx, senderpub,
1019 /* throw in a call with a too-short cipherlen */
1021 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen,
1025 /* fix back real cipherlen */
1026 cipherlen = OSSL_HPKE_TSTSIZE;
1027 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen,
1031 OSSL_HPKE_CTX_free(ctx);
1032 memset(clear, 0, clearlen);
1033 rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1034 OSSL_HPKE_ROLE_RECEIVER,
1036 if (!TEST_ptr(rctx))
1038 if (hpke_mode == OSSL_HPKE_MODE_PSK
1039 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
1040 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(rctx, pskidp,
1044 if (hpke_mode == OSSL_HPKE_MODE_AUTH
1045 || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
1046 /* check a borked p256 key */
1047 if (hpke_suite.kem_id == OSSL_HPKE_KEM_ID_P256) {
1048 /* set to fail decode of authpub this time */
1049 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(rctx,
1055 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx,
1060 if (!TEST_true(OSSL_HPKE_decap(rctx, senderpub,
1061 senderpublen, privp,
1064 /* throw in a call with a too-short clearlen */
1066 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen,
1067 aadp, aadlen, cipher,
1070 /* fix up real clearlen again */
1071 clearlen = OSSL_HPKE_TSTSIZE;
1072 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen,
1073 aadp, aadlen, cipher,
1076 OSSL_HPKE_CTX_free(rctx);
1077 EVP_PKEY_free(privp);
1080 if (!TEST_mem_eq(clear, clearlen, plain, plainlen)) {
1083 if (verbose || overallresult != 1) {
1084 const char *res = NULL;
1086 res = (overallresult == 1 ? "worked" : "failed");
1087 TEST_note("HPKE %s for mode: %s/0x%02x, "\
1088 "kem: %s/0x%02x, kdf: %s/0x%02x, "\
1089 "aead: %s/0x%02x", res,
1090 mode_str_list[mind], (int) mind,
1091 kem_str_list[kemind], kem_id,
1092 kdf_str_list[kdfind], kdf_id,
1093 aead_str_list[aeadind], aead_id);
1097 EVP_PKEY_free(authpriv);
1100 return overallresult;
1104 * @brief check roundtrip for export
1105 * @return 1 for success, other otherwise
1107 static int test_hpke_export(void)
1110 EVP_PKEY *privp = NULL;
1111 unsigned char pub[OSSL_HPKE_TSTSIZE];
1112 size_t publen = sizeof(pub);
1113 int hpke_mode = OSSL_HPKE_MODE_BASE;
1114 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1115 OSSL_HPKE_CTX *ctx = NULL;
1116 OSSL_HPKE_CTX *rctx = NULL;
1117 unsigned char exp[32];
1118 unsigned char exp2[32];
1119 unsigned char rexp[32];
1120 unsigned char rexp2[32];
1121 unsigned char plain[] = "quick brown fox";
1122 size_t plainlen = sizeof(plain);
1123 unsigned char enc[OSSL_HPKE_TSTSIZE];
1124 size_t enclen = sizeof(enc);
1125 unsigned char cipher[OSSL_HPKE_TSTSIZE];
1126 size_t cipherlen = sizeof(cipher);
1127 unsigned char clear[OSSL_HPKE_TSTSIZE];
1128 size_t clearlen = sizeof(clear);
1131 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1132 NULL, 0, testctx, NULL)))
1134 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1135 OSSL_HPKE_ROLE_SENDER,
1138 /* a few error cases 1st */
1139 if (!TEST_false(OSSL_HPKE_export(NULL, exp, sizeof(exp),
1140 (unsigned char *)estr, strlen(estr))))
1142 /* ctx before encap should fail too */
1143 if (!TEST_false(OSSL_HPKE_export(ctx, exp, sizeof(exp),
1144 (unsigned char *)estr, strlen(estr))))
1146 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1148 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1152 if (!TEST_true(OSSL_HPKE_export(ctx, exp, sizeof(exp),
1153 (unsigned char *)estr, strlen(estr))))
1155 /* check a 2nd call with same input gives same output */
1156 if (!TEST_true(OSSL_HPKE_export(ctx, exp2, sizeof(exp2),
1157 (unsigned char *)estr, strlen(estr))))
1159 if (!TEST_mem_eq(exp, sizeof(exp), exp2, sizeof(exp2)))
1161 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1162 OSSL_HPKE_ROLE_RECEIVER,
1165 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1167 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1168 cipher, cipherlen)))
1170 if (!TEST_true(OSSL_HPKE_export(rctx, rexp, sizeof(rexp),
1171 (unsigned char *)estr, strlen(estr))))
1173 /* check a 2nd call with same input gives same output */
1174 if (!TEST_true(OSSL_HPKE_export(rctx, rexp2, sizeof(rexp2),
1175 (unsigned char *)estr, strlen(estr))))
1177 if (!TEST_mem_eq(rexp, sizeof(rexp), rexp2, sizeof(rexp2)))
1179 if (!TEST_mem_eq(exp, sizeof(exp), rexp, sizeof(rexp)))
1183 OSSL_HPKE_CTX_free(ctx);
1184 OSSL_HPKE_CTX_free(rctx);
1185 EVP_PKEY_free(privp);
1190 * @brief Check mapping from strings to HPKE suites
1191 * @return 1 for success, other otherwise
1193 static int test_hpke_suite_strs(void)
1195 int overallresult = 1;
1201 OSSL_HPKE_SUITE stirred;
1204 for (kemind = 0; kemind != OSSL_NELEM(kem_str_list); kemind++) {
1205 for (kdfind = 0; kdfind != OSSL_NELEM(kdf_str_list); kdfind++) {
1206 for (aeadind = 0; aeadind != OSSL_NELEM(aead_str_list); aeadind++) {
1207 BIO_snprintf(sstr, 128, "%s,%s,%s", kem_str_list[kemind],
1208 kdf_str_list[kdfind], aead_str_list[aeadind]);
1209 if (TEST_true(OSSL_HPKE_str2suite(sstr, &stirred)) != 1) {
1211 TEST_note("Unexpected str2suite fail for :%s",
1212 bogus_suite_strs[sind]);
1218 for (sind = 0; sind != OSSL_NELEM(bogus_suite_strs); sind++) {
1219 if (TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs[sind],
1222 TEST_note("OSSL_HPKE_str2suite didn't fail for bogus[%d]:%s",
1223 sind, bogus_suite_strs[sind]);
1227 /* check a few errors */
1228 if (!TEST_false(OSSL_HPKE_str2suite("", &stirred)))
1230 if (!TEST_false(OSSL_HPKE_str2suite(NULL, &stirred)))
1232 if (!TEST_false(OSSL_HPKE_str2suite("", NULL)))
1234 memset(giant, 'A', sizeof(giant) - 1);
1235 giant[sizeof(giant) - 1] = '\0';
1236 if (!TEST_false(OSSL_HPKE_str2suite(giant, &stirred)))
1239 return overallresult;
1243 * @brief try the various GREASEy APIs
1244 * @return 1 for success, other otherwise
1246 static int test_hpke_grease(void)
1248 int overallresult = 1;
1249 OSSL_HPKE_SUITE g_suite;
1250 unsigned char g_pub[OSSL_HPKE_TSTSIZE];
1251 size_t g_pub_len = OSSL_HPKE_TSTSIZE;
1252 unsigned char g_cipher[OSSL_HPKE_TSTSIZE];
1253 size_t g_cipher_len = 266;
1254 size_t clearlen = 128;
1255 size_t expanded = 0;
1259 memset(&g_suite, 0, sizeof(OSSL_HPKE_SUITE));
1261 /* check too short for public value */
1263 if (TEST_false(OSSL_HPKE_get_grease_value(NULL, &g_suite,
1265 g_cipher, g_cipher_len,
1266 testctx, NULL)) != 1) {
1270 g_pub_len = OSSL_HPKE_TSTSIZE;
1271 if (TEST_true(OSSL_HPKE_get_grease_value(NULL, &g_suite,
1273 g_cipher, g_cipher_len,
1274 testctx, NULL)) != 1) {
1278 expanded = OSSL_HPKE_get_ciphertext_size(g_suite, clearlen);
1279 if (!TEST_size_t_gt(expanded, clearlen)) {
1282 enclen = OSSL_HPKE_get_public_encap_size(g_suite);
1283 if (!TEST_size_t_ne(enclen, 0))
1285 /* not really GREASE but we'll check ikmelen thing */
1286 ikmelen = OSSL_HPKE_get_recommended_ikmelen(g_suite);
1287 if (!TEST_size_t_ne(ikmelen, 0))
1290 return overallresult;
1294 * Make a set of calls with odd parameters
1296 static int test_hpke_oddcalls(void)
1299 EVP_PKEY *privp = NULL;
1300 unsigned char pub[OSSL_HPKE_TSTSIZE];
1301 size_t publen = sizeof(pub);
1302 int hpke_mode = OSSL_HPKE_MODE_BASE;
1303 int bad_mode = 0xbad;
1304 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1305 OSSL_HPKE_SUITE bad_suite = { 0xbad, 0xbad, 0xbad };
1306 OSSL_HPKE_CTX *ctx = NULL;
1307 OSSL_HPKE_CTX *rctx = NULL;
1308 unsigned char plain[] = "quick brown fox";
1309 size_t plainlen = sizeof(plain);
1310 unsigned char enc[OSSL_HPKE_TSTSIZE];
1311 size_t enclen = sizeof(enc);
1312 unsigned char cipher[OSSL_HPKE_TSTSIZE];
1313 size_t cipherlen = sizeof(cipher);
1314 unsigned char clear[OSSL_HPKE_TSTSIZE];
1315 size_t clearlen = sizeof(clear);
1316 unsigned char fake_ikm[OSSL_HPKE_TSTSIZE];
1317 char *badpropq = "yeah, this won't work";
1319 char giant_pskid[OSSL_HPKE_MAX_PARMLEN + 10];
1320 unsigned char info[OSSL_HPKE_TSTSIZE];
1322 /* many of the calls below are designed to get better test coverage */
1324 /* NULL ctx calls */
1325 OSSL_HPKE_CTX_free(NULL);
1326 if (!TEST_false(OSSL_HPKE_CTX_set_seq(NULL, 1)))
1328 if (!TEST_false(OSSL_HPKE_CTX_get_seq(NULL, &lseq)))
1330 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(NULL, pub, publen)))
1332 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(NULL, privp)))
1334 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(NULL, NULL, 0)))
1336 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(NULL, NULL, NULL, 0)))
1339 /* bad suite calls */
1340 hpke_suite.aead_id = 0xbad;
1341 if (!TEST_false(OSSL_HPKE_suite_check(hpke_suite)))
1343 hpke_suite.aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128;
1344 if (!TEST_false(OSSL_HPKE_suite_check(bad_suite)))
1346 if (!TEST_false(OSSL_HPKE_get_recommended_ikmelen(bad_suite)))
1348 if (!TEST_false(OSSL_HPKE_get_public_encap_size(bad_suite)))
1350 if (!TEST_false(OSSL_HPKE_get_ciphertext_size(bad_suite, 0)))
1352 if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp,
1353 NULL, 0, testctx, badpropq)))
1355 if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp,
1356 NULL, 0, testctx, NULL)))
1359 /* dodgy keygen calls */
1361 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, NULL, &publen, &privp,
1362 NULL, 0, testctx, NULL)))
1364 /* ikmlen but NULL ikm */
1365 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1366 NULL, 80, testctx, NULL)))
1368 /* zero ikmlen but ikm */
1369 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1370 fake_ikm, 0, testctx, NULL)))
1373 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1374 fake_ikm, -1, testctx, NULL)))
1378 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1379 NULL, 0, testctx, NULL)))
1381 publen = sizeof(pub);
1383 /* encap/decap with NULLs */
1384 if (!TEST_false(OSSL_HPKE_encap(NULL, NULL, NULL, NULL, 0, NULL, 0)))
1386 if (!TEST_false(OSSL_HPKE_decap(NULL, NULL, 0, NULL, NULL, 0)))
1390 * run through a sender/recipient set of calls but with
1391 * failing calls interspersed whenever possible
1394 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1395 NULL, 0, testctx, NULL)))
1398 /* a psk context with no psk => encap fail */
1399 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite,
1400 OSSL_HPKE_ROLE_SENDER,
1403 /* set bad length psk */
1404 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo",
1405 (unsigned char *)"bar", -1)))
1407 /* set bad length pskid */
1408 memset(giant_pskid, 'A', sizeof(giant_pskid) - 1);
1409 giant_pskid[sizeof(giant_pskid) - 1] = '\0';
1410 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, giant_pskid,
1411 (unsigned char *)"bar", 3)))
1413 /* still no psk really set so encap fails */
1414 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1416 OSSL_HPKE_CTX_free(ctx);
1419 if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(hpke_mode, bad_suite,
1420 OSSL_HPKE_ROLE_SENDER,
1424 if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(bad_mode, hpke_suite,
1425 OSSL_HPKE_ROLE_SENDER,
1429 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1430 OSSL_HPKE_ROLE_SENDER,
1434 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, -1)))
1436 /* zero length ikm */
1437 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, 0)))
1440 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(ctx, NULL, 0)))
1442 /* NULL auth priv */
1443 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, NULL)))
1445 /* priv good, but mode is bad */
1446 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, privp)))
1448 /* bad mode for psk */
1449 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo",
1450 (unsigned char *)"bar", 3)))
1452 /* seal before encap */
1453 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1456 /* encap with dodgy public */
1457 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, NULL, 0)))
1459 /* encap with too big info */
1460 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, info, -1)))
1463 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1465 /* second encap fail */
1466 if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1469 /* should fail for no plaintext */
1470 if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1473 plainlen = sizeof(plain);
1475 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1480 /* decap fail with psk mode but no psk set */
1481 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite,
1482 OSSL_HPKE_ROLE_RECEIVER,
1485 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1487 /* done with PSK mode */
1488 OSSL_HPKE_CTX_free(rctx);
1490 /* back good calls for base mode */
1491 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1492 OSSL_HPKE_ROLE_RECEIVER,
1495 /* open before decap */
1496 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1497 cipher, cipherlen)))
1499 /* decap with info too long */
1500 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, info, -1)))
1503 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1505 /* second decap fail */
1506 if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1508 /* no space for recovered clear */
1510 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1511 cipher, cipherlen)))
1513 clearlen = OSSL_HPKE_TSTSIZE;
1514 /* seq wrap around test */
1515 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, -1)))
1517 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1518 cipher, cipherlen)))
1520 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0)))
1522 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1523 cipher, cipherlen)))
1525 if (!TEST_mem_eq(plain, plainlen, clear, clearlen))
1529 OSSL_HPKE_CTX_free(ctx);
1530 OSSL_HPKE_CTX_free(rctx);
1531 EVP_PKEY_free(privp);
1535 /* from RFC 9180 Appendix A.1.1 */
1536 static const unsigned char ikm25519[] = {
1537 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43,
1538 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13,
1539 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2,
1540 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34
1542 static const unsigned char pub25519[] = {
1543 0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28,
1544 0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d,
1545 0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44,
1546 0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31
1549 /* from RFC9180 Appendix A.3.1 */
1550 static const unsigned char ikmp256[] = {
1551 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d,
1552 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f,
1553 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f,
1554 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e
1556 static const unsigned char pubp256[] = {
1557 0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50,
1558 0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14,
1559 0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e,
1560 0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a,
1561 0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4,
1562 0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00,
1563 0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b,
1564 0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18,
1569 * A test vector that exercises the counter iteration
1570 * for p256. This was contributed by Ilari L. on the
1571 * CFRG list, see the mail archive:
1572 * https://mailarchive.ietf.org/arch/msg/cfrg/4zwl_y5YN6OU9oeWZOMHNOlOa2w/
1574 static const unsigned char ikmiter[] = {
1575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1578 0x00, 0x00, 0x00, 0x03, 0x01, 0x38, 0xb5, 0xec
1580 static const unsigned char pubiter[] = {
1581 0x04, 0x7d, 0x0c, 0x87, 0xff, 0xd5, 0xd1, 0x45,
1582 0x54, 0xa7, 0x51, 0xdf, 0xa3, 0x99, 0x26, 0xa9,
1583 0xe3, 0x0e, 0x7c, 0x3c, 0x65, 0x62, 0x4f, 0x4b,
1584 0x5f, 0xb3, 0xad, 0x7a, 0xa4, 0xda, 0xc2, 0x4a,
1585 0xd8, 0xf5, 0xbe, 0xd0, 0xe8, 0x6e, 0xb8, 0x84,
1586 0x1c, 0xe4, 0x89, 0x2e, 0x0f, 0xc3, 0x87, 0xbb,
1587 0xdb, 0xfe, 0x16, 0x0d, 0x58, 0x9c, 0x89, 0x2d,
1588 0xd4, 0xb1, 0x46, 0x4a, 0xc3, 0x51, 0xc5, 0x6f,
1592 /* from RFC9180 Appendix A.6.1 */
1593 static const unsigned char ikmp521[] = {
1594 0x7f, 0x06, 0xab, 0x82, 0x15, 0x10, 0x5f, 0xc4,
1595 0x6a, 0xce, 0xeb, 0x2e, 0x3d, 0xc5, 0x02, 0x8b,
1596 0x44, 0x36, 0x4f, 0x96, 0x04, 0x26, 0xeb, 0x0d,
1597 0x8e, 0x40, 0x26, 0xc2, 0xf8, 0xb5, 0xd7, 0xe7,
1598 0xa9, 0x86, 0x68, 0x8f, 0x15, 0x91, 0xab, 0xf5,
1599 0xab, 0x75, 0x3c, 0x35, 0x7a, 0x5d, 0x6f, 0x04,
1600 0x40, 0x41, 0x4b, 0x4e, 0xd4, 0xed, 0xe7, 0x13,
1601 0x17, 0x77, 0x2a, 0xc9, 0x8d, 0x92, 0x39, 0xf7,
1604 static const unsigned char pubp521[] = {
1605 0x04, 0x01, 0x38, 0xb3, 0x85, 0xca, 0x16, 0xbb,
1606 0x0d, 0x5f, 0xa0, 0xc0, 0x66, 0x5f, 0xbb, 0xd7,
1607 0xe6, 0x9e, 0x3e, 0xe2, 0x9f, 0x63, 0x99, 0x1d,
1608 0x3e, 0x9b, 0x5f, 0xa7, 0x40, 0xaa, 0xb8, 0x90,
1609 0x0a, 0xae, 0xed, 0x46, 0xed, 0x73, 0xa4, 0x90,
1610 0x55, 0x75, 0x84, 0x25, 0xa0, 0xce, 0x36, 0x50,
1611 0x7c, 0x54, 0xb2, 0x9c, 0xc5, 0xb8, 0x5a, 0x5c,
1612 0xee, 0x6b, 0xae, 0x0c, 0xf1, 0xc2, 0x1f, 0x27,
1613 0x31, 0xec, 0xe2, 0x01, 0x3d, 0xc3, 0xfb, 0x7c,
1614 0x8d, 0x21, 0x65, 0x4b, 0xb1, 0x61, 0xb4, 0x63,
1615 0x96, 0x2c, 0xa1, 0x9e, 0x8c, 0x65, 0x4f, 0xf2,
1616 0x4c, 0x94, 0xdd, 0x28, 0x98, 0xde, 0x12, 0x05,
1617 0x1f, 0x1e, 0xd0, 0x69, 0x22, 0x37, 0xfb, 0x02,
1618 0xb2, 0xf8, 0xd1, 0xdc, 0x1c, 0x73, 0xe9, 0xb3,
1619 0x66, 0xb5, 0x29, 0xeb, 0x43, 0x6e, 0x98, 0xa9,
1620 0x96, 0xee, 0x52, 0x2a, 0xef, 0x86, 0x3d, 0xd5,
1621 0x73, 0x9d, 0x2f, 0x29, 0xb0
1624 static int test_hpke_random_suites(void)
1626 OSSL_HPKE_SUITE def_suite = OSSL_HPKE_SUITE_DEFAULT;
1627 OSSL_HPKE_SUITE suite = OSSL_HPKE_SUITE_DEFAULT;
1628 OSSL_HPKE_SUITE suite2 = { 0xff01, 0xff02, 0xff03 };
1629 unsigned char enc[200];
1630 size_t enclen = sizeof(enc);
1631 unsigned char ct[500];
1632 size_t ctlen = sizeof(ct);
1634 /* test with NULL/0 inputs */
1635 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL, NULL,
1636 NULL, NULL, NULL, 0,
1640 if (!TEST_false(OSSL_HPKE_get_grease_value(&def_suite, &suite2,
1641 enc, &enclen, ct, ctlen,
1645 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1646 /* test with a should-be-good suite */
1647 if (!TEST_true(OSSL_HPKE_get_grease_value(&def_suite, &suite2,
1648 enc, &enclen, ct, ctlen,
1651 /* no suggested suite */
1652 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1653 if (!TEST_true(OSSL_HPKE_get_grease_value(NULL, &suite2,
1658 /* suggested suite with P-521, just to be sure we hit long values */
1659 enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1660 suite.kem_id = OSSL_HPKE_KEM_ID_P521;
1661 if (!TEST_true(OSSL_HPKE_get_grease_value(&suite, &suite2,
1662 enc, &enclen, ct, ctlen,
1665 enclen = sizeof(enc);
1666 ctlen = 2; /* too-short cttext (can't fit an aead tag) */
1667 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL, &suite2,
1668 enc, &enclen, ct, ctlen,
1673 enclen = sizeof(enc);
1675 suite.kem_id = OSSL_HPKE_KEM_ID_X25519; /* back to default */
1676 suite.aead_id = 0x1234; /* bad aead */
1677 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2,
1678 enc, &enclen, ct, ctlen,
1681 enclen = sizeof(enc);
1682 suite.aead_id = def_suite.aead_id; /* good aead */
1683 suite.kdf_id = 0x3451; /* bad kdf */
1684 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2,
1685 enc, &enclen, ct, ctlen,
1688 enclen = sizeof(enc);
1689 suite.kdf_id = def_suite.kdf_id; /* good kdf */
1690 suite.kem_id = 0x4517; /* bad kem */
1691 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite, &suite2,
1692 enc, &enclen, ct, ctlen,
1699 * @brief generate a key pair from initial key material (ikm) and check public
1700 * @param kem_id the KEM to use (RFC9180 code point)
1701 * @ikm is the initial key material buffer
1702 * @ikmlen is the length of ikm
1703 * @pub is the public key buffer
1704 * @publen is the length of the public key
1705 * @return 1 for good, other otherwise
1707 * This calls OSSL_HPKE_keygen specifying only the IKM, then
1708 * compares the key pair values with the already-known values
1711 static int test_hpke_one_ikm_gen(uint16_t kem_id,
1712 const unsigned char *ikm, size_t ikmlen,
1713 const unsigned char *pub, size_t publen)
1715 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1716 unsigned char lpub[OSSL_HPKE_TSTSIZE];
1717 size_t lpublen = OSSL_HPKE_TSTSIZE;
1718 EVP_PKEY *sk = NULL;
1720 hpke_suite.kem_id = kem_id;
1721 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, lpub, &lpublen, &sk,
1722 ikm, ikmlen, testctx, NULL)))
1727 if (!TEST_mem_eq(pub, publen, lpub, lpublen))
1733 * @brief test some uses of IKM produce the expected public keys
1735 static int test_hpke_ikms(void)
1739 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_X25519,
1740 ikm25519, sizeof(ikm25519),
1741 pub25519, sizeof(pub25519));
1745 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P521,
1746 ikmp521, sizeof(ikmp521),
1747 pubp521, sizeof(pubp521));
1751 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256,
1752 ikmp256, sizeof(ikmp256),
1753 pubp256, sizeof(pubp256));
1757 res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256,
1758 ikmiter, sizeof(ikmiter),
1759 pubiter, sizeof(pubiter));
1767 * Test that use of a compressed format auth public key works
1768 * We'll do a typical round-trip for auth mode but provide the
1769 * auth public key in compressed form. That should work.
1771 static int test_hpke_compressed(void)
1774 EVP_PKEY *privp = NULL;
1775 unsigned char pub[OSSL_HPKE_TSTSIZE];
1776 size_t publen = sizeof(pub);
1777 EVP_PKEY *authpriv = NULL;
1778 unsigned char authpub[OSSL_HPKE_TSTSIZE];
1779 size_t authpublen = sizeof(authpub);
1780 int hpke_mode = OSSL_HPKE_MODE_AUTH;
1781 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1782 OSSL_HPKE_CTX *ctx = NULL;
1783 OSSL_HPKE_CTX *rctx = NULL;
1784 unsigned char plain[] = "quick brown fox";
1785 size_t plainlen = sizeof(plain);
1786 unsigned char enc[OSSL_HPKE_TSTSIZE];
1787 size_t enclen = sizeof(enc);
1788 unsigned char cipher[OSSL_HPKE_TSTSIZE];
1789 size_t cipherlen = sizeof(cipher);
1790 unsigned char clear[OSSL_HPKE_TSTSIZE];
1791 size_t clearlen = sizeof(clear);
1793 hpke_suite.kem_id = OSSL_HPKE_KEM_ID_P256;
1795 /* generate auth key pair */
1796 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, &authpriv,
1797 NULL, 0, testctx, NULL)))
1799 /* now get the compressed form public key */
1800 if (!TEST_true(EVP_PKEY_set_utf8_string_param(authpriv,
1801 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
1802 OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED)))
1804 if (!TEST_true(EVP_PKEY_get_octet_string_param(authpriv,
1805 OSSL_PKEY_PARAM_PUB_KEY,
1811 /* sender side as usual */
1812 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1813 NULL, 0, testctx, NULL)))
1815 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1816 OSSL_HPKE_ROLE_SENDER,
1819 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx, authpriv)))
1821 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1823 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1827 /* receiver side providing compressed form of auth public */
1828 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1829 OSSL_HPKE_ROLE_RECEIVER,
1832 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx, authpub, authpublen)))
1834 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1836 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1837 cipher, cipherlen)))
1842 EVP_PKEY_free(privp);
1843 EVP_PKEY_free(authpriv);
1844 OSSL_HPKE_CTX_free(ctx);
1845 OSSL_HPKE_CTX_free(rctx);
1850 * Test that nonce reuse calls are prevented as we expect
1852 static int test_hpke_noncereuse(void)
1855 EVP_PKEY *privp = NULL;
1856 unsigned char pub[OSSL_HPKE_TSTSIZE];
1857 size_t publen = sizeof(pub);
1858 int hpke_mode = OSSL_HPKE_MODE_BASE;
1859 OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1860 OSSL_HPKE_CTX *ctx = NULL;
1861 OSSL_HPKE_CTX *rctx = NULL;
1862 unsigned char plain[] = "quick brown fox";
1863 size_t plainlen = sizeof(plain);
1864 unsigned char enc[OSSL_HPKE_TSTSIZE];
1865 size_t enclen = sizeof(enc);
1866 unsigned char cipher[OSSL_HPKE_TSTSIZE];
1867 size_t cipherlen = sizeof(cipher);
1868 unsigned char clear[OSSL_HPKE_TSTSIZE];
1869 size_t clearlen = sizeof(clear);
1870 uint64_t seq = 0xbad1dea;
1872 /* sender side is not allowed set seq once some crypto done */
1873 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1874 NULL, 0, testctx, NULL)))
1876 if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1877 OSSL_HPKE_ROLE_SENDER,
1880 /* set seq will fail before any crypto done */
1881 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq)))
1883 if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1885 /* set seq will also fail after some crypto done */
1886 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq + 1)))
1888 if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1892 /* receiver side is allowed control seq */
1893 if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1894 OSSL_HPKE_ROLE_RECEIVER,
1897 /* set seq will work before any crypto done */
1898 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq)))
1900 if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1902 /* set seq will work for receivers even after crypto done */
1903 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq)))
1905 /* but that value isn't good so decap will fail */
1906 if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1907 cipher, cipherlen)))
1909 /* reset seq to correct value and _open() should work */
1910 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0)))
1912 if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1913 cipher, cipherlen)))
1918 EVP_PKEY_free(privp);
1919 OSSL_HPKE_CTX_free(ctx);
1920 OSSL_HPKE_CTX_free(rctx);
1924 typedef enum OPTION_choice {
1931 const OPTIONS *test_get_options(void)
1933 static const OPTIONS test_options[] = {
1934 OPT_TEST_OPTIONS_DEFAULT_USAGE,
1935 { "v", OPT_VERBOSE, '-', "Enable verbose mode" },
1936 { OPT_HELP_STR, 1, '-', "Run HPKE tests\n" },
1939 return test_options;
1942 int setup_tests(void)
1946 while ((o = opt_next()) != OPT_EOF) {
1949 verbose = 1; /* Print progress dots */
1951 case OPT_TEST_CASES:
1958 if (!test_get_libctx(&testctx, &nullprov, NULL, &deflprov, "default"))
1960 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_base_test);
1961 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_psk_test);
1962 ADD_TEST(P256kdfsha256_hkdfsha256_aes128gcm_base_test);
1963 ADD_TEST(export_only_test);
1964 ADD_TEST(test_hpke_export);
1965 ADD_TEST(test_hpke_modes_suites);
1966 ADD_TEST(test_hpke_suite_strs);
1967 ADD_TEST(test_hpke_grease);
1968 ADD_TEST(test_hpke_ikms);
1969 ADD_TEST(test_hpke_random_suites);
1970 ADD_TEST(test_hpke_oddcalls);
1971 ADD_TEST(test_hpke_compressed);
1972 ADD_TEST(test_hpke_noncereuse);
1976 void cleanup_tests(void)
1978 OSSL_PROVIDER_unload(deflprov);
1979 OSSL_PROVIDER_unload(nullprov);
1980 OSSL_LIB_CTX_free(testctx);