diff options
Diffstat (limited to 'src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h')
-rw-r--r-- | src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h new file mode 100644 index 0000000..4736b51 --- /dev/null +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h @@ -0,0 +1,893 @@ +/* + * ngtcp2 + * + * Copyright (c) 2019 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGTCP2_CRYPTO_H +#define NGTCP2_CRYPTO_H + +#include <ngtcp2/ngtcp2.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <ws2tcpip.h> +#endif /* WIN32 */ + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_SECRETLEN` is the length of secret + * for Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_KEYLEN` is the length of key for + * Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_KEYLEN 16 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_IVLEN` is the length of IV for + * Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_IVLEN 12 + +/** + * @function + * + * `ngtcp2_crypto_ctx_tls` initializes |ctx| by extracting negotiated + * ciphers and message digests from native TLS session + * |tls_native_handle|. This is used for encrypting/decrypting + * Handshake and Short header packets. + * + * If libngtcp2_crypto_openssl is linked, |tls_native_handle| must be + * a pointer to SSL object. + */ +NGTCP2_EXTERN ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, + void *tls_native_handle); + +/** + * @function + * + * `ngtcp2_crypto_ctx_tls_early` initializes |ctx| by extracting early + * ciphers and message digests from native TLS session + * |tls_native_handle|. This is used for encrypting/decrypting 0RTT + * packets. + * + * If libngtcp2_crypto_openssl is linked, |tls_native_handle| must be + * a pointer to SSL object. + */ +NGTCP2_EXTERN ngtcp2_crypto_ctx * +ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx *ctx, void *tls_native_handle); + +/** + * @function + * + * `ngtcp2_crypto_md_init` initializes |md| with the provided + * |md_native_handle| which is an underlying message digest object. + * + * If libngtcp2_crypto_openssl is linked, |md_native_handle| must be a + * pointer to EVP_MD. + * + * If libngtcp2_crypto_gnutls is linked, |md_native_handle| must be + * gnutls_mac_algorithm_t casted to ``void *``. + * + * If libngtcp2_crypto_boringssl is linked, |md_native_handle| must be + * a pointer to EVP_MD. + */ +NGTCP2_EXTERN ngtcp2_crypto_md *ngtcp2_crypto_md_init(ngtcp2_crypto_md *md, + void *md_native_handle); + +/** + * @function + * + * `ngtcp2_crypto_md_hashlen` returns the length of |md| output. + */ +NGTCP2_EXTERN size_t ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md *md); + +/** + * @function + * + * `ngtcp2_crypto_aead_keylen` returns the length of key for |aead|. + */ +NGTCP2_EXTERN size_t ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead *aead); + +/** + * @function + * + * `ngtcp2_crypto_aead_noncelen` returns the length of nonce for + * |aead|. + */ +NGTCP2_EXTERN size_t +ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead); + +/** + * @function + * + * `ngtcp2_crypto_hkdf_extract` performs HKDF extract operation. The + * result is the length of |md| and is stored to the buffer pointed by + * |dest|. The caller is responsible to specify the buffer that can + * store the output. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen, + const uint8_t *salt, size_t saltlen); + +/** + * @function + * + * `ngtcp2_crypto_hkdf_expand` performs HKDF expand operation. The + * result is |destlen| bytes long and is stored to the buffer pointed + * by |dest|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, + const ngtcp2_crypto_md *md, + const uint8_t *secret, + size_t secretlen, + const uint8_t *info, + size_t infolen); + +/** + * @function + * + * `ngtcp2_crypto_hkdf` performs HKDF operation. The result is + * |destlen| bytes long and is stored to the buffer pointed by |dest|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, + const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen, + const uint8_t *salt, size_t saltlen, + const uint8_t *info, size_t infolen); + +/** + * @function + * + * `ngtcp2_crypto_hkdf_expand_label` performs HKDF expand label. The + * result is |destlen| bytes long and is stored to the buffer pointed + * by |dest|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen, + const ngtcp2_crypto_md *md, + const uint8_t *secret, + size_t secretlen, + const uint8_t *label, + size_t labellen); + +/** + * @enum + * + * :type:`ngtcp2_crypto_side` indicates which side the application + * implements; client or server. + */ +typedef enum ngtcp2_crypto_side { + /** + * :enum:`NGTCP2_CRYPTO_SIDE_CLIENT` indicates that the application + * is client. + */ + NGTCP2_CRYPTO_SIDE_CLIENT, + /** + * :enum:`NGTCP2_CRYPTO_SIDE_SERVER` indicates that the application + * is server. + */ + NGTCP2_CRYPTO_SIDE_SERVER +} ngtcp2_crypto_side; + +/** + * @function + * + * `ngtcp2_crypto_packet_protection_ivlen` returns the length of IV + * used to encrypt QUIC packet. + */ +NGTCP2_EXTERN size_t +ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead); + +/** + * @function + * + * `ngtcp2_crypto_encrypt` encrypts |plaintext| of length + * |plaintextlen| and writes the ciphertext into the buffer pointed by + * |dest|. The length of ciphertext is plaintextlen + + * :member:`aead->max_overhead <ngtcp2_crypto_aead.max_overhead>` + * bytes long. |dest| must have enough capacity to store the + * ciphertext. It is allowed to specify the same value to |dest| and + * |plaintext|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_encrypt(uint8_t *dest, + const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *plaintext, + size_t plaintextlen, + const uint8_t *nonce, size_t noncelen, + const uint8_t *aad, size_t aadlen); + +/** + * @function + * + * `ngtcp2_crypto_encrypt_cb` is a wrapper function around + * `ngtcp2_crypto_encrypt`. It can be directly passed to + * :member:`ngtcp2_callbacks.encrypt` field. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *plaintext, size_t plaintextlen, + const uint8_t *nonce, size_t noncelen, + const uint8_t *aad, size_t aadlen); + +/** + * @function + * + * `ngtcp2_crypto_decrypt` decrypts |ciphertext| of length + * |ciphertextlen| and writes the plaintext into the buffer pointed by + * |dest|. The length of plaintext is ciphertextlen - + * :member:`aead->max_overhead <ngtcp2_crypto_aead.max_overhead>` + * bytes long. |dest| must have enough capacity to store the + * plaintext. It is allowed to specify the same value to |dest| and + * |ciphertext|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_decrypt(uint8_t *dest, + const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *ciphertext, + size_t ciphertextlen, + const uint8_t *nonce, size_t noncelen, + const uint8_t *aad, size_t aadlen); + +/** + * @function + * + * `ngtcp2_crypto_decrypt_cb` is a wrapper function around + * `ngtcp2_crypto_decrypt`. It can be directly passed to + * :member:`ngtcp2_callbacks.decrypt` field. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_TLS_DECRYPT`. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *ciphertext, size_t ciphertextlen, + const uint8_t *nonce, size_t noncelen, + const uint8_t *aad, size_t aadlen); + +/** + * @function + * + * `ngtcp2_crypto_hp_mask` generates mask which is used in packet + * header encryption. The mask is written to the buffer pointed by + * |dest|. The sample is passed as |sample| which is + * :macro:`NGTCP2_HP_SAMPLELEN` bytes long. The length of mask must + * be at least :macro:`NGTCP2_HP_MASKLEN`. The library only uses the + * first :macro:`NGTCP2_HP_MASKLEN` bytes of the produced mask. The + * buffer pointed by |dest| must have at least + * :macro:`NGTCP2_HP_SAMPLELEN` bytes available. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_hp_mask(uint8_t *dest, + const ngtcp2_crypto_cipher *hp, + const ngtcp2_crypto_cipher_ctx *hp_ctx, + const uint8_t *sample); + +/** + * @function + * + * `ngtcp2_crypto_hp_mask_cb` is a wrapper function around + * `ngtcp2_crypto_hp_mask`. It can be directly passed to + * :member:`ngtcp2_callbacks.hp_mask` field. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, + const ngtcp2_crypto_cipher_ctx *hp_ctx, + const uint8_t *sample); + +/** + * @function + * + * `ngtcp2_crypto_derive_and_install_rx_key` derives the rx keys from + * |secret| and installs new keys to |conn|. + * + * If |key| is not NULL, the derived packet protection key for + * decryption is written to the buffer pointed by |key|. If |iv| is + * not NULL, the derived packet protection IV for decryption is + * written to the buffer pointed by |iv|. If |hp| is not NULL, the + * derived header protection key for decryption is written to the + * buffer pointed by |hp|. + * + * |secretlen| specifies the length of |secret|. + * + * The length of packet protection key and header protection key is + * `ngtcp2_crypto_aead_keylen(ctx->aead) <ngtcp2_crypto_aead_keylen>`, + * and the length of packet protection IV is + * `ngtcp2_crypto_packet_protection_ivlen(ctx->aead) + * <ngtcp2_crypto_packet_protection_ivlen>` where ctx is obtained by + * `ngtcp2_crypto_ctx_tls` (or `ngtcp2_crypto_ctx_tls_early` if + * |level| == :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`). + * + * In the first call of this function, it calls + * `ngtcp2_conn_set_crypto_ctx` (or `ngtcp2_conn_set_early_crypto_ctx` + * if |level| == + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to set + * negotiated AEAD and message digest algorithm. After the successful + * call of this function, application can use + * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` + * if |level| == + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to get + * :type:`ngtcp2_crypto_ctx`. + * + * If |conn| is initialized as client, and |level| is + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_APPLICATION`, this + * function retrieves a remote QUIC transport parameters extension + * from an object obtained by `ngtcp2_conn_get_tls_native_handle` and + * sets it to |conn| by calling + * `ngtcp2_conn_decode_remote_transport_params`. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( + ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, + ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen); + +/** + * @function + * + * `ngtcp2_crypto_derive_and_install_tx_key` derives the tx keys from + * |secret| and installs new keys to |conn|. + * + * If |key| is not NULL, the derived packet protection key for + * encryption is written to the buffer pointed by |key|. If |iv| is + * not NULL, the derived packet protection IV for encryption is + * written to the buffer pointed by |iv|. If |hp| is not NULL, the + * derived header protection key for encryption is written to the + * buffer pointed by |hp|. + * + * |secretlen| specifies the length of |secret|. + * + * The length of packet protection key and header protection key is + * `ngtcp2_crypto_aead_keylen(ctx->aead) <ngtcp2_crypto_aead_keylen>`, + * and the length of packet protection IV is + * `ngtcp2_crypto_packet_protection_ivlen(ctx->aead) + * <ngtcp2_crypto_packet_protection_ivlen>` where ctx is obtained by + * `ngtcp2_crypto_ctx_tls` (or `ngtcp2_crypto_ctx_tls_early` if + * |level| == :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`). + * + * In the first call of this function, it calls + * `ngtcp2_conn_set_crypto_ctx` (or `ngtcp2_conn_set_early_crypto_ctx` + * if |level| == + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to set + * negotiated AEAD and message digest algorithm. After the successful + * call of this function, application can use + * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` + * if |level| == + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to get + * :type:`ngtcp2_crypto_ctx`. + * + * If |conn| is initialized as server, and |level| is + * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_APPLICATION`, this + * function retrieves a remote QUIC transport parameters extension + * from an object obtained by `ngtcp2_conn_get_tls_native_handle` and + * sets it to |conn| by calling + * `ngtcp2_conn_decode_remote_transport_params`. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key( + ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, + ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen); + +/** + * @function + * + * `ngtcp2_crypto_update_key` updates traffic keying materials. + * + * The new traffic secret for decryption is written to the buffer + * pointed by |rx_secret|. The length of secret is |secretlen| bytes, + * and |rx_secret| must point to the buffer which has enough capacity. + * + * The new traffic secret for encryption is written to the buffer + * pointed by |tx_secret|. The length of secret is |secretlen| bytes, + * and |tx_secret| must point to the buffer which has enough capacity. + * + * The derived packet protection key for decryption is written to the + * buffer pointed by |rx_key|. The derived packet protection IV for + * decryption is written to the buffer pointed by |rx_iv|. + * |rx_aead_ctx| must be constructed with |rx_key|. + * + * The derived packet protection key for encryption is written to the + * buffer pointed by |tx_key|. The derived packet protection IV for + * encryption is written to the buffer pointed by |tx_iv|. + * |tx_aead_ctx| must be constructed with |rx_key|. + * + * |current_rx_secret| and |current_tx_secret| are the current traffic + * secrets for decryption and encryption. |secretlen| specifies the + * length of |rx_secret| and |tx_secret|. + * + * The length of packet protection key and header protection key is + * `ngtcp2_crypto_aead_keylen(ctx->aead) <ngtcp2_crypto_aead_keylen>`, + * and the length of packet protection IV is + * `ngtcp2_crypto_packet_protection_ivlen(ctx->aead) + * <ngtcp2_crypto_packet_protection_ivlen>` where ctx is obtained by + * `ngtcp2_crypto_ctx_tls`. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_update_key( + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen); + +/** + * @function + * + * `ngtcp2_crypto_update_key_cb` is a wrapper function around + * `ngtcp2_crypto_update_key`. It can be directly passed to + * :member:`ngtcp2_callbacks.update_key` field. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb( + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen, void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_client_initial_cb` installs initial secrets and + * encryption keys and sets QUIC transport parameters. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.client_initial` field. It is only used + * by client. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, + void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_recv_retry_cb` re-installs initial secrets in + * response to incoming Retry packet. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.recv_retry` field. It is only used + * by client. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn, + const ngtcp2_pkt_hd *hd, + void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_recv_client_initial_cb` installs initial secrets in + * response to an incoming Initial packet from client, and sets QUIC + * transport parameters. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.recv_client_initial` field. It is + * only used by server. + * + * This function returns 0 if it succeeds, or + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. + */ +NGTCP2_EXTERN int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn, + const ngtcp2_cid *dcid, + void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_read_write_crypto_data` reads CRYPTO data |data| of + * length |datalen| in encryption level |crypto_level| and may feed + * outgoing CRYPTO data to |conn|. This function can drive handshake. + * This function can be also used after handshake completes. It is + * allowed to call this function with |datalen| == 0. In this case, + * no additional read operation is done. + * + * This function returns 0 if it succeeds, or a negative error code. + * The generic error code is -1 if a specific error code is not + * suitable. The error codes less than -10000 are specific to + * underlying TLS implementation. For OpenSSL, the error codes are + * defined in *ngtcp2_crypto_openssl.h*. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, + ngtcp2_crypto_level crypto_level, + const uint8_t *data, size_t datalen); + +/** + * @function + * + * `ngtcp2_crypto_recv_crypto_data_cb` is a wrapper function around + * `ngtcp2_crypto_read_write_crypto_data`. It can be directly passed + * to :member:`ngtcp2_callbacks.recv_crypto_data` field. + * + * If this function is used, the TLS implementation specific error + * codes described in `ngtcp2_crypto_read_write_crypto_data` are + * treated as if it returns -1. Do not use this function if an + * application wishes to use the TLS implementation specific error + * codes. + */ +NGTCP2_EXTERN int ngtcp2_crypto_recv_crypto_data_cb( + ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, uint64_t offset, + const uint8_t *data, size_t datalen, void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_generate_stateless_reset_token` generates a + * stateless reset token using HKDF extraction using the given |cid| + * and static key |secret| as input. The token will be written to + * the buffer pointed by |token| and it must have a capacity of at + * least :macro:`NGTCP2_STATELESS_RESET_TOKENLEN` bytes. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_cid *cid); + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_TOKEN_RAND_DATALEN` is the length of random + * data added to a token generated by + * `ngtcp2_crypto_generate_retry_token` or + * `ngtcp2_crypto_generate_regular_token`. + */ +#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 32 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY` is the magic byte for + * Retry token generated by `ngtcp2_crypto_generate_retry_token`. + */ +#define NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY 0xb6 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR` is the magic byte for a + * token generated by `ngtcp2_crypto_generate_regular_token`. + */ +#define NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR 0x36 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN` is the maximum length of + * a token generated by `ngtcp2_crypto_generate_retry_token`. + */ +#define NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN \ + (/* magic = */ 1 + /* cid len = */ 1 + NGTCP2_MAX_CIDLEN + \ + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ + NGTCP2_CRYPTO_TOKEN_RAND_DATALEN) + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` is the maximum length + * of a token generated by `ngtcp2_crypto_generate_regular_token`. + */ +#define NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN \ + (/* magic = */ 1 + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ + NGTCP2_CRYPTO_TOKEN_RAND_DATALEN) + +/** + * @function + * + * `ngtcp2_crypto_generate_retry_token` generates a token in the + * buffer pointed by |token| that is sent with Retry packet. The + * buffer pointed by |token| must have at least + * :macro:`NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN` bytes long. The + * successfully generated token starts with + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY`. |secret| of length + * |secretlen| is an initial keying material to generate keys to + * encrypt the token. |version| is QUIC version. |remote_addr| of + * length |remote_addrlen| is an address of client. |retry_scid| is a + * Source Connection ID chosen by server and set in Retry packet. + * |odcid| is a Destination Connection ID in Initial packet sent by + * client. |ts| is the timestamp when the token is generated. + * + * This function returns the length of generated token if it succeeds, + * or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_retry_token( + uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_verify_retry_token` verifies Retry token stored in + * the buffer pointed by |token| of length |tokenlen|. |secret| of + * length |secretlen| is an initial keying material to generate keys + * to decrypt the token. |version| is QUIC version of the Initial + * packet that contains this token. |remote_addr| of length + * |remote_addrlen| is an address of client. |dcid| is a Destination + * Connection ID in Initial packet sent by client. |timeout| is the + * period during which the token is valid. |ts| is the current + * timestamp. When validation succeeds, the extracted Destination + * Connection ID (which is the Destination Connection ID in Initial + * packet sent by client that triggered Retry packet) is stored to the + * buffer pointed by |odcid|. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_verify_retry_token( + ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_generate_regular_token` generates a token in the + * buffer pointed by |token| that is sent with NEW_TOKEN frame. The + * buffer pointed by |token| must have at least + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes long. The + * successfully generated token starts with + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`. |secret| of length + * |secretlen| is an initial keying material to generate keys to + * encrypt the token. |remote_addr| of length |remote_addrlen| is an + * address of client. |ts| is the timestamp when the token is + * generated. + * + * This function returns the length of generated token if it succeeds, + * or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_verify_regular_token` verifies a regular token + * stored in the buffer pointed by |token| of length |tokenlen|. + * |secret| of length |secretlen| is an initial keying material to + * generate keys to decrypt the token. |remote_addr| of length + * |remote_addrlen| is an address of client. |timeout| is the period + * during which the token is valid. |ts| is the current timestamp. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token( + const uint8_t *token, size_t tokenlen, const uint8_t *secret, + size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_write_connection_close` writes Initial packet + * containing CONNECTION_CLOSE with the given |error_code| and the + * optional |reason| of length |reasonlen| to the buffer pointed by + * |dest| of length |destlen|. This function is designed for server + * to close connection without committing the state when validating + * Retry token fails. This function must not be used by client. The + * |dcid| must be the Source Connection ID in Initial packet from + * client. The |scid| must be the Destination Connection ID in + * Initial packet from client. |scid| is used to derive initial + * keying materials. + * + * This function wraps around `ngtcp2_pkt_write_connection_close` for + * easier use. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_connection_close( + uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, uint64_t error_code, const uint8_t *reason, + size_t reasonlen); + +/** + * @function + * + * `ngtcp2_crypto_write_retry` writes Retry packet to the buffer + * pointed by |dest| of length |destlen|. |odcid| specifies Original + * Destination Connection ID. |token| specifies Retry Token, and + * |tokenlen| specifies its length. + * + * This function wraps around `ngtcp2_pkt_write_retry` for easier use. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_retry( + uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, + size_t tokenlen); + +/** + * @function + * + * `ngtcp2_crypto_aead_ctx_encrypt_init` initializes |aead_ctx| with + * new AEAD cipher context object for encryption which is constructed + * to use |key| as encryption key. |aead| specifies AEAD cipher to + * use. |noncelen| is the length of nonce. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx, + const ngtcp2_crypto_aead *aead, + const uint8_t *key, size_t noncelen); + +/** + * @function + * + * `ngtcp2_crypto_aead_ctx_decrypt_init` initializes |aead_ctx| with + * new AEAD cipher context object for decryption which is constructed + * to use |key| as encryption key. |aead| specifies AEAD cipher to + * use. |noncelen| is the length of nonce. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx, + const ngtcp2_crypto_aead *aead, + const uint8_t *key, size_t noncelen); + +/** + * @function + * + * `ngtcp2_crypto_aead_ctx_free` frees up resources used by + * |aead_ctx|. This function does not free the memory pointed by + * |aead_ctx| itself. + */ +NGTCP2_EXTERN void +ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx); + +/** + * @function + * + * `ngtcp2_crypto_delete_crypto_aead_ctx_cb` deletes the given |aead_ctx|. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` field. + */ +NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_aead_ctx_cb( + ngtcp2_conn *conn, ngtcp2_crypto_aead_ctx *aead_ctx, void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_delete_crypto_cipher_ctx_cb` deletes the given + * |cipher_ctx|. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` field. + */ +NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_cipher_ctx_cb( + ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_get_path_challenge_data_cb` writes unpredictable + * sequence of :macro:`NGTCP2_PATH_CHALLENGE_DATALEN` bytes to |data| + * which is sent with PATH_CHALLENGE frame. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.get_path_challenge_data` field. + */ +NGTCP2_EXTERN int ngtcp2_crypto_get_path_challenge_data_cb(ngtcp2_conn *conn, + uint8_t *data, + void *user_data); + +/** + * @function + * + * `ngtcp2_crypto_version_negotiation_cb` installs Initial keys for + * |version| which is negotiated or being negotiated. |client_dcid| + * is the destination connection ID in first Initial packet of client. + * + * This function can be directly passed to + * :member:`ngtcp2_callbacks.version_negotiation` field. + */ +NGTCP2_EXTERN int +ngtcp2_crypto_version_negotiation_cb(ngtcp2_conn *conn, uint32_t version, + const ngtcp2_cid *client_dcid, + void *user_data); + +typedef struct ngtcp2_crypto_conn_ref ngtcp2_crypto_conn_ref; + +/** + * @functypedef + * + * :type:`ngtcp2_crypto_get_conn` is a callback function to get a + * pointer to :type:`ngtcp2_conn` from |conn_ref|. The implementation + * must return non-NULL :type:`ngtcp2_conn` object. + */ +typedef ngtcp2_conn *(*ngtcp2_crypto_get_conn)( + ngtcp2_crypto_conn_ref *conn_ref); + +/** + * @struct + * + * :type:`ngtcp2_crypto_conn_ref` is a structure to get a pointer to + * :type:`ngtcp2_conn`. It is meant to be set to TLS native handle as + * an application specific data (e.g. SSL_set_app_data in OpenSSL). + */ +typedef struct ngtcp2_crypto_conn_ref { + /** + * :member:`get_conn` is a callback function to get a pointer to + * :type:`ngtcp2_conn` object. + */ + ngtcp2_crypto_get_conn get_conn; + /** + * :member:`user_data` is a pointer to arbitrary user data. + */ + void *user_data; +} ngtcp2_crypto_conn_ref; + +#ifdef __cplusplus +} +#endif + +#endif /* NGTCP2_CRYPTO_H */ |