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