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