diff options
Diffstat (limited to 'deps/ngtcp2/lib/ngtcp2_crypto.c')
-rw-r--r-- | deps/ngtcp2/lib/ngtcp2_crypto.c | 173 |
1 files changed, 128 insertions, 45 deletions
diff --git a/deps/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/lib/ngtcp2_crypto.c index dd65ff7e303..26eacb87299 100644 --- a/deps/ngtcp2/lib/ngtcp2_crypto.c +++ b/deps/ngtcp2/lib/ngtcp2_crypto.c @@ -72,6 +72,7 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen, (*pckm)->iv.base = p; (*pckm)->iv.len = ivlen; (*pckm)->pkt_num = -1; + (*pckm)->use_count = 0; (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE; return 0; @@ -118,6 +119,33 @@ static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, return ngtcp2_put_varint(p, value); } +/* + * cid_paramlen returns the length of a single transport parameter + * which has |cid| as value. + */ +static size_t cid_paramlen(ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(cid->datalen) + + cid->datalen; +} + +/* + * write_cid_param writes parameter |id| of the given |cid|. It + * returns p + the number of bytes written. + */ +static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); + assert(cid->datalen <= NGTCP2_MAX_CIDLEN); + + p = ngtcp2_put_varint(p, id); + p = ngtcp2_put_varint(p, cid->datalen); + if (cid->datalen) { + p = ngtcp2_cpymem(p, cid->data, cid->datalen); + } + return p; +} + ngtcp2_ssize ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype, @@ -131,6 +159,10 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO: break; case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS: + len += + cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + if (params->stateless_reset_token_present) { len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + @@ -138,8 +170,7 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, NGTCP2_STATELESS_RESET_TOKENLEN; } if (params->preferred_address_present) { - assert(params->preferred_address.cid.datalen == 0 || - params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN); + assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN); assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN); preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ + 2 /* ipv6Port */ @@ -149,17 +180,18 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen; } - if (params->original_connection_id_present) { - len += - ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID) + - ngtcp2_put_varint_len(params->original_connection_id.datalen) + - params->original_connection_id.datalen; + if (params->retry_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); } break; default: return NGTCP2_ERR_INVALID_ARGUMENT; } + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + if (params->initial_max_stream_data_bidi_local) { len += varint_paramlen( NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, @@ -186,9 +218,9 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, params->initial_max_streams_uni); } - if (params->max_packet_size != NGTCP2_MAX_PKT_SIZE) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE, - params->max_packet_size); + if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); } if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, @@ -221,6 +253,10 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, p = dest; if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { + p = write_cid_param( + p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + if (params->stateless_reset_token_present) { p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token)); @@ -248,14 +284,15 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, p, params->preferred_address.stateless_reset_token, sizeof(params->preferred_address.stateless_reset_token)); } - if (params->original_connection_id_present) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID); - p = ngtcp2_put_varint(p, params->original_connection_id.datalen); - p = ngtcp2_cpymem(p, params->original_connection_id.data, - params->original_connection_id.datalen); + if (params->retry_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); } } + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + if (params->initial_max_stream_data_bidi_local) { p = write_varint_param( p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, @@ -289,9 +326,9 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen, params->initial_max_streams_uni); } - if (params->max_packet_size != NGTCP2_MAX_PKT_SIZE) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE, - params->max_packet_size); + if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); } if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { @@ -371,6 +408,10 @@ static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p, p += nread; + if (p == end) { + return -1; + } + if ((uint64_t)(end - p) < valuelen) { return -1; } @@ -386,6 +427,37 @@ static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p, return (ngtcp2_ssize)(p - begin); } +/* + * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer + * pointed by |p| of length |end - p|. The length is encoded in + * varint form. If it decodes a value successfully, it stores the + * value in |*pdest| and returns the number of bytes read. Otherwise + * it returns -1. + */ +static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p, + const uint8_t *end) { + const uint8_t *begin = p; + uint64_t valuelen; + ngtcp2_ssize nread = decode_varint(&valuelen, p, end); + + if (nread < 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + p += nread; + + if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || + valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + ngtcp2_cid_init(pdest, p, (size_t)valuelen); + + p += valuelen; + + return (ngtcp2_ssize)(p - begin); +} + int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, ngtcp2_transport_params_type exttype, const uint8_t *data, size_t datalen) { @@ -394,37 +466,37 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, uint64_t param_type; uint64_t valuelen; ngtcp2_ssize nread; - uint8_t scb[8192]; - size_t scb_idx; - size_t scb_shift; + int initial_scid_present = 0; + int original_dcid_present = 0; p = data; end = data + datalen; /* Set default values */ + memset(params, 0, sizeof(*params)); params->initial_max_streams_bidi = 0; params->initial_max_streams_uni = 0; params->initial_max_stream_data_bidi_local = 0; params->initial_max_stream_data_bidi_remote = 0; params->initial_max_stream_data_uni = 0; - params->max_packet_size = NGTCP2_MAX_PKT_SIZE; + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE; params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; params->stateless_reset_token_present = 0; params->preferred_address_present = 0; - memset(¶ms->preferred_address, 0, sizeof(params->preferred_address)); params->disable_active_migration = 0; params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; params->max_idle_timeout = 0; params->active_connection_id_limit = NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - params->original_connection_id_present = 0; + params->retry_scid_present = 0; + memset(¶ms->retry_scid, 0, sizeof(params->retry_scid)); + memset(¶ms->initial_scid, 0, sizeof(params->initial_scid)); + memset(¶ms->original_dcid, 0, sizeof(params->original_dcid)); if (datalen == 0) { return 0; } - memset(scb, 0, sizeof(scb)); - for (; (size_t)(end - p) >= 2;) { nread = decode_varint(¶m_type, p, end); if (nread < 0) { @@ -432,13 +504,6 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, } p += nread; - scb_idx = param_type / 8; - scb_shift = param_type % 8; - - if (scb[scb_idx] & (1 << scb_shift)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - scb[scb_idx] |= (uint8_t)(1 << scb_shift); switch (param_type) { case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_local, @@ -498,8 +563,8 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, params->max_idle_timeout *= NGTCP2_MILLISECONDS; p += nread; break; - case NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE: - nread = decode_varint_param(¶ms->max_packet_size, p, end); + case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: + nread = decode_varint_param(¶ms->max_udp_payload_size, p, end); if (nread < 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } @@ -570,8 +635,7 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, len += params->preferred_address.cid.datalen; if (valuelen != len || params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN || - (params->preferred_address.cid.datalen != 0 && - params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN)) { + params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } if (params->preferred_address.cid.datalen) { @@ -594,22 +658,35 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, p += nread; params->disable_active_migration = 1; break; - case NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID: + case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - nread = decode_varint(&valuelen, p, end); + nread = decode_cid_param(¶ms->original_dcid, p, end); if (nread < 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + return (int)nread; } + original_dcid_present = 1; p += nread; - if (valuelen < NGTCP2_MIN_CIDLEN || valuelen > NGTCP2_MAX_CIDLEN || - (size_t)(end - p) < valuelen) { + break; + case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: + if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - ngtcp2_cid_init(¶ms->original_connection_id, p, valuelen); - params->original_connection_id_present = 1; - p += valuelen; + nread = decode_cid_param(¶ms->retry_scid, p, end); + if (nread < 0) { + return (int)nread; + } + params->retry_scid_present = 1; + p += nread; + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: + nread = decode_cid_param(¶ms->initial_scid, p, end); + if (nread < 0) { + return (int)nread; + } + initial_scid_present = 1; + p += nread; break; case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: nread = decode_varint_param(¶ms->max_ack_delay, p, end); @@ -645,5 +722,11 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params, return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } + if (!initial_scid_present || + (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS && + !original_dcid_present)) { + return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; + } + return 0; } |