Automatically generated by Pod::Man 5.0102 (Pod::Simple 3.45)
Standard preamble:
========================================================================
..
.... \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
. ds C` "" . ds C' "" 'br\} . ds C` . ds C' 'br\}
Escape single quotes in literal strings from groff's Unicode transform.
If the F register is >0, we'll generate index entries on stderr for
titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
entries marked with X<> in POD. Of course, you'll have to process the
output yourself in some meaningful fashion.
Avoid warning from groff about undefined register 'F'.
.. .nr rF 0 . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF ========================================================================
Title "OSSL_HPKE_CTX_NEW 3ossl"
way too many mistakes in technical documents.
HPKE is a standardised, highly flexible construct for encrypting "to" a public key that supports combinations of a key encapsulation method (KEM), a key derivation function (KDF) and an authenticated encryption with additional data (AEAD) algorithm, with optional sender authentication.
The sender and a receiver here will generally be using some application or protocol making use of HPKE. For example, with ECH, the sender will be a browser and the receiver will be a web server.
\fBOSSL_HPKE_CTX is a context that maintains internal state as HPKE operations are carried out. Separate OSSL_HPKE_CTX objects must be used for the sender and receiver. Attempting to use a single context for both will result in errors.
The KEM identifier kem_id is one of the following:
0
The KDF identifier kdf_id is one of the following:
0
The AEAD identifier aead_id is one of the following:
0
The last identifier above indicates that AEAD operations are not needed. \fBOSSL_HPKE_export() can be used, but OSSL_HPKE_open() and OSSL_HPKE_seal() will return an error if called with a context using that AEAD identifier.
For further information related to authentication see "Pre-Shared Key HPKE modes" and "Sender-authenticated HPKE Modes".
\fBOSSL_HPKE_CTX_free(), OSSL_HPKE_export(), OSSL_HPKE_CTX_set1_psk(), and OSSL_HPKE_CTX_get_seq() can be called regardless of role.
Calling a function with an incorrect role set on OSSL_HPKE_CTX will result in an error.
In accordance with RFC9180, section 9.5, we define a constant \fIOSSL_HPKE_MIN_PSKLEN with a value of 32 for the minimum length of a pre-shared key, passed in psklen.
While RFC9180 also RECOMMENDS a 64 octet limit for the infolen parameter, that is not sufficient for TLS Encrypted ClientHello (ECH) processing, so we enforce a limit of OSSL_HPKE_MAX_INFOLEN with a value of 1024 as the limit for the infolen parameter.
Subsection "Context Construct/Free" \fBOSSL_HPKE_CTX_new() creates a OSSL_HPKE_CTX context object used for subsequent HPKE operations, given a mode (See "HPKE Modes"), suite (see "OSSL_HPKE_SUITE Identifiers") and a role (see "HPKE Roles"). The \fIlibctx and propq are used when fetching algorithms from providers and may be set to NULL.\fBOSSL_HPKE_CTX_free() frees the ctx OSSL_HPKE_CTX that was created previously by a call to OSSL_HPKE_CTX_new(). If the argument to \fBOSSL_HPKE_CTX_free() is NULL, nothing is done.
\fBOSSL_HPKE_encap() uses the HPKE context ctx, the recipient public value \fIpub of size publen, and an optional info parameter of size infolen, to produce the encapsulated public value enc. On input enclen should contain the maximum size of the enc buffer, and returns the output size. An error will occur if the input enclen is smaller than the value returned from OSSL_HPKE_get_public_encap_size(). \fIinfo may be used to bind other protocol or application artefacts such as identifiers. Generally, the encapsulated public value enc corresponds to a single-use ephemeral private value created as part of the encapsulation process. Only a single call to OSSL_HPKE_encap() is allowed for a given \fBOSSL_HPKE_CTX.
\fBOSSL_HPKE_seal() takes the OSSL_HPKE_CTX context ctx, the plaintext buffer pt of size ptlen and optional additional authenticated data buffer \fIaad of size aadlen, and returns the ciphertext ct of size ctlen. On input ctlen should contain the maximum size of the ct buffer, and returns the output size. An error will occur if the input ctlen is smaller than the value returned from OSSL_HPKE_get_public_encap_size().
\fBOSSL_HPKE_encap() must be called before the OSSL_HPKE_seal(). OSSL_HPKE_seal() may be called multiple times, with an internal "nonce" being incremented by one after each call.
In order to enable encapsulation, the recipient needs to make it's public value available to the sender. There is no generic HPKE format defined for that - the relevant formatting is intended to be defined by the application/protocols that makes use of HPKE. ECH for example defines an ECHConfig data structure that combines the public value with other ECH data items. Normal library functions must therefore be used to extract the public value in the required format based on the EVP_PKEY\|(3) for the private value.
\fBOSSL_HPKE_keygen() provides a way for recipients to generate a key pair based on the HPKE suite to be used. It returns a EVP_PKEY\|(3) pointer for the private value priv and a encoded public key pub of size publen. On input publen should contain the maximum size of the pub buffer, and returns the output size. An error will occur if the input publen is too small. The libctx and propq are used when fetching algorithms from providers and may be set to NULL. The HPKE specification also defines a deterministic key generation scheme where the private value is derived from initial keying material (IKM), so \fBOSSL_HPKE_keygen() also has an option to use that scheme, using the ikm parameter of size ikmlen. If either ikm is NULL or ikmlen is zero, then a randomly generated key for the relevant suite will be produced. If required ikmlen should be greater than or equal to \fBOSSL_HPKE_get_recommended_ikmelen().
\fBOSSL_HPKE_decap() takes as input the sender's encapsulated public value produced by OSSL_HPKE_encap() (enc) and the recipient's EVP_PKEY\|(3) pointer (prov), and then re-generates the internal secret derived by the sender. As before, an optional info parameter allows binding that derived secret to other application/protocol artefacts. Only a single call to \fBOSSL_HPKE_decap() is allowed for a given OSSL_HPKE_CTX.
\fBOSSL_HPKE_open() is used by the recipient to decrypt the ciphertext ct of size ctlen using the ctx and additional authenticated data aad of size aadlen, to produce the plaintext pt of size ptlen. On input ptlen should contain the maximum size of the pt buffer, and returns the output size. A pt buffer that is the same size as the \fIct buffer will suffice - generally the plaintext output will be a little smaller than the ciphertext input. An error will occur if the input ptlen is too small. \fBOSSL_HPKE_open() may be called multiple times, but as with OSSL_HPKE_seal() there is an internally incrementing nonce value so ciphertexts need to be presented in the same order as used by the OSSL_HPKE_seal(). See "Re-sequencing" if you need to process multiple ciphertexts in a different order.
\fBOSSL_HPKE_export() takes as input the OSSL_HPKE_CTX, and an application supplied label label of size labellen, to produce a secret secret of size secretlen. The sender must first call OSSL_HPKE_encap(), and the receiver must call OSSL_HPKE_decap() in order to derive the same shared secret.
Multiple calls to OSSL_HPKE_export() with the same inputs will produce the same secret. \fIOSSL_HPKE_AEAD_ID_EXPORTONLY may be used as the OSSL_HPKE_SUITE aead_id that is passed to OSSL_HPKE_CTX_new() if the user needs to produce a shared secret, but does not wish to perform HPKE encryption.
\fBOSSL_HPKE_CTX_set1_authpriv() can be used by the sender to set the senders private priv EVP_PKEY key into the OSSL_HPKE_CTX ctx before calling \fBOSSL_HPKE_encap().
\fBOSSL_HPKE_CTX_set1_authpub() can be used by the receiver to set the senders encoded pub key pub of size publen into the OSSL_HPKE_CTX ctx before calling OSSL_HPKE_decap().
\fBOSSL_HPKE_CTX_set1_psk() sets the PSK identifier pskid string, and PSK buffer \fIpsk of size psklen into the ctx. If required this must be called before OSSL_HPKE_encap() or OSSL_HPKE_decap(). As per RFC9180, if required, both psk and pskid must be set to non-NULL values. As PSKs are symmetric the same calls must happen on both sender and receiver sides.
It is generally undesirable to use OSSL_HPKE_CTX_set1_ikme(), since it exposes the relevant secret to the application rather then preserving it within the library, and is more likely to result in use of predictable values or values that leak.
A baseline nonce value is established based on the encapsulation or decapsulation operation and is then incremented by 1 for each call to seal or open. (In other words, the first seq increment defaults to zero.)
If a caller needs to determine how many calls to seal or open have been made the OSSL_HPKE_CTX_get_seq() API can be used to retrieve the increment (in the \fIseq output) that will be used in the next call to seal or open. That would return 0 before the first call a sender made to OSSL_HPKE_seal() and 1 after that first call.
Note that reuse of the same nonce and key with different plaintexts would be very dangerous and could lead to loss of confidentiality and integrity. We therefore only support application control over seq for decryption (i.e. OSSL_HPKE_open()) operations.
For compatibility with other implementations these seq increments are represented as uint64_t.
\fBOSSL_HPKE_suite_check() checks if a specific OSSL_HPKE_SUITE suite is supported locally.
To assist with memory allocation, OSSL_HPKE_get_ciphertext_size() provides a way for the caller to know by how much ciphertext will be longer than a plaintext of length clearlen. (AEAD algorithms add a data integrity tag, so there is a small amount of ciphertext expansion.)
\fBOSSL_HPKE_get_public_encap_size() provides a way for senders to know how big the encapsulated public value will be for a given HPKE suite.
\fBOSSL_HPKE_get_recommended_ikmelen() returns the recommended Input Key Material size (in bytes) for a given suite. This is needed in cases where the same public value needs to be regenerated by a sender before calling OSSL_HPKE_seal(). \fIikmlen should be at least this size.
\fBOSSL_HPKE_get_grease_value() produces values of the appropriate length for a given suite_in value (or a random value if suite_in is NULL) so that a protocol using HPKE can send so-called GREASE (see RFC8701) values that are harder to distinguish from a real use of HPKE. The buffer sizes should be supplied on input. The output enc value will have an appropriate length for suite_out and a random value, and the ct output will be a random value. The relevant sizes for buffers can be found using \fBOSSL_HPKE_get_ciphertext_size() and OSSL_HPKE_get_public_encap_size().
\fBOSSL_HPKE_str2suite() maps input str strings to an OSSL_HPKE_SUITE object. The input str should be a comma-separated string with a KEM, KDF and AEAD name in that order, for example "x25519,hkdf-sha256,aes128gcm". This can be used by command line tools that accept string form names for HPKE codepoints. Valid (case-insensitive) names are: "p-256", "p-384", "p-521", "x25519" and "x448" for KEM, "hkdf-sha256", "hkdf-sha384" and "hkdf-sha512" for KDF, and "aes-gcm-128", "aes-gcm-256", "chacha20-poly1305" and "exporter" for AEAD. String variants of the numbers listed in "OSSL_HPKE_SUITE Identifiers" can also be used.
\fBOSSL_HPKE_get_ciphertext_size(), OSSL_HPKE_get_public_encap_size(), \fBOSSL_HPKE_get_recommended_ikmelen() all return a size_t with the relevant value or zero on error.
All other functions return 1 for success or zero for error.
.Vb 4 #include <stddef.h> #include <string.h> #include <openssl/hpke.h> #include <openssl/evp.h> \& /* * this is big enough for this example, real code would need different * handling */ #define LBUFSIZE 48 \& /* Do a round-trip, generating a key, encrypting and decrypting */ int main(int argc, char **argv) { int ok = 0; int hpke_mode = OSSL_HPKE_MODE_BASE; OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; OSSL_HPKE_CTX *sctx = NULL, *rctx = NULL; EVP_PKEY *priv = NULL; unsigned char pub[LBUFSIZE]; size_t publen = sizeof(pub); unsigned char enc[LBUFSIZE]; size_t enclen = sizeof(enc); unsigned char ct[LBUFSIZE]; size_t ctlen = sizeof(ct); unsigned char clear[LBUFSIZE]; size_t clearlen = sizeof(clear); const unsigned char *pt = "a message not in a bottle"; size_t ptlen = strlen((char *)pt); const unsigned char *info = "Some info"; size_t infolen = strlen((char *)info); unsigned char aad[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; size_t aadlen = sizeof(aad); \& /* * Generate receiver\*(Aqs key pair. * The receiver gives this public key to the sender. */ if (OSSL_HPKE_keygen(hpke_suite, pub, &publen, &priv, NULL, 0, NULL, NULL) != 1) goto err; \& /* sender\*(Aqs actions - encrypt data using the receivers public key */ if ((sctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, OSSL_HPKE_ROLE_SENDER, NULL, NULL)) == NULL) goto err; if (OSSL_HPKE_encap(sctx, enc, &enclen, pub, publen, info, infolen) != 1) goto err; if (OSSL_HPKE_seal(sctx, ct, &ctlen, aad, aadlen, pt, ptlen) != 1) goto err; \& /* receiver\*(Aqs actions - decrypt data using the receivers private key */ if ((rctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, OSSL_HPKE_ROLE_RECEIVER, NULL, NULL)) == NULL) goto err; if (OSSL_HPKE_decap(rctx, enc, enclen, priv, info, infolen) != 1) goto err; if (OSSL_HPKE_open(rctx, clear, &clearlen, aad, aadlen, ct, ctlen) != 1) goto err; ok = 1; err: /* clean up */ printf(ok ? "All Good!\en" : "Error!\en"); OSSL_HPKE_CTX_free(rctx); OSSL_HPKE_CTX_free(sctx); EVP_PKEY_free(priv); return 0; } .Ve
Use of an IKM value for deterministic key generation (via \fBOSSL_HPKE_CTX_set1_ikme() or OSSL_HPKE_keygen()) creates the potential for leaking keys (or IKM values). Only use that if really needed and if you understand how keys or IKM values could be abused.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.