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