Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
deps: update ngtcp2 to draft-25
Browse files Browse the repository at this point in the history
PR-URL: #305
Reviewed-By: Anna Henningsen <[email protected]>
  • Loading branch information
jasnell committed Feb 3, 2020
1 parent b946ba3 commit bfda347
Show file tree
Hide file tree
Showing 17 changed files with 1,260 additions and 637 deletions.
48 changes: 48 additions & 0 deletions deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx);
NGTCP2_EXTERN ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx,
void *tls_native_handle);

/**
* @function
*
* `ngtcp2_crypto_aead_retry` initializes |aead| with the AEAD cipher
* AEAD_AES_128_GCM for Retry packet integrity protection.
*/
NGTCP2_EXTERN ngtcp2_crypto_aead *
ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead);

/**
* @function
*
Expand Down Expand Up @@ -507,6 +516,45 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
uint8_t *token, const ngtcp2_crypto_md *md, const uint8_t *secret,
size_t secretlen, const ngtcp2_cid *cid);

/**
* @function
*
* `ngtcp2_crypto_write_connection_close` writes Initial packet
* containing CONNECTION_CLOSE with the given |error_code| 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, const ngtcp2_cid *dcid,
const ngtcp2_cid *scid, uint64_t error_code);

/**
* @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, const ngtcp2_cid *dcid,
const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
const uint8_t *token, size_t tokenlen);

#ifdef __cplusplus
}
#endif
Expand Down
5 changes: 5 additions & 0 deletions deps/ngtcp2/crypto/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) {
return ctx;
}

ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) {
aead->native_handle = (void *)EVP_aes_128_gcm();
return aead;
}

static const EVP_CIPHER *crypto_ssl_get_aead(SSL *ssl) {
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
case TLS1_3_CK_AES_128_GCM_SHA256:
Expand Down
59 changes: 59 additions & 0 deletions deps/ngtcp2/crypto/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ int ngtcp2_crypto_derive_and_install_initial_key(
uint8_t tx_ivbuf[NGTCP2_CRYPTO_INITIAL_IVLEN];
uint8_t tx_hp_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
ngtcp2_crypto_ctx ctx;
ngtcp2_crypto_aead retry_aead;
int rv;

ngtcp2_crypto_ctx_initial(&ctx);
Expand Down Expand Up @@ -323,6 +324,8 @@ int ngtcp2_crypto_derive_and_install_initial_key(
return -1;
}

ngtcp2_conn_set_retry_aead(conn, ngtcp2_crypto_aead_retry(&retry_aead));

return 0;
}

Expand Down Expand Up @@ -442,3 +445,59 @@ int ngtcp2_crypto_generate_stateless_reset_token(uint8_t *token,

return 0;
}

ngtcp2_ssize ngtcp2_crypto_write_connection_close(uint8_t *dest, size_t destlen,
const ngtcp2_cid *dcid,
const ngtcp2_cid *scid,
uint64_t error_code) {
uint8_t rx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
uint8_t tx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
uint8_t initial_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
uint8_t tx_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
uint8_t tx_iv[NGTCP2_CRYPTO_INITIAL_IVLEN];
uint8_t tx_hp_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
ngtcp2_crypto_ctx ctx;
ngtcp2_ssize spktlen;

ngtcp2_crypto_ctx_initial(&ctx);

if (ngtcp2_crypto_derive_initial_secrets(rx_secret, tx_secret, initial_secret,
scid,
NGTCP2_CRYPTO_SIDE_SERVER) != 0) {
return -1;
}

if (ngtcp2_crypto_derive_packet_protection_key(
tx_key, tx_iv, tx_hp_key, &ctx.aead, &ctx.md, tx_secret,
NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) {
return -1;
}

spktlen = ngtcp2_pkt_write_connection_close(
dest, destlen, dcid, scid, error_code, ngtcp2_crypto_encrypt_cb,
&ctx.aead, tx_key, tx_iv, ngtcp2_crypto_hp_mask_cb, &ctx.hp, tx_hp_key);
if (spktlen < 0) {
return -1;
}

return spktlen;
}

ngtcp2_ssize ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen,
const ngtcp2_cid *dcid,
const ngtcp2_cid *scid,
const ngtcp2_cid *odcid,
const uint8_t *token, size_t tokenlen) {
ngtcp2_crypto_aead aead;
ngtcp2_ssize spktlen;

ngtcp2_crypto_aead_retry(&aead);

spktlen = ngtcp2_pkt_write_retry(dest, destlen, dcid, scid, odcid, token,
tokenlen, ngtcp2_crypto_encrypt_cb, &aead);
if (spktlen < 0) {
return -1;
}

return spktlen;
}
143 changes: 110 additions & 33 deletions deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ typedef struct ngtcp2_mem {
} ngtcp2_mem;

/* NGTCP2_PROTO_VER is the supported QUIC protocol version. */
#define NGTCP2_PROTO_VER 0xff000018u
#define NGTCP2_PROTO_VER 0xff000019u
/* NGTCP2_PROTO_VER_MAX is the highest QUIC version the library
supports. */
#define NGTCP2_PROTO_VER_MAX NGTCP2_PROTO_VER

/* NGTCP2_ALPN_H3 is a serialized form of HTTP/3 ALPN protocol
identifier this library supports. Notice that the first byte is
the length of the following protocol identifier. */
#define NGTCP2_ALPN_H3 "\x5h3-24"
#define NGTCP2_ALPN_H3 "\x5h3-25"

#define NGTCP2_MAX_PKTLEN_IPV4 1252
#define NGTCP2_MAX_PKTLEN_IPV6 1232
Expand Down Expand Up @@ -227,6 +227,7 @@ typedef enum ngtcp2_lib_error {
NGTCP2_ERR_STREAM_IN_USE = -209,
NGTCP2_ERR_STREAM_DATA_BLOCKED = -210,
NGTCP2_ERR_FLOW_CONTROL = -211,
NGTCP2_ERR_CONNECTION_ID_LIMIT = -212,
NGTCP2_ERR_STREAM_LIMIT = -213,
NGTCP2_ERR_FINAL_SIZE = -214,
NGTCP2_ERR_CRYPTO = -215,
Expand Down Expand Up @@ -286,7 +287,9 @@ typedef enum ngtcp2_pkt_type {
#define NGTCP2_FINAL_SIZE_ERROR 0x6u
#define NGTCP2_FRAME_ENCODING_ERROR 0x7u
#define NGTCP2_TRANSPORT_PARAMETER_ERROR 0x8u
#define NGTCP2_CONNECTION_ID_LIMIT_ERROR 0x9u
#define NGTCP2_PROTOCOL_VIOLATION 0xau
#define NGTCP2_INVALID_TOKEN 0xbu
#define NGTCP2_CRYPTO_BUFFER_EXCEEDED 0xdu
#define NGTCP2_KEY_UPDATE_ERROR 0xeu
#define NGTCP2_CRYPTO_ERROR 0x100u
Expand Down Expand Up @@ -377,10 +380,14 @@ typedef struct ngtcp2_pkt_stateless_reset {
size_t randlen;
} ngtcp2_pkt_stateless_reset;

/* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */
#define NGTCP2_RETRY_TAGLEN 16

typedef struct ngtcp2_pkt_retry {
ngtcp2_cid odcid;
const uint8_t *token;
size_t tokenlen;
uint8_t tag[NGTCP2_RETRY_TAGLEN];
} ngtcp2_pkt_retry;

#if defined(__cplusplus) && __cplusplus >= 201103L
Expand All @@ -389,7 +396,7 @@ typedef enum ngtcp2_transport_param_id : uint16_t {
typedef enum ngtcp2_transport_param_id {
#endif
NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID = 0x0000,
NGTCP2_TRANSPORT_PARAM_IDLE_TIMEOUT = 0x0001,
NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT = 0x0001,
NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN = 0x0002,
NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE = 0x0003,
NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA = 0x0004,
Expand Down Expand Up @@ -452,6 +459,14 @@ typedef enum ngtcp2_rand_ctx {
*/
#define NGTCP2_DEFAULT_MAX_ACK_DELAY (25 * NGTCP2_MILLISECONDS)

/**
* @macro
*
* NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT is the default value of
* active_connection_id_limit transport parameter value if omitted.
*/
#define NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT 2

/**
* @macro
*
Expand Down Expand Up @@ -499,10 +514,12 @@ typedef struct ngtcp2_transport_params {
/* initial_max_streams_uni is the number of concurrent
unidirectional streams that the remote endpoint can create. */
uint64_t initial_max_streams_uni;
/* idle_timeout is a duration during which endpoint allows
/* max_idle_timeout is a duration during which sender allows
quiescent. */
ngtcp2_duration idle_timeout;
ngtcp2_duration max_idle_timeout;
uint64_t max_packet_size;
/* active_connection_id_limit is the maximum number of Connection ID
that sender can store. */
uint64_t active_connection_id_limit;
uint64_t ack_delay_exponent;
ngtcp2_duration max_ack_delay;
Expand Down Expand Up @@ -559,13 +576,12 @@ typedef struct ngtcp2_rcvry_stat {
ngtcp2_duration smoothed_rtt;
ngtcp2_duration rttvar;
size_t pto_count;
/* probe_pkt_left is the number of probe packet to sent */
size_t probe_pkt_left;
ngtcp2_tstamp loss_detection_timer;
/* last_tx_pkt_ts corresponds to
time_of_last_sent_ack_eliciting_packet in
draft-ietf-quic-recovery-23. */
ngtcp2_tstamp last_tx_pkt_ts;
draft-ietf-quic-recovery-25. It is indexed by
ngtcp2_crypto_level. No last_tx_pkt_ts for 0RTT packet. */
ngtcp2_tstamp last_tx_pkt_ts[3];
} ngtcp2_rcvry_stat;

typedef struct ngtcp2_cc_stat {
Expand Down Expand Up @@ -835,29 +851,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest,
* :macro:`NGTCP2_MIN_STATELESS_RETRY_RANDLEN`.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_stateless_reset(
uint8_t *dest, size_t destlen, uint8_t *stateless_reset_token,
uint8_t *rand, size_t randlen);

/**
* @function
*
* `ngtcp2_pkt_write_retry` writes Retry packet in the buffer pointed
* by |dest| whose length is |destlen|. |hd| must be long packet
* header, and its type must be :enum:`NGTCP2_PKT_RETRY`. |odcid|
* specifies Original Destination Connection ID. |token| specifies
* Retry Token, and |tokenlen| specifies its length.
*
* This function returns the number of bytes written to the buffer, or
* one of the following negative error codes:
*
* :enum:`NGTCP2_ERR_NOBUF`
* Buffer is too small.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen,
const ngtcp2_pkt_hd *hd,
const ngtcp2_cid *odcid,
const uint8_t *token,
size_t tokenlen);
uint8_t *dest, size_t destlen, const uint8_t *stateless_reset_token,
const uint8_t *rand, size_t randlen);

/**
* @function
Expand Down Expand Up @@ -1010,6 +1005,19 @@ typedef int (*ngtcp2_recv_crypto_data)(ngtcp2_conn *conn,
*/
typedef int (*ngtcp2_handshake_completed)(ngtcp2_conn *conn, void *user_data);

/**
* @functypedef
*
* :type:`ngtcp2_handshake_confirmed` is invoked when QUIC
* cryptographic handshake is confirmed. The handshake confirmation
* means that both endpoints agree that handshake has finished.
*
* The callback function must return 0 if it succeeds. Returning
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
* immediately.
*/
typedef int (*ngtcp2_handshake_confirmed)(ngtcp2_conn *conn, void *user_data);

/**
* @functypedef
*
Expand Down Expand Up @@ -1608,9 +1616,67 @@ typedef struct ngtcp2_conn_callbacks {
* destination Connection ID is now deactivated.
*/
ngtcp2_connection_id_status dcid_status;
/**
* handshake_confirmed is a callback function which is invoked when
* both endpoints agree that handshake has finished. This field is
* ignored by server because handshake_completed indicates the
* handshake confirmation for server.
*/
ngtcp2_handshake_confirmed handshake_confirmed;
} ngtcp2_conn_callbacks;

/*
/**
* @function
*
* `ngtcp2_pkt_write_connection_close` writes Initial packet
* containing CONNECTION_CLOSE frame with the given |error_code| to
* the buffer pointed by |dest| of length |destlen|. All encryption
* parameters are for Initial packet encryption. The packet number is
* always 0.
*
* The primary use case of this function is for server to send
* CONNECTION_CLOSE frame in Initial packet to close connection
* without committing the state when validating Retry token fails.
*
* This function returns the number of bytes written if it succeeds,
* or one of the following negative error codes:
*
* :enum:`NGTCP2_ERR_NOBUF`
* Buffer is too small.
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE
* Callback function failed.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt,
const ngtcp2_crypto_aead *aead, const uint8_t *key, const uint8_t *iv,
ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp,
const uint8_t *hp_key);

/**
* @function
*
* `ngtcp2_pkt_write_retry` writes Retry packet in the buffer pointed
* by |dest| whose length is |destlen|. |odcid| specifies Original
* Destination Connection ID. |token| specifies Retry Token, and
* |tokenlen| specifies its length. |aead| must be AEAD_AES_128_GCM.
*
* This function returns the number of bytes written to the buffer, or
* one of the following negative error codes:
*
* :enum:`NGTCP2_ERR_NOBUF`
* Buffer is too small.
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE
* Callback function failed.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry(
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead);

/**
* @function
*
* `ngtcp2_accept` is used by server implementation, and decides
* whether packet |pkt| of length |pktlen| is acceptable for initial
* packet from client.
Expand Down Expand Up @@ -2596,6 +2662,17 @@ ngtcp2_conn_get_initial_crypto_ctx(ngtcp2_conn *conn);
NGTCP2_EXTERN void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn,
const ngtcp2_crypto_ctx *ctx);

/**
* @function
*
* `ngtcp2_conn_set_retry_aead` sets |aead| for Retry integrity tag
* verification. It must be AEAD_AES_128_GCM. This function must be
* called if |conn| is initialized as client. Server does not verify
* the tag and has no need to call this function.
*/
NGTCP2_EXTERN void ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn,
const ngtcp2_crypto_aead *aead);

/**
* @function
*
Expand Down
Loading

0 comments on commit bfda347

Please sign in to comment.