Use $config{build_file} instead of $target{build_file}
[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                                               OSSL_HPKE_ROLE_SENDER,
127                                               libctx, propq)))
128         goto end;
129     if (!TEST_true(OSSL_HPKE_CTX_set1_ikme(sealctx, base->ikmE, base->ikmElen)))
130         goto end;
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))
134             goto end;
135         if (!TEST_true(OSSL_HPKE_keygen(base->suite,
136                                         authpub, &authpublen, &authpriv,
137                                         base->ikmAuth, base->ikmAuthlen,
138                                         libctx, propq)))
139             goto end;
140         if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(sealctx, authpriv)))
141             goto end;
142     }
143     if (!TEST_true(OSSL_HPKE_keygen(base->suite, rpub, &rpublen, &privR,
144                                     base->ikmR, base->ikmRlen, libctx, propq)))
145         goto end;
146     if (!TEST_true(cmpkey(privR, base->expected_pkRm, base->expected_pkRmlen)))
147         goto end;
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)))
152             goto end;
153     }
154     if (!TEST_true(OSSL_HPKE_encap(sealctx, enc, &enclen,
155                                    rpub, rpublen,
156                                    base->ksinfo, base->ksinfolen)))
157         goto end;
158     if (!TEST_true(cmpkey(privE, enc, enclen)))
159         goto end;
160     for (i = 0; i < aeadsz; ++i) {
161         ctlen = sizeof(ct);
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)))
166             goto end;
167         if (!TEST_mem_eq(ct, ctlen, aead[i].expected_ct,
168                          aead[i].expected_ctlen))
169             goto end;
170         if (!TEST_true(OSSL_HPKE_CTX_get_seq(sealctx, &lastseq)))
171             goto end;
172         if (lastseq != (uint64_t)(i + 1))
173             goto end;
174     }
175     if (!TEST_ptr(openctx = OSSL_HPKE_CTX_new(base->mode, base->suite,
176                                               OSSL_HPKE_ROLE_RECEIVER,
177                                               libctx, propq)))
178         goto end;
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))
183             goto end;
184         if (!TEST_true(OSSL_HPKE_CTX_set1_psk(openctx, base->pskid,
185                                               base->psk, base->psklen)))
186             goto end;
187     }
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)))
192             goto end;
193     }
194     if (!TEST_true(OSSL_HPKE_decap(openctx, enc, enclen, privR,
195                                    base->ksinfo, base->ksinfolen)))
196         goto end;
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,
202                                       aead[i].expected_ct,
203                                       aead[i].expected_ctlen)))
204             goto end;
205         if (!TEST_mem_eq(aead[i].pt, aead[i].ptlen, ptout, ptoutlen))
206             goto end;
207         /* check the sequence is being incremented as expected */
208         if (!TEST_true(OSSL_HPKE_CTX_get_seq(openctx, &lastseq)))
209             goto end;
210         if (lastseq != (uint64_t)(i + 1))
211             goto end;
212     }
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];
217
218         if (len > sizeof(eval))
219             goto end;
220         /* export with too long label should fail */
221         if (!TEST_false(OSSL_HPKE_export(sealctx, eval, len,
222                                          export[i].context, -1)))
223             goto end;
224         /* good export call */
225         if (!TEST_true(OSSL_HPKE_export(sealctx, eval, len,
226                                         export[i].context,
227                                         export[i].contextlen)))
228             goto end;
229         if (!TEST_mem_eq(eval, len, export[i].expected_secret,
230                          export[i].expected_secretlen))
231             goto end;
232
233         /* check seal fails if export only mode */
234         if (aeadsz == 0) {
235
236             if (!TEST_false(OSSL_HPKE_seal(sealctx, ct, &ctlen,
237                                            NULL, 0, ptout, ptoutlen)))
238                 goto end;
239         }
240     }
241     ret = 1;
242 end:
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);
248     return ret;
249 }
250
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
256 };
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
261 };
262 /*
263  * static const char *pskid = "Ennyn Durin aran Moria";
264  */
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
269 };
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
275 };
276
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
283 };
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
289 };
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,
295 };
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
301 };
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
307 };
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
313 };
314 static const unsigned char first_aad0[] = {
315     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
316 };
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
324 };
325 static const unsigned char first_aad1[] = {
326     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
327 };
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
335 };
336 static const unsigned char first_aad2[] = {
337     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x32
338 };
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
346 };
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
352 };
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
359 };
360 static const unsigned char first_context3[] = {
361     0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
362     0x65, 0x78, 0x74
363 };
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
369 };
370
371 static int x25519kdfsha256_hkdfsha256_aes128gcm_psk_test(void)
372 {
373     const TEST_BASEDATA pskdata = {
374         /* "X25519", NULL, "SHA256", "SHA256", "AES-128-GCM", */
375         OSSL_HPKE_MODE_PSK,
376         {
377             OSSL_HPKE_KEM_ID_X25519,
378             OSSL_HPKE_KDF_ID_HKDF_SHA256,
379             OSSL_HPKE_AEAD_ID_AES_GCM_128
380         },
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
390     };
391     const TEST_AEADDATA aeaddata[] = {
392         {
393             0,
394             pt, sizeof(pt),
395             first_aad0, sizeof(first_aad0),
396             first_ct0, sizeof(first_ct0)
397         },
398         {
399             1,
400             pt, sizeof(pt),
401             first_aad1, sizeof(first_aad1),
402             first_ct1, sizeof(first_ct1)
403         },
404         {
405             2,
406             pt, sizeof(pt),
407             first_aad2, sizeof(first_aad2),
408             first_ct2, sizeof(first_ct2)
409         }
410     };
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) },
417     };
418     return do_testhpke(&pskdata, aeaddata, OSSL_NELEM(aeaddata),
419                        exportdata, OSSL_NELEM(exportdata));
420 }
421
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
427 };
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,
433 };
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
439 };
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
445 };
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
451 };
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
457 };
458 static const unsigned char second_aead0[] = {
459     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
460 };
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
468 };
469 static const unsigned char second_aead1[] = {
470     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
471 };
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
479 };
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
485 };
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
492 };
493 static const unsigned char second_context3[] = {
494     0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
495     0x65, 0x78, 0x74
496 };
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
502 };
503
504 static int x25519kdfsha256_hkdfsha256_aes128gcm_base_test(void)
505 {
506     const TEST_BASEDATA basedata = {
507         OSSL_HPKE_MODE_BASE,
508         {
509             OSSL_HPKE_KEM_ID_X25519,
510             OSSL_HPKE_KDF_ID_HKDF_SHA256,
511             OSSL_HPKE_AEAD_ID_AES_GCM_128
512         },
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 */
522     };
523     const TEST_AEADDATA aeaddata[] = {
524         {
525             0,
526             pt, sizeof(pt),
527             second_aead0, sizeof(second_aead0),
528             second_ct0, sizeof(second_ct0)
529         },
530         {
531             1,
532             pt, sizeof(pt),
533             second_aead1, sizeof(second_aead1),
534             second_ct1, sizeof(second_ct1)
535         }
536     };
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) },
543     };
544     return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata),
545                        exportdata, OSSL_NELEM(exportdata));
546 }
547
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
553 };
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,
563     0xc4,
564 };
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
570 };
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,
580     0xa0
581 };
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
587 };
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
593 };
594 static const unsigned char third_aead0[] = {
595     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
596 };
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
604 };
605 static const unsigned char third_aead1[] = {
606     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
607 };
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
615 };
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
621 };
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
628 };
629 static const unsigned char third_context3[] = {
630     0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
631     0x65, 0x78, 0x74
632 };
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
638 };
639
640 static int P256kdfsha256_hkdfsha256_aes128gcm_base_test(void)
641 {
642     const TEST_BASEDATA basedata = {
643         OSSL_HPKE_MODE_BASE,
644         {
645             OSSL_HPKE_KEM_ID_P256,
646             OSSL_HPKE_KDF_ID_HKDF_SHA256,
647             OSSL_HPKE_AEAD_ID_AES_GCM_128
648         },
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 */
658     };
659     const TEST_AEADDATA aeaddata[] = {
660         {
661             0,
662             pt, sizeof(pt),
663             third_aead0, sizeof(third_aead0),
664             third_ct0, sizeof(third_ct0)
665         },
666         {
667             1,
668             pt, sizeof(pt),
669             third_aead1, sizeof(third_aead1),
670             third_ct1, sizeof(third_ct1)
671         }
672     };
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) },
679     };
680     return do_testhpke(&basedata, aeaddata, OSSL_NELEM(aeaddata),
681                        exportdata, OSSL_NELEM(exportdata));
682 }
683
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
689 };
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
695 };
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
701 };
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
707 };
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
713 };
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
719 };
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
725 };
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
732 };
733 static const unsigned char fourth_context3[] = {
734     0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
735     0x65, 0x78, 0x74
736 };
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
742 };
743
744 static int export_only_test(void)
745 {
746     /* based on RFC9180 A.7 */
747     const TEST_BASEDATA basedata = {
748         OSSL_HPKE_MODE_BASE,
749         {
750             OSSL_HPKE_KEM_ID_X25519,
751             OSSL_HPKE_KDF_ID_HKDF_SHA256,
752             OSSL_HPKE_AEAD_ID_EXPORTONLY
753         },
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 */
763     };
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) },
770     };
771     return do_testhpke(&basedata, NULL, 0,
772                        exportdata, OSSL_NELEM(exportdata));
773 }
774
775 /*
776  * Randomly toss a coin
777  */
778 #define COIN_IS_HEADS (test_random() % 2)
779
780 /* tables of HPKE modes and suite values */
781 static int hpke_mode_list[] = {
782     OSSL_HPKE_MODE_BASE,
783     OSSL_HPKE_MODE_PSK,
784     OSSL_HPKE_MODE_AUTH,
785     OSSL_HPKE_MODE_PSKAUTH
786 };
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
793 };
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
798 };
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
804 #endif
805 };
806
807 /*
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()
815  */
816 static const char *mode_str_list[] = {
817     "base", "psk", "auth", "pskauth"
818 };
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"
823 };
824 static const char *kdf_str_list[] = {
825     "hkdf-sha256", "hkdf-sha384", "hkdf-sha512",
826     "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
827     "1", "2", "3"
828 };
829 static const char *aead_str_list[] = {
830     "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "exporter",
831     "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
832     "1", "2", "3",
833     "0xff", "255"
834 };
835 /* table of bogus strings that better not work */
836 static const char *bogus_suite_strs[] = {
837     "3,33,3",
838     "bogus,bogus,bogus",
839     "bogus,33,3,1,bogus",
840     "bogus,33,3,1",
841     "bogus,bogus",
842     "bogus",
843     /* one bad token */
844     "0x10,0x01,bogus",
845     "0x10,bogus,0x01",
846     "bogus,0x02,0x01",
847     /* in reverse order */
848     "aes-256-gcm,hkdf-sha512,x25519",
849     /* surplus separators */
850     ",,0x10,0x01,0x02",
851     "0x10,,0x01,0x02",
852     "0x10,0x01,,0x02",
853     /* embedded NUL chars */
854     "0x10,\00x01,,0x02",
855     "0x10,\0""0x01,0x02",
856     "0x10\0,0x01,0x02",
857     "0x10,0x01\0,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 */
867     "0x10,0x01,0x02,",
868     "0x10,0x01,0x02,,,",
869     "0x10,0x01,0x01,0x02",
870     "0x10,0x01,0x01,blah",
871     "0x10,0x01,0x01 0x02",
872     /* too few but good tokens */
873     "0x10,0x01",
874     "0x10",
875     /* empty things */
876     NULL,
877     "",
878     ",",
879     ",,"
880 };
881
882 /**
883  * @brief round-trips, generating keys, encrypt and decrypt
884  *
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.
889  *
890  * @return 1 for success, other otherwise
891  */
892 static int test_hpke_modes_suites(void)
893 {
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 */
899
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;
906         size_t infolen = 32;
907         unsigned char info[32];
908         unsigned char *infop = NULL;
909         unsigned char lpsk[32];
910         unsigned char *pskp = NULL;
911         char lpskid[32];
912         size_t psklen = 32;
913         char *pskidp = 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;
920
921         memset(plain, 0x00, OSSL_HPKE_TSTSIZE);
922         strcpy((char *)plain, "a message not in a bottle");
923         plainlen = strlen((char *)plain);
924         /*
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.
929          */
930         if (COIN_IS_HEADS) {
931             aadp = aad;
932             memset(aad, 'a', aadlen);
933         } else {
934             aadlen = 0;
935         }
936         if (COIN_IS_HEADS) {
937             infop = info;
938             memset(info, 'i', infolen);
939         } else {
940             infolen = 0;
941         }
942         if (hpke_mode == OSSL_HPKE_MODE_PSK
943             || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) {
944             pskp = lpsk;
945             memset(lpsk, 'P', psklen);
946             pskidp = lpskid;
947             memset(lpskid, 'I', psklen - 1);
948             lpskid[psklen - 1] = '\0';
949         } else {
950             psklen = 0;
951         }
952         for (kemind = 0; /* iterate over the kems, kdfs and aeads */
953              overallresult == 1 && kemind < OSSL_NELEM(hpke_kem_list);
954              kemind++) {
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;
960
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,
965                                                &authpriv, NULL, 0,
966                                                testctx, NULL)) != 1) {
967                     overallresult = 0;
968                 }
969                 authpubp = authpub;
970             } else {
971                 authpublen = 0;
972             }
973             for (kdfind = 0;
974                  overallresult == 1 && kdfind < OSSL_NELEM(hpke_kdf_list);
975                  kdfind++) {
976                 uint16_t kdf_id = hpke_kdf_list[kdfind];
977
978                 hpke_suite.kdf_id = kdf_id;
979                 for (aeadind = 0;
980                      overallresult == 1
981                      && aeadind < OSSL_NELEM(hpke_aead_list);
982                      aeadind++) {
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];
992
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)))
997                         overallresult = 0;
998                     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
999                                                           OSSL_HPKE_ROLE_SENDER,
1000                                                           testctx, NULL)))
1001                         overallresult = 0;
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,
1005                                                               pskp, psklen)))
1006                             overallresult = 0;
1007                     }
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,
1011                                                                    authpriv)))
1012                             overallresult = 0;
1013                     }
1014                     if (!TEST_true(OSSL_HPKE_encap(ctx, senderpub,
1015                                                    &senderpublen,
1016                                                    pub, publen,
1017                                                    infop, infolen)))
1018                         overallresult = 0;
1019                     /* throw in a call with a too-short cipherlen */
1020                     cipherlen = 15;
1021                     if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen,
1022                                                    aadp, aadlen,
1023                                                    plain, plainlen)))
1024                         overallresult = 0;
1025                     /* fix back real cipherlen */
1026                     cipherlen = OSSL_HPKE_TSTSIZE;
1027                     if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen,
1028                                                   aadp, aadlen,
1029                                                   plain, plainlen)))
1030                         overallresult = 0;
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,
1035                                              testctx, NULL);
1036                     if (!TEST_ptr(rctx))
1037                         overallresult = 0;
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,
1041                                                               pskp, psklen)))
1042                             overallresult = 0;
1043                     }
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,
1050                                                                        authpub,
1051                                                                        10
1052                                                                        )))
1053                                 overallresult = 0;
1054                         }
1055                         if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx,
1056                                                                   authpubp,
1057                                                                   authpublen)))
1058                             overallresult = 0;
1059                     }
1060                     if (!TEST_true(OSSL_HPKE_decap(rctx, senderpub,
1061                                                    senderpublen, privp,
1062                                                    infop, infolen)))
1063                         overallresult = 0;
1064                     /* throw in a call with a too-short clearlen */
1065                     clearlen = 15;
1066                     if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen,
1067                                                    aadp, aadlen, cipher,
1068                                                    cipherlen)))
1069                         overallresult = 0;
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,
1074                                                   cipherlen)))
1075                         overallresult = 0;
1076                     OSSL_HPKE_CTX_free(rctx);
1077                     EVP_PKEY_free(privp);
1078                     privp = NULL;
1079                     /* check output */
1080                     if (!TEST_mem_eq(clear, clearlen, plain, plainlen)) {
1081                         overallresult = 0;
1082                     }
1083                     if (verbose || overallresult != 1) {
1084                         const char *res = NULL;
1085
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);
1094                     }
1095                 }
1096             }
1097             EVP_PKEY_free(authpriv);
1098         }
1099     }
1100     return overallresult;
1101 }
1102
1103 /**
1104  * @brief check roundtrip for export
1105  * @return 1 for success, other otherwise
1106  */
1107 static int test_hpke_export(void)
1108 {
1109     int erv = 0;
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);
1129     char *estr = "foo";
1130
1131     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1132                                     NULL, 0, testctx, NULL)))
1133         goto end;
1134     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1135                                           OSSL_HPKE_ROLE_SENDER,
1136                                           testctx, NULL)))
1137         goto end;
1138     /* a few error cases 1st */
1139     if (!TEST_false(OSSL_HPKE_export(NULL, exp, sizeof(exp),
1140                                      (unsigned char *)estr, strlen(estr))))
1141         goto end;
1142     /* ctx before encap should fail too */
1143     if (!TEST_false(OSSL_HPKE_export(ctx, exp, sizeof(exp),
1144                                      (unsigned char *)estr, strlen(estr))))
1145         goto end;
1146     if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1147         goto end;
1148     if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1149                                   plain, plainlen)))
1150         goto end;
1151     /* now for real */
1152     if (!TEST_true(OSSL_HPKE_export(ctx, exp, sizeof(exp),
1153                                     (unsigned char *)estr, strlen(estr))))
1154         goto end;
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))))
1158         goto end;
1159     if (!TEST_mem_eq(exp, sizeof(exp), exp2, sizeof(exp2)))
1160         goto end;
1161     if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1162                                            OSSL_HPKE_ROLE_RECEIVER,
1163                                            testctx, NULL)))
1164         goto end;
1165     if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1166         goto end;
1167     if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1168                                   cipher, cipherlen)))
1169         goto end;
1170     if (!TEST_true(OSSL_HPKE_export(rctx, rexp, sizeof(rexp),
1171                                     (unsigned char *)estr, strlen(estr))))
1172         goto end;
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))))
1176         goto end;
1177     if (!TEST_mem_eq(rexp, sizeof(rexp), rexp2, sizeof(rexp2)))
1178         goto end;
1179     if (!TEST_mem_eq(exp, sizeof(exp), rexp, sizeof(rexp)))
1180         goto end;
1181     erv = 1;
1182 end:
1183     OSSL_HPKE_CTX_free(ctx);
1184     OSSL_HPKE_CTX_free(rctx);
1185     EVP_PKEY_free(privp);
1186     return erv;
1187 }
1188
1189 /**
1190  * @brief Check mapping from strings to HPKE suites
1191  * @return 1 for success, other otherwise
1192  */
1193 static int test_hpke_suite_strs(void)
1194 {
1195     int overallresult = 1;
1196     int kemind = 0;
1197     int kdfind = 0;
1198     int aeadind = 0;
1199     int sind = 0;
1200     char sstr[128];
1201     OSSL_HPKE_SUITE stirred;
1202     char giant[2048];
1203
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) {
1210                     if (verbose)
1211                         TEST_note("Unexpected str2suite fail for :%s",
1212                                   bogus_suite_strs[sind]);
1213                     overallresult = 0;
1214                 }
1215             }
1216         }
1217     }
1218     for (sind = 0; sind != OSSL_NELEM(bogus_suite_strs); sind++) {
1219         if (TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs[sind],
1220                                            &stirred)) != 1) {
1221             if (verbose)
1222                 TEST_note("OSSL_HPKE_str2suite didn't fail for bogus[%d]:%s",
1223                           sind, bogus_suite_strs[sind]);
1224             overallresult = 0;
1225         }
1226     }
1227     /* check a few errors */
1228     if (!TEST_false(OSSL_HPKE_str2suite("", &stirred)))
1229         overallresult = 0;
1230     if (!TEST_false(OSSL_HPKE_str2suite(NULL, &stirred)))
1231         overallresult = 0;
1232     if (!TEST_false(OSSL_HPKE_str2suite("", NULL)))
1233         overallresult = 0;
1234     memset(giant, 'A', sizeof(giant) - 1);
1235     giant[sizeof(giant) - 1] = '\0';
1236     if (!TEST_false(OSSL_HPKE_str2suite(giant, &stirred)))
1237         overallresult = 0;
1238
1239     return overallresult;
1240 }
1241
1242 /**
1243  * @brief try the various GREASEy APIs
1244  * @return 1 for success, other otherwise
1245  */
1246 static int test_hpke_grease(void)
1247 {
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;
1256     size_t enclen = 0;
1257     size_t ikmelen = 0;
1258
1259     memset(&g_suite, 0, sizeof(OSSL_HPKE_SUITE));
1260     /* GREASEing */
1261     /* check too short for public value */
1262     g_pub_len = 10;
1263     if (TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, NULL, &g_suite,
1264                                               g_pub, &g_pub_len,
1265                                               g_cipher, g_cipher_len)) != 1) {
1266         overallresult = 0;
1267     }
1268     /* reset to work */
1269     g_pub_len = OSSL_HPKE_TSTSIZE;
1270     if (TEST_true(OSSL_HPKE_get_grease_value(testctx, NULL, NULL, &g_suite,
1271                                              g_pub, &g_pub_len,
1272                                              g_cipher, g_cipher_len)) != 1) {
1273         overallresult = 0;
1274     }
1275     /* expansion */
1276     expanded = OSSL_HPKE_get_ciphertext_size(g_suite, clearlen);
1277     if (!TEST_size_t_gt(expanded, clearlen)) {
1278         overallresult = 0;
1279     }
1280     enclen = OSSL_HPKE_get_public_encap_size(g_suite);
1281     if (!TEST_size_t_ne(enclen, 0))
1282         overallresult = 0;
1283     /* not really GREASE but we'll check ikmelen thing */
1284     ikmelen = OSSL_HPKE_get_recommended_ikmelen(g_suite);
1285     if (!TEST_size_t_ne(ikmelen, 0))
1286         overallresult = 0;
1287
1288     return overallresult;
1289 }
1290
1291 /*
1292  * Make a set of calls with odd parameters
1293  */
1294 static int test_hpke_oddcalls(void)
1295 {
1296     int erv = 0;
1297     EVP_PKEY *privp = NULL;
1298     unsigned char pub[OSSL_HPKE_TSTSIZE];
1299     size_t publen = sizeof(pub);
1300     int hpke_mode = OSSL_HPKE_MODE_BASE;
1301     int bad_mode = 0xbad;
1302     OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1303     OSSL_HPKE_SUITE bad_suite = { 0xbad, 0xbad, 0xbad };
1304     OSSL_HPKE_CTX *ctx = NULL;
1305     OSSL_HPKE_CTX *rctx = NULL;
1306     unsigned char plain[] = "quick brown fox";
1307     size_t plainlen = sizeof(plain);
1308     unsigned char enc[OSSL_HPKE_TSTSIZE];
1309     size_t enclen = sizeof(enc);
1310     unsigned char cipher[OSSL_HPKE_TSTSIZE];
1311     size_t cipherlen = sizeof(cipher);
1312     unsigned char clear[OSSL_HPKE_TSTSIZE];
1313     size_t clearlen = sizeof(clear);
1314     unsigned char fake_ikm[OSSL_HPKE_TSTSIZE];
1315     char *badpropq = "yeah, this won't work";
1316     uint64_t lseq = 0;
1317     char giant_pskid[OSSL_HPKE_MAX_PARMLEN + 10];
1318     unsigned char info[OSSL_HPKE_TSTSIZE];
1319
1320     /* many of the calls below are designed to get better test coverage */
1321
1322     /* NULL ctx calls */
1323     OSSL_HPKE_CTX_free(NULL);
1324     if (!TEST_false(OSSL_HPKE_CTX_set_seq(NULL, 1)))
1325         goto end;
1326     if (!TEST_false(OSSL_HPKE_CTX_get_seq(NULL, &lseq)))
1327         goto end;
1328     if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(NULL, pub, publen)))
1329         goto end;
1330     if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(NULL, privp)))
1331         goto end;
1332     if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(NULL, NULL, 0)))
1333         goto end;
1334     if (!TEST_false(OSSL_HPKE_CTX_set1_psk(NULL, NULL, NULL, 0)))
1335         goto end;
1336
1337     /* bad suite calls */
1338     hpke_suite.aead_id = 0xbad;
1339     if (!TEST_false(OSSL_HPKE_suite_check(hpke_suite)))
1340         goto end;
1341     hpke_suite.aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128;
1342     if (!TEST_false(OSSL_HPKE_suite_check(bad_suite)))
1343         goto end;
1344     if (!TEST_false(OSSL_HPKE_get_recommended_ikmelen(bad_suite)))
1345         goto end;
1346     if (!TEST_false(OSSL_HPKE_get_public_encap_size(bad_suite)))
1347         goto end;
1348     if (!TEST_false(OSSL_HPKE_get_ciphertext_size(bad_suite, 0)))
1349         goto end;
1350     if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp,
1351                                      NULL, 0, testctx, badpropq)))
1352         goto end;
1353     if (!TEST_false(OSSL_HPKE_keygen(bad_suite, pub, &publen, &privp,
1354                                      NULL, 0, testctx, NULL)))
1355         goto end;
1356
1357     /* dodgy keygen calls */
1358     /* no pub */
1359     if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, NULL, &publen, &privp,
1360                                      NULL, 0, testctx, NULL)))
1361         goto end;
1362     /* ikmlen but NULL ikm */
1363     if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1364                                      NULL, 80, testctx, NULL)))
1365         goto end;
1366     /* zero ikmlen but ikm */
1367     if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1368                                      fake_ikm, 0, testctx, NULL)))
1369         goto end;
1370     /* GIANT ikmlen */
1371     if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1372                                      fake_ikm, -1, testctx, NULL)))
1373         goto end;
1374     /* short publen */
1375     publen = 10;
1376     if (!TEST_false(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1377                                      NULL, 0, testctx, NULL)))
1378         goto end;
1379     publen = sizeof(pub);
1380
1381     /* encap/decap with NULLs */
1382     if (!TEST_false(OSSL_HPKE_encap(NULL, NULL, NULL, NULL, 0, NULL, 0)))
1383         goto end;
1384     if (!TEST_false(OSSL_HPKE_decap(NULL, NULL, 0, NULL, NULL, 0)))
1385         goto end;
1386
1387     /*
1388      * run through a sender/recipient set of calls but with
1389      * failing calls interspersed whenever possible
1390      */
1391     /* good keygen */
1392     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1393                                     NULL, 0, testctx, NULL)))
1394         goto end;
1395
1396     /* a psk context with no psk => encap fail */
1397     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite,
1398                                           OSSL_HPKE_ROLE_SENDER,
1399                                           testctx, NULL)))
1400         goto end;
1401     /* set bad length psk */
1402     if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo",
1403                                            (unsigned char *)"bar", -1)))
1404         goto end;
1405     /* set bad length pskid */
1406     memset(giant_pskid, 'A', sizeof(giant_pskid) - 1);
1407     giant_pskid[sizeof(giant_pskid) - 1] = '\0';
1408     if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, giant_pskid,
1409                                            (unsigned char *)"bar", 3)))
1410         goto end;
1411     /* still no psk really set so encap fails */
1412     if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1413         goto end;
1414     OSSL_HPKE_CTX_free(ctx);
1415
1416     /* bad suite */
1417     if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(hpke_mode, bad_suite,
1418                                                OSSL_HPKE_ROLE_SENDER,
1419                                                testctx, NULL)))
1420         goto end;
1421     /* bad mode */
1422     if (!TEST_ptr_null(ctx = OSSL_HPKE_CTX_new(bad_mode, hpke_suite,
1423                                                OSSL_HPKE_ROLE_SENDER,
1424                                                testctx, NULL)))
1425         goto end;
1426     /* make good ctx */
1427     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1428                                           OSSL_HPKE_ROLE_SENDER,
1429                                           testctx, NULL)))
1430         goto end;
1431     /* too long ikm */
1432     if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, -1)))
1433         goto end;
1434     /* zero length ikm */
1435     if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx, fake_ikm, 0)))
1436         goto end;
1437     /* NULL authpub */
1438     if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(ctx, NULL, 0)))
1439         goto end;
1440     /* NULL auth priv */
1441     if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, NULL)))
1442         goto end;
1443     /* priv good, but mode is bad */
1444     if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx, privp)))
1445         goto end;
1446     /* bad mode for psk */
1447     if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx, "foo",
1448                                            (unsigned char *)"bar", 3)))
1449         goto end;
1450     /* seal before encap */
1451     if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1452                                    plain, plainlen)))
1453         goto end;
1454     /* encap with dodgy public */
1455     if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, NULL, 0)))
1456         goto end;
1457     /* encap with too big info */
1458     if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, 1, info, -1)))
1459         goto end;
1460     /* good encap */
1461     if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1462         goto end;
1463     /* second encap fail */
1464     if (!TEST_false(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1465         goto end;
1466     plainlen = 0;
1467     /* should fail for no plaintext */
1468     if (!TEST_false(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1469                                    plain, plainlen)))
1470         goto end;
1471     plainlen = sizeof(plain);
1472     /* working seal */
1473     if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1474                                   plain, plainlen)))
1475         goto end;
1476
1477     /* receiver side */
1478     /* decap fail with psk mode but no psk set */
1479     if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK, hpke_suite,
1480                                            OSSL_HPKE_ROLE_RECEIVER,
1481                                            testctx, NULL)))
1482         goto end;
1483     if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1484         goto end;
1485     /* done with PSK mode */
1486     OSSL_HPKE_CTX_free(rctx);
1487
1488     /* back good calls for base mode  */
1489     if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1490                                            OSSL_HPKE_ROLE_RECEIVER,
1491                                            testctx, NULL)))
1492         goto end;
1493     /* open before decap */
1494     if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1495                                    cipher, cipherlen)))
1496         goto end;
1497     /* decap with info too long */
1498     if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, info, -1)))
1499         goto end;
1500     /* good decap */
1501     if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1502         goto end;
1503     /* second decap fail */
1504     if (!TEST_false(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1505         goto end;
1506     /* no space for recovered clear */
1507     clearlen = 0;
1508     if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1509                                    cipher, cipherlen)))
1510         goto end;
1511     clearlen = OSSL_HPKE_TSTSIZE;
1512     /* seq wrap around test */
1513     if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, -1)))
1514         goto end;
1515     if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1516                                    cipher, cipherlen)))
1517         goto end;
1518     if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0)))
1519         goto end;
1520     if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1521                                   cipher, cipherlen)))
1522         goto end;
1523     if (!TEST_mem_eq(plain, plainlen, clear, clearlen))
1524         goto end;
1525     erv = 1;
1526 end:
1527     OSSL_HPKE_CTX_free(ctx);
1528     OSSL_HPKE_CTX_free(rctx);
1529     EVP_PKEY_free(privp);
1530     return erv;
1531 }
1532
1533 /* from RFC 9180 Appendix A.1.1 */
1534 static const unsigned char ikm25519[] = {
1535     0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43,
1536     0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13,
1537     0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2,
1538     0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34
1539 };
1540 static const unsigned char pub25519[] = {
1541     0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28,
1542     0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d,
1543     0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44,
1544     0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31
1545 };
1546
1547 /* from RFC9180 Appendix A.3.1 */
1548 static const unsigned char ikmp256[] = {
1549     0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d,
1550     0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f,
1551     0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f,
1552     0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e
1553 };
1554 static const unsigned char pubp256[] = {
1555     0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50,
1556     0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14,
1557     0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e,
1558     0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a,
1559     0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4,
1560     0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00,
1561     0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b,
1562     0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18,
1563     0xc4
1564 };
1565
1566 /*
1567  * A test vector that exercises the counter iteration
1568  * for p256. This was contributed by Ilari L. on the
1569  * CFRG list, see the mail archive:
1570  * https://mailarchive.ietf.org/arch/msg/cfrg/4zwl_y5YN6OU9oeWZOMHNOlOa2w/
1571  */
1572 static const unsigned char ikmiter[] = {
1573     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1576     0x00, 0x00, 0x00, 0x03, 0x01, 0x38, 0xb5, 0xec
1577 };
1578 static const unsigned char pubiter[] = {
1579     0x04, 0x7d, 0x0c, 0x87, 0xff, 0xd5, 0xd1, 0x45,
1580     0x54, 0xa7, 0x51, 0xdf, 0xa3, 0x99, 0x26, 0xa9,
1581     0xe3, 0x0e, 0x7c, 0x3c, 0x65, 0x62, 0x4f, 0x4b,
1582     0x5f, 0xb3, 0xad, 0x7a, 0xa4, 0xda, 0xc2, 0x4a,
1583     0xd8, 0xf5, 0xbe, 0xd0, 0xe8, 0x6e, 0xb8, 0x84,
1584     0x1c, 0xe4, 0x89, 0x2e, 0x0f, 0xc3, 0x87, 0xbb,
1585     0xdb, 0xfe, 0x16, 0x0d, 0x58, 0x9c, 0x89, 0x2d,
1586     0xd4, 0xb1, 0x46, 0x4a, 0xc3, 0x51, 0xc5, 0x6f,
1587     0xb6
1588 };
1589
1590 /* from RFC9180 Appendix A.6.1 */
1591 static const unsigned char ikmp521[] = {
1592     0x7f, 0x06, 0xab, 0x82, 0x15, 0x10, 0x5f, 0xc4,
1593     0x6a, 0xce, 0xeb, 0x2e, 0x3d, 0xc5, 0x02, 0x8b,
1594     0x44, 0x36, 0x4f, 0x96, 0x04, 0x26, 0xeb, 0x0d,
1595     0x8e, 0x40, 0x26, 0xc2, 0xf8, 0xb5, 0xd7, 0xe7,
1596     0xa9, 0x86, 0x68, 0x8f, 0x15, 0x91, 0xab, 0xf5,
1597     0xab, 0x75, 0x3c, 0x35, 0x7a, 0x5d, 0x6f, 0x04,
1598     0x40, 0x41, 0x4b, 0x4e, 0xd4, 0xed, 0xe7, 0x13,
1599     0x17, 0x77, 0x2a, 0xc9, 0x8d, 0x92, 0x39, 0xf7,
1600     0x09, 0x04
1601 };
1602 static const unsigned char pubp521[] = {
1603     0x04, 0x01, 0x38, 0xb3, 0x85, 0xca, 0x16, 0xbb,
1604     0x0d, 0x5f, 0xa0, 0xc0, 0x66, 0x5f, 0xbb, 0xd7,
1605     0xe6, 0x9e, 0x3e, 0xe2, 0x9f, 0x63, 0x99, 0x1d,
1606     0x3e, 0x9b, 0x5f, 0xa7, 0x40, 0xaa, 0xb8, 0x90,
1607     0x0a, 0xae, 0xed, 0x46, 0xed, 0x73, 0xa4, 0x90,
1608     0x55, 0x75, 0x84, 0x25, 0xa0, 0xce, 0x36, 0x50,
1609     0x7c, 0x54, 0xb2, 0x9c, 0xc5, 0xb8, 0x5a, 0x5c,
1610     0xee, 0x6b, 0xae, 0x0c, 0xf1, 0xc2, 0x1f, 0x27,
1611     0x31, 0xec, 0xe2, 0x01, 0x3d, 0xc3, 0xfb, 0x7c,
1612     0x8d, 0x21, 0x65, 0x4b, 0xb1, 0x61, 0xb4, 0x63,
1613     0x96, 0x2c, 0xa1, 0x9e, 0x8c, 0x65, 0x4f, 0xf2,
1614     0x4c, 0x94, 0xdd, 0x28, 0x98, 0xde, 0x12, 0x05,
1615     0x1f, 0x1e, 0xd0, 0x69, 0x22, 0x37, 0xfb, 0x02,
1616     0xb2, 0xf8, 0xd1, 0xdc, 0x1c, 0x73, 0xe9, 0xb3,
1617     0x66, 0xb5, 0x29, 0xeb, 0x43, 0x6e, 0x98, 0xa9,
1618     0x96, 0xee, 0x52, 0x2a, 0xef, 0x86, 0x3d, 0xd5,
1619     0x73, 0x9d, 0x2f, 0x29, 0xb0
1620 };
1621
1622 static int test_hpke_random_suites(void)
1623 {
1624     OSSL_HPKE_SUITE def_suite = OSSL_HPKE_SUITE_DEFAULT;
1625     OSSL_HPKE_SUITE suite = OSSL_HPKE_SUITE_DEFAULT;
1626     OSSL_HPKE_SUITE suite2 = { 0xff01, 0xff02, 0xff03 };
1627     unsigned char enc[200];
1628     size_t enclen = sizeof(enc);
1629     unsigned char ct[500];
1630     size_t ctlen = sizeof(ct);
1631
1632     /* test with NULL/0 inputs */
1633     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, NULL, NULL,
1634                                                NULL, NULL, NULL, 0)))
1635         return 0;
1636     enclen = 10;
1637     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, &def_suite,
1638                                                &suite2, enc, &enclen,
1639                                                ct, ctlen)))
1640         return 0;
1641
1642     enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1643     /* test with a should-be-good suite */
1644     if (!TEST_true(OSSL_HPKE_get_grease_value(testctx, NULL, &def_suite,
1645                                               &suite2, enc, &enclen,
1646                                               ct, ctlen)))
1647         return 0;
1648     /* no suggested suite */
1649     enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1650     if (!TEST_true(OSSL_HPKE_get_grease_value(testctx, NULL, NULL, &suite2,
1651                                               enc, &enclen, ct, ctlen)))
1652         return 0;
1653     /* suggested suite with P-521, just to be sure we hit long values */
1654     enclen = sizeof(enc); /* reset, 'cause get_grease() will have set */
1655     suite.kem_id = OSSL_HPKE_KEM_ID_P521;
1656     if (!TEST_true(OSSL_HPKE_get_grease_value(testctx, NULL, &suite, &suite2,
1657                                               enc, &enclen, ct, ctlen)))
1658         return 0;
1659     enclen = sizeof(enc);
1660     ctlen = 2; /* too-short cttext (can't fit an aead tag) */
1661     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, NULL, &suite2,
1662                                                enc, &enclen, ct, ctlen)))
1663         return 0;
1664
1665     ctlen = sizeof(ct);
1666     enclen = sizeof(enc);
1667
1668     suite.kem_id = OSSL_HPKE_KEM_ID_X25519; /* back to default */
1669     suite.aead_id = 0x1234; /* bad aead */
1670     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, &suite, &suite2,
1671                                                enc, &enclen, ct, ctlen)))
1672         return 0;
1673     enclen = sizeof(enc);
1674     suite.aead_id = def_suite.aead_id; /* good aead */
1675     suite.kdf_id = 0x3451; /* bad kdf */
1676     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, &suite, &suite2,
1677                                                enc, &enclen, ct, ctlen)))
1678         return 0;
1679     enclen = sizeof(enc);
1680     suite.kdf_id = def_suite.kdf_id; /* good kdf */
1681     suite.kem_id = 0x4517; /* bad kem */
1682     if (!TEST_false(OSSL_HPKE_get_grease_value(testctx, NULL, &suite, &suite2,
1683                                                enc, &enclen, ct, ctlen)))
1684         return 0;
1685     return 1;
1686 }
1687
1688 /*
1689  * @brief generate a key pair from initial key material (ikm) and check public
1690  * @param kem_id the KEM to use (RFC9180 code point)
1691  * @ikm is the initial key material buffer
1692  * @ikmlen is the length of ikm
1693  * @pub is the public key buffer
1694  * @publen is the length of the public key
1695  * @return 1 for good, other otherwise
1696  *
1697  * This calls OSSL_HPKE_keygen specifying only the IKM, then
1698  * compares the key pair values with the already-known values
1699  * that were input.
1700  */
1701 static int test_hpke_one_ikm_gen(uint16_t kem_id,
1702                                  const unsigned char *ikm, size_t ikmlen,
1703                                  const unsigned char *pub, size_t publen)
1704 {
1705     OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1706     unsigned char lpub[OSSL_HPKE_TSTSIZE];
1707     size_t lpublen = OSSL_HPKE_TSTSIZE;
1708     EVP_PKEY *sk = NULL;
1709
1710     hpke_suite.kem_id = kem_id;
1711     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, lpub, &lpublen, &sk,
1712                                     ikm, ikmlen, testctx, NULL)))
1713         return 0;
1714     if (!TEST_ptr(sk))
1715         return 0;
1716     EVP_PKEY_free(sk);
1717     if (!TEST_mem_eq(pub, publen, lpub, lpublen))
1718         return 0;
1719     return 1;
1720 }
1721
1722 /*
1723  * @brief test some uses of IKM produce the expected public keys
1724  */
1725 static int test_hpke_ikms(void)
1726 {
1727     int res = 1;
1728
1729     res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_X25519,
1730                                 ikm25519, sizeof(ikm25519),
1731                                 pub25519, sizeof(pub25519));
1732     if (res != 1)
1733         return res;
1734
1735     res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P521,
1736                                 ikmp521, sizeof(ikmp521),
1737                                 pubp521, sizeof(pubp521));
1738     if (res != 1)
1739         return res;
1740
1741     res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256,
1742                                 ikmp256, sizeof(ikmp256),
1743                                 pubp256, sizeof(pubp256));
1744     if (res != 1)
1745         return res;
1746
1747     res = test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256,
1748                                 ikmiter, sizeof(ikmiter),
1749                                 pubiter, sizeof(pubiter));
1750     if (res != 1)
1751         return res;
1752
1753     return res;
1754 }
1755
1756 /*
1757  * Test that use of a compressed format auth public key works
1758  * We'll do a typical round-trip for auth mode but provide the
1759  * auth public key in compressed form. That should work.
1760  */
1761 static int test_hpke_compressed(void)
1762 {
1763     int erv = 0;
1764     EVP_PKEY *privp = NULL;
1765     unsigned char pub[OSSL_HPKE_TSTSIZE];
1766     size_t publen = sizeof(pub);
1767     EVP_PKEY *authpriv = NULL;
1768     unsigned char authpub[OSSL_HPKE_TSTSIZE];
1769     size_t authpublen = sizeof(authpub);
1770     int hpke_mode = OSSL_HPKE_MODE_AUTH;
1771     OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1772     OSSL_HPKE_CTX *ctx = NULL;
1773     OSSL_HPKE_CTX *rctx = NULL;
1774     unsigned char plain[] = "quick brown fox";
1775     size_t plainlen = sizeof(plain);
1776     unsigned char enc[OSSL_HPKE_TSTSIZE];
1777     size_t enclen = sizeof(enc);
1778     unsigned char cipher[OSSL_HPKE_TSTSIZE];
1779     size_t cipherlen = sizeof(cipher);
1780     unsigned char clear[OSSL_HPKE_TSTSIZE];
1781     size_t clearlen = sizeof(clear);
1782
1783     hpke_suite.kem_id = OSSL_HPKE_KEM_ID_P256;
1784
1785     /* generate auth key pair */
1786     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, &authpriv,
1787                                     NULL, 0, testctx, NULL)))
1788         goto end;
1789     /* now get the compressed form public key */
1790     if (!TEST_true(EVP_PKEY_set_utf8_string_param(authpriv,
1791                       OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
1792                       OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED)))
1793         goto end;
1794     if (!TEST_true(EVP_PKEY_get_octet_string_param(authpriv,
1795                                                    OSSL_PKEY_PARAM_PUB_KEY,
1796                                                    authpub,
1797                                                    sizeof(authpub),
1798                                                    &authpublen)))
1799         goto end;
1800
1801     /* sender side as usual */
1802     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1803                                     NULL, 0, testctx, NULL)))
1804         goto end;
1805     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1806                                           OSSL_HPKE_ROLE_SENDER,
1807                                           testctx, NULL)))
1808         goto end;
1809     if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx, authpriv)))
1810         goto end;
1811     if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1812         goto end;
1813     if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1814                                   plain, plainlen)))
1815         goto end;
1816
1817     /* receiver side providing compressed form of auth public */
1818     if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1819                                            OSSL_HPKE_ROLE_RECEIVER,
1820                                            testctx, NULL)))
1821         goto end;
1822     if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx, authpub, authpublen)))
1823         goto end;
1824     if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1825         goto end;
1826     if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1827                                   cipher, cipherlen)))
1828         goto end;
1829     erv = 1;
1830
1831 end:
1832     EVP_PKEY_free(privp);
1833     EVP_PKEY_free(authpriv);
1834     OSSL_HPKE_CTX_free(ctx);
1835     OSSL_HPKE_CTX_free(rctx);
1836     return erv;
1837 }
1838
1839 /*
1840  * Test that nonce reuse calls are prevented as we expect
1841  */
1842 static int test_hpke_noncereuse(void)
1843 {
1844     int erv = 0;
1845     EVP_PKEY *privp = NULL;
1846     unsigned char pub[OSSL_HPKE_TSTSIZE];
1847     size_t publen = sizeof(pub);
1848     int hpke_mode = OSSL_HPKE_MODE_BASE;
1849     OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
1850     OSSL_HPKE_CTX *ctx = NULL;
1851     OSSL_HPKE_CTX *rctx = NULL;
1852     unsigned char plain[] = "quick brown fox";
1853     size_t plainlen = sizeof(plain);
1854     unsigned char enc[OSSL_HPKE_TSTSIZE];
1855     size_t enclen = sizeof(enc);
1856     unsigned char cipher[OSSL_HPKE_TSTSIZE];
1857     size_t cipherlen = sizeof(cipher);
1858     unsigned char clear[OSSL_HPKE_TSTSIZE];
1859     size_t clearlen = sizeof(clear);
1860     uint64_t seq = 0xbad1dea;
1861
1862     /* sender side is not allowed set seq once some crypto done */
1863     if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, pub, &publen, &privp,
1864                                     NULL, 0, testctx, NULL)))
1865         goto end;
1866     if (!TEST_ptr(ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1867                                           OSSL_HPKE_ROLE_SENDER,
1868                                           testctx, NULL)))
1869         goto end;
1870     /* set seq will fail before any crypto done */
1871     if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq)))
1872         goto end;
1873     if (!TEST_true(OSSL_HPKE_encap(ctx, enc, &enclen, pub, publen, NULL, 0)))
1874         goto end;
1875     /* set seq will also fail after some crypto done */
1876     if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx, seq + 1)))
1877         goto end;
1878     if (!TEST_true(OSSL_HPKE_seal(ctx, cipher, &cipherlen, NULL, 0,
1879                                   plain, plainlen)))
1880         goto end;
1881
1882     /* receiver side is allowed control seq */
1883     if (!TEST_ptr(rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
1884                                            OSSL_HPKE_ROLE_RECEIVER,
1885                                            testctx, NULL)))
1886         goto end;
1887     /* set seq will work before any crypto done */
1888     if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq)))
1889         goto end;
1890     if (!TEST_true(OSSL_HPKE_decap(rctx, enc, enclen, privp, NULL, 0)))
1891         goto end;
1892     /* set seq will work for receivers even after crypto done */
1893     if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, seq)))
1894         goto end;
1895     /* but that value isn't good so decap will fail */
1896     if (!TEST_false(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1897                                    cipher, cipherlen)))
1898         goto end;
1899     /* reset seq to correct value and _open() should work */
1900     if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx, 0)))
1901         goto end;
1902     if (!TEST_true(OSSL_HPKE_open(rctx, clear, &clearlen, NULL, 0,
1903                                   cipher, cipherlen)))
1904         goto end;
1905     erv = 1;
1906
1907 end:
1908     EVP_PKEY_free(privp);
1909     OSSL_HPKE_CTX_free(ctx);
1910     OSSL_HPKE_CTX_free(rctx);
1911     return erv;
1912 }
1913
1914 typedef enum OPTION_choice {
1915     OPT_ERR = -1,
1916     OPT_EOF = 0,
1917     OPT_VERBOSE,
1918     OPT_TEST_ENUM
1919 } OPTION_CHOICE;
1920
1921 const OPTIONS *test_get_options(void)
1922 {
1923     static const OPTIONS test_options[] = {
1924         OPT_TEST_OPTIONS_DEFAULT_USAGE,
1925         { "v", OPT_VERBOSE, '-', "Enable verbose mode" },
1926         { OPT_HELP_STR, 1, '-', "Run HPKE tests\n" },
1927         { NULL }
1928     };
1929     return test_options;
1930 }
1931
1932 int setup_tests(void)
1933 {
1934     OPTION_CHOICE o;
1935
1936     while ((o = opt_next()) != OPT_EOF) {
1937         switch (o) {
1938         case OPT_VERBOSE:
1939             verbose = 1; /* Print progress dots */
1940             break;
1941         case OPT_TEST_CASES:
1942             break;
1943         default:
1944             return 0;
1945         }
1946     }
1947
1948     if (!test_get_libctx(&testctx, &nullprov, NULL, &deflprov, "default"))
1949         return 0;
1950     ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_base_test);
1951     ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_psk_test);
1952     ADD_TEST(P256kdfsha256_hkdfsha256_aes128gcm_base_test);
1953     ADD_TEST(export_only_test);
1954     ADD_TEST(test_hpke_export);
1955     ADD_TEST(test_hpke_modes_suites);
1956     ADD_TEST(test_hpke_suite_strs);
1957     ADD_TEST(test_hpke_grease);
1958     ADD_TEST(test_hpke_ikms);
1959     ADD_TEST(test_hpke_random_suites);
1960     ADD_TEST(test_hpke_oddcalls);
1961     ADD_TEST(test_hpke_compressed);
1962     ADD_TEST(test_hpke_noncereuse);
1963     return 1;
1964 }
1965
1966 void cleanup_tests(void)
1967 {
1968     OSSL_PROVIDER_unload(deflprov);
1969     OSSL_PROVIDER_unload(nullprov);
1970     OSSL_LIB_CTX_free(testctx);
1971 }