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