2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/evp.h>
11 #include <openssl/core_names.h>
12 #include <openssl/rand.h>
13 #include <openssl/hpke.h>
16 /* a size to use for stack buffers */
17 #define OSSL_HPKE_TSTSIZE 512
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;
27 OSSL_HPKE_SUITE suite
;
28 const unsigned char *ikmE
;
30 const unsigned char *expected_pkEm
;
31 size_t expected_pkEmlen
;
32 const unsigned char *ikmR
;
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
;
42 const unsigned char *ikmAuth
;
44 const unsigned char *psk
;
46 const char *pskid
; /* want terminating NUL here */
52 const unsigned char *pt
;
54 const unsigned char *aad
;
56 const unsigned char *expected_ct
;
57 size_t expected_ctlen
;
62 const unsigned char *context
;
64 const unsigned char *expected_secret
;
65 size_t expected_secretlen
;
69 * @brief Test that an EVP_PKEY encoded public key matches the supplied buffer
70 * @param pkey is the EVP_PKEY we want to check
71 * @param pub is the expected public key buffer
72 * @param publen is the length of the above
73 * @return 1 for good, 0 for bad
75 static int cmpkey(const EVP_PKEY
*pkey
,
76 const unsigned char *pub
, size_t publen
)
78 unsigned char pubbuf
[256];
82 if (!TEST_true(publen
<= sizeof(pubbuf
)))
84 erv
= EVP_PKEY_get_octet_string_param(pkey
,
85 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY
,
86 pubbuf
, sizeof(pubbuf
), &pubbuflen
);
89 if (pub
!= NULL
&& !TEST_mem_eq(pubbuf
, pubbuflen
, pub
, publen
))
94 static int do_testhpke(const TEST_BASEDATA
*base
,
95 const TEST_AEADDATA
*aead
, size_t aeadsz
,
96 const TEST_EXPORTDATA
*export
, size_t exportsz
)
98 OSSL_LIB_CTX
*libctx
= testctx
;
99 const char *propq
= testpropq
;
100 OSSL_HPKE_CTX
*sealctx
= NULL
, *openctx
= NULL
;
101 unsigned char ct
[256];
102 unsigned char enc
[256];
103 unsigned char ptout
[256];
104 size_t ptoutlen
= sizeof(ptout
);
105 size_t enclen
= sizeof(enc
);
106 size_t ctlen
= sizeof(ct
);
107 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
108 size_t publen
= sizeof(pub
);
109 EVP_PKEY
*privE
= NULL
;
110 unsigned char authpub
[OSSL_HPKE_TSTSIZE
];
111 size_t authpublen
= sizeof(authpub
);
112 EVP_PKEY
*authpriv
= NULL
;
113 unsigned char rpub
[OSSL_HPKE_TSTSIZE
];
114 size_t rpublen
= sizeof(pub
);
115 EVP_PKEY
*privR
= NULL
;
118 uint64_t lastseq
= 0;
120 if (!TEST_true(OSSL_HPKE_keygen(base
->suite
, pub
, &publen
, &privE
,
121 base
->ikmE
, base
->ikmElen
, libctx
, propq
)))
123 if (!TEST_true(cmpkey(privE
, base
->expected_pkEm
, base
->expected_pkEmlen
)))
125 if (!TEST_ptr(sealctx
= OSSL_HPKE_CTX_new(base
->mode
, base
->suite
,
126 OSSL_HPKE_ROLE_SENDER
,
129 if (!TEST_true(OSSL_HPKE_CTX_set1_ikme(sealctx
, base
->ikmE
, base
->ikmElen
)))
131 if (base
->mode
== OSSL_HPKE_MODE_AUTH
132 || base
->mode
== OSSL_HPKE_MODE_PSKAUTH
) {
133 if (!TEST_true(base
->ikmAuth
!= NULL
&& base
->ikmAuthlen
> 0))
135 if (!TEST_true(OSSL_HPKE_keygen(base
->suite
,
136 authpub
, &authpublen
, &authpriv
,
137 base
->ikmAuth
, base
->ikmAuthlen
,
140 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(sealctx
, authpriv
)))
143 if (!TEST_true(OSSL_HPKE_keygen(base
->suite
, rpub
, &rpublen
, &privR
,
144 base
->ikmR
, base
->ikmRlen
, libctx
, propq
)))
146 if (!TEST_true(cmpkey(privR
, base
->expected_pkRm
, base
->expected_pkRmlen
)))
148 if (base
->mode
== OSSL_HPKE_MODE_PSK
149 || base
->mode
== OSSL_HPKE_MODE_PSKAUTH
) {
150 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(sealctx
, base
->pskid
,
151 base
->psk
, base
->psklen
)))
154 if (!TEST_true(OSSL_HPKE_encap(sealctx
, enc
, &enclen
,
156 base
->ksinfo
, base
->ksinfolen
)))
158 if (!TEST_true(cmpkey(privE
, enc
, enclen
)))
160 for (i
= 0; i
< aeadsz
; ++i
) {
162 memset(ct
, 0, ctlen
);
163 if (!TEST_true(OSSL_HPKE_seal(sealctx
, ct
, &ctlen
,
164 aead
[i
].aad
, aead
[i
].aadlen
,
165 aead
[i
].pt
, aead
[i
].ptlen
)))
167 if (!TEST_mem_eq(ct
, ctlen
, aead
[i
].expected_ct
,
168 aead
[i
].expected_ctlen
))
170 if (!TEST_true(OSSL_HPKE_CTX_get_seq(sealctx
, &lastseq
)))
172 if (lastseq
!= (uint64_t)(i
+ 1))
175 if (!TEST_ptr(openctx
= OSSL_HPKE_CTX_new(base
->mode
, base
->suite
,
176 OSSL_HPKE_ROLE_RECEIVER
,
179 if (base
->mode
== OSSL_HPKE_MODE_PSK
180 || base
->mode
== OSSL_HPKE_MODE_PSKAUTH
) {
181 if (!TEST_true(base
->pskid
!= NULL
&& base
->psk
!= NULL
182 && base
->psklen
> 0))
184 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(openctx
, base
->pskid
,
185 base
->psk
, base
->psklen
)))
188 if (base
->mode
== OSSL_HPKE_MODE_AUTH
189 || base
->mode
== OSSL_HPKE_MODE_PSKAUTH
) {
190 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(openctx
,
191 authpub
, authpublen
)))
194 if (!TEST_true(OSSL_HPKE_decap(openctx
, enc
, enclen
, privR
,
195 base
->ksinfo
, base
->ksinfolen
)))
197 for (i
= 0; i
< aeadsz
; ++i
) {
198 ptoutlen
= sizeof(ptout
);
199 memset(ptout
, 0, ptoutlen
);
200 if (!TEST_true(OSSL_HPKE_open(openctx
, ptout
, &ptoutlen
,
201 aead
[i
].aad
, aead
[i
].aadlen
,
203 aead
[i
].expected_ctlen
)))
205 if (!TEST_mem_eq(aead
[i
].pt
, aead
[i
].ptlen
, ptout
, ptoutlen
))
207 /* check the sequence is being incremented as expected */
208 if (!TEST_true(OSSL_HPKE_CTX_get_seq(openctx
, &lastseq
)))
210 if (lastseq
!= (uint64_t)(i
+ 1))
213 /* check exporters */
214 for (i
= 0; i
< exportsz
; ++i
) {
215 size_t len
= export
[i
].expected_secretlen
;
216 unsigned char eval
[OSSL_HPKE_TSTSIZE
];
218 if (len
> sizeof(eval
))
220 /* export with too long label should fail */
221 if (!TEST_false(OSSL_HPKE_export(sealctx
, eval
, len
,
222 export
[i
].context
, -1)))
224 /* good export call */
225 if (!TEST_true(OSSL_HPKE_export(sealctx
, eval
, len
,
227 export
[i
].contextlen
)))
229 if (!TEST_mem_eq(eval
, len
, export
[i
].expected_secret
,
230 export
[i
].expected_secretlen
))
233 /* check seal fails if export only mode */
236 if (!TEST_false(OSSL_HPKE_seal(sealctx
, ct
, &ctlen
,
237 NULL
, 0, ptout
, ptoutlen
)))
243 OSSL_HPKE_CTX_free(sealctx
);
244 OSSL_HPKE_CTX_free(openctx
);
245 EVP_PKEY_free(privE
);
246 EVP_PKEY_free(privR
);
247 EVP_PKEY_free(authpriv
);
251 static const unsigned char pt
[] = {
252 0x42, 0x65, 0x61, 0x75, 0x74, 0x79, 0x20, 0x69,
253 0x73, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x2c,
254 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, 0x62,
255 0x65, 0x61, 0x75, 0x74, 0x79
257 static const unsigned char ksinfo
[] = {
258 0x4f, 0x64, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61,
259 0x20, 0x47, 0x72, 0x65, 0x63, 0x69, 0x61, 0x6e,
260 0x20, 0x55, 0x72, 0x6e
262 #ifndef OPENSSL_NO_ECX
264 * static const char *pskid = "Ennyn Durin aran Moria";
266 static const unsigned char pskid
[] = {
267 0x45, 0x6e, 0x6e, 0x79, 0x6e, 0x20, 0x44, 0x75,
268 0x72, 0x69, 0x6e, 0x20, 0x61, 0x72, 0x61, 0x6e,
269 0x20, 0x4d, 0x6f, 0x72, 0x69, 0x61, 0x00
271 static const unsigned char psk
[] = {
272 0x02, 0x47, 0xfd, 0x33, 0xb9, 0x13, 0x76, 0x0f,
273 0xa1, 0xfa, 0x51, 0xe1, 0x89, 0x2d, 0x9f, 0x30,
274 0x7f, 0xbe, 0x65, 0xeb, 0x17, 0x1e, 0x81, 0x32,
275 0xc2, 0xaf, 0x18, 0x55, 0x5a, 0x73, 0x8b, 0x82
278 /* these need to be "outside" the function below to keep check-ansi CI happy */
279 static const unsigned char first_ikme
[] = {
280 0x78, 0x62, 0x8c, 0x35, 0x4e, 0x46, 0xf3, 0xe1,
281 0x69, 0xbd, 0x23, 0x1b, 0xe7, 0xb2, 0xff, 0x1c,
282 0x77, 0xaa, 0x30, 0x24, 0x60, 0xa2, 0x6d, 0xbf,
283 0xa1, 0x55, 0x15, 0x68, 0x4c, 0x00, 0x13, 0x0b
285 static const unsigned char first_ikmr
[] = {
286 0xd4, 0xa0, 0x9d, 0x09, 0xf5, 0x75, 0xfe, 0xf4,
287 0x25, 0x90, 0x5d, 0x2a, 0xb3, 0x96, 0xc1, 0x44,
288 0x91, 0x41, 0x46, 0x3f, 0x69, 0x8f, 0x8e, 0xfd,
289 0xb7, 0xac, 0xcf, 0xaf, 0xf8, 0x99, 0x50, 0x98
291 static const unsigned char first_ikmepub
[] = {
292 0x0a, 0xd0, 0x95, 0x0d, 0x9f, 0xb9, 0x58, 0x8e,
293 0x59, 0x69, 0x0b, 0x74, 0xf1, 0x23, 0x7e, 0xcd,
294 0xf1, 0xd7, 0x75, 0xcd, 0x60, 0xbe, 0x2e, 0xca,
295 0x57, 0xaf, 0x5a, 0x4b, 0x04, 0x71, 0xc9, 0x1b,
297 static const unsigned char first_ikmrpub
[] = {
298 0x9f, 0xed, 0x7e, 0x8c, 0x17, 0x38, 0x75, 0x60,
299 0xe9, 0x2c, 0xc6, 0x46, 0x2a, 0x68, 0x04, 0x96,
300 0x57, 0x24, 0x6a, 0x09, 0xbf, 0xa8, 0xad, 0xe7,
301 0xae, 0xfe, 0x58, 0x96, 0x72, 0x01, 0x63, 0x66
303 static const unsigned char first_ikmrpriv
[] = {
304 0xc5, 0xeb, 0x01, 0xeb, 0x45, 0x7f, 0xe6, 0xc6,
305 0xf5, 0x75, 0x77, 0xc5, 0x41, 0x3b, 0x93, 0x15,
306 0x50, 0xa1, 0x62, 0xc7, 0x1a, 0x03, 0xac, 0x8d,
307 0x19, 0x6b, 0xab, 0xbd, 0x4e, 0x5c, 0xe0, 0xfd
309 static const unsigned char first_expected_shared_secret
[] = {
310 0x72, 0x76, 0x99, 0xf0, 0x09, 0xff, 0xe3, 0xc0,
311 0x76, 0x31, 0x50, 0x19, 0xc6, 0x96, 0x48, 0x36,
312 0x6b, 0x69, 0x17, 0x14, 0x39, 0xbd, 0x7d, 0xd0,
313 0x80, 0x77, 0x43, 0xbd, 0xe7, 0x69, 0x86, 0xcd
315 static const unsigned char first_aad0
[] = {
316 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
318 static const unsigned char first_ct0
[] = {
319 0xe5, 0x2c, 0x6f, 0xed, 0x7f, 0x75, 0x8d, 0x0c,
320 0xf7, 0x14, 0x56, 0x89, 0xf2, 0x1b, 0xc1, 0xbe,
321 0x6e, 0xc9, 0xea, 0x09, 0x7f, 0xef, 0x4e, 0x95,
322 0x94, 0x40, 0x01, 0x2f, 0x4f, 0xeb, 0x73, 0xfb,
323 0x61, 0x1b, 0x94, 0x61, 0x99, 0xe6, 0x81, 0xf4,
324 0xcf, 0xc3, 0x4d, 0xb8, 0xea
326 static const unsigned char first_aad1
[] = {
327 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
329 static const unsigned char first_ct1
[] = {
330 0x49, 0xf3, 0xb1, 0x9b, 0x28, 0xa9, 0xea, 0x9f,
331 0x43, 0xe8, 0xc7, 0x12, 0x04, 0xc0, 0x0d, 0x4a,
332 0x49, 0x0e, 0xe7, 0xf6, 0x13, 0x87, 0xb6, 0x71,
333 0x9d, 0xb7, 0x65, 0xe9, 0x48, 0x12, 0x3b, 0x45,
334 0xb6, 0x16, 0x33, 0xef, 0x05, 0x9b, 0xa2, 0x2c,
335 0xd6, 0x24, 0x37, 0xc8, 0xba
337 static const unsigned char first_aad2
[] = {
338 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x32
340 static const unsigned char first_ct2
[] = {
341 0x25, 0x7c, 0xa6, 0xa0, 0x84, 0x73, 0xdc, 0x85,
342 0x1f, 0xde, 0x45, 0xaf, 0xd5, 0x98, 0xcc, 0x83,
343 0xe3, 0x26, 0xdd, 0xd0, 0xab, 0xe1, 0xef, 0x23,
344 0xba, 0xa3, 0xba, 0xa4, 0xdd, 0x8c, 0xde, 0x99,
345 0xfc, 0xe2, 0xc1, 0xe8, 0xce, 0x68, 0x7b, 0x0b,
346 0x47, 0xea, 0xd1, 0xad, 0xc9
348 static const unsigned char first_export1
[] = {
349 0xdf, 0xf1, 0x7a, 0xf3, 0x54, 0xc8, 0xb4, 0x16,
350 0x73, 0x56, 0x7d, 0xb6, 0x25, 0x9f, 0xd6, 0x02,
351 0x99, 0x67, 0xb4, 0xe1, 0xaa, 0xd1, 0x30, 0x23,
352 0xc2, 0xae, 0x5d, 0xf8, 0xf4, 0xf4, 0x3b, 0xf6
354 static const unsigned char first_context2
[] = { 0x00 };
355 static const unsigned char first_export2
[] = {
356 0x6a, 0x84, 0x72, 0x61, 0xd8, 0x20, 0x7f, 0xe5,
357 0x96, 0xbe, 0xfb, 0x52, 0x92, 0x84, 0x63, 0x88,
358 0x1a, 0xb4, 0x93, 0xda, 0x34, 0x5b, 0x10, 0xe1,
359 0xdc, 0xc6, 0x45, 0xe3, 0xb9, 0x4e, 0x2d, 0x95
361 static const unsigned char first_context3
[] = {
362 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
365 static const unsigned char first_export3
[] = {
366 0x8a, 0xff, 0x52, 0xb4, 0x5a, 0x1b, 0xe3, 0xa7,
367 0x34, 0xbc, 0x7a, 0x41, 0xe2, 0x0b, 0x4e, 0x05,
368 0x5a, 0xd4, 0xc4, 0xd2, 0x21, 0x04, 0xb0, 0xc2,
369 0x02, 0x85, 0xa7, 0xc4, 0x30, 0x24, 0x01, 0xcd
372 static int x25519kdfsha256_hkdfsha256_aes128gcm_psk_test(void)
374 const TEST_BASEDATA pskdata
= {
375 /* "X25519", NULL, "SHA256", "SHA256", "AES-128-GCM", */
378 OSSL_HPKE_KEM_ID_X25519
,
379 OSSL_HPKE_KDF_ID_HKDF_SHA256
,
380 OSSL_HPKE_AEAD_ID_AES_GCM_128
382 first_ikme
, sizeof(first_ikme
),
383 first_ikmepub
, sizeof(first_ikmepub
),
384 first_ikmr
, sizeof(first_ikmr
),
385 first_ikmrpub
, sizeof(first_ikmrpub
),
386 first_ikmrpriv
, sizeof(first_ikmrpriv
),
387 first_expected_shared_secret
, sizeof(first_expected_shared_secret
),
388 ksinfo
, sizeof(ksinfo
),
389 NULL
, 0, /* No Auth */
390 psk
, sizeof(psk
), (char *) pskid
392 const TEST_AEADDATA aeaddata
[] = {
396 first_aad0
, sizeof(first_aad0
),
397 first_ct0
, sizeof(first_ct0
)
402 first_aad1
, sizeof(first_aad1
),
403 first_ct1
, sizeof(first_ct1
)
408 first_aad2
, sizeof(first_aad2
),
409 first_ct2
, sizeof(first_ct2
)
412 const TEST_EXPORTDATA exportdata
[] = {
413 { NULL
, 0, first_export1
, sizeof(first_export1
) },
414 { first_context2
, sizeof(first_context2
),
415 first_export2
, sizeof(first_export2
) },
416 { first_context3
, sizeof(first_context3
),
417 first_export3
, sizeof(first_export3
) },
419 return do_testhpke(&pskdata
, aeaddata
, OSSL_NELEM(aeaddata
),
420 exportdata
, OSSL_NELEM(exportdata
));
423 static const unsigned char second_ikme
[] = {
424 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43,
425 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13,
426 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2,
427 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34
429 static const unsigned char second_ikmepub
[] = {
430 0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28,
431 0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d,
432 0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44,
433 0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31,
435 static const unsigned char second_ikmr
[] = {
436 0x6d, 0xb9, 0xdf, 0x30, 0xaa, 0x07, 0xdd, 0x42,
437 0xee, 0x5e, 0x81, 0x81, 0xaf, 0xdb, 0x97, 0x7e,
438 0x53, 0x8f, 0x5e, 0x1f, 0xec, 0x8a, 0x06, 0x22,
439 0x3f, 0x33, 0xf7, 0x01, 0x3e, 0x52, 0x50, 0x37
441 static const unsigned char second_ikmrpub
[] = {
442 0x39, 0x48, 0xcf, 0xe0, 0xad, 0x1d, 0xdb, 0x69,
443 0x5d, 0x78, 0x0e, 0x59, 0x07, 0x71, 0x95, 0xda,
444 0x6c, 0x56, 0x50, 0x6b, 0x02, 0x73, 0x29, 0x79,
445 0x4a, 0xb0, 0x2b, 0xca, 0x80, 0x81, 0x5c, 0x4d
447 static const unsigned char second_ikmrpriv
[] = {
448 0x46, 0x12, 0xc5, 0x50, 0x26, 0x3f, 0xc8, 0xad,
449 0x58, 0x37, 0x5d, 0xf3, 0xf5, 0x57, 0xaa, 0xc5,
450 0x31, 0xd2, 0x68, 0x50, 0x90, 0x3e, 0x55, 0xa9,
451 0xf2, 0x3f, 0x21, 0xd8, 0x53, 0x4e, 0x8a, 0xc8
453 static const unsigned char second_expected_shared_secret
[] = {
454 0xfe, 0x0e, 0x18, 0xc9, 0xf0, 0x24, 0xce, 0x43,
455 0x79, 0x9a, 0xe3, 0x93, 0xc7, 0xe8, 0xfe, 0x8f,
456 0xce, 0x9d, 0x21, 0x88, 0x75, 0xe8, 0x22, 0x7b,
457 0x01, 0x87, 0xc0, 0x4e, 0x7d, 0x2e, 0xa1, 0xfc
459 static const unsigned char second_aead0
[] = {
460 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
462 static const unsigned char second_ct0
[] = {
463 0xf9, 0x38, 0x55, 0x8b, 0x5d, 0x72, 0xf1, 0xa2,
464 0x38, 0x10, 0xb4, 0xbe, 0x2a, 0xb4, 0xf8, 0x43,
465 0x31, 0xac, 0xc0, 0x2f, 0xc9, 0x7b, 0xab, 0xc5,
466 0x3a, 0x52, 0xae, 0x82, 0x18, 0xa3, 0x55, 0xa9,
467 0x6d, 0x87, 0x70, 0xac, 0x83, 0xd0, 0x7b, 0xea,
468 0x87, 0xe1, 0x3c, 0x51, 0x2a
470 static const unsigned char second_aead1
[] = {
471 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
473 static const unsigned char second_ct1
[] = {
474 0xaf, 0x2d, 0x7e, 0x9a, 0xc9, 0xae, 0x7e, 0x27,
475 0x0f, 0x46, 0xba, 0x1f, 0x97, 0x5b, 0xe5, 0x3c,
476 0x09, 0xf8, 0xd8, 0x75, 0xbd, 0xc8, 0x53, 0x54,
477 0x58, 0xc2, 0x49, 0x4e, 0x8a, 0x6e, 0xab, 0x25,
478 0x1c, 0x03, 0xd0, 0xc2, 0x2a, 0x56, 0xb8, 0xca,
479 0x42, 0xc2, 0x06, 0x3b, 0x84
481 static const unsigned char second_export1
[] = {
482 0x38, 0x53, 0xfe, 0x2b, 0x40, 0x35, 0x19, 0x5a,
483 0x57, 0x3f, 0xfc, 0x53, 0x85, 0x6e, 0x77, 0x05,
484 0x8e, 0x15, 0xd9, 0xea, 0x06, 0x4d, 0xe3, 0xe5,
485 0x9f, 0x49, 0x61, 0xd0, 0x09, 0x52, 0x50, 0xee
487 static const unsigned char second_context2
[] = { 0x00 };
488 static const unsigned char second_export2
[] = {
489 0x2e, 0x8f, 0x0b, 0x54, 0x67, 0x3c, 0x70, 0x29,
490 0x64, 0x9d, 0x4e, 0xb9, 0xd5, 0xe3, 0x3b, 0xf1,
491 0x87, 0x2c, 0xf7, 0x6d, 0x62, 0x3f, 0xf1, 0x64,
492 0xac, 0x18, 0x5d, 0xa9, 0xe8, 0x8c, 0x21, 0xa5
494 static const unsigned char second_context3
[] = {
495 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
498 static const unsigned char second_export3
[] = {
499 0xe9, 0xe4, 0x30, 0x65, 0x10, 0x2c, 0x38, 0x36,
500 0x40, 0x1b, 0xed, 0x8c, 0x3c, 0x3c, 0x75, 0xae,
501 0x46, 0xbe, 0x16, 0x39, 0x86, 0x93, 0x91, 0xd6,
502 0x2c, 0x61, 0xf1, 0xec, 0x7a, 0xf5, 0x49, 0x31
505 static int x25519kdfsha256_hkdfsha256_aes128gcm_base_test(void)
507 const TEST_BASEDATA basedata
= {
510 OSSL_HPKE_KEM_ID_X25519
,
511 OSSL_HPKE_KDF_ID_HKDF_SHA256
,
512 OSSL_HPKE_AEAD_ID_AES_GCM_128
514 second_ikme
, sizeof(second_ikme
),
515 second_ikmepub
, sizeof(second_ikmepub
),
516 second_ikmr
, sizeof(second_ikmr
),
517 second_ikmrpub
, sizeof(second_ikmrpub
),
518 second_ikmrpriv
, sizeof(second_ikmrpriv
),
519 second_expected_shared_secret
, sizeof(second_expected_shared_secret
),
520 ksinfo
, sizeof(ksinfo
),
521 NULL
, 0, /* no auth ikm */
522 NULL
, 0, NULL
/* no psk */
524 const TEST_AEADDATA aeaddata
[] = {
528 second_aead0
, sizeof(second_aead0
),
529 second_ct0
, sizeof(second_ct0
)
534 second_aead1
, sizeof(second_aead1
),
535 second_ct1
, sizeof(second_ct1
)
538 const TEST_EXPORTDATA exportdata
[] = {
539 { NULL
, 0, second_export1
, sizeof(second_export1
) },
540 { second_context2
, sizeof(second_context2
),
541 second_export2
, sizeof(second_export2
) },
542 { second_context3
, sizeof(second_context3
),
543 second_export3
, sizeof(second_export3
) },
545 return do_testhpke(&basedata
, aeaddata
, OSSL_NELEM(aeaddata
),
546 exportdata
, OSSL_NELEM(exportdata
));
550 static const unsigned char third_ikme
[] = {
551 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d,
552 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f,
553 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f,
554 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e
556 static const unsigned char third_ikmepub
[] = {
557 0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50,
558 0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14,
559 0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e,
560 0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a,
561 0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4,
562 0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00,
563 0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b,
564 0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18,
567 static const unsigned char third_ikmr
[] = {
568 0x66, 0x8b, 0x37, 0x17, 0x1f, 0x10, 0x72, 0xf3,
569 0xcf, 0x12, 0xea, 0x8a, 0x23, 0x6a, 0x45, 0xdf,
570 0x23, 0xfc, 0x13, 0xb8, 0x2a, 0xf3, 0x60, 0x9a,
571 0xd1, 0xe3, 0x54, 0xf6, 0xef, 0x81, 0x75, 0x50
573 static const unsigned char third_ikmrpub
[] = {
574 0x04, 0xfe, 0x8c, 0x19, 0xce, 0x09, 0x05, 0x19,
575 0x1e, 0xbc, 0x29, 0x8a, 0x92, 0x45, 0x79, 0x25,
576 0x31, 0xf2, 0x6f, 0x0c, 0xec, 0xe2, 0x46, 0x06,
577 0x39, 0xe8, 0xbc, 0x39, 0xcb, 0x7f, 0x70, 0x6a,
578 0x82, 0x6a, 0x77, 0x9b, 0x4c, 0xf9, 0x69, 0xb8,
579 0xa0, 0xe5, 0x39, 0xc7, 0xf6, 0x2f, 0xb3, 0xd3,
580 0x0a, 0xd6, 0xaa, 0x8f, 0x80, 0xe3, 0x0f, 0x1d,
581 0x12, 0x8a, 0xaf, 0xd6, 0x8a, 0x2c, 0xe7, 0x2e,
584 static const unsigned char third_ikmrpriv
[] = {
585 0xf3, 0xce, 0x7f, 0xda, 0xe5, 0x7e, 0x1a, 0x31,
586 0x0d, 0x87, 0xf1, 0xeb, 0xbd, 0xe6, 0xf3, 0x28,
587 0xbe, 0x0a, 0x99, 0xcd, 0xbc, 0xad, 0xf4, 0xd6,
588 0x58, 0x9c, 0xf2, 0x9d, 0xe4, 0xb8, 0xff, 0xd2
590 static const unsigned char third_expected_shared_secret
[] = {
591 0xc0, 0xd2, 0x6a, 0xea, 0xb5, 0x36, 0x60, 0x9a,
592 0x57, 0x2b, 0x07, 0x69, 0x5d, 0x93, 0x3b, 0x58,
593 0x9d, 0xcf, 0x36, 0x3f, 0xf9, 0xd9, 0x3c, 0x93,
594 0xad, 0xea, 0x53, 0x7a, 0xea, 0xbb, 0x8c, 0xb8
596 static const unsigned char third_aead0
[] = {
597 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x30
599 static const unsigned char third_ct0
[] = {
600 0x5a, 0xd5, 0x90, 0xbb, 0x8b, 0xaa, 0x57, 0x7f,
601 0x86, 0x19, 0xdb, 0x35, 0xa3, 0x63, 0x11, 0x22,
602 0x6a, 0x89, 0x6e, 0x73, 0x42, 0xa6, 0xd8, 0x36,
603 0xd8, 0xb7, 0xbc, 0xd2, 0xf2, 0x0b, 0x6c, 0x7f,
604 0x90, 0x76, 0xac, 0x23, 0x2e, 0x3a, 0xb2, 0x52,
605 0x3f, 0x39, 0x51, 0x34, 0x34
607 static const unsigned char third_aead1
[] = {
608 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x31
610 static const unsigned char third_ct1
[] = {
611 0xfa, 0x6f, 0x03, 0x7b, 0x47, 0xfc, 0x21, 0x82,
612 0x6b, 0x61, 0x01, 0x72, 0xca, 0x96, 0x37, 0xe8,
613 0x2d, 0x6e, 0x58, 0x01, 0xeb, 0x31, 0xcb, 0xd3,
614 0x74, 0x82, 0x71, 0xaf, 0xfd, 0x4e, 0xcb, 0x06,
615 0x64, 0x6e, 0x03, 0x29, 0xcb, 0xdf, 0x3c, 0x3c,
616 0xd6, 0x55, 0xb2, 0x8e, 0x82
618 static const unsigned char third_export1
[] = {
619 0x5e, 0x9b, 0xc3, 0xd2, 0x36, 0xe1, 0x91, 0x1d,
620 0x95, 0xe6, 0x5b, 0x57, 0x6a, 0x8a, 0x86, 0xd4,
621 0x78, 0xfb, 0x82, 0x7e, 0x8b, 0xdf, 0xe7, 0x7b,
622 0x74, 0x1b, 0x28, 0x98, 0x90, 0x49, 0x0d, 0x4d
624 static const unsigned char third_context2
[] = { 0x00 };
625 static const unsigned char third_export2
[] = {
626 0x6c, 0xff, 0x87, 0x65, 0x89, 0x31, 0xbd, 0xa8,
627 0x3d, 0xc8, 0x57, 0xe6, 0x35, 0x3e, 0xfe, 0x49,
628 0x87, 0xa2, 0x01, 0xb8, 0x49, 0x65, 0x8d, 0x9b,
629 0x04, 0x7a, 0xab, 0x4c, 0xf2, 0x16, 0xe7, 0x96
631 static const unsigned char third_context3
[] = {
632 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
635 static const unsigned char third_export3
[] = {
636 0xd8, 0xf1, 0xea, 0x79, 0x42, 0xad, 0xbb, 0xa7,
637 0x41, 0x2c, 0x6d, 0x43, 0x1c, 0x62, 0xd0, 0x13,
638 0x71, 0xea, 0x47, 0x6b, 0x82, 0x3e, 0xb6, 0x97,
639 0xe1, 0xf6, 0xe6, 0xca, 0xe1, 0xda, 0xb8, 0x5a
642 static int P256kdfsha256_hkdfsha256_aes128gcm_base_test(void)
644 const TEST_BASEDATA basedata
= {
647 OSSL_HPKE_KEM_ID_P256
,
648 OSSL_HPKE_KDF_ID_HKDF_SHA256
,
649 OSSL_HPKE_AEAD_ID_AES_GCM_128
651 third_ikme
, sizeof(third_ikme
),
652 third_ikmepub
, sizeof(third_ikmepub
),
653 third_ikmr
, sizeof(third_ikmr
),
654 third_ikmrpub
, sizeof(third_ikmrpub
),
655 third_ikmrpriv
, sizeof(third_ikmrpriv
),
656 third_expected_shared_secret
, sizeof(third_expected_shared_secret
),
657 ksinfo
, sizeof(ksinfo
),
658 NULL
, 0, /* no auth */
659 NULL
, 0, NULL
/* PSK stuff */
661 const TEST_AEADDATA aeaddata
[] = {
665 third_aead0
, sizeof(third_aead0
),
666 third_ct0
, sizeof(third_ct0
)
671 third_aead1
, sizeof(third_aead1
),
672 third_ct1
, sizeof(third_ct1
)
675 const TEST_EXPORTDATA exportdata
[] = {
676 { NULL
, 0, third_export1
, sizeof(third_export1
) },
677 { third_context2
, sizeof(third_context2
),
678 third_export2
, sizeof(third_export2
) },
679 { third_context3
, sizeof(third_context3
),
680 third_export3
, sizeof(third_export3
) },
682 return do_testhpke(&basedata
, aeaddata
, OSSL_NELEM(aeaddata
),
683 exportdata
, OSSL_NELEM(exportdata
));
686 #ifndef OPENSSL_NO_ECX
687 static const unsigned char fourth_ikme
[] = {
688 0x55, 0xbc, 0x24, 0x5e, 0xe4, 0xef, 0xda, 0x25,
689 0xd3, 0x8f, 0x2d, 0x54, 0xd5, 0xbb, 0x66, 0x65,
690 0x29, 0x1b, 0x99, 0xf8, 0x10, 0x8a, 0x8c, 0x4b,
691 0x68, 0x6c, 0x2b, 0x14, 0x89, 0x3e, 0xa5, 0xd9
693 static const unsigned char fourth_ikmepub
[] = {
694 0xe5, 0xe8, 0xf9, 0xbf, 0xff, 0x6c, 0x2f, 0x29,
695 0x79, 0x1f, 0xc3, 0x51, 0xd2, 0xc2, 0x5c, 0xe1,
696 0x29, 0x9a, 0xa5, 0xea, 0xca, 0x78, 0xa7, 0x57,
697 0xc0, 0xb4, 0xfb, 0x4b, 0xcd, 0x83, 0x09, 0x18
699 static const unsigned char fourth_ikmr
[] = {
700 0x68, 0x3a, 0xe0, 0xda, 0x1d, 0x22, 0x18, 0x1e,
701 0x74, 0xed, 0x2e, 0x50, 0x3e, 0xbf, 0x82, 0x84,
702 0x0d, 0xeb, 0x1d, 0x5e, 0x87, 0x2c, 0xad, 0xe2,
703 0x0f, 0x4b, 0x45, 0x8d, 0x99, 0x78, 0x3e, 0x31
705 static const unsigned char fourth_ikmrpub
[] = {
706 0x19, 0x41, 0x41, 0xca, 0x6c, 0x3c, 0x3b, 0xeb,
707 0x47, 0x92, 0xcd, 0x97, 0xba, 0x0e, 0xa1, 0xfa,
708 0xff, 0x09, 0xd9, 0x84, 0x35, 0x01, 0x23, 0x45,
709 0x76, 0x6e, 0xe3, 0x3a, 0xae, 0x2d, 0x76, 0x64
711 static const unsigned char fourth_ikmrpriv
[] = {
712 0x33, 0xd1, 0x96, 0xc8, 0x30, 0xa1, 0x2f, 0x9a,
713 0xc6, 0x5d, 0x6e, 0x56, 0x5a, 0x59, 0x0d, 0x80,
714 0xf0, 0x4e, 0xe9, 0xb1, 0x9c, 0x83, 0xc8, 0x7f,
715 0x2c, 0x17, 0x0d, 0x97, 0x2a, 0x81, 0x28, 0x48
717 static const unsigned char fourth_expected_shared_secret
[] = {
718 0xe8, 0x17, 0x16, 0xce, 0x8f, 0x73, 0x14, 0x1d,
719 0x4f, 0x25, 0xee, 0x90, 0x98, 0xef, 0xc9, 0x68,
720 0xc9, 0x1e, 0x5b, 0x8c, 0xe5, 0x2f, 0xff, 0xf5,
721 0x9d, 0x64, 0x03, 0x9e, 0x82, 0x91, 0x8b, 0x66
723 static const unsigned char fourth_export1
[] = {
724 0x7a, 0x36, 0x22, 0x1b, 0xd5, 0x6d, 0x50, 0xfb,
725 0x51, 0xee, 0x65, 0xed, 0xfd, 0x98, 0xd0, 0x6a,
726 0x23, 0xc4, 0xdc, 0x87, 0x08, 0x5a, 0xa5, 0x86,
727 0x6c, 0xb7, 0x08, 0x72, 0x44, 0xbd, 0x2a, 0x36
729 static const unsigned char fourth_context2
[] = { 0x00 };
730 static const unsigned char fourth_export2
[] = {
731 0xd5, 0x53, 0x5b, 0x87, 0x09, 0x9c, 0x6c, 0x3c,
732 0xe8, 0x0d, 0xc1, 0x12, 0xa2, 0x67, 0x1c, 0x6e,
733 0xc8, 0xe8, 0x11, 0xa2, 0xf2, 0x84, 0xf9, 0x48,
734 0xce, 0xc6, 0xdd, 0x17, 0x08, 0xee, 0x33, 0xf0
736 static const unsigned char fourth_context3
[] = {
737 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
740 static const unsigned char fourth_export3
[] = {
741 0xff, 0xaa, 0xbc, 0x85, 0xa7, 0x76, 0x13, 0x6c,
742 0xa0, 0xc3, 0x78, 0xe5, 0xd0, 0x84, 0xc9, 0x14,
743 0x0a, 0xb5, 0x52, 0xb7, 0x8f, 0x03, 0x9d, 0x2e,
744 0x87, 0x75, 0xf2, 0x6e, 0xff, 0xf4, 0xc7, 0x0e
747 static int export_only_test(void)
749 /* based on RFC9180 A.7 */
750 const TEST_BASEDATA basedata
= {
753 OSSL_HPKE_KEM_ID_X25519
,
754 OSSL_HPKE_KDF_ID_HKDF_SHA256
,
755 OSSL_HPKE_AEAD_ID_EXPORTONLY
757 fourth_ikme
, sizeof(fourth_ikme
),
758 fourth_ikmepub
, sizeof(fourth_ikmepub
),
759 fourth_ikmr
, sizeof(fourth_ikmr
),
760 fourth_ikmrpub
, sizeof(fourth_ikmrpub
),
761 fourth_ikmrpriv
, sizeof(fourth_ikmrpriv
),
762 fourth_expected_shared_secret
, sizeof(fourth_expected_shared_secret
),
763 ksinfo
, sizeof(ksinfo
),
764 NULL
, 0, /* no auth */
765 NULL
, 0, NULL
/* PSK stuff */
767 const TEST_EXPORTDATA exportdata
[] = {
768 { NULL
, 0, fourth_export1
, sizeof(fourth_export1
) },
769 { fourth_context2
, sizeof(fourth_context2
),
770 fourth_export2
, sizeof(fourth_export2
) },
771 { fourth_context3
, sizeof(fourth_context3
),
772 fourth_export3
, sizeof(fourth_export3
) },
774 return do_testhpke(&basedata
, NULL
, 0,
775 exportdata
, OSSL_NELEM(exportdata
));
780 * Randomly toss a coin
782 #define COIN_IS_HEADS (test_random() % 2)
784 /* tables of HPKE modes and suite values */
785 static int hpke_mode_list
[] = {
789 OSSL_HPKE_MODE_PSKAUTH
791 static uint16_t hpke_kem_list
[] = {
792 OSSL_HPKE_KEM_ID_P256
,
793 OSSL_HPKE_KEM_ID_P384
,
794 OSSL_HPKE_KEM_ID_P521
,
795 #ifndef OPENSSL_NO_ECX
796 OSSL_HPKE_KEM_ID_X25519
,
797 OSSL_HPKE_KEM_ID_X448
800 static uint16_t hpke_kdf_list
[] = {
801 OSSL_HPKE_KDF_ID_HKDF_SHA256
,
802 OSSL_HPKE_KDF_ID_HKDF_SHA384
,
803 OSSL_HPKE_KDF_ID_HKDF_SHA512
805 static uint16_t hpke_aead_list
[] = {
806 OSSL_HPKE_AEAD_ID_AES_GCM_128
,
807 OSSL_HPKE_AEAD_ID_AES_GCM_256
,
808 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
809 OSSL_HPKE_AEAD_ID_CHACHA_POLY1305
814 * Strings that can be used with names or IANA codepoints.
815 * Note that the initial entries from these lists should
816 * match the lists above, i.e. kem_str_list[0] and
817 * hpke_kem_list[0] should refer to the same KEM. We use
818 * that for verbose output via TEST_note() below.
819 * Subsequent entries are only used for tests of
820 * OSSL_HPKE_str2suite()
822 static const char *mode_str_list
[] = {
823 "base", "psk", "auth", "pskauth"
825 static const char *kem_str_list
[] = {
826 #ifndef OPENSSL_NO_ECX
827 "P-256", "P-384", "P-521", "x25519", "x448",
828 "0x10", "0x11", "0x12", "0x20", "0x21",
829 "16", "17", "18", "32", "33"
831 "P-256", "P-384", "P-521",
832 "0x10", "0x11", "0x12",
836 static const char *kdf_str_list
[] = {
837 "hkdf-sha256", "hkdf-sha384", "hkdf-sha512",
838 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
841 static const char *aead_str_list
[] = {
842 "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "exporter",
843 "0x1", "0x01", "0x2", "0x02", "0x3", "0x03",
847 /* table of bogus strings that better not work */
848 static const char *bogus_suite_strs
[] = {
851 "bogus,33,3,1,bogus",
859 /* in reverse order */
860 "aes-256-gcm,hkdf-sha512,x25519",
861 /* surplus separators */
865 /* embedded NUL chars */
867 "0x10,\0""0x01,0x02",
870 "0x10,0x01,\0""0x02",
871 /* embedded whitespace */
872 " aes-256-gcm,hkdf-sha512,x25519",
873 "aes-256-gcm, hkdf-sha512,x25519",
874 "aes-256-gcm ,hkdf-sha512,x25519",
875 "aes-256-gcm,hkdf-sha512, x25519",
876 "aes-256-gcm,hkdf-sha512 ,x25519",
877 "aes-256-gcm,hkdf-sha512,x25519 ",
878 /* good value followed by extra stuff */
881 "0x10,0x01,0x01,0x02",
882 "0x10,0x01,0x01,blah",
883 "0x10,0x01,0x01 0x02",
884 /* too few but good tokens */
895 * @brief round-trips, generating keys, encrypt and decrypt
897 * This iterates over all mode and ciphersuite options trying
898 * a key gen, encrypt and decrypt for each. The aad, info, and
899 * seq inputs are randomly set or omitted each time. EVP and
900 * non-EVP key generation are randomly selected.
902 * @return 1 for success, other otherwise
904 static int test_hpke_modes_suites(void)
906 int overallresult
= 1;
907 size_t mind
= 0; /* index into hpke_mode_list */
908 size_t kemind
= 0; /* index into hpke_kem_list */
909 size_t kdfind
= 0; /* index into hpke_kdf_list */
910 size_t aeadind
= 0; /* index into hpke_aead_list */
912 /* iterate over the different modes */
913 for (mind
= 0; mind
< OSSL_NELEM(hpke_mode_list
); mind
++) {
914 int hpke_mode
= hpke_mode_list
[mind
];
915 size_t aadlen
= OSSL_HPKE_TSTSIZE
;
916 unsigned char aad
[OSSL_HPKE_TSTSIZE
];
917 unsigned char *aadp
= NULL
;
919 unsigned char info
[32];
920 unsigned char *infop
= NULL
;
921 unsigned char lpsk
[32];
922 unsigned char *pskp
= NULL
;
926 EVP_PKEY
*privp
= NULL
;
927 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
928 size_t plainlen
= OSSL_HPKE_TSTSIZE
;
929 unsigned char plain
[OSSL_HPKE_TSTSIZE
];
930 OSSL_HPKE_CTX
*rctx
= NULL
;
931 OSSL_HPKE_CTX
*ctx
= NULL
;
933 memset(plain
, 0x00, OSSL_HPKE_TSTSIZE
);
934 strcpy((char *)plain
, "a message not in a bottle");
935 plainlen
= strlen((char *)plain
);
937 * Randomly try with/without info, aad, seq. Given mode and suite
938 * combos, and this being run even a few times, we'll exercise many
939 * code paths fairly quickly. We don't really care what the values
940 * are but it'll be easier to debug if they're known, so we set 'em.
944 memset(aad
, 'a', aadlen
);
950 memset(info
, 'i', infolen
);
954 if (hpke_mode
== OSSL_HPKE_MODE_PSK
955 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
957 memset(lpsk
, 'P', psklen
);
959 memset(lpskid
, 'I', psklen
- 1);
960 lpskid
[psklen
- 1] = '\0';
964 for (kemind
= 0; /* iterate over the kems, kdfs and aeads */
965 overallresult
== 1 && kemind
< OSSL_NELEM(hpke_kem_list
);
967 uint16_t kem_id
= hpke_kem_list
[kemind
];
968 size_t authpublen
= OSSL_HPKE_TSTSIZE
;
969 unsigned char authpub
[OSSL_HPKE_TSTSIZE
];
970 unsigned char *authpubp
= NULL
;
971 EVP_PKEY
*authpriv
= NULL
;
973 hpke_suite
.kem_id
= kem_id
;
974 if (hpke_mode
== OSSL_HPKE_MODE_AUTH
975 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
976 if (TEST_true(OSSL_HPKE_keygen(hpke_suite
, authpub
, &authpublen
,
978 testctx
, NULL
)) != 1) {
986 overallresult
== 1 && kdfind
< OSSL_NELEM(hpke_kdf_list
);
988 uint16_t kdf_id
= hpke_kdf_list
[kdfind
];
990 hpke_suite
.kdf_id
= kdf_id
;
993 && aeadind
< OSSL_NELEM(hpke_aead_list
);
995 uint16_t aead_id
= hpke_aead_list
[aeadind
];
996 size_t publen
= OSSL_HPKE_TSTSIZE
;
997 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
998 size_t senderpublen
= OSSL_HPKE_TSTSIZE
;
999 unsigned char senderpub
[OSSL_HPKE_TSTSIZE
];
1000 size_t cipherlen
= OSSL_HPKE_TSTSIZE
;
1001 unsigned char cipher
[OSSL_HPKE_TSTSIZE
];
1002 size_t clearlen
= OSSL_HPKE_TSTSIZE
;
1003 unsigned char clear
[OSSL_HPKE_TSTSIZE
];
1005 hpke_suite
.aead_id
= aead_id
;
1006 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
,
1007 pub
, &publen
, &privp
,
1008 NULL
, 0, testctx
, NULL
)))
1010 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1011 OSSL_HPKE_ROLE_SENDER
,
1014 if (hpke_mode
== OSSL_HPKE_MODE_PSK
1015 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
1016 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(ctx
, pskidp
,
1020 if (hpke_mode
== OSSL_HPKE_MODE_AUTH
1021 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
1022 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx
,
1026 if (!TEST_true(OSSL_HPKE_encap(ctx
, senderpub
,
1031 /* throw in a call with a too-short cipherlen */
1033 if (!TEST_false(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
,
1037 /* fix back real cipherlen */
1038 cipherlen
= OSSL_HPKE_TSTSIZE
;
1039 if (!TEST_true(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
,
1043 OSSL_HPKE_CTX_free(ctx
);
1044 memset(clear
, 0, clearlen
);
1045 rctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1046 OSSL_HPKE_ROLE_RECEIVER
,
1048 if (!TEST_ptr(rctx
))
1050 if (hpke_mode
== OSSL_HPKE_MODE_PSK
1051 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
1052 if (!TEST_true(OSSL_HPKE_CTX_set1_psk(rctx
, pskidp
,
1056 if (hpke_mode
== OSSL_HPKE_MODE_AUTH
1057 || hpke_mode
== OSSL_HPKE_MODE_PSKAUTH
) {
1058 /* check a borked p256 key */
1059 if (hpke_suite
.kem_id
== OSSL_HPKE_KEM_ID_P256
) {
1060 /* set to fail decode of authpub this time */
1061 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(rctx
,
1067 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx
,
1072 if (!TEST_true(OSSL_HPKE_decap(rctx
, senderpub
,
1073 senderpublen
, privp
,
1076 /* throw in a call with a too-short clearlen */
1078 if (!TEST_false(OSSL_HPKE_open(rctx
, clear
, &clearlen
,
1079 aadp
, aadlen
, cipher
,
1082 /* fix up real clearlen again */
1083 clearlen
= OSSL_HPKE_TSTSIZE
;
1084 if (!TEST_true(OSSL_HPKE_open(rctx
, clear
, &clearlen
,
1085 aadp
, aadlen
, cipher
,
1088 OSSL_HPKE_CTX_free(rctx
);
1089 EVP_PKEY_free(privp
);
1092 if (!TEST_mem_eq(clear
, clearlen
, plain
, plainlen
)) {
1095 if (verbose
|| overallresult
!= 1) {
1096 const char *res
= NULL
;
1098 res
= (overallresult
== 1 ? "worked" : "failed");
1099 TEST_note("HPKE %s for mode: %s/0x%02x, "\
1100 "kem: %s/0x%02x, kdf: %s/0x%02x, "\
1101 "aead: %s/0x%02x", res
,
1102 mode_str_list
[mind
], (int) mind
,
1103 kem_str_list
[kemind
], kem_id
,
1104 kdf_str_list
[kdfind
], kdf_id
,
1105 aead_str_list
[aeadind
], aead_id
);
1109 EVP_PKEY_free(authpriv
);
1112 return overallresult
;
1116 * @brief check roundtrip for export
1117 * @return 1 for success, other otherwise
1119 static int test_hpke_export(void)
1122 EVP_PKEY
*privp
= NULL
;
1123 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
1124 size_t publen
= sizeof(pub
);
1125 int hpke_mode
= OSSL_HPKE_MODE_BASE
;
1126 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1127 OSSL_HPKE_CTX
*ctx
= NULL
;
1128 OSSL_HPKE_CTX
*rctx
= NULL
;
1129 unsigned char exp
[32];
1130 unsigned char exp2
[32];
1131 unsigned char rexp
[32];
1132 unsigned char rexp2
[32];
1133 unsigned char plain
[] = "quick brown fox";
1134 size_t plainlen
= sizeof(plain
);
1135 unsigned char enc
[OSSL_HPKE_TSTSIZE
];
1136 size_t enclen
= sizeof(enc
);
1137 unsigned char cipher
[OSSL_HPKE_TSTSIZE
];
1138 size_t cipherlen
= sizeof(cipher
);
1139 unsigned char clear
[OSSL_HPKE_TSTSIZE
];
1140 size_t clearlen
= sizeof(clear
);
1143 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1144 NULL
, 0, testctx
, NULL
)))
1146 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1147 OSSL_HPKE_ROLE_SENDER
,
1150 /* a few error cases 1st */
1151 if (!TEST_false(OSSL_HPKE_export(NULL
, exp
, sizeof(exp
),
1152 (unsigned char *)estr
, strlen(estr
))))
1154 /* ctx before encap should fail too */
1155 if (!TEST_false(OSSL_HPKE_export(ctx
, exp
, sizeof(exp
),
1156 (unsigned char *)estr
, strlen(estr
))))
1158 if (!TEST_true(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1160 if (!TEST_true(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1164 if (!TEST_true(OSSL_HPKE_export(ctx
, exp
, sizeof(exp
),
1165 (unsigned char *)estr
, strlen(estr
))))
1167 /* check a 2nd call with same input gives same output */
1168 if (!TEST_true(OSSL_HPKE_export(ctx
, exp2
, sizeof(exp2
),
1169 (unsigned char *)estr
, strlen(estr
))))
1171 if (!TEST_mem_eq(exp
, sizeof(exp
), exp2
, sizeof(exp2
)))
1173 if (!TEST_ptr(rctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1174 OSSL_HPKE_ROLE_RECEIVER
,
1177 if (!TEST_true(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1179 if (!TEST_true(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1180 cipher
, cipherlen
)))
1182 if (!TEST_true(OSSL_HPKE_export(rctx
, rexp
, sizeof(rexp
),
1183 (unsigned char *)estr
, strlen(estr
))))
1185 /* check a 2nd call with same input gives same output */
1186 if (!TEST_true(OSSL_HPKE_export(rctx
, rexp2
, sizeof(rexp2
),
1187 (unsigned char *)estr
, strlen(estr
))))
1189 if (!TEST_mem_eq(rexp
, sizeof(rexp
), rexp2
, sizeof(rexp2
)))
1191 if (!TEST_mem_eq(exp
, sizeof(exp
), rexp
, sizeof(rexp
)))
1195 OSSL_HPKE_CTX_free(ctx
);
1196 OSSL_HPKE_CTX_free(rctx
);
1197 EVP_PKEY_free(privp
);
1202 * @brief Check mapping from strings to HPKE suites
1203 * @return 1 for success, other otherwise
1205 static int test_hpke_suite_strs(void)
1207 int overallresult
= 1;
1213 OSSL_HPKE_SUITE stirred
;
1216 for (kemind
= 0; kemind
!= OSSL_NELEM(kem_str_list
); kemind
++) {
1217 for (kdfind
= 0; kdfind
!= OSSL_NELEM(kdf_str_list
); kdfind
++) {
1218 for (aeadind
= 0; aeadind
!= OSSL_NELEM(aead_str_list
); aeadind
++) {
1219 BIO_snprintf(sstr
, 128, "%s,%s,%s", kem_str_list
[kemind
],
1220 kdf_str_list
[kdfind
], aead_str_list
[aeadind
]);
1221 if (TEST_true(OSSL_HPKE_str2suite(sstr
, &stirred
)) != 1) {
1223 TEST_note("Unexpected str2suite fail for :%s",
1224 bogus_suite_strs
[sind
]);
1230 for (sind
= 0; sind
!= OSSL_NELEM(bogus_suite_strs
); sind
++) {
1231 if (TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs
[sind
],
1234 TEST_note("OSSL_HPKE_str2suite didn't fail for bogus[%d]:%s",
1235 sind
, bogus_suite_strs
[sind
]);
1239 /* check a few errors */
1240 if (!TEST_false(OSSL_HPKE_str2suite("", &stirred
)))
1242 if (!TEST_false(OSSL_HPKE_str2suite(NULL
, &stirred
)))
1244 if (!TEST_false(OSSL_HPKE_str2suite("", NULL
)))
1246 memset(giant
, 'A', sizeof(giant
) - 1);
1247 giant
[sizeof(giant
) - 1] = '\0';
1248 if (!TEST_false(OSSL_HPKE_str2suite(giant
, &stirred
)))
1251 return overallresult
;
1255 * @brief try the various GREASEy APIs
1256 * @return 1 for success, other otherwise
1258 static int test_hpke_grease(void)
1260 int overallresult
= 1;
1261 OSSL_HPKE_SUITE g_suite
;
1262 unsigned char g_pub
[OSSL_HPKE_TSTSIZE
];
1263 size_t g_pub_len
= OSSL_HPKE_TSTSIZE
;
1264 unsigned char g_cipher
[OSSL_HPKE_TSTSIZE
];
1265 size_t g_cipher_len
= 266;
1266 size_t clearlen
= 128;
1267 size_t expanded
= 0;
1271 memset(&g_suite
, 0, sizeof(OSSL_HPKE_SUITE
));
1273 /* check too short for public value */
1275 if (TEST_false(OSSL_HPKE_get_grease_value(NULL
, &g_suite
,
1277 g_cipher
, g_cipher_len
,
1278 testctx
, NULL
)) != 1) {
1282 g_pub_len
= OSSL_HPKE_TSTSIZE
;
1283 if (TEST_true(OSSL_HPKE_get_grease_value(NULL
, &g_suite
,
1285 g_cipher
, g_cipher_len
,
1286 testctx
, NULL
)) != 1) {
1290 expanded
= OSSL_HPKE_get_ciphertext_size(g_suite
, clearlen
);
1291 if (!TEST_size_t_gt(expanded
, clearlen
)) {
1294 enclen
= OSSL_HPKE_get_public_encap_size(g_suite
);
1295 if (!TEST_size_t_ne(enclen
, 0))
1297 /* not really GREASE but we'll check ikmelen thing */
1298 ikmelen
= OSSL_HPKE_get_recommended_ikmelen(g_suite
);
1299 if (!TEST_size_t_ne(ikmelen
, 0))
1302 return overallresult
;
1306 * Make a set of calls with odd parameters
1308 static int test_hpke_oddcalls(void)
1311 EVP_PKEY
*privp
= NULL
;
1312 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
1313 size_t publen
= sizeof(pub
);
1314 int hpke_mode
= OSSL_HPKE_MODE_BASE
;
1315 int bad_mode
= 0xbad;
1316 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1317 OSSL_HPKE_SUITE bad_suite
= { 0xbad, 0xbad, 0xbad };
1318 OSSL_HPKE_CTX
*ctx
= NULL
;
1319 OSSL_HPKE_CTX
*rctx
= NULL
;
1320 unsigned char plain
[] = "quick brown fox";
1321 size_t plainlen
= sizeof(plain
);
1322 unsigned char enc
[OSSL_HPKE_TSTSIZE
];
1323 size_t enclen
= sizeof(enc
);
1324 unsigned char cipher
[OSSL_HPKE_TSTSIZE
];
1325 size_t cipherlen
= sizeof(cipher
);
1326 unsigned char clear
[OSSL_HPKE_TSTSIZE
];
1327 size_t clearlen
= sizeof(clear
);
1328 unsigned char fake_ikm
[OSSL_HPKE_TSTSIZE
];
1329 char *badpropq
= "yeah, this won't work";
1331 char giant_pskid
[OSSL_HPKE_MAX_PARMLEN
+ 10];
1332 unsigned char info
[OSSL_HPKE_TSTSIZE
];
1334 /* many of the calls below are designed to get better test coverage */
1336 /* NULL ctx calls */
1337 OSSL_HPKE_CTX_free(NULL
);
1338 if (!TEST_false(OSSL_HPKE_CTX_set_seq(NULL
, 1)))
1340 if (!TEST_false(OSSL_HPKE_CTX_get_seq(NULL
, &lseq
)))
1342 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(NULL
, pub
, publen
)))
1344 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(NULL
, privp
)))
1346 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(NULL
, NULL
, 0)))
1348 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(NULL
, NULL
, NULL
, 0)))
1351 /* bad suite calls */
1352 hpke_suite
.aead_id
= 0xbad;
1353 if (!TEST_false(OSSL_HPKE_suite_check(hpke_suite
)))
1355 hpke_suite
.aead_id
= OSSL_HPKE_AEAD_ID_AES_GCM_128
;
1356 if (!TEST_false(OSSL_HPKE_suite_check(bad_suite
)))
1358 if (!TEST_false(OSSL_HPKE_get_recommended_ikmelen(bad_suite
)))
1360 if (!TEST_false(OSSL_HPKE_get_public_encap_size(bad_suite
)))
1362 if (!TEST_false(OSSL_HPKE_get_ciphertext_size(bad_suite
, 0)))
1364 if (!TEST_false(OSSL_HPKE_keygen(bad_suite
, pub
, &publen
, &privp
,
1365 NULL
, 0, testctx
, badpropq
)))
1367 if (!TEST_false(OSSL_HPKE_keygen(bad_suite
, pub
, &publen
, &privp
,
1368 NULL
, 0, testctx
, NULL
)))
1371 /* dodgy keygen calls */
1373 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite
, NULL
, &publen
, &privp
,
1374 NULL
, 0, testctx
, NULL
)))
1376 /* ikmlen but NULL ikm */
1377 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1378 NULL
, 80, testctx
, NULL
)))
1380 /* zero ikmlen but ikm */
1381 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1382 fake_ikm
, 0, testctx
, NULL
)))
1385 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1386 fake_ikm
, -1, testctx
, NULL
)))
1390 if (!TEST_false(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1391 NULL
, 0, testctx
, NULL
)))
1393 publen
= sizeof(pub
);
1395 /* encap/decap with NULLs */
1396 if (!TEST_false(OSSL_HPKE_encap(NULL
, NULL
, NULL
, NULL
, 0, NULL
, 0)))
1398 if (!TEST_false(OSSL_HPKE_decap(NULL
, NULL
, 0, NULL
, NULL
, 0)))
1402 * run through a sender/recipient set of calls but with
1403 * failing calls interspersed whenever possible
1406 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1407 NULL
, 0, testctx
, NULL
)))
1410 /* a psk context with no psk => encap fail */
1411 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK
, hpke_suite
,
1412 OSSL_HPKE_ROLE_SENDER
,
1415 /* set bad length psk */
1416 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx
, "foo",
1417 (unsigned char *)"bar", -1)))
1419 /* set bad length pskid */
1420 memset(giant_pskid
, 'A', sizeof(giant_pskid
) - 1);
1421 giant_pskid
[sizeof(giant_pskid
) - 1] = '\0';
1422 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx
, giant_pskid
,
1423 (unsigned char *)"bar", 3)))
1425 /* still no psk really set so encap fails */
1426 if (!TEST_false(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1428 OSSL_HPKE_CTX_free(ctx
);
1431 if (!TEST_ptr_null(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, bad_suite
,
1432 OSSL_HPKE_ROLE_SENDER
,
1436 if (!TEST_ptr_null(ctx
= OSSL_HPKE_CTX_new(bad_mode
, hpke_suite
,
1437 OSSL_HPKE_ROLE_SENDER
,
1441 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1442 OSSL_HPKE_ROLE_SENDER
,
1446 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx
, fake_ikm
, -1)))
1448 /* zero length ikm */
1449 if (!TEST_false(OSSL_HPKE_CTX_set1_ikme(ctx
, fake_ikm
, 0)))
1452 if (!TEST_false(OSSL_HPKE_CTX_set1_authpub(ctx
, NULL
, 0)))
1454 /* NULL auth priv */
1455 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx
, NULL
)))
1457 /* priv good, but mode is bad */
1458 if (!TEST_false(OSSL_HPKE_CTX_set1_authpriv(ctx
, privp
)))
1460 /* bad mode for psk */
1461 if (!TEST_false(OSSL_HPKE_CTX_set1_psk(ctx
, "foo",
1462 (unsigned char *)"bar", 3)))
1464 /* seal before encap */
1465 if (!TEST_false(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1468 /* encap with dodgy public */
1469 if (!TEST_false(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, 1, NULL
, 0)))
1471 /* encap with too big info */
1472 if (!TEST_false(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, 1, info
, -1)))
1475 if (!TEST_true(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1477 /* second encap fail */
1478 if (!TEST_false(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1481 /* should fail for no plaintext */
1482 if (!TEST_false(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1485 plainlen
= sizeof(plain
);
1487 if (!TEST_true(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1492 /* decap fail with psk mode but no psk set */
1493 if (!TEST_ptr(rctx
= OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_PSK
, hpke_suite
,
1494 OSSL_HPKE_ROLE_RECEIVER
,
1497 if (!TEST_false(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1499 /* done with PSK mode */
1500 OSSL_HPKE_CTX_free(rctx
);
1502 /* back good calls for base mode */
1503 if (!TEST_ptr(rctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1504 OSSL_HPKE_ROLE_RECEIVER
,
1507 /* open before decap */
1508 if (!TEST_false(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1509 cipher
, cipherlen
)))
1511 /* decap with info too long */
1512 if (!TEST_false(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, info
, -1)))
1515 if (!TEST_true(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1517 /* second decap fail */
1518 if (!TEST_false(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1520 /* no space for recovered clear */
1522 if (!TEST_false(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1523 cipher
, cipherlen
)))
1525 clearlen
= OSSL_HPKE_TSTSIZE
;
1526 /* seq wrap around test */
1527 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx
, -1)))
1529 if (!TEST_false(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1530 cipher
, cipherlen
)))
1532 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx
, 0)))
1534 if (!TEST_true(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1535 cipher
, cipherlen
)))
1537 if (!TEST_mem_eq(plain
, plainlen
, clear
, clearlen
))
1541 OSSL_HPKE_CTX_free(ctx
);
1542 OSSL_HPKE_CTX_free(rctx
);
1543 EVP_PKEY_free(privp
);
1547 #ifndef OPENSSL_NO_ECX
1548 /* from RFC 9180 Appendix A.1.1 */
1549 static const unsigned char ikm25519
[] = {
1550 0x72, 0x68, 0x60, 0x0d, 0x40, 0x3f, 0xce, 0x43,
1551 0x15, 0x61, 0xae, 0xf5, 0x83, 0xee, 0x16, 0x13,
1552 0x52, 0x7c, 0xff, 0x65, 0x5c, 0x13, 0x43, 0xf2,
1553 0x98, 0x12, 0xe6, 0x67, 0x06, 0xdf, 0x32, 0x34
1555 static const unsigned char pub25519
[] = {
1556 0x37, 0xfd, 0xa3, 0x56, 0x7b, 0xdb, 0xd6, 0x28,
1557 0xe8, 0x86, 0x68, 0xc3, 0xc8, 0xd7, 0xe9, 0x7d,
1558 0x1d, 0x12, 0x53, 0xb6, 0xd4, 0xea, 0x6d, 0x44,
1559 0xc1, 0x50, 0xf7, 0x41, 0xf1, 0xbf, 0x44, 0x31
1563 /* from RFC9180 Appendix A.3.1 */
1564 static const unsigned char ikmp256
[] = {
1565 0x42, 0x70, 0xe5, 0x4f, 0xfd, 0x08, 0xd7, 0x9d,
1566 0x59, 0x28, 0x02, 0x0a, 0xf4, 0x68, 0x6d, 0x8f,
1567 0x6b, 0x7d, 0x35, 0xdb, 0xe4, 0x70, 0x26, 0x5f,
1568 0x1f, 0x5a, 0xa2, 0x28, 0x16, 0xce, 0x86, 0x0e
1570 static const unsigned char pubp256
[] = {
1571 0x04, 0xa9, 0x27, 0x19, 0xc6, 0x19, 0x5d, 0x50,
1572 0x85, 0x10, 0x4f, 0x46, 0x9a, 0x8b, 0x98, 0x14,
1573 0xd5, 0x83, 0x8f, 0xf7, 0x2b, 0x60, 0x50, 0x1e,
1574 0x2c, 0x44, 0x66, 0xe5, 0xe6, 0x7b, 0x32, 0x5a,
1575 0xc9, 0x85, 0x36, 0xd7, 0xb6, 0x1a, 0x1a, 0xf4,
1576 0xb7, 0x8e, 0x5b, 0x7f, 0x95, 0x1c, 0x09, 0x00,
1577 0xbe, 0x86, 0x3c, 0x40, 0x3c, 0xe6, 0x5c, 0x9b,
1578 0xfc, 0xb9, 0x38, 0x26, 0x57, 0x22, 0x2d, 0x18,
1583 * A test vector that exercises the counter iteration
1584 * for p256. This was contributed by Ilari L. on the
1585 * CFRG list, see the mail archive:
1586 * https://mailarchive.ietf.org/arch/msg/cfrg/4zwl_y5YN6OU9oeWZOMHNOlOa2w/
1588 static const unsigned char ikmiter
[] = {
1589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1592 0x00, 0x00, 0x00, 0x03, 0x01, 0x38, 0xb5, 0xec
1594 static const unsigned char pubiter
[] = {
1595 0x04, 0x7d, 0x0c, 0x87, 0xff, 0xd5, 0xd1, 0x45,
1596 0x54, 0xa7, 0x51, 0xdf, 0xa3, 0x99, 0x26, 0xa9,
1597 0xe3, 0x0e, 0x7c, 0x3c, 0x65, 0x62, 0x4f, 0x4b,
1598 0x5f, 0xb3, 0xad, 0x7a, 0xa4, 0xda, 0xc2, 0x4a,
1599 0xd8, 0xf5, 0xbe, 0xd0, 0xe8, 0x6e, 0xb8, 0x84,
1600 0x1c, 0xe4, 0x89, 0x2e, 0x0f, 0xc3, 0x87, 0xbb,
1601 0xdb, 0xfe, 0x16, 0x0d, 0x58, 0x9c, 0x89, 0x2d,
1602 0xd4, 0xb1, 0x46, 0x4a, 0xc3, 0x51, 0xc5, 0x6f,
1606 /* from RFC9180 Appendix A.6.1 */
1607 static const unsigned char ikmp521
[] = {
1608 0x7f, 0x06, 0xab, 0x82, 0x15, 0x10, 0x5f, 0xc4,
1609 0x6a, 0xce, 0xeb, 0x2e, 0x3d, 0xc5, 0x02, 0x8b,
1610 0x44, 0x36, 0x4f, 0x96, 0x04, 0x26, 0xeb, 0x0d,
1611 0x8e, 0x40, 0x26, 0xc2, 0xf8, 0xb5, 0xd7, 0xe7,
1612 0xa9, 0x86, 0x68, 0x8f, 0x15, 0x91, 0xab, 0xf5,
1613 0xab, 0x75, 0x3c, 0x35, 0x7a, 0x5d, 0x6f, 0x04,
1614 0x40, 0x41, 0x4b, 0x4e, 0xd4, 0xed, 0xe7, 0x13,
1615 0x17, 0x77, 0x2a, 0xc9, 0x8d, 0x92, 0x39, 0xf7,
1618 static const unsigned char pubp521
[] = {
1619 0x04, 0x01, 0x38, 0xb3, 0x85, 0xca, 0x16, 0xbb,
1620 0x0d, 0x5f, 0xa0, 0xc0, 0x66, 0x5f, 0xbb, 0xd7,
1621 0xe6, 0x9e, 0x3e, 0xe2, 0x9f, 0x63, 0x99, 0x1d,
1622 0x3e, 0x9b, 0x5f, 0xa7, 0x40, 0xaa, 0xb8, 0x90,
1623 0x0a, 0xae, 0xed, 0x46, 0xed, 0x73, 0xa4, 0x90,
1624 0x55, 0x75, 0x84, 0x25, 0xa0, 0xce, 0x36, 0x50,
1625 0x7c, 0x54, 0xb2, 0x9c, 0xc5, 0xb8, 0x5a, 0x5c,
1626 0xee, 0x6b, 0xae, 0x0c, 0xf1, 0xc2, 0x1f, 0x27,
1627 0x31, 0xec, 0xe2, 0x01, 0x3d, 0xc3, 0xfb, 0x7c,
1628 0x8d, 0x21, 0x65, 0x4b, 0xb1, 0x61, 0xb4, 0x63,
1629 0x96, 0x2c, 0xa1, 0x9e, 0x8c, 0x65, 0x4f, 0xf2,
1630 0x4c, 0x94, 0xdd, 0x28, 0x98, 0xde, 0x12, 0x05,
1631 0x1f, 0x1e, 0xd0, 0x69, 0x22, 0x37, 0xfb, 0x02,
1632 0xb2, 0xf8, 0xd1, 0xdc, 0x1c, 0x73, 0xe9, 0xb3,
1633 0x66, 0xb5, 0x29, 0xeb, 0x43, 0x6e, 0x98, 0xa9,
1634 0x96, 0xee, 0x52, 0x2a, 0xef, 0x86, 0x3d, 0xd5,
1635 0x73, 0x9d, 0x2f, 0x29, 0xb0
1638 static int test_hpke_random_suites(void)
1640 OSSL_HPKE_SUITE def_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1641 OSSL_HPKE_SUITE suite
= OSSL_HPKE_SUITE_DEFAULT
;
1642 OSSL_HPKE_SUITE suite2
= { 0xff01, 0xff02, 0xff03 };
1643 unsigned char enc
[200];
1644 size_t enclen
= sizeof(enc
);
1645 unsigned char ct
[500];
1646 size_t ctlen
= sizeof(ct
);
1648 /* test with NULL/0 inputs */
1649 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL
, NULL
,
1650 NULL
, NULL
, NULL
, 0,
1654 if (!TEST_false(OSSL_HPKE_get_grease_value(&def_suite
, &suite2
,
1655 enc
, &enclen
, ct
, ctlen
,
1659 enclen
= sizeof(enc
); /* reset, 'cause get_grease() will have set */
1660 /* test with a should-be-good suite */
1661 if (!TEST_true(OSSL_HPKE_get_grease_value(&def_suite
, &suite2
,
1662 enc
, &enclen
, ct
, ctlen
,
1665 /* no suggested suite */
1666 enclen
= sizeof(enc
); /* reset, 'cause get_grease() will have set */
1667 if (!TEST_true(OSSL_HPKE_get_grease_value(NULL
, &suite2
,
1672 /* suggested suite with P-521, just to be sure we hit long values */
1673 enclen
= sizeof(enc
); /* reset, 'cause get_grease() will have set */
1674 suite
.kem_id
= OSSL_HPKE_KEM_ID_P521
;
1675 if (!TEST_true(OSSL_HPKE_get_grease_value(&suite
, &suite2
,
1676 enc
, &enclen
, ct
, ctlen
,
1679 enclen
= sizeof(enc
);
1680 ctlen
= 2; /* too-short cttext (can't fit an aead tag) */
1681 if (!TEST_false(OSSL_HPKE_get_grease_value(NULL
, &suite2
,
1682 enc
, &enclen
, ct
, ctlen
,
1687 enclen
= sizeof(enc
);
1689 suite
.kem_id
= OSSL_HPKE_KEM_ID_X25519
; /* back to default */
1690 suite
.aead_id
= 0x1234; /* bad aead */
1691 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite
, &suite2
,
1692 enc
, &enclen
, ct
, ctlen
,
1695 enclen
= sizeof(enc
);
1696 suite
.aead_id
= def_suite
.aead_id
; /* good aead */
1697 suite
.kdf_id
= 0x3451; /* bad kdf */
1698 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite
, &suite2
,
1699 enc
, &enclen
, ct
, ctlen
,
1702 enclen
= sizeof(enc
);
1703 suite
.kdf_id
= def_suite
.kdf_id
; /* good kdf */
1704 suite
.kem_id
= 0x4517; /* bad kem */
1705 if (!TEST_false(OSSL_HPKE_get_grease_value(&suite
, &suite2
,
1706 enc
, &enclen
, ct
, ctlen
,
1713 * @brief generate a key pair from initial key material (ikm) and check public
1714 * @param kem_id the KEM to use (RFC9180 code point)
1715 * @ikm is the initial key material buffer
1716 * @ikmlen is the length of ikm
1717 * @pub is the public key buffer
1718 * @publen is the length of the public key
1719 * @return 1 for good, other otherwise
1721 * This calls OSSL_HPKE_keygen specifying only the IKM, then
1722 * compares the key pair values with the already-known values
1725 static int test_hpke_one_ikm_gen(uint16_t kem_id
,
1726 const unsigned char *ikm
, size_t ikmlen
,
1727 const unsigned char *pub
, size_t publen
)
1729 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1730 unsigned char lpub
[OSSL_HPKE_TSTSIZE
];
1731 size_t lpublen
= OSSL_HPKE_TSTSIZE
;
1732 EVP_PKEY
*sk
= NULL
;
1734 hpke_suite
.kem_id
= kem_id
;
1735 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, lpub
, &lpublen
, &sk
,
1736 ikm
, ikmlen
, testctx
, NULL
)))
1741 if (!TEST_mem_eq(pub
, publen
, lpub
, lpublen
))
1747 * @brief test some uses of IKM produce the expected public keys
1749 static int test_hpke_ikms(void)
1753 #ifndef OPENSSL_NO_ECX
1754 res
= test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_X25519
,
1755 ikm25519
, sizeof(ikm25519
),
1756 pub25519
, sizeof(pub25519
));
1761 res
= test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P521
,
1762 ikmp521
, sizeof(ikmp521
),
1763 pubp521
, sizeof(pubp521
));
1767 res
= test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256
,
1768 ikmp256
, sizeof(ikmp256
),
1769 pubp256
, sizeof(pubp256
));
1773 res
= test_hpke_one_ikm_gen(OSSL_HPKE_KEM_ID_P256
,
1774 ikmiter
, sizeof(ikmiter
),
1775 pubiter
, sizeof(pubiter
));
1783 * Test that use of a compressed format auth public key works
1784 * We'll do a typical round-trip for auth mode but provide the
1785 * auth public key in compressed form. That should work.
1787 static int test_hpke_compressed(void)
1790 EVP_PKEY
*privp
= NULL
;
1791 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
1792 size_t publen
= sizeof(pub
);
1793 EVP_PKEY
*authpriv
= NULL
;
1794 unsigned char authpub
[OSSL_HPKE_TSTSIZE
];
1795 size_t authpublen
= sizeof(authpub
);
1796 int hpke_mode
= OSSL_HPKE_MODE_AUTH
;
1797 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1798 OSSL_HPKE_CTX
*ctx
= NULL
;
1799 OSSL_HPKE_CTX
*rctx
= NULL
;
1800 unsigned char plain
[] = "quick brown fox";
1801 size_t plainlen
= sizeof(plain
);
1802 unsigned char enc
[OSSL_HPKE_TSTSIZE
];
1803 size_t enclen
= sizeof(enc
);
1804 unsigned char cipher
[OSSL_HPKE_TSTSIZE
];
1805 size_t cipherlen
= sizeof(cipher
);
1806 unsigned char clear
[OSSL_HPKE_TSTSIZE
];
1807 size_t clearlen
= sizeof(clear
);
1809 hpke_suite
.kem_id
= OSSL_HPKE_KEM_ID_P256
;
1811 /* generate auth key pair */
1812 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, authpub
, &authpublen
, &authpriv
,
1813 NULL
, 0, testctx
, NULL
)))
1815 /* now get the compressed form public key */
1816 if (!TEST_true(EVP_PKEY_set_utf8_string_param(authpriv
,
1817 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
,
1818 OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED
)))
1820 if (!TEST_true(EVP_PKEY_get_octet_string_param(authpriv
,
1821 OSSL_PKEY_PARAM_PUB_KEY
,
1827 /* sender side as usual */
1828 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1829 NULL
, 0, testctx
, NULL
)))
1831 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1832 OSSL_HPKE_ROLE_SENDER
,
1835 if (!TEST_true(OSSL_HPKE_CTX_set1_authpriv(ctx
, authpriv
)))
1837 if (!TEST_true(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1839 if (!TEST_true(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1843 /* receiver side providing compressed form of auth public */
1844 if (!TEST_ptr(rctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1845 OSSL_HPKE_ROLE_RECEIVER
,
1848 if (!TEST_true(OSSL_HPKE_CTX_set1_authpub(rctx
, authpub
, authpublen
)))
1850 if (!TEST_true(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1852 if (!TEST_true(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1853 cipher
, cipherlen
)))
1858 EVP_PKEY_free(privp
);
1859 EVP_PKEY_free(authpriv
);
1860 OSSL_HPKE_CTX_free(ctx
);
1861 OSSL_HPKE_CTX_free(rctx
);
1866 * Test that nonce reuse calls are prevented as we expect
1868 static int test_hpke_noncereuse(void)
1871 EVP_PKEY
*privp
= NULL
;
1872 unsigned char pub
[OSSL_HPKE_TSTSIZE
];
1873 size_t publen
= sizeof(pub
);
1874 int hpke_mode
= OSSL_HPKE_MODE_BASE
;
1875 OSSL_HPKE_SUITE hpke_suite
= OSSL_HPKE_SUITE_DEFAULT
;
1876 OSSL_HPKE_CTX
*ctx
= NULL
;
1877 OSSL_HPKE_CTX
*rctx
= NULL
;
1878 unsigned char plain
[] = "quick brown fox";
1879 size_t plainlen
= sizeof(plain
);
1880 unsigned char enc
[OSSL_HPKE_TSTSIZE
];
1881 size_t enclen
= sizeof(enc
);
1882 unsigned char cipher
[OSSL_HPKE_TSTSIZE
];
1883 size_t cipherlen
= sizeof(cipher
);
1884 unsigned char clear
[OSSL_HPKE_TSTSIZE
];
1885 size_t clearlen
= sizeof(clear
);
1886 uint64_t seq
= 0xbad1dea;
1888 /* sender side is not allowed set seq once some crypto done */
1889 if (!TEST_true(OSSL_HPKE_keygen(hpke_suite
, pub
, &publen
, &privp
,
1890 NULL
, 0, testctx
, NULL
)))
1892 if (!TEST_ptr(ctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1893 OSSL_HPKE_ROLE_SENDER
,
1896 /* set seq will fail before any crypto done */
1897 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx
, seq
)))
1899 if (!TEST_true(OSSL_HPKE_encap(ctx
, enc
, &enclen
, pub
, publen
, NULL
, 0)))
1901 /* set seq will also fail after some crypto done */
1902 if (!TEST_false(OSSL_HPKE_CTX_set_seq(ctx
, seq
+ 1)))
1904 if (!TEST_true(OSSL_HPKE_seal(ctx
, cipher
, &cipherlen
, NULL
, 0,
1908 /* receiver side is allowed control seq */
1909 if (!TEST_ptr(rctx
= OSSL_HPKE_CTX_new(hpke_mode
, hpke_suite
,
1910 OSSL_HPKE_ROLE_RECEIVER
,
1913 /* set seq will work before any crypto done */
1914 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx
, seq
)))
1916 if (!TEST_true(OSSL_HPKE_decap(rctx
, enc
, enclen
, privp
, NULL
, 0)))
1918 /* set seq will work for receivers even after crypto done */
1919 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx
, seq
)))
1921 /* but that value isn't good so decap will fail */
1922 if (!TEST_false(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1923 cipher
, cipherlen
)))
1925 /* reset seq to correct value and _open() should work */
1926 if (!TEST_true(OSSL_HPKE_CTX_set_seq(rctx
, 0)))
1928 if (!TEST_true(OSSL_HPKE_open(rctx
, clear
, &clearlen
, NULL
, 0,
1929 cipher
, cipherlen
)))
1934 EVP_PKEY_free(privp
);
1935 OSSL_HPKE_CTX_free(ctx
);
1936 OSSL_HPKE_CTX_free(rctx
);
1940 typedef enum OPTION_choice
{
1947 const OPTIONS
*test_get_options(void)
1949 static const OPTIONS test_options
[] = {
1950 OPT_TEST_OPTIONS_DEFAULT_USAGE
,
1951 { "v", OPT_VERBOSE
, '-', "Enable verbose mode" },
1952 { OPT_HELP_STR
, 1, '-', "Run HPKE tests\n" },
1955 return test_options
;
1958 int setup_tests(void)
1962 while ((o
= opt_next()) != OPT_EOF
) {
1965 verbose
= 1; /* Print progress dots */
1967 case OPT_TEST_CASES
:
1974 if (!test_get_libctx(&testctx
, &nullprov
, NULL
, &deflprov
, "default"))
1976 #ifndef OPENSSL_NO_ECX
1977 ADD_TEST(export_only_test
);
1978 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_base_test
);
1979 ADD_TEST(x25519kdfsha256_hkdfsha256_aes128gcm_psk_test
);
1981 ADD_TEST(P256kdfsha256_hkdfsha256_aes128gcm_base_test
);
1982 ADD_TEST(test_hpke_export
);
1983 ADD_TEST(test_hpke_modes_suites
);
1984 ADD_TEST(test_hpke_suite_strs
);
1985 ADD_TEST(test_hpke_grease
);
1986 ADD_TEST(test_hpke_ikms
);
1987 ADD_TEST(test_hpke_random_suites
);
1988 ADD_TEST(test_hpke_oddcalls
);
1989 ADD_TEST(test_hpke_compressed
);
1990 ADD_TEST(test_hpke_noncereuse
);
1994 void cleanup_tests(void)
1996 OSSL_PROVIDER_unload(deflprov
);
1997 OSSL_PROVIDER_unload(nullprov
);
1998 OSSL_LIB_CTX_free(testctx
);