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