Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 1 | /* Copyright (c) 2020, Google Inc. |
| 2 | * |
| 3 | * Permission to use, copy, modify, and/or distribute this software for any |
| 4 | * purpose with or without fee is hereby granted, provided that the above |
| 5 | * copyright notice and this permission notice appear in all copies. |
| 6 | * |
| 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
| 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
| 14 | |
| 15 | #ifndef OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H |
| 16 | #define OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H |
| 17 | |
| 18 | #include <openssl/aead.h> |
| 19 | #include <openssl/base.h> |
| 20 | #include <openssl/curve25519.h> |
Dan McArdle | 1920c6f | 2020-03-11 17:29:40 -0400 | [diff] [blame] | 21 | #include <openssl/digest.h> |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 22 | |
| 23 | #if defined(__cplusplus) |
| 24 | extern "C" { |
| 25 | #endif |
| 26 | |
| 27 | |
| 28 | // Hybrid Public Key Encryption. |
| 29 | // |
| 30 | // Hybrid Public Key Encryption (HPKE) enables a sender to encrypt messages to a |
David Benjamin | e4d6556 | 2021-05-03 16:01:32 -0400 | [diff] [blame] | 31 | // receiver with a public key. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 32 | // |
David Benjamin | c76da9d | 2022-02-25 10:53:31 -0500 | [diff] [blame] | 33 | // See RFC 9180. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 34 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 35 | |
| 36 | // Parameters. |
| 37 | // |
David Benjamin | 070a6c3 | 2021-05-05 15:39:27 -0400 | [diff] [blame] | 38 | // An HPKE context is parameterized by KEM, KDF, and AEAD algorithms, |
| 39 | // represented by |EVP_HPKE_KEM|, |EVP_HPKE_KDF|, and |EVP_HPKE_AEAD| types, |
| 40 | // respectively. |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 41 | |
| 42 | // The following constants are KEM identifiers. |
Daniel McArdle | 00e434d | 2021-02-18 11:47:18 -0500 | [diff] [blame] | 43 | #define EVP_HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 |
| 44 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 45 | // The following functions are KEM algorithms which may be used with HPKE. Note |
| 46 | // that, while some HPKE KEMs use KDFs internally, this is separate from the |
| 47 | // |EVP_HPKE_KDF| selection. |
| 48 | OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void); |
| 49 | |
| 50 | // EVP_HPKE_KEM_id returns the HPKE KEM identifier for |kem|, which |
| 51 | // will be one of the |EVP_HPKE_KEM_*| constants. |
| 52 | OPENSSL_EXPORT uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem); |
| 53 | |
David Benjamin | 46a1c7e | 2022-09-29 17:02:53 -0400 | [diff] [blame] | 54 | // EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of an encoded public key |
| 55 | // for all KEMs currently supported by this library. |
| 56 | #define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 32 |
| 57 | |
| 58 | // EVP_HPKE_KEM_public_key_len returns the length of a public key for |kem|. |
| 59 | // This value will be at most |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH|. |
| 60 | OPENSSL_EXPORT size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem); |
| 61 | |
| 62 | // EVP_HPKE_MAX_PRIVATE_KEY_LENGTH is the maximum length of an encoded private |
| 63 | // key for all KEMs currently supported by this library. |
| 64 | #define EVP_HPKE_MAX_PRIVATE_KEY_LENGTH 32 |
| 65 | |
| 66 | // EVP_HPKE_KEM_private_key_len returns the length of a private key for |kem|. |
| 67 | // This value will be at most |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH|. |
| 68 | OPENSSL_EXPORT size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem); |
| 69 | |
David Benjamin | 779f7d0 | 2022-08-26 16:02:49 -0400 | [diff] [blame] | 70 | // EVP_HPKE_MAX_ENC_LENGTH is the maximum length of "enc", the encapsulated |
David Benjamin | 46a1c7e | 2022-09-29 17:02:53 -0400 | [diff] [blame] | 71 | // shared secret, for all KEMs currently supported by this library. |
David Benjamin | 779f7d0 | 2022-08-26 16:02:49 -0400 | [diff] [blame] | 72 | #define EVP_HPKE_MAX_ENC_LENGTH 32 |
| 73 | |
| 74 | // EVP_HPKE_KEM_enc_len returns the length of the "enc", the encapsulated shared |
| 75 | // secret, for |kem|. This value will be at most |EVP_HPKE_MAX_ENC_LENGTH|. |
| 76 | OPENSSL_EXPORT size_t EVP_HPKE_KEM_enc_len(const EVP_HPKE_KEM *kem); |
| 77 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 78 | // The following constants are KDF identifiers. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 79 | #define EVP_HPKE_HKDF_SHA256 0x0001 |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 80 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 81 | // The following functions are KDF algorithms which may be used with HPKE. |
| 82 | OPENSSL_EXPORT const EVP_HPKE_KDF *EVP_hpke_hkdf_sha256(void); |
| 83 | |
| 84 | // EVP_HPKE_KDF_id returns the HPKE KDF identifier for |kdf|. |
| 85 | OPENSSL_EXPORT uint16_t EVP_HPKE_KDF_id(const EVP_HPKE_KDF *kdf); |
| 86 | |
David Benjamin | ee477d4 | 2022-08-26 16:24:49 -0400 | [diff] [blame] | 87 | // EVP_HPKE_KDF_hkdf_md returns the HKDF hash function corresponding to |kdf|, |
| 88 | // or NULL if |kdf| is not an HKDF-based KDF. All currently supported KDFs are |
| 89 | // HKDF-based. |
| 90 | OPENSSL_EXPORT const EVP_MD *EVP_HPKE_KDF_hkdf_md(const EVP_HPKE_KDF *kdf); |
| 91 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 92 | // The following constants are AEAD identifiers. |
| 93 | #define EVP_HPKE_AES_128_GCM 0x0001 |
| 94 | #define EVP_HPKE_AES_256_GCM 0x0002 |
| 95 | #define EVP_HPKE_CHACHA20_POLY1305 0x0003 |
| 96 | |
| 97 | // The following functions are AEAD algorithms which may be used with HPKE. |
| 98 | OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_aes_128_gcm(void); |
| 99 | OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_aes_256_gcm(void); |
| 100 | OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_chacha20_poly1305(void); |
| 101 | |
| 102 | // EVP_HPKE_AEAD_id returns the HPKE AEAD identifier for |aead|. |
| 103 | OPENSSL_EXPORT uint16_t EVP_HPKE_AEAD_id(const EVP_HPKE_AEAD *aead); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 104 | |
David Benjamin | 83a4993 | 2021-05-20 15:57:09 -0400 | [diff] [blame] | 105 | // EVP_HPKE_AEAD_aead returns the |EVP_AEAD| corresponding to |aead|. |
| 106 | OPENSSL_EXPORT const EVP_AEAD *EVP_HPKE_AEAD_aead(const EVP_HPKE_AEAD *aead); |
| 107 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 108 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 109 | // Recipient keys. |
| 110 | // |
| 111 | // An HPKE recipient maintains a long-term KEM key. This library represents keys |
| 112 | // with the |EVP_HPKE_KEY| type. |
| 113 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 114 | // EVP_HPKE_KEY_zero sets an uninitialized |EVP_HPKE_KEY| to the zero state. The |
David Benjamin | c890ae5 | 2021-06-06 13:32:29 -0400 | [diff] [blame] | 115 | // caller should then use |EVP_HPKE_KEY_init|, |EVP_HPKE_KEY_copy|, or |
| 116 | // |EVP_HPKE_KEY_generate| to finish initializing |key|. |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 117 | // |
| 118 | // It is safe, but not necessary to call |EVP_HPKE_KEY_cleanup| in this state. |
| 119 | // This may be used for more uniform cleanup of |EVP_HPKE_KEY|. |
| 120 | OPENSSL_EXPORT void EVP_HPKE_KEY_zero(EVP_HPKE_KEY *key); |
| 121 | |
| 122 | // EVP_HPKE_KEY_cleanup releases memory referenced by |key|. |
| 123 | OPENSSL_EXPORT void EVP_HPKE_KEY_cleanup(EVP_HPKE_KEY *key); |
| 124 | |
David Benjamin | 897a2ca | 2021-07-16 12:05:40 -0400 | [diff] [blame] | 125 | // EVP_HPKE_KEY_new returns a newly-allocated |EVP_HPKE_KEY|, or NULL on error. |
| 126 | // The caller must call |EVP_HPKE_KEY_free| on the result to release it. |
| 127 | // |
| 128 | // This is a convenience function for callers that need a heap-allocated |
| 129 | // |EVP_HPKE_KEY|. |
| 130 | OPENSSL_EXPORT EVP_HPKE_KEY *EVP_HPKE_KEY_new(void); |
| 131 | |
| 132 | // EVP_HPKE_KEY_free releases memory associated with |key|, which must have been |
| 133 | // created with |EVP_HPKE_KEY_new|. |
| 134 | OPENSSL_EXPORT void EVP_HPKE_KEY_free(EVP_HPKE_KEY *key); |
| 135 | |
David Benjamin | c890ae5 | 2021-06-06 13:32:29 -0400 | [diff] [blame] | 136 | // EVP_HPKE_KEY_copy sets |dst| to a copy of |src|. It returns one on success |
| 137 | // and zero on error. On success, the caller must call |EVP_HPKE_KEY_cleanup| to |
| 138 | // release |dst|. On failure, calling |EVP_HPKE_KEY_cleanup| is safe, but not |
| 139 | // necessary. |
| 140 | OPENSSL_EXPORT int EVP_HPKE_KEY_copy(EVP_HPKE_KEY *dst, |
| 141 | const EVP_HPKE_KEY *src); |
| 142 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 143 | // EVP_HPKE_KEY_init decodes |priv_key| as a private key for |kem| and |
| 144 | // initializes |key| with the result. It returns one on success and zero if |
| 145 | // |priv_key| was invalid. On success, the caller must call |
| 146 | // |EVP_HPKE_KEY_cleanup| to release the key. On failure, calling |
| 147 | // |EVP_HPKE_KEY_cleanup| is safe, but not necessary. |
| 148 | OPENSSL_EXPORT int EVP_HPKE_KEY_init(EVP_HPKE_KEY *key, const EVP_HPKE_KEM *kem, |
| 149 | const uint8_t *priv_key, |
| 150 | size_t priv_key_len); |
| 151 | |
David Benjamin | c890ae5 | 2021-06-06 13:32:29 -0400 | [diff] [blame] | 152 | // EVP_HPKE_KEY_generate sets |key| to a newly-generated key using |kem|. |
| 153 | OPENSSL_EXPORT int EVP_HPKE_KEY_generate(EVP_HPKE_KEY *key, |
| 154 | const EVP_HPKE_KEM *kem); |
| 155 | |
| 156 | // EVP_HPKE_KEY_kem returns the HPKE KEM used by |key|. |
| 157 | OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_HPKE_KEY_kem(const EVP_HPKE_KEY *key); |
| 158 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 159 | // EVP_HPKE_KEY_public_key writes |key|'s public key to |out| and sets |
| 160 | // |*out_len| to the number of bytes written. On success, it returns one and |
| 161 | // writes at most |max_out| bytes. If |max_out| is too small, it returns zero. |
| 162 | // Setting |max_out| to |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH| will ensure the public |
David Benjamin | 46a1c7e | 2022-09-29 17:02:53 -0400 | [diff] [blame] | 163 | // key fits. An exact size can also be determined by |
| 164 | // |EVP_HPKE_KEM_public_key_len|. |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 165 | OPENSSL_EXPORT int EVP_HPKE_KEY_public_key(const EVP_HPKE_KEY *key, |
| 166 | uint8_t *out, size_t *out_len, |
| 167 | size_t max_out); |
| 168 | |
David Benjamin | c890ae5 | 2021-06-06 13:32:29 -0400 | [diff] [blame] | 169 | // EVP_HPKE_KEY_private_key writes |key|'s private key to |out| and sets |
| 170 | // |*out_len| to the number of bytes written. On success, it returns one and |
| 171 | // writes at most |max_out| bytes. If |max_out| is too small, it returns zero. |
| 172 | // Setting |max_out| to |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH| will ensure the |
David Benjamin | 46a1c7e | 2022-09-29 17:02:53 -0400 | [diff] [blame] | 173 | // private key fits. An exact size can also be determined by |
| 174 | // |EVP_HPKE_KEM_private_key_len|. |
David Benjamin | c890ae5 | 2021-06-06 13:32:29 -0400 | [diff] [blame] | 175 | OPENSSL_EXPORT int EVP_HPKE_KEY_private_key(const EVP_HPKE_KEY *key, |
| 176 | uint8_t *out, size_t *out_len, |
| 177 | size_t max_out); |
| 178 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 179 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 180 | // Encryption contexts. |
David Benjamin | 070a6c3 | 2021-05-05 15:39:27 -0400 | [diff] [blame] | 181 | // |
| 182 | // An HPKE encryption context is represented by the |EVP_HPKE_CTX| type. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 183 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 184 | // EVP_HPKE_CTX_zero sets an uninitialized |EVP_HPKE_CTX| to the zero state. The |
| 185 | // caller should then use one of the |EVP_HPKE_CTX_setup_*| functions to finish |
| 186 | // setting up |ctx|. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 187 | // |
| 188 | // It is safe, but not necessary to call |EVP_HPKE_CTX_cleanup| in this state. |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 189 | // This may be used for more uniform cleanup of |EVP_HPKE_CTX|. |
| 190 | OPENSSL_EXPORT void EVP_HPKE_CTX_zero(EVP_HPKE_CTX *ctx); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 191 | |
| 192 | // EVP_HPKE_CTX_cleanup releases memory referenced by |ctx|. |ctx| must have |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 193 | // been initialized with |EVP_HPKE_CTX_zero| or one of the |
| 194 | // |EVP_HPKE_CTX_setup_*| functions. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 195 | OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx); |
| 196 | |
David Benjamin | 897a2ca | 2021-07-16 12:05:40 -0400 | [diff] [blame] | 197 | // EVP_HPKE_CTX_new returns a newly-allocated |EVP_HPKE_CTX|, or NULL on error. |
| 198 | // The caller must call |EVP_HPKE_CTX_free| on the result to release it. |
| 199 | // |
| 200 | // This is a convenience function for callers that need a heap-allocated |
| 201 | // |EVP_HPKE_CTX|. |
| 202 | OPENSSL_EXPORT EVP_HPKE_CTX *EVP_HPKE_CTX_new(void); |
| 203 | |
| 204 | // EVP_HPKE_CTX_free releases memory associated with |ctx|, which must have been |
| 205 | // created with |EVP_HPKE_CTX_new|. |
| 206 | OPENSSL_EXPORT void EVP_HPKE_CTX_free(EVP_HPKE_CTX *ctx); |
| 207 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 208 | // EVP_HPKE_CTX_setup_sender implements the SetupBaseS HPKE operation. It |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 209 | // encapsulates a shared secret for |peer_public_key| and sets up |ctx| as a |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 210 | // sender context. It writes the encapsulated shared secret to |out_enc| and |
| 211 | // sets |*out_enc_len| to the number of bytes written. It writes at most |
| 212 | // |max_enc| bytes and fails if the buffer is too small. Setting |max_enc| to at |
David Benjamin | 779f7d0 | 2022-08-26 16:02:49 -0400 | [diff] [blame] | 213 | // least |EVP_HPKE_MAX_ENC_LENGTH| will ensure the buffer is large enough. An |
| 214 | // exact size may also be determined by |EVP_PKEY_KEM_enc_len|. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 215 | // |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 216 | // This function returns one on success and zero on error. Note that |
| 217 | // |peer_public_key| may be invalid, in which case this function will return an |
| 218 | // error. |
| 219 | // |
| 220 | // On success, callers may call |EVP_HPKE_CTX_seal| to encrypt messages for the |
| 221 | // recipient. Callers must then call |EVP_HPKE_CTX_cleanup| when done. On |
| 222 | // failure, calling |EVP_HPKE_CTX_cleanup| is safe, but not required. |
| 223 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_sender( |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 224 | EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 225 | const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, |
| 226 | const uint8_t *peer_public_key, size_t peer_public_key_len, |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 227 | const uint8_t *info, size_t info_len); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 228 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 229 | // EVP_HPKE_CTX_setup_sender_with_seed_for_testing behaves like |
| 230 | // |EVP_HPKE_CTX_setup_sender|, but takes a seed to behave deterministically. |
| 231 | // The seed's format depends on |kem|. For X25519, it is the sender's |
| 232 | // ephemeral private key. |
| 233 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_sender_with_seed_for_testing( |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 234 | EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 235 | const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, |
| 236 | const uint8_t *peer_public_key, size_t peer_public_key_len, |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 237 | const uint8_t *info, size_t info_len, const uint8_t *seed, size_t seed_len); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 238 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 239 | // EVP_HPKE_CTX_setup_recipient implements the SetupBaseR HPKE operation. It |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 240 | // decapsulates the shared secret in |enc| with |key| and sets up |ctx| as a |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 241 | // recipient context. It returns one on success and zero on failure. Note that |
| 242 | // |enc| may be invalid, in which case this function will return an error. |
Dan McArdle | d9ee55a | 2021-03-15 16:55:36 -0400 | [diff] [blame] | 243 | // |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 244 | // On success, callers may call |EVP_HPKE_CTX_open| to decrypt messages from the |
| 245 | // sender. Callers must then call |EVP_HPKE_CTX_cleanup| when done. On failure, |
| 246 | // calling |EVP_HPKE_CTX_cleanup| is safe, but not required. |
| 247 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_recipient( |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 248 | EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 249 | const EVP_HPKE_AEAD *aead, const uint8_t *enc, size_t enc_len, |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 250 | const uint8_t *info, size_t info_len); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 251 | |
David Benjamin | 4c8bcf0 | 2023-04-28 17:59:18 -0400 | [diff] [blame] | 252 | // EVP_HPKE_CTX_setup_auth_sender implements the SetupAuthS HPKE operation. It |
| 253 | // behaves like |EVP_HPKE_CTX_setup_sender| but authenticates the resulting |
| 254 | // context with |key|. |
| 255 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_sender( |
| 256 | EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, |
| 257 | const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, |
| 258 | const uint8_t *peer_public_key, size_t peer_public_key_len, |
| 259 | const uint8_t *info, size_t info_len); |
| 260 | |
| 261 | // EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing behaves like |
| 262 | // |EVP_HPKE_CTX_setup_auth_sender|, but takes a seed to behave |
| 263 | // deterministically. The seed's format depends on |kem|. For X25519, it is the |
| 264 | // sender's ephemeral private key. |
| 265 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing( |
| 266 | EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, |
| 267 | const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, |
| 268 | const uint8_t *peer_public_key, size_t peer_public_key_len, |
| 269 | const uint8_t *info, size_t info_len, const uint8_t *seed, size_t seed_len); |
| 270 | |
| 271 | // EVP_HPKE_CTX_setup_auth_recipient implements the SetupAuthR HPKE operation. |
| 272 | // It behaves like |EVP_HPKE_CTX_setup_recipient| but checks the resulting |
| 273 | // context was authenticated with |peer_public_key|. |
| 274 | OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_recipient( |
| 275 | EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, |
| 276 | const EVP_HPKE_AEAD *aead, const uint8_t *enc, size_t enc_len, |
| 277 | const uint8_t *info, size_t info_len, const uint8_t *peer_public_key, |
| 278 | size_t peer_public_key_len); |
| 279 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 280 | |
| 281 | // Using an HPKE context. |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 282 | // |
| 283 | // Once set up, callers may encrypt or decrypt with an |EVP_HPKE_CTX| using the |
| 284 | // following functions. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 285 | |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 286 | // EVP_HPKE_CTX_open uses the HPKE context |ctx| to authenticate |in_len| bytes |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 287 | // from |in| and |ad_len| bytes from |ad| and to decrypt at most |in_len| bytes |
| 288 | // into |out|. It returns one on success, and zero otherwise. |
| 289 | // |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 290 | // This operation will fail if the |ctx| context is not set up as a receiver. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 291 | // |
| 292 | // Note that HPKE encryption is stateful and ordered. The sender's first call to |
| 293 | // |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to |
| 294 | // |EVP_HPKE_CTX_open|, etc. |
| 295 | // |
| 296 | // At most |in_len| bytes are written to |out|. In order to ensure success, |
| 297 | // |max_out_len| should be at least |in_len|. On successful return, |*out_len| |
| 298 | // is set to the actual number of bytes written. |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 299 | OPENSSL_EXPORT int EVP_HPKE_CTX_open(EVP_HPKE_CTX *ctx, uint8_t *out, |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 300 | size_t *out_len, size_t max_out_len, |
| 301 | const uint8_t *in, size_t in_len, |
| 302 | const uint8_t *ad, size_t ad_len); |
| 303 | |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 304 | // EVP_HPKE_CTX_seal uses the HPKE context |ctx| to encrypt and authenticate |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 305 | // |in_len| bytes of ciphertext |in| and authenticate |ad_len| bytes from |ad|, |
| 306 | // writing the result to |out|. It returns one on success and zero otherwise. |
| 307 | // |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 308 | // This operation will fail if the |ctx| context is not set up as a sender. |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 309 | // |
| 310 | // Note that HPKE encryption is stateful and ordered. The sender's first call to |
| 311 | // |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to |
| 312 | // |EVP_HPKE_CTX_open|, etc. |
| 313 | // |
| 314 | // At most, |max_out_len| encrypted bytes are written to |out|. On successful |
| 315 | // return, |*out_len| is set to the actual number of bytes written. |
| 316 | // |
| 317 | // To ensure success, |max_out_len| should be |in_len| plus the result of |
| 318 | // |EVP_HPKE_CTX_max_overhead| or |EVP_HPKE_MAX_OVERHEAD|. |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 319 | OPENSSL_EXPORT int EVP_HPKE_CTX_seal(EVP_HPKE_CTX *ctx, uint8_t *out, |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 320 | size_t *out_len, size_t max_out_len, |
| 321 | const uint8_t *in, size_t in_len, |
| 322 | const uint8_t *ad, size_t ad_len); |
| 323 | |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 324 | // EVP_HPKE_CTX_export uses the HPKE context |ctx| to export a secret of |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 325 | // |secret_len| bytes into |out|. This function uses |context_len| bytes from |
| 326 | // |context| as a context string for the secret. This is necessary to separate |
| 327 | // different uses of exported secrets and bind relevant caller-specific context |
| 328 | // into the output. It returns one on success and zero otherwise. |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 329 | OPENSSL_EXPORT int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *ctx, uint8_t *out, |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 330 | size_t secret_len, |
| 331 | const uint8_t *context, |
| 332 | size_t context_len); |
| 333 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 334 | // EVP_HPKE_MAX_OVERHEAD contains the largest value that |
| 335 | // |EVP_HPKE_CTX_max_overhead| would ever return for any context. |
| 336 | #define EVP_HPKE_MAX_OVERHEAD EVP_AEAD_MAX_OVERHEAD |
| 337 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 338 | // EVP_HPKE_CTX_max_overhead returns the maximum number of additional bytes |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 339 | // added by sealing data with |EVP_HPKE_CTX_seal|. The |ctx| context must be set |
| 340 | // up as a sender. |
| 341 | OPENSSL_EXPORT size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *ctx); |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 342 | |
David Benjamin | 779f7d0 | 2022-08-26 16:02:49 -0400 | [diff] [blame] | 343 | // EVP_HPKE_CTX_kem returns |ctx|'s configured KEM, or NULL if the context has |
| 344 | // not been set up. |
| 345 | OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_HPKE_CTX_kem(const EVP_HPKE_CTX *ctx); |
| 346 | |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 347 | // EVP_HPKE_CTX_aead returns |ctx|'s configured AEAD, or NULL if the context has |
| 348 | // not been set up. |
| 349 | OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_HPKE_CTX_aead(const EVP_HPKE_CTX *ctx); |
Daniel McArdle | 00e434d | 2021-02-18 11:47:18 -0500 | [diff] [blame] | 350 | |
David Benjamin | 1eb7769 | 2021-05-07 14:32:39 -0400 | [diff] [blame] | 351 | // EVP_HPKE_CTX_kdf returns |ctx|'s configured KDF, or NULL if the context has |
| 352 | // not been set up. |
| 353 | OPENSSL_EXPORT const EVP_HPKE_KDF *EVP_HPKE_CTX_kdf(const EVP_HPKE_CTX *ctx); |
Daniel McArdle | 00e434d | 2021-02-18 11:47:18 -0500 | [diff] [blame] | 354 | |
Dan McArdle | 1920c6f | 2020-03-11 17:29:40 -0400 | [diff] [blame] | 355 | |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 356 | // Private structures. |
| 357 | // |
| 358 | // The following structures are exported so their types are stack-allocatable, |
| 359 | // but accessing or modifying their fields is forbidden. |
| 360 | |
| 361 | struct evp_hpke_ctx_st { |
David Benjamin | 779f7d0 | 2022-08-26 16:02:49 -0400 | [diff] [blame] | 362 | const EVP_HPKE_KEM *kem; |
David Benjamin | f39c81d | 2021-05-03 18:39:46 -0400 | [diff] [blame] | 363 | const EVP_HPKE_AEAD *aead; |
| 364 | const EVP_HPKE_KDF *kdf; |
| 365 | EVP_AEAD_CTX aead_ctx; |
| 366 | uint8_t base_nonce[EVP_AEAD_MAX_NONCE_LENGTH]; |
| 367 | uint8_t exporter_secret[EVP_MAX_MD_SIZE]; |
| 368 | uint64_t seq; |
| 369 | int is_sender; |
| 370 | }; |
Dan McArdle | 1920c6f | 2020-03-11 17:29:40 -0400 | [diff] [blame] | 371 | |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 372 | struct evp_hpke_key_st { |
| 373 | const EVP_HPKE_KEM *kem; |
| 374 | uint8_t private_key[X25519_PRIVATE_KEY_LEN]; |
| 375 | uint8_t public_key[X25519_PUBLIC_VALUE_LEN]; |
| 376 | }; |
| 377 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 378 | |
| 379 | #if defined(__cplusplus) |
| 380 | } // extern C |
| 381 | #endif |
| 382 | |
| 383 | #if !defined(BORINGSSL_NO_CXX) |
| 384 | extern "C++" { |
| 385 | |
| 386 | BSSL_NAMESPACE_BEGIN |
| 387 | |
| 388 | using ScopedEVP_HPKE_CTX = |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 389 | internal::StackAllocated<EVP_HPKE_CTX, void, EVP_HPKE_CTX_zero, |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 390 | EVP_HPKE_CTX_cleanup>; |
David Benjamin | 1d58cd1 | 2021-05-04 15:24:24 -0400 | [diff] [blame] | 391 | using ScopedEVP_HPKE_KEY = |
| 392 | internal::StackAllocated<EVP_HPKE_KEY, void, EVP_HPKE_KEY_zero, |
| 393 | EVP_HPKE_KEY_cleanup>; |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 394 | |
David Benjamin | 897a2ca | 2021-07-16 12:05:40 -0400 | [diff] [blame] | 395 | BORINGSSL_MAKE_DELETER(EVP_HPKE_CTX, EVP_HPKE_CTX_free) |
| 396 | BORINGSSL_MAKE_DELETER(EVP_HPKE_KEY, EVP_HPKE_KEY_free) |
| 397 | |
Daniel McArdle | 8b601c8 | 2020-07-16 14:10:52 -0400 | [diff] [blame] | 398 | BSSL_NAMESPACE_END |
| 399 | |
| 400 | } // extern C++ |
| 401 | #endif |
| 402 | |
| 403 | #endif // OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H |