xref: /openssl/doc/man3/OSSL_HPKE_CTX_new.pod (revision 7ed6de99)
1=pod
2
3=head1 NAME
4
5OSSL_HPKE_CTX_new, OSSL_HPKE_CTX_free,
6OSSL_HPKE_encap, OSSL_HPKE_decap,
7OSSL_HPKE_seal, OSSL_HPKE_open, OSSL_HPKE_export,
8OSSL_HPKE_suite_check, OSSL_HPKE_str2suite,
9OSSL_HPKE_keygen, OSSL_HPKE_get_grease_value,
10OSSL_HPKE_get_ciphertext_size, OSSL_HPKE_get_public_encap_size,
11OSSL_HPKE_get_recommended_ikmelen,
12OSSL_HPKE_CTX_set1_psk, OSSL_HPKE_CTX_set1_ikme,
13OSSL_HPKE_CTX_set1_authpriv, OSSL_HPKE_CTX_set1_authpub,
14OSSL_HPKE_CTX_get_seq, OSSL_HPKE_CTX_set_seq
15- Hybrid Public Key Encryption (HPKE) functions
16
17=head1 SYNOPSIS
18
19 #include <openssl/hpke.h>
20
21 typedef struct {
22     uint16_t    kem_id;
23     uint16_t    kdf_id;
24     uint16_t    aead_id;
25 } OSSL_HPKE_SUITE;
26
27 OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite, int role,
28                                  OSSL_LIB_CTX *libctx, const char *propq);
29 void OSSL_HPKE_CTX_free(OSSL_HPKE_CTX *ctx);
30
31 int OSSL_HPKE_encap(OSSL_HPKE_CTX *ctx,
32                     unsigned char *enc, size_t *enclen,
33                     const unsigned char *pub, size_t publen,
34                     const unsigned char *info, size_t infolen);
35 int OSSL_HPKE_seal(OSSL_HPKE_CTX *ctx,
36                    unsigned char *ct, size_t *ctlen,
37                    const unsigned char *aad, size_t aadlen,
38                    const unsigned char *pt, size_t ptlen);
39
40 int OSSL_HPKE_keygen(OSSL_HPKE_SUITE suite,
41                      unsigned char *pub, size_t *publen, EVP_PKEY **priv,
42                      const unsigned char *ikm, size_t ikmlen,
43                      OSSL_LIB_CTX *libctx, const char *propq);
44 int OSSL_HPKE_decap(OSSL_HPKE_CTX *ctx,
45                     const unsigned char *enc, size_t enclen,
46                     EVP_PKEY *recippriv,
47                     const unsigned char *info, size_t infolen);
48 int OSSL_HPKE_open(OSSL_HPKE_CTX *ctx,
49                    unsigned char *pt, size_t *ptlen,
50                    const unsigned char *aad, size_t aadlen,
51                    const unsigned char *ct, size_t ctlen);
52
53 int OSSL_HPKE_export(OSSL_HPKE_CTX *ctx,
54                      unsigned char *secret, size_t secretlen,
55                      const unsigned char *label, size_t labellen);
56
57 int OSSL_HPKE_CTX_set1_authpriv(OSSL_HPKE_CTX *ctx, EVP_PKEY *priv);
58 int OSSL_HPKE_CTX_set1_authpub(OSSL_HPKE_CTX *ctx,
59                                unsigned char *pub, size_t publen);
60 int OSSL_HPKE_CTX_set1_psk(OSSL_HPKE_CTX *ctx,
61                            const char *pskid,
62                            const unsigned char *psk, size_t psklen);
63
64 int OSSL_HPKE_CTX_get_seq(OSSL_HPKE_CTX *ctx, uint64_t *seq);
65 int OSSL_HPKE_CTX_set_seq(OSSL_HPKE_CTX *ctx, uint64_t seq);
66
67 int OSSL_HPKE_CTX_set1_ikme(OSSL_HPKE_CTX *ctx,
68                             const unsigned char *ikme, size_t ikmelen);
69
70 int OSSL_HPKE_suite_check(OSSL_HPKE_SUITE suite);
71 int OSSL_HPKE_get_grease_value(const OSSL_HPKE_SUITE *suite_in,
72                                OSSL_HPKE_SUITE *suite,
73                                unsigned char *enc, size_t *enclen,
74                                unsigned char *ct, size_t ctlen,
75                                OSSL_LIB_CTX *libctx, const char *propq);
76
77 int OSSL_HPKE_str2suite(const char *str, OSSL_HPKE_SUITE *suite);
78 size_t OSSL_HPKE_get_ciphertext_size(OSSL_HPKE_SUITE suite, size_t clearlen);
79 size_t OSSL_HPKE_get_public_encap_size(OSSL_HPKE_SUITE suite);
80 size_t OSSL_HPKE_get_recommended_ikmelen(OSSL_HPKE_SUITE suite);
81
82=head1 DESCRIPTION
83
84These functions provide an API for using the form of Hybrid Public Key
85Encryption (HPKE) defined in RFC9180. Understanding the HPKE specification
86is likely required before using these APIs.  HPKE is used by various
87other IETF specifications, including the TLS Encrypted Client
88Hello (ECH) specification and others.
89
90HPKE is a standardised, highly flexible construct for encrypting "to" a public
91key that supports combinations of a key encapsulation method (KEM), a key
92derivation function (KDF) and an authenticated encryption with additional data
93(AEAD) algorithm, with optional sender authentication.
94
95The sender and a receiver here will generally be using some application or
96protocol making use of HPKE. For example, with ECH,
97the sender will be a browser and the receiver will be a web server.
98
99=head2 Data Structures
100
101B<OSSL_HPKE_SUITE> is a structure that holds identifiers for the algorithms
102used for KEM, KDF and AEAD operations.
103
104B<OSSL_HPKE_CTX> is a context that maintains internal state as HPKE
105operations are carried out. Separate B<OSSL_HPKE_CTX> objects must be used for
106the sender and receiver. Attempting to use a single context for both will
107result in errors.
108
109=head2 OSSL_HPKE_SUITE Identifiers
110
111The identifiers used by B<OSSL_HPKE_SUITE> are:
112
113The KEM identifier I<kem_id> is one of the following:
114
115=over 4
116
117=item 0x10 B<OSSL_HPKE_KEM_ID_P256>
118
119=item 0x11 B<OSSL_HPKE_KEM_ID_P384>
120
121=item 0x12 B<OSSL_HPKE_KEM_ID_P521>
122
123=item 0x20 B<OSSL_HPKE_KEM_ID_X25519>
124
125=item 0x21 B<OSSL_HPKE_KEM_ID_X448>
126
127=back
128
129The KDF identifier I<kdf_id> is one of the following:
130
131=over 4
132
133=item 0x01 B<OSSL_HPKE_KDF_ID_HKDF_SHA256>
134
135=item 0x02 B<OSSL_HPKE_KDF_ID_HKDF_SHA384>
136
137=item 0x03 B<OSSL_HPKE_KDF_ID_HKDF_SHA512>
138
139=back
140
141The AEAD identifier I<aead_id> is one of the following:
142
143=over 4
144
145=item 0x01 B<OSSL_HPKE_AEAD_ID_AES_GCM_128>
146
147=item 0x02 B<OSSL_HPKE_AEAD_ID_AES_GCM_256>
148
149=item 0x03 B<OSSL_HPKE_AEAD_ID_CHACHA_POLY1305>
150
151=item 0xFFFF B<OSSL_HPKE_AEAD_ID_EXPORTONLY>
152
153The last identifier above indicates that AEAD operations are not needed.
154OSSL_HPKE_export() can be used, but OSSL_HPKE_open() and OSSL_HPKE_seal() will
155return an error if called with a context using that AEAD identifier.
156
157=back
158
159=head2 HPKE Modes
160
161HPKE supports the following variants of Authentication using a mode Identifier:
162
163=over 4
164
165=item B<OSSL_HPKE_MODE_BASE>, 0x00
166
167Authentication is not used.
168
169=item B<OSSL_HPKE_MODE_PSK>, 0x01
170
171Authenticates possession of a pre-shared key (PSK).
172
173=item B<OSSL_HPKE_MODE_AUTH>, 0x02
174
175Authenticates possession of a KEM-based sender private key.
176
177=item B<OSSL_HPKE_MODE_PSKAUTH>, 0x03
178
179A combination of B<OSSL_HPKE_MODE_PSK> and B<OSSL_HPKE_MODE_AUTH>.
180Both the PSK and the senders authentication public/private must be
181supplied before the encapsulation/decapsulation operation will work.
182
183=back
184
185For further information related to authentication see L</Pre-Shared Key HPKE
186modes> and L</Sender-authenticated HPKE Modes>.
187
188=head2 HPKE Roles
189
190HPKE contexts have a role - either sender or receiver. This is used
191to control which functions can be called and so that senders do not
192reuse a key and nonce with different plaintexts.
193
194OSSL_HPKE_CTX_free(), OSSL_HPKE_export(), OSSL_HPKE_CTX_set1_psk(),
195and OSSL_HPKE_CTX_get_seq() can be called regardless of role.
196
197=over 4
198
199=item B<OSSL_HPKE_ROLE_SENDER>, 0
200
201An I<OSSL_HPKE_CTX> with this role can be used with
202OSSL_HPKE_encap(), OSSL_HPKE_seal(), OSSL_HPKE_CTX_set1_ikme() and
203OSSL_HPKE_CTX_set1_authpriv().
204
205=item B<OSSL_HPKE_ROLE_RECEIVER>, 1
206
207An I<OSSL_HPKE_CTX> with this role can be used with OSSL_HPKE_decap(),
208OSSL_HPKE_open(), OSSL_HPKE_CTX_set1_authpub() and OSSL_HPKE_CTX_set_seq().
209
210=back
211
212Calling a function with an incorrect role set on I<OSSL_HPKE_CTX> will result
213in an error.
214
215=head2 Parameter Size Limits
216
217In order to improve interoperability, RFC9180, section 7.2.1 suggests a
218RECOMMENDED maximum size of 64 octets for various input parameters.  In this
219implementation we apply a limit of 66 octets for the I<ikmlen>, I<psklen>, and
220I<labellen> parameters, and for the length of the string I<pskid> for HPKE
221functions below. The constant I<OSSL_HPKE_MAX_PARMLEN> is defined as the limit
222of this value.  (We chose 66 octets so that we can validate all the test
223vectors present in RFC9180, Appendix A.)
224
225In accordance with RFC9180, section 9.5, we define a constant
226I<OSSL_HPKE_MIN_PSKLEN> with a value of 32 for the minimum length of a
227pre-shared key, passed in I<psklen>.
228
229While RFC9180 also RECOMMENDS a 64 octet limit for the I<infolen> parameter,
230that is not sufficient for TLS Encrypted ClientHello (ECH) processing, so we
231enforce a limit of I<OSSL_HPKE_MAX_INFOLEN> with a value of 1024 as the limit
232for the I<infolen> parameter.
233
234=head2 Context Construct/Free
235
236OSSL_HPKE_CTX_new() creates a B<OSSL_HPKE_CTX> context object used for
237subsequent HPKE operations, given a I<mode> (See L</HPKE Modes>), I<suite> (see
238L</OSSL_HPKE_SUITE Identifiers>) and a I<role> (see L</HPKE Roles>). The
239I<libctx> and I<propq> are used when fetching algorithms from providers and may
240be set to NULL.
241
242OSSL_HPKE_CTX_free() frees the I<ctx> B<OSSL_HPKE_CTX> that was created
243previously by a call to OSSL_HPKE_CTX_new().  If the argument to
244OSSL_HPKE_CTX_free() is NULL, nothing is done.
245
246=head2 Sender APIs
247
248A sender's goal is to use HPKE to encrypt using a public key, via use of a
249KEM, then a KDF and finally an AEAD.  The first step is to encapsulate (using
250OSSL_HPKE_encap()) the sender's public value using the recipient's public key,
251(I<pub>) and to internally derive secrets. This produces the encapsulated public value
252(I<enc>) to be sent to the recipient in whatever protocol is using HPKE. Having done the
253encapsulation step, the sender can then make one or more calls to
254OSSL_HPKE_seal() to encrypt plaintexts using the secret stored within I<ctx>.
255
256OSSL_HPKE_encap() uses the HPKE context I<ctx>, the recipient public value
257I<pub> of size I<publen>, and an optional I<info> parameter of size I<infolen>,
258to produce the encapsulated public value I<enc>.
259On input I<enclen> should contain the maximum size of the I<enc> buffer, and returns
260the output size. An error will occur if the input I<enclen> is
261smaller than the value returned from OSSL_HPKE_get_public_encap_size().
262I<info> may be used to bind other protocol or application artefacts such as identifiers.
263Generally, the encapsulated public value I<enc> corresponds to a
264single-use ephemeral private value created as part of the encapsulation
265process. Only a single call to OSSL_HPKE_encap() is allowed for a given
266B<OSSL_HPKE_CTX>.
267
268OSSL_HPKE_seal() takes the B<OSSL_HPKE_CTX> context I<ctx>, the plaintext
269buffer I<pt> of size I<ptlen> and optional additional authenticated data buffer
270I<aad> of size I<aadlen>, and returns the ciphertext I<ct> of size I<ctlen>.
271On input I<ctlen> should contain the maximum size of the I<ct> buffer, and returns
272the output size. An error will occur if the input I<ctlen> is
273smaller than the value returned from OSSL_HPKE_get_public_encap_size().
274
275OSSL_HPKE_encap() must be called before the OSSL_HPKE_seal().  OSSL_HPKE_seal()
276may be called multiple times, with an internal "nonce" being incremented by one
277after each call.
278
279=head2 Recipient APIs
280
281Recipients using HPKE require a typically less ephemeral private value so that
282the public value can be distributed to potential senders via whatever protocol
283is using HPKE. For this reason, recipients will generally first generate a key
284pair and will need to manage their private key value using standard mechanisms
285outside the scope of this API. Private keys use normal L<EVP_PKEY(3)> pointers
286so normal private key management mechanisms can be used for the relevant
287values.
288
289In order to enable encapsulation, the recipient needs to make it's public value
290available to the sender. There is no generic HPKE format defined for that - the
291relevant formatting is intended to be defined by the application/protocols that
292makes use of HPKE. ECH for example defines an ECHConfig data structure that
293combines the public value with other ECH data items. Normal library functions
294must therefore be used to extract the public value in the required format based
295on the L<EVP_PKEY(3)> for the private value.
296
297OSSL_HPKE_keygen() provides a way for recipients to generate a key pair based
298on the HPKE I<suite> to be used. It returns a L<EVP_PKEY(3)> pointer
299for the private value I<priv> and a encoded public key I<pub> of size I<publen>.
300On input I<publen> should contain the maximum size of the I<pub> buffer, and
301returns the output size. An error will occur if the input I<publen> is too small.
302The I<libctx> and I<propq> are used when fetching algorithms from providers
303and may be set to NULL.
304The HPKE specification also defines a deterministic key generation scheme where
305the private value is derived from initial keying material (IKM), so
306OSSL_HPKE_keygen() also has an option to use that scheme, using the I<ikm>
307parameter of size I<ikmlen>. If either I<ikm> is NULL or I<ikmlen> is zero,
308then a randomly generated key for the relevant I<suite> will be produced.
309If required I<ikmlen> should be greater than or equal to
310OSSL_HPKE_get_recommended_ikmelen().
311
312OSSL_HPKE_decap() takes as input the sender's encapsulated public value
313produced by OSSL_HPKE_encap() (I<enc>) and the recipient's L<EVP_PKEY(3)>
314pointer (I<prov>), and then re-generates the internal secret derived by the
315sender. As before, an optional I<info> parameter allows binding that derived
316secret to other application/protocol artefacts. Only a single call to
317OSSL_HPKE_decap() is allowed for a given B<OSSL_HPKE_CTX>.
318
319OSSL_HPKE_open() is used by the recipient to decrypt the ciphertext I<ct> of
320size I<ctlen> using the I<ctx> and additional authenticated data I<aad> of
321size I<aadlen>, to produce the plaintext I<pt> of size I<ptlen>.
322On input I<ptlen> should contain the maximum size of the I<pt> buffer, and
323returns the output size. A I<pt> buffer that is the same size as the
324I<ct> buffer will suffice - generally the plaintext output will be
325a little smaller than the ciphertext input.
326An error will occur if the input I<ptlen> is too small.
327OSSL_HPKE_open() may be called multiple times, but as with OSSL_HPKE_seal()
328there is an internally incrementing nonce value so ciphertexts need to be
329presented in the same order as used by the OSSL_HPKE_seal().
330See L</Re-sequencing> if you need to process multiple ciphertexts in a
331different order.
332
333=head2 Exporting Secrets
334
335HPKE defines a way to produce exported secrets for use by the
336application.
337
338OSSL_HPKE_export() takes as input the B<OSSL_HPKE_CTX>, and an application
339supplied label I<label> of size I<labellen>, to produce a secret I<secret>
340of size I<secretlen>. The sender must first call OSSL_HPKE_encap(), and the
341receiver must call OSSL_HPKE_decap() in order to derive the same shared secret.
342
343Multiple calls to OSSL_HPKE_export() with the same inputs will produce the
344same secret.
345I<OSSL_HPKE_AEAD_ID_EXPORTONLY> may be used as the B<OSSL_HPKE_SUITE> I<aead_id>
346that is passed to OSSL_HPKE_CTX_new() if the user needs to produce a shared
347secret, but does not wish to perform HPKE encryption.
348
349=head2 Sender-authenticated HPKE Modes
350
351HPKE defines modes that support KEM-based sender-authentication
352B<OSSL_HPKE_MODE_AUTH> and B<OSSL_HPKE_MODE_PSKAUTH>. This works by binding
353the sender's authentication private/public values into the encapsulation and
354decapsulation operations. The key used for such modes must also use the same
355KEM as used for the overall exchange. OSSL_HPKE_keygen() can be used to
356generate the private value required.
357
358OSSL_HPKE_CTX_set1_authpriv() can be used by the sender to set the senders
359private I<priv> B<EVP_PKEY> key into the B<OSSL_HPKE_CTX> I<ctx> before calling
360OSSL_HPKE_encap().
361
362OSSL_HPKE_CTX_set1_authpub() can be used by the receiver to set the senders
363encoded pub key I<pub> of size I<publen> into the B<OSSL_HPKE_CTX> I<ctx> before
364calling OSSL_HPKE_decap().
365
366=head2 Pre-Shared Key HPKE modes
367
368HPKE also defines a symmetric equivalent to the authentication described above
369using a pre-shared key (PSK) and a PSK identifier. PSKs can be used with the
370B<OSSL_HPKE_MODE_PSK> and B<OSSL_HPKE_MODE_PSKAUTH> modes.
371
372OSSL_HPKE_CTX_set1_psk() sets the PSK identifier I<pskid> string, and PSK buffer
373I<psk> of size I<psklen> into the I<ctx>. If required this must be called
374before OSSL_HPKE_encap() or OSSL_HPKE_decap().
375As per RFC9180, if required, both I<psk> and I<pskid> must be set to non-NULL values.
376As PSKs are symmetric the same calls must happen on both sender and receiver
377sides.
378
379=head2 Deterministic key generation for senders
380
381Normally the senders ephemeral private key is generated randomly inside
382OSSL_HPKE_encap() and remains secret.
383OSSL_HPKE_CTX_set1_ikme() allows the user to override this behaviour by
384setting a deterministic input key material I<ikm> of size I<ikmlen> into
385the B<OSSL_HPKE_CTX> I<ctx>.
386If required OSSL_HPKE_CTX_set1_ikme() can optionally be called before
387OSSL_HPKE_encap().
388I<ikmlen> should be greater than or equal to OSSL_HPKE_get_recommended_ikmelen().
389
390It is generally undesirable to use OSSL_HPKE_CTX_set1_ikme(), since it
391exposes the relevant secret to the application rather then preserving it
392within the library, and is more likely to result in use of predictable values
393or values that leak.
394
395=head2 Re-sequencing
396
397Some protocols may have to deal with packet loss while still being able to
398decrypt arriving packets later. We provide a way to set the increment used for
399the nonce to the next subsequent call to OSSL_HPKE_open() (but not to
400OSSL_HPKE_seal() as explained below).  The OSSL_HPKE_CTX_set_seq() API can be
401used for such purposes with the I<seq> parameter value resetting the internal
402nonce increment to be used for the next call.
403
404A baseline nonce value is established based on the encapsulation or
405decapsulation operation and is then incremented by 1 for each call to seal or
406open. (In other words, the first I<seq> increment defaults to zero.)
407
408If a caller needs to determine how many calls to seal or open have been made
409the OSSL_HPKE_CTX_get_seq() API can be used to retrieve the increment (in the
410I<seq> output) that will be used in the next call to seal or open. That would
411return 0 before the first call a sender made to OSSL_HPKE_seal() and 1 after
412that first call.
413
414Note that reuse of the same nonce and key with different plaintexts would
415be very dangerous and could lead to loss of confidentiality and integrity.
416We therefore only support application control over I<seq> for decryption
417(i.e. OSSL_HPKE_open()) operations.
418
419For compatibility with other implementations these I<seq> increments are
420represented as I<uint64_t>.
421
422=head2 Protocol Convenience Functions
423
424Additional convenience APIs allow the caller to access internal details of
425local HPKE support and/or algorithms, such as parameter lengths.
426
427OSSL_HPKE_suite_check() checks if a specific B<OSSL_HPKE_SUITE> I<suite>
428is supported locally.
429
430To assist with memory allocation, OSSL_HPKE_get_ciphertext_size() provides a
431way for the caller to know by how much ciphertext will be longer than a
432plaintext of length I<clearlen>.  (AEAD algorithms add a data integrity tag,
433so there is a small amount of ciphertext expansion.)
434
435OSSL_HPKE_get_public_encap_size() provides a way for senders to know how big
436the encapsulated public value will be for a given HPKE I<suite>.
437
438OSSL_HPKE_get_recommended_ikmelen() returns the recommended Input Key Material
439size (in bytes) for a given I<suite>. This is needed in cases where the same
440public value needs to be regenerated by a sender before calling OSSL_HPKE_seal().
441I<ikmlen> should be at least this size.
442
443OSSL_HPKE_get_grease_value() produces values of the appropriate length for a
444given I<suite_in> value (or a random value if I<suite_in> is NULL) so that a
445protocol using HPKE can send so-called GREASE (see RFC8701) values that are
446harder to distinguish from a real use of HPKE. The buffer sizes should
447be supplied on input. The output I<enc> value will have an appropriate
448length for I<suite_out> and a random value, and the I<ct> output will be
449a random value. The relevant sizes for buffers can be found using
450OSSL_HPKE_get_ciphertext_size() and OSSL_HPKE_get_public_encap_size().
451
452OSSL_HPKE_str2suite() maps input I<str> strings to an B<OSSL_HPKE_SUITE> object.
453The input I<str> should be a comma-separated string with a KEM,
454KDF and AEAD name in that order, for example "x25519,hkdf-sha256,aes128gcm".
455This can be used by command line tools that accept string form names for HPKE
456codepoints. Valid (case-insensitive) names are:
457"p256", "p384", "p521", "x25519" and "x448" for KEM,
458"hkdf-SHA256", "hkdf-SHA384" and "hkdf-SHA512" for KDF, and
459"aes-gcm-128", "aes-gcm-256" and "chacha20-poly1305" for AEAD.
460String variants of the numbers listed in L</OSSL_HPKE_SUITE Identifiers>
461can also be used.
462
463=head1 RETURN VALUES
464
465OSSL_HPKE_CTX_new() returns an OSSL_HPKE_CTX pointer or NULL on error.
466
467OSSL_HPKE_get_ciphertext_size(), OSSL_HPKE_get_public_encap_size(),
468OSSL_HPKE_get_recommended_ikmelen() all return a size_t with the
469relevant value or zero on error.
470
471All other functions return 1 for success or zero for error.
472
473=head1 EXAMPLES
474
475This example demonstrates a minimal round-trip using HPKE.
476
477    #include <stddef.h>
478    #include <string.h>
479    #include <openssl/hpke.h>
480    #include <openssl/evp.h>
481
482    /*
483     * this is big enough for this example, real code would need different
484     * handling
485     */
486    #define LBUFSIZE 48
487
488    /* Do a round-trip, generating a key, encrypting and decrypting */
489    int main(int argc, char **argv)
490    {
491        int ok = 0;
492        int hpke_mode = OSSL_HPKE_MODE_BASE;
493        OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
494        OSSL_HPKE_CTX *sctx = NULL, *rctx = NULL;
495        EVP_PKEY *priv = NULL;
496        unsigned char pub[LBUFSIZE];
497        size_t publen = sizeof(pub);
498        unsigned char enc[LBUFSIZE];
499        size_t enclen = sizeof(enc);
500        unsigned char ct[LBUFSIZE];
501        size_t ctlen = sizeof(ct);
502        unsigned char clear[LBUFSIZE];
503        size_t clearlen = sizeof(clear);
504        const unsigned char *pt = "a message not in a bottle";
505        size_t ptlen = strlen((char *)pt);
506        const unsigned char *info = "Some info";
507        size_t infolen = strlen((char *)info);
508        unsigned char aad[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
509        size_t aadlen = sizeof(aad);
510
511        /*
512         * Generate receiver's key pair.
513         * The receiver gives this public key to the sender.
514         */
515        if (OSSL_HPKE_keygen(hpke_suite, pub, &publen, &priv,
516                             NULL, 0, NULL, NULL) != 1)
517            goto err;
518
519        /* sender's actions - encrypt data using the receivers public key */
520        if ((sctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
521                                      OSSL_HPKE_ROLE_SENDER,
522                                      NULL, NULL)) == NULL)
523            goto err;
524        if (OSSL_HPKE_encap(sctx, enc, &enclen, pub, publen, info, infolen) != 1)
525            goto err;
526        if (OSSL_HPKE_seal(sctx, ct, &ctlen, aad, aadlen, pt, ptlen) != 1)
527            goto err;
528
529        /* receiver's actions - decrypt data using the receivers private key */
530        if ((rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
531                                      OSSL_HPKE_ROLE_RECEIVER,
532                                      NULL, NULL)) == NULL)
533            goto err;
534        if (OSSL_HPKE_decap(rctx, enc, enclen, priv, info, infolen) != 1)
535            goto err;
536        if (OSSL_HPKE_open(rctx, clear, &clearlen, aad, aadlen, ct, ctlen) != 1)
537            goto err;
538        ok = 1;
539    err:
540        /* clean up */
541        printf(ok ? "All Good!\n" : "Error!\n");
542        OSSL_HPKE_CTX_free(rctx);
543        OSSL_HPKE_CTX_free(sctx);
544        EVP_PKEY_free(priv);
545        return 0;
546    }
547
548=head1 WARNINGS
549
550Note that the OSSL_HPKE_CTX_set_seq() API could be dangerous - if used with GCM
551that could lead to nonce-reuse, which is a known danger. So avoid that
552entirely, or be very very careful when using that API.
553
554Use of an IKM value for deterministic key generation (via
555OSSL_HPKE_CTX_set1_ikme() or OSSL_HPKE_keygen()) creates the potential for
556leaking keys (or IKM values). Only use that if really needed and if you
557understand how keys or IKM values could be abused.
558
559=head1 SEE ALSO
560
561The RFC9180 specification: https://datatracker.ietf.org/doc/rfc9180/
562
563=head1 HISTORY
564
565This functionality described here was added in OpenSSL 3.2.
566
567=head1 COPYRIGHT
568
569Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
570
571Licensed under the Apache License 2.0 (the "License").  You may not use
572this file except in compliance with the License.  You can obtain a copy
573in the file LICENSE in the source distribution or at
574L<https://www.openssl.org/source/license.html>.
575
576=cut
577