1 | =pod
|
---|
2 |
|
---|
3 | =head1 NAME
|
---|
4 |
|
---|
5 | OSSL_HPKE_CTX_new, OSSL_HPKE_CTX_free,
|
---|
6 | OSSL_HPKE_encap, OSSL_HPKE_decap,
|
---|
7 | OSSL_HPKE_seal, OSSL_HPKE_open, OSSL_HPKE_export,
|
---|
8 | OSSL_HPKE_suite_check, OSSL_HPKE_str2suite,
|
---|
9 | OSSL_HPKE_keygen, OSSL_HPKE_get_grease_value,
|
---|
10 | OSSL_HPKE_get_ciphertext_size, OSSL_HPKE_get_public_encap_size,
|
---|
11 | OSSL_HPKE_get_recommended_ikmelen,
|
---|
12 | OSSL_HPKE_CTX_set1_psk, OSSL_HPKE_CTX_set1_ikme,
|
---|
13 | OSSL_HPKE_CTX_set1_authpriv, OSSL_HPKE_CTX_set1_authpub,
|
---|
14 | OSSL_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 |
|
---|
84 | These functions provide an API for using the form of Hybrid Public Key
|
---|
85 | Encryption (HPKE) defined in RFC9180. Understanding the HPKE specification
|
---|
86 | is likely required before using these APIs. HPKE is used by various
|
---|
87 | other IETF specifications, including the TLS Encrypted Client
|
---|
88 | Hello (ECH) specification and others.
|
---|
89 |
|
---|
90 | HPKE is a standardised, highly flexible construct for encrypting "to" a public
|
---|
91 | key that supports combinations of a key encapsulation method (KEM), a key
|
---|
92 | derivation function (KDF) and an authenticated encryption with additional data
|
---|
93 | (AEAD) algorithm, with optional sender authentication.
|
---|
94 |
|
---|
95 | The sender and a receiver here will generally be using some application or
|
---|
96 | protocol making use of HPKE. For example, with ECH,
|
---|
97 | the sender will be a browser and the receiver will be a web server.
|
---|
98 |
|
---|
99 | =head2 Data Structures
|
---|
100 |
|
---|
101 | B<OSSL_HPKE_SUITE> is a structure that holds identifiers for the algorithms
|
---|
102 | used for KEM, KDF and AEAD operations.
|
---|
103 |
|
---|
104 | B<OSSL_HPKE_CTX> is a context that maintains internal state as HPKE
|
---|
105 | operations are carried out. Separate B<OSSL_HPKE_CTX> objects must be used for
|
---|
106 | the sender and receiver. Attempting to use a single context for both will
|
---|
107 | result in errors.
|
---|
108 |
|
---|
109 | =head2 OSSL_HPKE_SUITE Identifiers
|
---|
110 |
|
---|
111 | The identifiers used by B<OSSL_HPKE_SUITE> are:
|
---|
112 |
|
---|
113 | The 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 |
|
---|
129 | The 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 |
|
---|
141 | The 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 |
|
---|
153 | The last identifier above indicates that AEAD operations are not needed.
|
---|
154 | OSSL_HPKE_export() can be used, but OSSL_HPKE_open() and OSSL_HPKE_seal() will
|
---|
155 | return an error if called with a context using that AEAD identifier.
|
---|
156 |
|
---|
157 | =back
|
---|
158 |
|
---|
159 | =head2 HPKE Modes
|
---|
160 |
|
---|
161 | HPKE supports the following variants of Authentication using a mode Identifier:
|
---|
162 |
|
---|
163 | =over 4
|
---|
164 |
|
---|
165 | =item B<OSSL_HPKE_MODE_BASE>, 0x00
|
---|
166 |
|
---|
167 | Authentication is not used.
|
---|
168 |
|
---|
169 | =item B<OSSL_HPKE_MODE_PSK>, 0x01
|
---|
170 |
|
---|
171 | Authenticates possession of a pre-shared key (PSK).
|
---|
172 |
|
---|
173 | =item B<OSSL_HPKE_MODE_AUTH>, 0x02
|
---|
174 |
|
---|
175 | Authenticates possession of a KEM-based sender private key.
|
---|
176 |
|
---|
177 | =item B<OSSL_HPKE_MODE_PSKAUTH>, 0x03
|
---|
178 |
|
---|
179 | A combination of B<OSSL_HPKE_MODE_PSK> and B<OSSL_HPKE_MODE_AUTH>.
|
---|
180 | Both the PSK and the senders authentication public/private must be
|
---|
181 | supplied before the encapsulation/decapsulation operation will work.
|
---|
182 |
|
---|
183 | =back
|
---|
184 |
|
---|
185 | For further information related to authentication see L</Pre-Shared Key HPKE
|
---|
186 | modes> and L</Sender-authenticated HPKE Modes>.
|
---|
187 |
|
---|
188 | =head2 HPKE Roles
|
---|
189 |
|
---|
190 | HPKE contexts have a role - either sender or receiver. This is used
|
---|
191 | to control which functions can be called and so that senders do not
|
---|
192 | reuse a key and nonce with different plaintexts.
|
---|
193 |
|
---|
194 | OSSL_HPKE_CTX_free(), OSSL_HPKE_export(), OSSL_HPKE_CTX_set1_psk(),
|
---|
195 | and 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 |
|
---|
201 | An I<OSSL_HPKE_CTX> with this role can be used with
|
---|
202 | OSSL_HPKE_encap(), OSSL_HPKE_seal(), OSSL_HPKE_CTX_set1_ikme() and
|
---|
203 | OSSL_HPKE_CTX_set1_authpriv().
|
---|
204 |
|
---|
205 | =item B<OSSL_HPKE_ROLE_RECEIVER>, 1
|
---|
206 |
|
---|
207 | An I<OSSL_HPKE_CTX> with this role can be used with OSSL_HPKE_decap(),
|
---|
208 | OSSL_HPKE_open(), OSSL_HPKE_CTX_set1_authpub() and OSSL_HPKE_CTX_set_seq().
|
---|
209 |
|
---|
210 | =back
|
---|
211 |
|
---|
212 | Calling a function with an incorrect role set on I<OSSL_HPKE_CTX> will result
|
---|
213 | in an error.
|
---|
214 |
|
---|
215 | =head2 Parameter Size Limits
|
---|
216 |
|
---|
217 | In order to improve interoperability, RFC9180, section 7.2.1 suggests a
|
---|
218 | RECOMMENDED maximum size of 64 octets for various input parameters. In this
|
---|
219 | implementation we apply a limit of 66 octets for the I<ikmlen>, I<psklen>, and
|
---|
220 | I<labellen> parameters, and for the length of the string I<pskid> for HPKE
|
---|
221 | functions below. The constant I<OSSL_HPKE_MAX_PARMLEN> is defined as the limit
|
---|
222 | of this value. (We chose 66 octets so that we can validate all the test
|
---|
223 | vectors present in RFC9180, Appendix A.)
|
---|
224 |
|
---|
225 | In accordance with RFC9180, section 9.5, we define a constant
|
---|
226 | I<OSSL_HPKE_MIN_PSKLEN> with a value of 32 for the minimum length of a
|
---|
227 | pre-shared key, passed in I<psklen>.
|
---|
228 |
|
---|
229 | While RFC9180 also RECOMMENDS a 64 octet limit for the I<infolen> parameter,
|
---|
230 | that is not sufficient for TLS Encrypted ClientHello (ECH) processing, so we
|
---|
231 | enforce a limit of I<OSSL_HPKE_MAX_INFOLEN> with a value of 1024 as the limit
|
---|
232 | for the I<infolen> parameter.
|
---|
233 |
|
---|
234 | =head2 Context Construct/Free
|
---|
235 |
|
---|
236 | OSSL_HPKE_CTX_new() creates a B<OSSL_HPKE_CTX> context object used for
|
---|
237 | subsequent HPKE operations, given a I<mode> (See L</HPKE Modes>), I<suite> (see
|
---|
238 | L</OSSL_HPKE_SUITE Identifiers>) and a I<role> (see L</HPKE Roles>). The
|
---|
239 | I<libctx> and I<propq> are used when fetching algorithms from providers and may
|
---|
240 | be set to NULL.
|
---|
241 |
|
---|
242 | OSSL_HPKE_CTX_free() frees the I<ctx> B<OSSL_HPKE_CTX> that was created
|
---|
243 | previously by a call to OSSL_HPKE_CTX_new(). If the argument to
|
---|
244 | OSSL_HPKE_CTX_free() is NULL, nothing is done.
|
---|
245 |
|
---|
246 | =head2 Sender APIs
|
---|
247 |
|
---|
248 | A sender's goal is to use HPKE to encrypt using a public key, via use of a
|
---|
249 | KEM, then a KDF and finally an AEAD. The first step is to encapsulate (using
|
---|
250 | OSSL_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
|
---|
253 | encapsulation step, the sender can then make one or more calls to
|
---|
254 | OSSL_HPKE_seal() to encrypt plaintexts using the secret stored within I<ctx>.
|
---|
255 |
|
---|
256 | OSSL_HPKE_encap() uses the HPKE context I<ctx>, the recipient public value
|
---|
257 | I<pub> of size I<publen>, and an optional I<info> parameter of size I<infolen>,
|
---|
258 | to produce the encapsulated public value I<enc>.
|
---|
259 | On input I<enclen> should contain the maximum size of the I<enc> buffer, and returns
|
---|
260 | the output size. An error will occur if the input I<enclen> is
|
---|
261 | smaller than the value returned from OSSL_HPKE_get_public_encap_size().
|
---|
262 | I<info> may be used to bind other protocol or application artefacts such as identifiers.
|
---|
263 | Generally, the encapsulated public value I<enc> corresponds to a
|
---|
264 | single-use ephemeral private value created as part of the encapsulation
|
---|
265 | process. Only a single call to OSSL_HPKE_encap() is allowed for a given
|
---|
266 | B<OSSL_HPKE_CTX>.
|
---|
267 |
|
---|
268 | OSSL_HPKE_seal() takes the B<OSSL_HPKE_CTX> context I<ctx>, the plaintext
|
---|
269 | buffer I<pt> of size I<ptlen> and optional additional authenticated data buffer
|
---|
270 | I<aad> of size I<aadlen>, and returns the ciphertext I<ct> of size I<ctlen>.
|
---|
271 | On input I<ctlen> should contain the maximum size of the I<ct> buffer, and returns
|
---|
272 | the output size. An error will occur if the input I<ctlen> is
|
---|
273 | smaller than the value returned from OSSL_HPKE_get_public_encap_size().
|
---|
274 |
|
---|
275 | OSSL_HPKE_encap() must be called before the OSSL_HPKE_seal(). OSSL_HPKE_seal()
|
---|
276 | may be called multiple times, with an internal "nonce" being incremented by one
|
---|
277 | after each call.
|
---|
278 |
|
---|
279 | =head2 Recipient APIs
|
---|
280 |
|
---|
281 | Recipients using HPKE require a typically less ephemeral private value so that
|
---|
282 | the public value can be distributed to potential senders via whatever protocol
|
---|
283 | is using HPKE. For this reason, recipients will generally first generate a key
|
---|
284 | pair and will need to manage their private key value using standard mechanisms
|
---|
285 | outside the scope of this API. Private keys use normal L<EVP_PKEY(3)> pointers
|
---|
286 | so normal private key management mechanisms can be used for the relevant
|
---|
287 | values.
|
---|
288 |
|
---|
289 | In order to enable encapsulation, the recipient needs to make it's public value
|
---|
290 | available to the sender. There is no generic HPKE format defined for that - the
|
---|
291 | relevant formatting is intended to be defined by the application/protocols that
|
---|
292 | makes use of HPKE. ECH for example defines an ECHConfig data structure that
|
---|
293 | combines the public value with other ECH data items. Normal library functions
|
---|
294 | must therefore be used to extract the public value in the required format based
|
---|
295 | on the L<EVP_PKEY(3)> for the private value.
|
---|
296 |
|
---|
297 | OSSL_HPKE_keygen() provides a way for recipients to generate a key pair based
|
---|
298 | on the HPKE I<suite> to be used. It returns a L<EVP_PKEY(3)> pointer
|
---|
299 | for the private value I<priv> and a encoded public key I<pub> of size I<publen>.
|
---|
300 | On input I<publen> should contain the maximum size of the I<pub> buffer, and
|
---|
301 | returns the output size. An error will occur if the input I<publen> is too small.
|
---|
302 | The I<libctx> and I<propq> are used when fetching algorithms from providers
|
---|
303 | and may be set to NULL.
|
---|
304 | The HPKE specification also defines a deterministic key generation scheme where
|
---|
305 | the private value is derived from initial keying material (IKM), so
|
---|
306 | OSSL_HPKE_keygen() also has an option to use that scheme, using the I<ikm>
|
---|
307 | parameter of size I<ikmlen>. If either I<ikm> is NULL or I<ikmlen> is zero,
|
---|
308 | then a randomly generated key for the relevant I<suite> will be produced.
|
---|
309 | If required I<ikmlen> should be greater than or equal to
|
---|
310 | OSSL_HPKE_get_recommended_ikmelen().
|
---|
311 |
|
---|
312 | OSSL_HPKE_decap() takes as input the sender's encapsulated public value
|
---|
313 | produced by OSSL_HPKE_encap() (I<enc>) and the recipient's L<EVP_PKEY(3)>
|
---|
314 | pointer (I<prov>), and then re-generates the internal secret derived by the
|
---|
315 | sender. As before, an optional I<info> parameter allows binding that derived
|
---|
316 | secret to other application/protocol artefacts. Only a single call to
|
---|
317 | OSSL_HPKE_decap() is allowed for a given B<OSSL_HPKE_CTX>.
|
---|
318 |
|
---|
319 | OSSL_HPKE_open() is used by the recipient to decrypt the ciphertext I<ct> of
|
---|
320 | size I<ctlen> using the I<ctx> and additional authenticated data I<aad> of
|
---|
321 | size I<aadlen>, to produce the plaintext I<pt> of size I<ptlen>.
|
---|
322 | On input I<ptlen> should contain the maximum size of the I<pt> buffer, and
|
---|
323 | returns the output size. A I<pt> buffer that is the same size as the
|
---|
324 | I<ct> buffer will suffice - generally the plaintext output will be
|
---|
325 | a little smaller than the ciphertext input.
|
---|
326 | An error will occur if the input I<ptlen> is too small.
|
---|
327 | OSSL_HPKE_open() may be called multiple times, but as with OSSL_HPKE_seal()
|
---|
328 | there is an internally incrementing nonce value so ciphertexts need to be
|
---|
329 | presented in the same order as used by the OSSL_HPKE_seal().
|
---|
330 | See L</Re-sequencing> if you need to process multiple ciphertexts in a
|
---|
331 | different order.
|
---|
332 |
|
---|
333 | =head2 Exporting Secrets
|
---|
334 |
|
---|
335 | HPKE defines a way to produce exported secrets for use by the
|
---|
336 | application.
|
---|
337 |
|
---|
338 | OSSL_HPKE_export() takes as input the B<OSSL_HPKE_CTX>, and an application
|
---|
339 | supplied label I<label> of size I<labellen>, to produce a secret I<secret>
|
---|
340 | of size I<secretlen>. The sender must first call OSSL_HPKE_encap(), and the
|
---|
341 | receiver must call OSSL_HPKE_decap() in order to derive the same shared secret.
|
---|
342 |
|
---|
343 | Multiple calls to OSSL_HPKE_export() with the same inputs will produce the
|
---|
344 | same secret.
|
---|
345 | I<OSSL_HPKE_AEAD_ID_EXPORTONLY> may be used as the B<OSSL_HPKE_SUITE> I<aead_id>
|
---|
346 | that is passed to OSSL_HPKE_CTX_new() if the user needs to produce a shared
|
---|
347 | secret, but does not wish to perform HPKE encryption.
|
---|
348 |
|
---|
349 | =head2 Sender-authenticated HPKE Modes
|
---|
350 |
|
---|
351 | HPKE defines modes that support KEM-based sender-authentication
|
---|
352 | B<OSSL_HPKE_MODE_AUTH> and B<OSSL_HPKE_MODE_PSKAUTH>. This works by binding
|
---|
353 | the sender's authentication private/public values into the encapsulation and
|
---|
354 | decapsulation operations. The key used for such modes must also use the same
|
---|
355 | KEM as used for the overall exchange. OSSL_HPKE_keygen() can be used to
|
---|
356 | generate the private value required.
|
---|
357 |
|
---|
358 | OSSL_HPKE_CTX_set1_authpriv() can be used by the sender to set the senders
|
---|
359 | private I<priv> B<EVP_PKEY> key into the B<OSSL_HPKE_CTX> I<ctx> before calling
|
---|
360 | OSSL_HPKE_encap().
|
---|
361 |
|
---|
362 | OSSL_HPKE_CTX_set1_authpub() can be used by the receiver to set the senders
|
---|
363 | encoded pub key I<pub> of size I<publen> into the B<OSSL_HPKE_CTX> I<ctx> before
|
---|
364 | calling OSSL_HPKE_decap().
|
---|
365 |
|
---|
366 | =head2 Pre-Shared Key HPKE modes
|
---|
367 |
|
---|
368 | HPKE also defines a symmetric equivalent to the authentication described above
|
---|
369 | using a pre-shared key (PSK) and a PSK identifier. PSKs can be used with the
|
---|
370 | B<OSSL_HPKE_MODE_PSK> and B<OSSL_HPKE_MODE_PSKAUTH> modes.
|
---|
371 |
|
---|
372 | OSSL_HPKE_CTX_set1_psk() sets the PSK identifier I<pskid> string, and PSK buffer
|
---|
373 | I<psk> of size I<psklen> into the I<ctx>. If required this must be called
|
---|
374 | before OSSL_HPKE_encap() or OSSL_HPKE_decap().
|
---|
375 | As per RFC9180, if required, both I<psk> and I<pskid> must be set to non-NULL values.
|
---|
376 | As PSKs are symmetric the same calls must happen on both sender and receiver
|
---|
377 | sides.
|
---|
378 |
|
---|
379 | =head2 Deterministic key generation for senders
|
---|
380 |
|
---|
381 | Normally the senders ephemeral private key is generated randomly inside
|
---|
382 | OSSL_HPKE_encap() and remains secret.
|
---|
383 | OSSL_HPKE_CTX_set1_ikme() allows the user to override this behaviour by
|
---|
384 | setting a deterministic input key material I<ikm> of size I<ikmlen> into
|
---|
385 | the B<OSSL_HPKE_CTX> I<ctx>.
|
---|
386 | If required OSSL_HPKE_CTX_set1_ikme() can optionally be called before
|
---|
387 | OSSL_HPKE_encap().
|
---|
388 | I<ikmlen> should be greater than or equal to OSSL_HPKE_get_recommended_ikmelen().
|
---|
389 |
|
---|
390 | It is generally undesirable to use OSSL_HPKE_CTX_set1_ikme(), since it
|
---|
391 | exposes the relevant secret to the application rather then preserving it
|
---|
392 | within the library, and is more likely to result in use of predictable values
|
---|
393 | or values that leak.
|
---|
394 |
|
---|
395 | =head2 Re-sequencing
|
---|
396 |
|
---|
397 | Some protocols may have to deal with packet loss while still being able to
|
---|
398 | decrypt arriving packets later. We provide a way to set the increment used for
|
---|
399 | the nonce to the next subsequent call to OSSL_HPKE_open() (but not to
|
---|
400 | OSSL_HPKE_seal() as explained below). The OSSL_HPKE_CTX_set_seq() API can be
|
---|
401 | used for such purposes with the I<seq> parameter value resetting the internal
|
---|
402 | nonce increment to be used for the next call.
|
---|
403 |
|
---|
404 | A baseline nonce value is established based on the encapsulation or
|
---|
405 | decapsulation operation and is then incremented by 1 for each call to seal or
|
---|
406 | open. (In other words, the first I<seq> increment defaults to zero.)
|
---|
407 |
|
---|
408 | If a caller needs to determine how many calls to seal or open have been made
|
---|
409 | the OSSL_HPKE_CTX_get_seq() API can be used to retrieve the increment (in the
|
---|
410 | I<seq> output) that will be used in the next call to seal or open. That would
|
---|
411 | return 0 before the first call a sender made to OSSL_HPKE_seal() and 1 after
|
---|
412 | that first call.
|
---|
413 |
|
---|
414 | Note that reuse of the same nonce and key with different plaintexts would
|
---|
415 | be very dangerous and could lead to loss of confidentiality and integrity.
|
---|
416 | We therefore only support application control over I<seq> for decryption
|
---|
417 | (i.e. OSSL_HPKE_open()) operations.
|
---|
418 |
|
---|
419 | For compatibility with other implementations these I<seq> increments are
|
---|
420 | represented as I<uint64_t>.
|
---|
421 |
|
---|
422 | =head2 Protocol Convenience Functions
|
---|
423 |
|
---|
424 | Additional convenience APIs allow the caller to access internal details of
|
---|
425 | local HPKE support and/or algorithms, such as parameter lengths.
|
---|
426 |
|
---|
427 | OSSL_HPKE_suite_check() checks if a specific B<OSSL_HPKE_SUITE> I<suite>
|
---|
428 | is supported locally.
|
---|
429 |
|
---|
430 | To assist with memory allocation, OSSL_HPKE_get_ciphertext_size() provides a
|
---|
431 | way for the caller to know by how much ciphertext will be longer than a
|
---|
432 | plaintext of length I<clearlen>. (AEAD algorithms add a data integrity tag,
|
---|
433 | so there is a small amount of ciphertext expansion.)
|
---|
434 |
|
---|
435 | OSSL_HPKE_get_public_encap_size() provides a way for senders to know how big
|
---|
436 | the encapsulated public value will be for a given HPKE I<suite>.
|
---|
437 |
|
---|
438 | OSSL_HPKE_get_recommended_ikmelen() returns the recommended Input Key Material
|
---|
439 | size (in bytes) for a given I<suite>. This is needed in cases where the same
|
---|
440 | public value needs to be regenerated by a sender before calling OSSL_HPKE_seal().
|
---|
441 | I<ikmlen> should be at least this size.
|
---|
442 |
|
---|
443 | OSSL_HPKE_get_grease_value() produces values of the appropriate length for a
|
---|
444 | given I<suite_in> value (or a random value if I<suite_in> is NULL) so that a
|
---|
445 | protocol using HPKE can send so-called GREASE (see RFC8701) values that are
|
---|
446 | harder to distinguish from a real use of HPKE. The buffer sizes should
|
---|
447 | be supplied on input. The output I<enc> value will have an appropriate
|
---|
448 | length for I<suite_out> and a random value, and the I<ct> output will be
|
---|
449 | a random value. The relevant sizes for buffers can be found using
|
---|
450 | OSSL_HPKE_get_ciphertext_size() and OSSL_HPKE_get_public_encap_size().
|
---|
451 |
|
---|
452 | OSSL_HPKE_str2suite() maps input I<str> strings to an B<OSSL_HPKE_SUITE> object.
|
---|
453 | The input I<str> should be a comma-separated string with a KEM,
|
---|
454 | KDF and AEAD name in that order, for example "x25519,hkdf-sha256,aes128gcm".
|
---|
455 | This can be used by command line tools that accept string form names for HPKE
|
---|
456 | codepoints. 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.
|
---|
460 | String variants of the numbers listed in L</OSSL_HPKE_SUITE Identifiers>
|
---|
461 | can also be used.
|
---|
462 |
|
---|
463 | =head1 RETURN VALUES
|
---|
464 |
|
---|
465 | OSSL_HPKE_CTX_new() returns an OSSL_HPKE_CTX pointer or NULL on error.
|
---|
466 |
|
---|
467 | OSSL_HPKE_get_ciphertext_size(), OSSL_HPKE_get_public_encap_size(),
|
---|
468 | OSSL_HPKE_get_recommended_ikmelen() all return a size_t with the
|
---|
469 | relevant value or zero on error.
|
---|
470 |
|
---|
471 | All other functions return 1 for success or zero for error.
|
---|
472 |
|
---|
473 | =head1 EXAMPLES
|
---|
474 |
|
---|
475 | This 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 |
|
---|
550 | Note that the OSSL_HPKE_CTX_set_seq() API could be dangerous - if used with GCM
|
---|
551 | that could lead to nonce-reuse, which is a known danger. So avoid that
|
---|
552 | entirely, or be very very careful when using that API.
|
---|
553 |
|
---|
554 | Use of an IKM value for deterministic key generation (via
|
---|
555 | OSSL_HPKE_CTX_set1_ikme() or OSSL_HPKE_keygen()) creates the potential for
|
---|
556 | leaking keys (or IKM values). Only use that if really needed and if you
|
---|
557 | understand how keys or IKM values could be abused.
|
---|
558 |
|
---|
559 | =head1 SEE ALSO
|
---|
560 |
|
---|
561 | The RFC9180 specification: https://datatracker.ietf.org/doc/rfc9180/
|
---|
562 |
|
---|
563 | =head1 HISTORY
|
---|
564 |
|
---|
565 | This functionality described here was added in OpenSSL 3.2.
|
---|
566 |
|
---|
567 | =head1 COPYRIGHT
|
---|
568 |
|
---|
569 | Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
|
---|
570 |
|
---|
571 | Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
572 | this file except in compliance with the License. You can obtain a copy
|
---|
573 | in the file LICENSE in the source distribution or at
|
---|
574 | L<https://www.openssl.org/source/license.html>.
|
---|
575 |
|
---|
576 | =cut
|
---|