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