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