diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9f216938..6e27892fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -116,7 +116,7 @@ _Type_: _Example_: ```bash -[~]: Update CONTRIBUTING.md +[~] Update CONTRIBUTING.md ``` #### Tests diff --git a/README.md b/README.md index d00d8ec6a..5aa326306 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,9 @@ sh ../scripts/xquic_test.sh - [draft-ietf-quic-http-34-zh](./docs/translation/draft-ietf-quic-http-34-zh.md) - [draft-ietf-quic-qpack-21-zh](./docs/translation/draft-ietf-quic-qpack-21-zh.md) -* For other frequently asked questions, see the [FAQs](./docs/FAQ.md). +* For using event_log module, see the [Event_log module docs](./docs/docs-zh/Event_log-zh.md) +* For testing the library, see the [Testing docs](./docs/docs-zh/Testing-zh.md). +* For other frequently asked questions, see the [FAQs](./docs/docs-zh/FAQ-zh.md) and [Trouble Shooting Guide](./docs/docs-zh/Troubleshooting-zh.md). ## Contributing diff --git a/bssl_symbols.txt b/bssl_symbols.txt deleted file mode 100644 index fa90e160f..000000000 --- a/bssl_symbols.txt +++ /dev/null @@ -1,3248 +0,0 @@ -ACCESS_DESCRIPTION_free -ACCESS_DESCRIPTION_it -ACCESS_DESCRIPTION_new -AES_CMAC -AES_cbc_encrypt -AES_cfb128_encrypt -AES_ctr128_encrypt -AES_decrypt -AES_ecb_encrypt -AES_encrypt -AES_ofb128_encrypt -AES_set_decrypt_key -AES_set_encrypt_key -AES_unwrap_key -AES_unwrap_key_padded -AES_wrap_key -AES_wrap_key_padded -ASN1_ANY_it -ASN1_BIT_STRING_check -ASN1_BIT_STRING_free -ASN1_BIT_STRING_get_bit -ASN1_BIT_STRING_it -ASN1_BIT_STRING_new -ASN1_BIT_STRING_set -ASN1_BIT_STRING_set_bit -ASN1_BMPSTRING_free -ASN1_BMPSTRING_it -ASN1_BMPSTRING_new -ASN1_BOOLEAN_it -ASN1_ENUMERATED_free -ASN1_ENUMERATED_get -ASN1_ENUMERATED_it -ASN1_ENUMERATED_new -ASN1_ENUMERATED_set -ASN1_ENUMERATED_to_BN -ASN1_FBOOLEAN_it -ASN1_GENERALIZEDTIME_adj -ASN1_GENERALIZEDTIME_check -ASN1_GENERALIZEDTIME_free -ASN1_GENERALIZEDTIME_it -ASN1_GENERALIZEDTIME_new -ASN1_GENERALIZEDTIME_print -ASN1_GENERALIZEDTIME_set -ASN1_GENERALIZEDTIME_set_string -ASN1_GENERALSTRING_free -ASN1_GENERALSTRING_it -ASN1_GENERALSTRING_new -ASN1_IA5STRING_free -ASN1_IA5STRING_it -ASN1_IA5STRING_new -ASN1_INTEGER_cmp -ASN1_INTEGER_dup -ASN1_INTEGER_free -ASN1_INTEGER_get -ASN1_INTEGER_it -ASN1_INTEGER_new -ASN1_INTEGER_set -ASN1_INTEGER_set_uint64 -ASN1_INTEGER_to_BN -ASN1_NULL_free -ASN1_NULL_it -ASN1_NULL_new -ASN1_OBJECT_create -ASN1_OBJECT_free -ASN1_OBJECT_it -ASN1_OBJECT_new -ASN1_OCTET_STRING_NDEF_it -ASN1_OCTET_STRING_cmp -ASN1_OCTET_STRING_dup -ASN1_OCTET_STRING_free -ASN1_OCTET_STRING_it -ASN1_OCTET_STRING_new -ASN1_OCTET_STRING_set -ASN1_PRINTABLESTRING_free -ASN1_PRINTABLESTRING_it -ASN1_PRINTABLESTRING_new -ASN1_PRINTABLE_free -ASN1_PRINTABLE_it -ASN1_PRINTABLE_new -ASN1_PRINTABLE_type -ASN1_SEQUENCE_ANY_it -ASN1_SEQUENCE_it -ASN1_SET_ANY_it -ASN1_STRING_TABLE_add -ASN1_STRING_TABLE_cleanup -ASN1_STRING_TABLE_get -ASN1_STRING_cmp -ASN1_STRING_copy -ASN1_STRING_data -ASN1_STRING_dup -ASN1_STRING_free -ASN1_STRING_get0_data -ASN1_STRING_get_default_mask -ASN1_STRING_length -ASN1_STRING_length_set -ASN1_STRING_new -ASN1_STRING_print -ASN1_STRING_print_ex -ASN1_STRING_print_ex_fp -ASN1_STRING_set -ASN1_STRING_set0 -ASN1_STRING_set_by_NID -ASN1_STRING_set_default_mask -ASN1_STRING_set_default_mask_asc -ASN1_STRING_to_UTF8 -ASN1_STRING_type -ASN1_STRING_type_new -ASN1_T61STRING_free -ASN1_T61STRING_it -ASN1_T61STRING_new -ASN1_TBOOLEAN_it -ASN1_TIME_adj -ASN1_TIME_check -ASN1_TIME_diff -ASN1_TIME_free -ASN1_TIME_it -ASN1_TIME_new -ASN1_TIME_print -ASN1_TIME_set -ASN1_TIME_set_string -ASN1_TIME_to_generalizedtime -ASN1_TYPE_cmp -ASN1_TYPE_free -ASN1_TYPE_get -ASN1_TYPE_new -ASN1_TYPE_set -ASN1_TYPE_set1 -ASN1_UNIVERSALSTRING_free -ASN1_UNIVERSALSTRING_it -ASN1_UNIVERSALSTRING_new -ASN1_UTCTIME_adj -ASN1_UTCTIME_check -ASN1_UTCTIME_cmp_time_t -ASN1_UTCTIME_free -ASN1_UTCTIME_it -ASN1_UTCTIME_new -ASN1_UTCTIME_print -ASN1_UTCTIME_set -ASN1_UTCTIME_set_string -ASN1_UTF8STRING_free -ASN1_UTF8STRING_it -ASN1_UTF8STRING_new -ASN1_VISIBLESTRING_free -ASN1_VISIBLESTRING_it -ASN1_VISIBLESTRING_new -ASN1_digest -ASN1_generate_nconf -ASN1_generate_v3 -ASN1_get_object -ASN1_item_d2i -ASN1_item_d2i_bio -ASN1_item_d2i_fp -ASN1_item_digest -ASN1_item_dup -ASN1_item_ex_d2i -ASN1_item_ex_free -ASN1_item_ex_i2d -ASN1_item_ex_new -ASN1_item_free -ASN1_item_i2d -ASN1_item_i2d_bio -ASN1_item_i2d_fp -ASN1_item_ndef_i2d -ASN1_item_new -ASN1_item_pack -ASN1_item_sign -ASN1_item_sign_ctx -ASN1_item_unpack -ASN1_item_verify -ASN1_mbstring_copy -ASN1_mbstring_ncopy -ASN1_object_size -ASN1_primitive_free -ASN1_primitive_new -ASN1_put_eoc -ASN1_put_object -ASN1_tag2bit -ASN1_tag2str -ASN1_template_free -ASN1_template_new -AUTHORITY_INFO_ACCESS_free -AUTHORITY_INFO_ACCESS_it -AUTHORITY_INFO_ACCESS_new -AUTHORITY_KEYID_free -AUTHORITY_KEYID_it -AUTHORITY_KEYID_new -BASIC_CONSTRAINTS_free -BASIC_CONSTRAINTS_it -BASIC_CONSTRAINTS_new -BIO_append_filename -BIO_callback_ctrl -BIO_clear_flags -BIO_clear_retry_flags -BIO_copy_next_retry -BIO_ctrl -BIO_ctrl_get_read_request -BIO_ctrl_get_write_guarantee -BIO_ctrl_pending -BIO_do_connect -BIO_eof -BIO_f_ssl -BIO_find_type -BIO_flush -BIO_free -BIO_free_all -BIO_get_data -BIO_get_fd -BIO_get_fp -BIO_get_init -BIO_get_mem_data -BIO_get_mem_ptr -BIO_get_new_index -BIO_get_retry_flags -BIO_get_retry_reason -BIO_get_shutdown -BIO_gets -BIO_hexdump -BIO_indent -BIO_int_ctrl -BIO_mem_contents -BIO_meth_free -BIO_meth_new -BIO_meth_set_create -BIO_meth_set_ctrl -BIO_meth_set_destroy -BIO_meth_set_gets -BIO_meth_set_puts -BIO_meth_set_read -BIO_meth_set_write -BIO_method_type -BIO_new -BIO_new_bio_pair -BIO_new_connect -BIO_new_fd -BIO_new_file -BIO_new_fp -BIO_new_mem_buf -BIO_new_socket -BIO_next -BIO_number_read -BIO_number_written -BIO_pending -BIO_pop -BIO_printf -BIO_ptr_ctrl -BIO_push -BIO_puts -BIO_read -BIO_read_asn1 -BIO_read_filename -BIO_reset -BIO_rw_filename -BIO_s_connect -BIO_s_fd -BIO_s_file -BIO_s_mem -BIO_s_socket -BIO_set_close -BIO_set_conn_hostname -BIO_set_conn_int_port -BIO_set_conn_port -BIO_set_data -BIO_set_fd -BIO_set_flags -BIO_set_fp -BIO_set_init -BIO_set_mem_buf -BIO_set_mem_eof_return -BIO_set_nbio -BIO_set_retry_read -BIO_set_retry_special -BIO_set_retry_write -BIO_set_shutdown -BIO_set_ssl -BIO_set_write_buffer_size -BIO_should_io_special -BIO_should_read -BIO_should_retry -BIO_should_write -BIO_shutdown_wr -BIO_snprintf -BIO_test_flags -BIO_up_ref -BIO_vfree -BIO_vsnprintf -BIO_wpending -BIO_write -BIO_write_all -BIO_write_filename -BN_BLINDING_convert -BN_BLINDING_free -BN_BLINDING_invalidate -BN_BLINDING_invert -BN_BLINDING_new -BN_CTX_end -BN_CTX_free -BN_CTX_get -BN_CTX_new -BN_CTX_start -BN_GENCB_call -BN_GENCB_set -BN_MONT_CTX_copy -BN_MONT_CTX_free -BN_MONT_CTX_new -BN_MONT_CTX_new_consttime -BN_MONT_CTX_new_for_modulus -BN_MONT_CTX_set -BN_MONT_CTX_set_locked -BN_abs_is_word -BN_add -BN_add_word -BN_asc2bn -BN_bin2bn -BN_bn2bin -BN_bn2bin_padded -BN_bn2binpad -BN_bn2cbb_padded -BN_bn2dec -BN_bn2hex -BN_bn2le_padded -BN_bn2mpi -BN_clear -BN_clear_bit -BN_clear_free -BN_cmp -BN_cmp_word -BN_copy -BN_count_low_zero_bits -BN_dec2bn -BN_div -BN_div_word -BN_dup -BN_enhanced_miller_rabin_primality_test -BN_equal_consttime -BN_exp -BN_free -BN_from_montgomery -BN_gcd -BN_generate_prime_ex -BN_get_rfc3526_prime_1536 -BN_get_u64 -BN_get_word -BN_hex2bn -BN_init -BN_is_bit_set -BN_is_negative -BN_is_odd -BN_is_one -BN_is_pow2 -BN_is_prime_ex -BN_is_prime_fasttest_ex -BN_is_word -BN_is_zero -BN_le2bn -BN_lshift -BN_lshift1 -BN_marshal_asn1 -BN_mask_bits -BN_mod_add -BN_mod_add_quick -BN_mod_exp -BN_mod_exp2_mont -BN_mod_exp_mont -BN_mod_exp_mont_consttime -BN_mod_exp_mont_word -BN_mod_inverse -BN_mod_inverse_blinded -BN_mod_inverse_odd -BN_mod_lshift -BN_mod_lshift1 -BN_mod_lshift1_quick -BN_mod_lshift_quick -BN_mod_mul -BN_mod_mul_montgomery -BN_mod_pow2 -BN_mod_sqr -BN_mod_sqrt -BN_mod_sub -BN_mod_sub_quick -BN_mod_word -BN_mpi2bn -BN_mul -BN_mul_word -BN_new -BN_nnmod -BN_nnmod_pow2 -BN_num_bits -BN_num_bits_word -BN_num_bytes -BN_one -BN_parse_asn1_unsigned -BN_primality_test -BN_print -BN_print_fp -BN_pseudo_rand -BN_pseudo_rand_range -BN_rand -BN_rand_range -BN_rand_range_ex -BN_rshift -BN_rshift1 -BN_set_bit -BN_set_negative -BN_set_u64 -BN_set_word -BN_sqr -BN_sqrt -BN_sub -BN_sub_word -BN_to_ASN1_ENUMERATED -BN_to_ASN1_INTEGER -BN_to_montgomery -BN_uadd -BN_ucmp -BN_usub -BN_value_one -BN_zero -BORINGSSL_self_test -BUF_MEM_append -BUF_MEM_free -BUF_MEM_grow -BUF_MEM_grow_clean -BUF_MEM_new -BUF_MEM_reserve -BUF_memdup -BUF_strdup -BUF_strlcat -BUF_strlcpy -BUF_strndup -BUF_strnlen -CBB_add_asn1 -CBB_add_asn1_bool -CBB_add_asn1_int64 -CBB_add_asn1_octet_string -CBB_add_asn1_oid_from_text -CBB_add_asn1_uint64 -CBB_add_bytes -CBB_add_space -CBB_add_u16 -CBB_add_u16_length_prefixed -CBB_add_u16le -CBB_add_u24 -CBB_add_u24_length_prefixed -CBB_add_u32 -CBB_add_u32le -CBB_add_u64 -CBB_add_u64le -CBB_add_u8 -CBB_add_u8_length_prefixed -CBB_cleanup -CBB_data -CBB_did_write -CBB_discard_child -CBB_finish -CBB_finish_i2d -CBB_flush -CBB_flush_asn1_set_of -CBB_init -CBB_init_fixed -CBB_len -CBB_reserve -CBB_zero -CBS_asn1_ber_to_der -CBS_asn1_bitstring_has_bit -CBS_asn1_oid_to_text -CBS_contains_zero_byte -CBS_copy_bytes -CBS_data -CBS_get_any_asn1 -CBS_get_any_asn1_element -CBS_get_any_ber_asn1_element -CBS_get_asn1 -CBS_get_asn1_bool -CBS_get_asn1_element -CBS_get_asn1_implicit_string -CBS_get_asn1_int64 -CBS_get_asn1_uint64 -CBS_get_bytes -CBS_get_last_u8 -CBS_get_optional_asn1 -CBS_get_optional_asn1_bool -CBS_get_optional_asn1_octet_string -CBS_get_optional_asn1_uint64 -CBS_get_u16 -CBS_get_u16_length_prefixed -CBS_get_u16le -CBS_get_u24 -CBS_get_u24_length_prefixed -CBS_get_u32 -CBS_get_u32le -CBS_get_u64 -CBS_get_u64le -CBS_get_u8 -CBS_get_u8_length_prefixed -CBS_init -CBS_is_valid_asn1_bitstring -CBS_len -CBS_mem_equal -CBS_peek_asn1_tag -CBS_skip -CBS_stow -CBS_strdup -CERTIFICATEPOLICIES_free -CERTIFICATEPOLICIES_it -CERTIFICATEPOLICIES_new -CMAC_CTX_copy -CMAC_CTX_free -CMAC_CTX_new -CMAC_Final -CMAC_Init -CMAC_Reset -CMAC_Update -CONF_VALUE_new -CONF_modules_free -CONF_modules_load_file -CONF_parse_list -CRL_DIST_POINTS_free -CRL_DIST_POINTS_it -CRL_DIST_POINTS_new -CRYPTO_BUFFER_POOL_free -CRYPTO_BUFFER_POOL_new -CRYPTO_BUFFER_alloc -CRYPTO_BUFFER_data -CRYPTO_BUFFER_free -CRYPTO_BUFFER_init_CBS -CRYPTO_BUFFER_len -CRYPTO_BUFFER_new -CRYPTO_BUFFER_new_from_CBS -CRYPTO_BUFFER_up_ref -CRYPTO_MUTEX_cleanup -CRYPTO_MUTEX_init -CRYPTO_MUTEX_lock_read -CRYPTO_MUTEX_lock_write -CRYPTO_MUTEX_unlock_read -CRYPTO_MUTEX_unlock_write -CRYPTO_POLYVAL_finish -CRYPTO_POLYVAL_init -CRYPTO_POLYVAL_update_blocks -CRYPTO_STATIC_MUTEX_lock_read -CRYPTO_STATIC_MUTEX_lock_write -CRYPTO_STATIC_MUTEX_unlock_read -CRYPTO_STATIC_MUTEX_unlock_write -CRYPTO_THREADID_current -CRYPTO_THREADID_set_callback -CRYPTO_THREADID_set_numeric -CRYPTO_THREADID_set_pointer -CRYPTO_cbc128_decrypt -CRYPTO_cbc128_encrypt -CRYPTO_cfb128_1_encrypt -CRYPTO_cfb128_8_encrypt -CRYPTO_cfb128_encrypt -CRYPTO_chacha_20 -CRYPTO_cleanup_all_ex_data -CRYPTO_ctr128_encrypt -CRYPTO_ctr128_encrypt_ctr32 -CRYPTO_free_ex_data -CRYPTO_gcm128_aad -CRYPTO_gcm128_decrypt -CRYPTO_gcm128_decrypt_ctr32 -CRYPTO_gcm128_encrypt -CRYPTO_gcm128_encrypt_ctr32 -CRYPTO_gcm128_finish -CRYPTO_gcm128_init_key -CRYPTO_gcm128_setiv -CRYPTO_gcm128_tag -CRYPTO_get_dynlock_create_callback -CRYPTO_get_dynlock_destroy_callback -CRYPTO_get_dynlock_lock_callback -CRYPTO_get_ex_data -CRYPTO_get_ex_new_index -CRYPTO_get_fork_generation -CRYPTO_get_lock_name -CRYPTO_get_locking_callback -CRYPTO_get_thread_local -CRYPTO_ghash_init -CRYPTO_has_asm -CRYPTO_hchacha20 -CRYPTO_init_sysrand -CRYPTO_is_confidential_build -CRYPTO_library_init -CRYPTO_malloc_init -CRYPTO_memcmp -CRYPTO_new_ex_data -CRYPTO_num_locks -CRYPTO_ofb128_encrypt -CRYPTO_once -CRYPTO_poly1305_finish -CRYPTO_poly1305_init -CRYPTO_poly1305_update -CRYPTO_pre_sandbox_init -CRYPTO_refcount_dec_and_test_zero -CRYPTO_refcount_inc -CRYPTO_set_add_lock_callback -CRYPTO_set_dynlock_create_callback -CRYPTO_set_dynlock_destroy_callback -CRYPTO_set_dynlock_lock_callback -CRYPTO_set_ex_data -CRYPTO_set_id_callback -CRYPTO_set_locking_callback -CRYPTO_set_thread_local -CRYPTO_sysrand -CRYPTO_sysrand_if_available -CRYPTO_tls1_prf -CTR_DRBG_clear -CTR_DRBG_generate -CTR_DRBG_init -CTR_DRBG_reseed -ChaCha20_ctr32 -DES_decrypt3 -DES_ecb3_encrypt -DES_ecb_encrypt -DES_ede2_cbc_encrypt -DES_ede3_cbc_encrypt -DES_encrypt3 -DES_ncbc_encrypt -DES_set_key -DES_set_key_unchecked -DES_set_odd_parity -DH_check -DH_check_pub_key -DH_compute_key -DH_free -DH_generate_key -DH_generate_parameters_ex -DH_get0_g -DH_get0_key -DH_get0_p -DH_get0_pqg -DH_get0_priv_key -DH_get0_pub_key -DH_get0_q -DH_get_ex_data -DH_get_ex_new_index -DH_marshal_parameters -DH_new -DH_num_bits -DH_parse_parameters -DH_set0_key -DH_set0_pqg -DH_set_ex_data -DH_set_length -DH_size -DH_up_ref -DHparams_dup -DIRECTORYSTRING_free -DIRECTORYSTRING_it -DIRECTORYSTRING_new -DISPLAYTEXT_free -DISPLAYTEXT_it -DISPLAYTEXT_new -DIST_POINT_NAME_free -DIST_POINT_NAME_it -DIST_POINT_NAME_new -DIST_POINT_free -DIST_POINT_it -DIST_POINT_new -DIST_POINT_set_dpname -DSA_SIG_free -DSA_SIG_marshal -DSA_SIG_new -DSA_SIG_parse -DSA_check_signature -DSA_do_check_signature -DSA_do_sign -DSA_do_verify -DSA_dup_DH -DSA_free -DSA_generate_key -DSA_generate_parameters_ex -DSA_get0_g -DSA_get0_key -DSA_get0_p -DSA_get0_pqg -DSA_get0_priv_key -DSA_get0_pub_key -DSA_get0_q -DSA_get_ex_data -DSA_get_ex_new_index -DSA_marshal_parameters -DSA_marshal_private_key -DSA_marshal_public_key -DSA_new -DSA_parse_parameters -DSA_parse_private_key -DSA_parse_public_key -DSA_set0_key -DSA_set0_pqg -DSA_set_ex_data -DSA_sign -DSA_size -DSA_up_ref -DSA_verify -DSAparams_dup -DTLS_client_method -DTLS_method -DTLS_server_method -DTLS_with_buffers_method -DTLSv1_2_client_method -DTLSv1_2_method -DTLSv1_2_server_method -DTLSv1_client_method -DTLSv1_get_timeout -DTLSv1_handle_timeout -DTLSv1_method -DTLSv1_server_method -DTLSv1_set_initial_timeout_duration -ECDH_compute_key -ECDH_compute_key_fips -ECDSA_SIG_free -ECDSA_SIG_from_bytes -ECDSA_SIG_get0 -ECDSA_SIG_get0_r -ECDSA_SIG_get0_s -ECDSA_SIG_marshal -ECDSA_SIG_max_len -ECDSA_SIG_new -ECDSA_SIG_parse -ECDSA_SIG_set0 -ECDSA_SIG_to_bytes -ECDSA_do_sign -ECDSA_do_verify -ECDSA_sign -ECDSA_size -ECDSA_verify -EC_GFp_mont_method -EC_GFp_nistp256_method -EC_GROUP_cmp -EC_GROUP_dup -EC_GROUP_free -EC_GROUP_get0_generator -EC_GROUP_get0_order -EC_GROUP_get_cofactor -EC_GROUP_get_curve_GFp -EC_GROUP_get_curve_name -EC_GROUP_get_degree -EC_GROUP_get_order -EC_GROUP_method_of -EC_GROUP_new_by_curve_name -EC_GROUP_new_curve_GFp -EC_GROUP_order_bits -EC_GROUP_set_asn1_flag -EC_GROUP_set_generator -EC_GROUP_set_point_conversion_form -EC_KEY_check_fips -EC_KEY_check_key -EC_KEY_derive_from_secret -EC_KEY_dup -EC_KEY_free -EC_KEY_generate_key -EC_KEY_generate_key_fips -EC_KEY_get0_group -EC_KEY_get0_private_key -EC_KEY_get0_public_key -EC_KEY_get_conv_form -EC_KEY_get_enc_flags -EC_KEY_get_ex_data -EC_KEY_get_ex_new_index -EC_KEY_is_opaque -EC_KEY_key2buf -EC_KEY_marshal_curve_name -EC_KEY_marshal_private_key -EC_KEY_new -EC_KEY_new_by_curve_name -EC_KEY_new_method -EC_KEY_parse_curve_name -EC_KEY_parse_parameters -EC_KEY_parse_private_key -EC_KEY_set_asn1_flag -EC_KEY_set_conv_form -EC_KEY_set_enc_flags -EC_KEY_set_ex_data -EC_KEY_set_group -EC_KEY_set_private_key -EC_KEY_set_public_key -EC_KEY_set_public_key_affine_coordinates -EC_KEY_up_ref -EC_METHOD_get_field_type -EC_POINT_add -EC_POINT_clear_free -EC_POINT_cmp -EC_POINT_copy -EC_POINT_dbl -EC_POINT_dup -EC_POINT_free -EC_POINT_get_affine_coordinates_GFp -EC_POINT_invert -EC_POINT_is_at_infinity -EC_POINT_is_on_curve -EC_POINT_mul -EC_POINT_new -EC_POINT_oct2point -EC_POINT_point2cbb -EC_POINT_point2oct -EC_POINT_set_affine_coordinates_GFp -EC_POINT_set_compressed_coordinates_GFp -EC_POINT_set_to_infinity -EC_curve_nid2nist -EC_curve_nist2nid -EC_get_builtin_curves -ED25519_keypair -ED25519_keypair_from_seed -ED25519_sign -ED25519_verify -EDIPARTYNAME_free -EDIPARTYNAME_it -EDIPARTYNAME_new -ENGINE_free -ENGINE_get_ECDSA_method -ENGINE_get_RSA_method -ENGINE_load_builtin_engines -ENGINE_new -ENGINE_register_all_complete -ENGINE_set_ECDSA_method -ENGINE_set_RSA_method -ERR_SAVE_STATE_free -ERR_add_error_data -ERR_add_error_dataf -ERR_clear_error -ERR_clear_system_error -ERR_error_string -ERR_error_string_n -ERR_free_strings -ERR_func_error_string -ERR_get_error -ERR_get_error_line -ERR_get_error_line_data -ERR_get_next_error_library -ERR_lib_error_string -ERR_load_BIO_strings -ERR_load_ERR_strings -ERR_load_RAND_strings -ERR_load_SSL_strings -ERR_load_crypto_strings -ERR_peek_error -ERR_peek_error_line -ERR_peek_error_line_data -ERR_peek_last_error -ERR_peek_last_error_line -ERR_peek_last_error_line_data -ERR_pop_to_mark -ERR_print_errors -ERR_print_errors_cb -ERR_print_errors_fp -ERR_put_error -ERR_reason_error_string -ERR_remove_state -ERR_remove_thread_state -ERR_restore_state -ERR_save_state -ERR_set_mark -EVP_AEAD_CTX_aead -EVP_AEAD_CTX_cleanup -EVP_AEAD_CTX_free -EVP_AEAD_CTX_get_iv -EVP_AEAD_CTX_init -EVP_AEAD_CTX_init_with_direction -EVP_AEAD_CTX_new -EVP_AEAD_CTX_open -EVP_AEAD_CTX_open_gather -EVP_AEAD_CTX_seal -EVP_AEAD_CTX_seal_scatter -EVP_AEAD_CTX_tag_len -EVP_AEAD_CTX_zero -EVP_AEAD_key_length -EVP_AEAD_max_overhead -EVP_AEAD_max_tag_len -EVP_AEAD_nonce_length -EVP_BytesToKey -EVP_CIPHER_CTX_block_size -EVP_CIPHER_CTX_cipher -EVP_CIPHER_CTX_cleanup -EVP_CIPHER_CTX_copy -EVP_CIPHER_CTX_ctrl -EVP_CIPHER_CTX_encrypting -EVP_CIPHER_CTX_flags -EVP_CIPHER_CTX_free -EVP_CIPHER_CTX_get_app_data -EVP_CIPHER_CTX_init -EVP_CIPHER_CTX_iv_length -EVP_CIPHER_CTX_key_length -EVP_CIPHER_CTX_mode -EVP_CIPHER_CTX_new -EVP_CIPHER_CTX_nid -EVP_CIPHER_CTX_reset -EVP_CIPHER_CTX_set_app_data -EVP_CIPHER_CTX_set_flags -EVP_CIPHER_CTX_set_key_length -EVP_CIPHER_CTX_set_padding -EVP_CIPHER_block_size -EVP_CIPHER_flags -EVP_CIPHER_iv_length -EVP_CIPHER_key_length -EVP_CIPHER_mode -EVP_CIPHER_nid -EVP_Cipher -EVP_CipherFinal_ex -EVP_CipherInit -EVP_CipherInit_ex -EVP_CipherUpdate -EVP_DecodeBase64 -EVP_DecodeBlock -EVP_DecodeFinal -EVP_DecodeInit -EVP_DecodeUpdate -EVP_DecodedLength -EVP_DecryptFinal_ex -EVP_DecryptInit -EVP_DecryptInit_ex -EVP_DecryptUpdate -EVP_Digest -EVP_DigestFinal -EVP_DigestFinalXOF -EVP_DigestFinal_ex -EVP_DigestInit -EVP_DigestInit_ex -EVP_DigestSign -EVP_DigestSignFinal -EVP_DigestSignInit -EVP_DigestSignUpdate -EVP_DigestUpdate -EVP_DigestVerify -EVP_DigestVerifyFinal -EVP_DigestVerifyInit -EVP_DigestVerifyUpdate -EVP_EncodeBlock -EVP_EncodeFinal -EVP_EncodeInit -EVP_EncodeUpdate -EVP_EncodedLength -EVP_EncryptFinal_ex -EVP_EncryptInit -EVP_EncryptInit_ex -EVP_EncryptUpdate -EVP_MD_CTX_block_size -EVP_MD_CTX_cleanup -EVP_MD_CTX_copy -EVP_MD_CTX_copy_ex -EVP_MD_CTX_create -EVP_MD_CTX_destroy -EVP_MD_CTX_free -EVP_MD_CTX_init -EVP_MD_CTX_md -EVP_MD_CTX_new -EVP_MD_CTX_reset -EVP_MD_CTX_size -EVP_MD_CTX_type -EVP_MD_block_size -EVP_MD_flags -EVP_MD_meth_get_flags -EVP_MD_size -EVP_MD_type -EVP_PBE_scrypt -EVP_PKCS82PKEY -EVP_PKEY2PKCS8 -EVP_PKEY_CTX_ctrl -EVP_PKEY_CTX_dup -EVP_PKEY_CTX_free -EVP_PKEY_CTX_get0_pkey -EVP_PKEY_CTX_get0_rsa_oaep_label -EVP_PKEY_CTX_get_rsa_mgf1_md -EVP_PKEY_CTX_get_rsa_oaep_md -EVP_PKEY_CTX_get_rsa_padding -EVP_PKEY_CTX_get_rsa_pss_saltlen -EVP_PKEY_CTX_get_signature_md -EVP_PKEY_CTX_new -EVP_PKEY_CTX_new_id -EVP_PKEY_CTX_set0_rsa_oaep_label -EVP_PKEY_CTX_set_ec_param_enc -EVP_PKEY_CTX_set_ec_paramgen_curve_nid -EVP_PKEY_CTX_set_rsa_keygen_bits -EVP_PKEY_CTX_set_rsa_keygen_pubexp -EVP_PKEY_CTX_set_rsa_mgf1_md -EVP_PKEY_CTX_set_rsa_oaep_md -EVP_PKEY_CTX_set_rsa_padding -EVP_PKEY_CTX_set_rsa_pss_keygen_md -EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md -EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen -EVP_PKEY_CTX_set_rsa_pss_saltlen -EVP_PKEY_CTX_set_signature_md -EVP_PKEY_assign -EVP_PKEY_assign_DSA -EVP_PKEY_assign_EC_KEY -EVP_PKEY_assign_RSA -EVP_PKEY_base_id -EVP_PKEY_bits -EVP_PKEY_cmp -EVP_PKEY_cmp_parameters -EVP_PKEY_copy_parameters -EVP_PKEY_decrypt -EVP_PKEY_decrypt_init -EVP_PKEY_derive -EVP_PKEY_derive_init -EVP_PKEY_derive_set_peer -EVP_PKEY_encrypt -EVP_PKEY_encrypt_init -EVP_PKEY_free -EVP_PKEY_get0_DH -EVP_PKEY_get0_DSA -EVP_PKEY_get0_EC_KEY -EVP_PKEY_get0_RSA -EVP_PKEY_get1_DH -EVP_PKEY_get1_DSA -EVP_PKEY_get1_EC_KEY -EVP_PKEY_get1_RSA -EVP_PKEY_get1_tls_encodedpoint -EVP_PKEY_get_raw_private_key -EVP_PKEY_get_raw_public_key -EVP_PKEY_id -EVP_PKEY_is_opaque -EVP_PKEY_keygen -EVP_PKEY_keygen_init -EVP_PKEY_missing_parameters -EVP_PKEY_new -EVP_PKEY_new_raw_private_key -EVP_PKEY_new_raw_public_key -EVP_PKEY_paramgen -EVP_PKEY_paramgen_init -EVP_PKEY_print_params -EVP_PKEY_print_private -EVP_PKEY_print_public -EVP_PKEY_set1_DSA -EVP_PKEY_set1_EC_KEY -EVP_PKEY_set1_RSA -EVP_PKEY_set1_tls_encodedpoint -EVP_PKEY_set_type -EVP_PKEY_sign -EVP_PKEY_sign_init -EVP_PKEY_size -EVP_PKEY_type -EVP_PKEY_up_ref -EVP_PKEY_verify -EVP_PKEY_verify_init -EVP_PKEY_verify_recover -EVP_PKEY_verify_recover_init -EVP_SignFinal -EVP_SignInit -EVP_SignInit_ex -EVP_SignUpdate -EVP_VerifyFinal -EVP_VerifyInit -EVP_VerifyInit_ex -EVP_VerifyUpdate -EVP_add_cipher_alias -EVP_add_digest -EVP_aead_aes_128_cbc_sha1_tls -EVP_aead_aes_128_cbc_sha1_tls_implicit_iv -EVP_aead_aes_128_cbc_sha256_tls -EVP_aead_aes_128_ccm_bluetooth -EVP_aead_aes_128_ccm_bluetooth_8 -EVP_aead_aes_128_ctr_hmac_sha256 -EVP_aead_aes_128_gcm -EVP_aead_aes_128_gcm_siv -EVP_aead_aes_128_gcm_tls12 -EVP_aead_aes_128_gcm_tls13 -EVP_aead_aes_192_gcm -EVP_aead_aes_256_cbc_sha1_tls -EVP_aead_aes_256_cbc_sha1_tls_implicit_iv -EVP_aead_aes_256_cbc_sha256_tls -EVP_aead_aes_256_cbc_sha384_tls -EVP_aead_aes_256_ctr_hmac_sha256 -EVP_aead_aes_256_gcm -EVP_aead_aes_256_gcm_siv -EVP_aead_aes_256_gcm_tls12 -EVP_aead_aes_256_gcm_tls13 -EVP_aead_chacha20_poly1305 -EVP_aead_des_ede3_cbc_sha1_tls -EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv -EVP_aead_null_sha1_tls -EVP_aead_xchacha20_poly1305 -EVP_aes_128_cbc -EVP_aes_128_ctr -EVP_aes_128_ecb -EVP_aes_128_gcm -EVP_aes_128_ofb -EVP_aes_192_cbc -EVP_aes_192_ctr -EVP_aes_192_ecb -EVP_aes_192_gcm -EVP_aes_192_ofb -EVP_aes_256_cbc -EVP_aes_256_ctr -EVP_aes_256_ecb -EVP_aes_256_gcm -EVP_aes_256_ofb -EVP_cleanup -EVP_des_cbc -EVP_des_ecb -EVP_des_ede -EVP_des_ede3 -EVP_des_ede3_cbc -EVP_des_ede3_ecb -EVP_des_ede_cbc -EVP_enc_null -EVP_get_cipherbyname -EVP_get_cipherbynid -EVP_get_digestbyname -EVP_get_digestbynid -EVP_get_digestbyobj -EVP_has_aes_hardware -EVP_marshal_digest_algorithm -EVP_marshal_private_key -EVP_marshal_public_key -EVP_md4 -EVP_md5 -EVP_md5_sha1 -EVP_parse_digest_algorithm -EVP_parse_private_key -EVP_parse_public_key -EVP_rc2_40_cbc -EVP_rc2_cbc -EVP_rc4 -EVP_sha1 -EVP_sha224 -EVP_sha256 -EVP_sha384 -EVP_sha512 -EVP_sha512_256 -EVP_tls_cbc_copy_mac -EVP_tls_cbc_digest_record -EVP_tls_cbc_record_digest_supported -EVP_tls_cbc_remove_padding -EXTENDED_KEY_USAGE_free -EXTENDED_KEY_USAGE_it -EXTENDED_KEY_USAGE_new -FIPS_mode -FIPS_mode_set -GENERAL_NAMES_free -GENERAL_NAMES_it -GENERAL_NAMES_new -GENERAL_NAME_cmp -GENERAL_NAME_dup -GENERAL_NAME_free -GENERAL_NAME_get0_otherName -GENERAL_NAME_get0_value -GENERAL_NAME_it -GENERAL_NAME_new -GENERAL_NAME_print -GENERAL_NAME_set0_othername -GENERAL_NAME_set0_value -GENERAL_SUBTREE_free -GENERAL_SUBTREE_it -GENERAL_SUBTREE_new -HKDF -HKDF_expand -HKDF_extract -HMAC -HMAC_CTX_cleanup -HMAC_CTX_copy -HMAC_CTX_copy_ex -HMAC_CTX_free -HMAC_CTX_init -HMAC_CTX_new -HMAC_CTX_reset -HMAC_Final -HMAC_Init -HMAC_Init_ex -HMAC_Update -HMAC_size -HRSS_decap -HRSS_encap -HRSS_generate_key -HRSS_marshal_public_key -HRSS_parse_public_key -HRSS_poly3_invert -HRSS_poly3_mul -ISSUING_DIST_POINT_free -ISSUING_DIST_POINT_it -ISSUING_DIST_POINT_new -MD4 -MD4_Final -MD4_Init -MD4_Transform -MD4_Update -MD5 -MD5_Final -MD5_Init -MD5_Transform -MD5_Update -METHOD_ref -METHOD_unref -NAME_CONSTRAINTS_check -NAME_CONSTRAINTS_free -NAME_CONSTRAINTS_it -NAME_CONSTRAINTS_new -NCONF_free -NCONF_get_section -NCONF_get_string -NCONF_load -NCONF_load_bio -NCONF_new -NETSCAPE_SPKAC_free -NETSCAPE_SPKAC_it -NETSCAPE_SPKAC_new -NETSCAPE_SPKI_b64_decode -NETSCAPE_SPKI_b64_encode -NETSCAPE_SPKI_free -NETSCAPE_SPKI_get_pubkey -NETSCAPE_SPKI_it -NETSCAPE_SPKI_new -NETSCAPE_SPKI_set_pubkey -NETSCAPE_SPKI_sign -NETSCAPE_SPKI_verify -NOTICEREF_free -NOTICEREF_it -NOTICEREF_new -OBJ_cbs2nid -OBJ_cleanup -OBJ_cmp -OBJ_create -OBJ_dup -OBJ_find_sigid_algs -OBJ_find_sigid_by_algs -OBJ_get0_data -OBJ_length -OBJ_ln2nid -OBJ_nid2cbb -OBJ_nid2ln -OBJ_nid2obj -OBJ_nid2sn -OBJ_obj2nid -OBJ_obj2txt -OBJ_sn2nid -OBJ_txt2nid -OBJ_txt2obj -OPENSSL_add_all_algorithms_conf -OPENSSL_armcap_P -OPENSSL_built_in_curves -OPENSSL_cleanse -OPENSSL_cleanup -OPENSSL_clear_free -OPENSSL_config -OPENSSL_free -OPENSSL_gmtime -OPENSSL_gmtime_adj -OPENSSL_gmtime_diff -OPENSSL_hash32 -OPENSSL_init_crypto -OPENSSL_init_ssl -OPENSSL_load_builtin_modules -OPENSSL_malloc -OPENSSL_malloc_init -OPENSSL_memdup -OPENSSL_no_config -OPENSSL_realloc -OPENSSL_strcasecmp -OPENSSL_strdup -OPENSSL_strlcat -OPENSSL_strlcpy -OPENSSL_strncasecmp -OPENSSL_strndup -OPENSSL_strnlen -OPENSSL_tolower -OTHERNAME_cmp -OTHERNAME_free -OTHERNAME_it -OTHERNAME_new -OpenSSL_add_all_algorithms -OpenSSL_add_all_ciphers -OpenSSL_add_all_digests -OpenSSL_version -OpenSSL_version_num -PEM_ASN1_read -PEM_ASN1_read_bio -PEM_ASN1_write -PEM_ASN1_write_bio -PEM_X509_INFO_read -PEM_X509_INFO_read_bio -PEM_X509_INFO_write_bio -PEM_bytes_read_bio -PEM_def_callback -PEM_dek_info -PEM_do_header -PEM_get_EVP_CIPHER_INFO -PEM_proc_type -PEM_read -PEM_read_DHparams -PEM_read_DSAPrivateKey -PEM_read_DSA_PUBKEY -PEM_read_DSAparams -PEM_read_ECPrivateKey -PEM_read_EC_PUBKEY -PEM_read_PKCS7 -PEM_read_PKCS8 -PEM_read_PKCS8_PRIV_KEY_INFO -PEM_read_PUBKEY -PEM_read_PrivateKey -PEM_read_RSAPrivateKey -PEM_read_RSAPublicKey -PEM_read_RSA_PUBKEY -PEM_read_SSL_SESSION -PEM_read_X509 -PEM_read_X509_AUX -PEM_read_X509_CRL -PEM_read_X509_REQ -PEM_read_bio -PEM_read_bio_DHparams -PEM_read_bio_DSAPrivateKey -PEM_read_bio_DSA_PUBKEY -PEM_read_bio_DSAparams -PEM_read_bio_ECPrivateKey -PEM_read_bio_EC_PUBKEY -PEM_read_bio_PKCS7 -PEM_read_bio_PKCS8 -PEM_read_bio_PKCS8_PRIV_KEY_INFO -PEM_read_bio_PUBKEY -PEM_read_bio_PrivateKey -PEM_read_bio_RSAPrivateKey -PEM_read_bio_RSAPublicKey -PEM_read_bio_RSA_PUBKEY -PEM_read_bio_SSL_SESSION -PEM_read_bio_X509 -PEM_read_bio_X509_AUX -PEM_read_bio_X509_CRL -PEM_read_bio_X509_REQ -PEM_write -PEM_write_DHparams -PEM_write_DSAPrivateKey -PEM_write_DSA_PUBKEY -PEM_write_DSAparams -PEM_write_ECPrivateKey -PEM_write_EC_PUBKEY -PEM_write_PKCS7 -PEM_write_PKCS8 -PEM_write_PKCS8PrivateKey -PEM_write_PKCS8PrivateKey_nid -PEM_write_PKCS8_PRIV_KEY_INFO -PEM_write_PUBKEY -PEM_write_PrivateKey -PEM_write_RSAPrivateKey -PEM_write_RSAPublicKey -PEM_write_RSA_PUBKEY -PEM_write_SSL_SESSION -PEM_write_X509 -PEM_write_X509_AUX -PEM_write_X509_CRL -PEM_write_X509_REQ -PEM_write_X509_REQ_NEW -PEM_write_bio -PEM_write_bio_DHparams -PEM_write_bio_DSAPrivateKey -PEM_write_bio_DSA_PUBKEY -PEM_write_bio_DSAparams -PEM_write_bio_ECPrivateKey -PEM_write_bio_EC_PUBKEY -PEM_write_bio_PKCS7 -PEM_write_bio_PKCS8 -PEM_write_bio_PKCS8PrivateKey -PEM_write_bio_PKCS8PrivateKey_nid -PEM_write_bio_PKCS8_PRIV_KEY_INFO -PEM_write_bio_PUBKEY -PEM_write_bio_PrivateKey -PEM_write_bio_RSAPrivateKey -PEM_write_bio_RSAPublicKey -PEM_write_bio_RSA_PUBKEY -PEM_write_bio_SSL_SESSION -PEM_write_bio_X509 -PEM_write_bio_X509_AUX -PEM_write_bio_X509_CRL -PEM_write_bio_X509_REQ -PEM_write_bio_X509_REQ_NEW -PKCS12_PBE_add -PKCS12_create -PKCS12_free -PKCS12_get_key_and_certs -PKCS12_parse -PKCS12_verify_mac -PKCS5_PBKDF2_HMAC -PKCS5_PBKDF2_HMAC_SHA1 -PKCS5_pbe2_decrypt_init -PKCS5_pbe2_encrypt_init -PKCS7_bundle_CRLs -PKCS7_bundle_certificates -PKCS7_free -PKCS7_get_CRLs -PKCS7_get_PEM_CRLs -PKCS7_get_PEM_certificates -PKCS7_get_certificates -PKCS7_get_raw_certificates -PKCS7_sign -PKCS7_type_is_data -PKCS7_type_is_digest -PKCS7_type_is_encrypted -PKCS7_type_is_enveloped -PKCS7_type_is_signed -PKCS7_type_is_signedAndEnveloped -PKCS8_PRIV_KEY_INFO_free -PKCS8_PRIV_KEY_INFO_it -PKCS8_PRIV_KEY_INFO_new -PKCS8_decrypt -PKCS8_encrypt -PKCS8_marshal_encrypted_private_key -PKCS8_parse_encrypted_private_key -PKCS8_pkey_get0 -PKCS8_pkey_set0 -PKEY_USAGE_PERIOD_free -PKEY_USAGE_PERIOD_it -PKEY_USAGE_PERIOD_new -PMBTOKEN_PRETOKEN_free -POLICYINFO_free -POLICYINFO_it -POLICYINFO_new -POLICYQUALINFO_free -POLICYQUALINFO_it -POLICYQUALINFO_new -POLICY_CONSTRAINTS_free -POLICY_CONSTRAINTS_it -POLICY_CONSTRAINTS_new -POLICY_MAPPINGS_it -POLICY_MAPPING_free -POLICY_MAPPING_it -POLICY_MAPPING_new -PROXY_CERT_INFO_EXTENSION_free -PROXY_CERT_INFO_EXTENSION_it -PROXY_CERT_INFO_EXTENSION_new -PROXY_POLICY_free -PROXY_POLICY_it -PROXY_POLICY_new -RAND_SSLeay -RAND_add -RAND_bytes -RAND_bytes_with_additional_data -RAND_cleanup -RAND_egd -RAND_enable_fork_unsafe_buffering -RAND_file_name -RAND_get_rand_method -RAND_load_file -RAND_poll -RAND_pseudo_bytes -RAND_seed -RAND_set_rand_method -RAND_status -RC4 -RC4_set_key -RSAPrivateKey_dup -RSAPublicKey_dup -RSA_PSS_PARAMS_free -RSA_PSS_PARAMS_it -RSA_PSS_PARAMS_new -RSA_add_pkcs1_prefix -RSA_bits -RSA_blinding_on -RSA_check_fips -RSA_check_key -RSA_decrypt -RSA_default_method -RSA_encrypt -RSA_flags -RSA_free -RSA_generate_key_ex -RSA_generate_key_fips -RSA_get0_crt_params -RSA_get0_d -RSA_get0_dmp1 -RSA_get0_dmq1 -RSA_get0_e -RSA_get0_factors -RSA_get0_iqmp -RSA_get0_key -RSA_get0_n -RSA_get0_p -RSA_get0_q -RSA_get_ex_data -RSA_get_ex_new_index -RSA_is_opaque -RSA_marshal_private_key -RSA_marshal_public_key -RSA_new -RSA_new_method -RSA_padding_add_PKCS1_OAEP_mgf1 -RSA_padding_add_PKCS1_PSS_mgf1 -RSA_padding_add_PKCS1_type_1 -RSA_padding_add_PKCS1_type_2 -RSA_padding_add_none -RSA_padding_check_PKCS1_OAEP_mgf1 -RSA_padding_check_PKCS1_type_1 -RSA_padding_check_PKCS1_type_2 -RSA_parse_private_key -RSA_parse_public_key -RSA_print -RSA_private_decrypt -RSA_private_encrypt -RSA_private_key_from_bytes -RSA_private_key_to_bytes -RSA_private_transform -RSA_public_decrypt -RSA_public_encrypt -RSA_public_key_from_bytes -RSA_public_key_to_bytes -RSA_set0_crt_params -RSA_set0_factors -RSA_set0_key -RSA_set_ex_data -RSA_sign -RSA_sign_pss_mgf1 -RSA_sign_raw -RSA_size -RSA_up_ref -RSA_verify -RSA_verify_PKCS1_PSS_mgf1 -RSA_verify_pss_mgf1 -RSA_verify_raw -SHA1 -SHA1_Final -SHA1_Init -SHA1_Transform -SHA1_Update -SHA224 -SHA224_Final -SHA224_Init -SHA224_Update -SHA256 -SHA256_Final -SHA256_Init -SHA256_Transform -SHA256_TransformBlocks -SHA256_Update -SHA384 -SHA384_Final -SHA384_Init -SHA384_Update -SHA512 -SHA512_256 -SHA512_256_Final -SHA512_256_Init -SHA512_256_Update -SHA512_Final -SHA512_Init -SHA512_Transform -SHA512_Update -SIPHASH_24 -SPAKE2_CTX_free -SPAKE2_CTX_new -SPAKE2_generate_msg -SPAKE2_process_msg -SSL_CIPHER_description -SSL_CIPHER_get_auth_nid -SSL_CIPHER_get_bits -SSL_CIPHER_get_cipher_nid -SSL_CIPHER_get_digest_nid -SSL_CIPHER_get_id -SSL_CIPHER_get_kx_name -SSL_CIPHER_get_kx_nid -SSL_CIPHER_get_max_version -SSL_CIPHER_get_min_version -SSL_CIPHER_get_name -SSL_CIPHER_get_prf_nid -SSL_CIPHER_get_rfc_name -SSL_CIPHER_get_value -SSL_CIPHER_get_version -SSL_CIPHER_is_aead -SSL_CIPHER_is_block_cipher -SSL_CIPHER_standard_name -SSL_COMP_add_compression_method -SSL_COMP_free_compression_methods -SSL_COMP_get0_name -SSL_COMP_get_compression_methods -SSL_COMP_get_id -SSL_COMP_get_name -SSL_CTX_add0_chain_cert -SSL_CTX_add1_chain_cert -SSL_CTX_add_cert_compression_alg -SSL_CTX_add_client_CA -SSL_CTX_add_extra_chain_cert -SSL_CTX_add_session -SSL_CTX_check_private_key -SSL_CTX_cipher_in_group -SSL_CTX_clear_chain_certs -SSL_CTX_clear_extra_chain_certs -SSL_CTX_clear_mode -SSL_CTX_clear_options -SSL_CTX_enable_ocsp_stapling -SSL_CTX_enable_signed_cert_timestamps -SSL_CTX_enable_tls_channel_id -SSL_CTX_flush_sessions -SSL_CTX_free -SSL_CTX_get0_certificate -SSL_CTX_get0_chain -SSL_CTX_get0_chain_certs -SSL_CTX_get0_param -SSL_CTX_get0_privatekey -SSL_CTX_get_cert_store -SSL_CTX_get_channel_id_cb -SSL_CTX_get_ciphers -SSL_CTX_get_client_CA_list -SSL_CTX_get_default_passwd_cb -SSL_CTX_get_default_passwd_cb_userdata -SSL_CTX_get_ex_data -SSL_CTX_get_ex_new_index -SSL_CTX_get_extra_chain_certs -SSL_CTX_get_info_callback -SSL_CTX_get_keylog_callback -SSL_CTX_get_max_cert_list -SSL_CTX_get_max_proto_version -SSL_CTX_get_min_proto_version -SSL_CTX_get_mode -SSL_CTX_get_options -SSL_CTX_get_quiet_shutdown -SSL_CTX_get_read_ahead -SSL_CTX_get_session_cache_mode -SSL_CTX_get_timeout -SSL_CTX_get_tlsext_ticket_keys -SSL_CTX_get_verify_callback -SSL_CTX_get_verify_depth -SSL_CTX_get_verify_mode -SSL_CTX_load_verify_locations -SSL_CTX_need_tmp_RSA -SSL_CTX_new -SSL_CTX_remove_session -SSL_CTX_sess_accept -SSL_CTX_sess_accept_good -SSL_CTX_sess_accept_renegotiate -SSL_CTX_sess_cache_full -SSL_CTX_sess_cb_hits -SSL_CTX_sess_connect -SSL_CTX_sess_connect_good -SSL_CTX_sess_connect_renegotiate -SSL_CTX_sess_get_cache_size -SSL_CTX_sess_get_get_cb -SSL_CTX_sess_get_new_cb -SSL_CTX_sess_get_remove_cb -SSL_CTX_sess_hits -SSL_CTX_sess_misses -SSL_CTX_sess_number -SSL_CTX_sess_set_cache_size -SSL_CTX_sess_set_get_cb -SSL_CTX_sess_set_new_cb -SSL_CTX_sess_set_remove_cb -SSL_CTX_sess_timeouts -SSL_CTX_set0_buffer_pool -SSL_CTX_set0_chain -SSL_CTX_set0_client_CAs -SSL_CTX_set0_verify_cert_store -SSL_CTX_set1_chain -SSL_CTX_set1_curves -SSL_CTX_set1_curves_list -SSL_CTX_set1_param -SSL_CTX_set1_sigalgs -SSL_CTX_set1_sigalgs_list -SSL_CTX_set1_tls_channel_id -SSL_CTX_set1_verify_cert_store -SSL_CTX_set_allow_unknown_alpn_protos -SSL_CTX_set_alpn_protos -SSL_CTX_set_alpn_select_cb -SSL_CTX_set_cert_cb -SSL_CTX_set_cert_store -SSL_CTX_set_cert_verify_callback -SSL_CTX_set_chain_and_key -SSL_CTX_set_channel_id_cb -SSL_CTX_set_cipher_list -SSL_CTX_set_client_CA_list -SSL_CTX_set_client_cert_cb -SSL_CTX_set_current_time_cb -SSL_CTX_set_custom_verify -SSL_CTX_set_default_passwd_cb -SSL_CTX_set_default_passwd_cb_userdata -SSL_CTX_set_default_verify_paths -SSL_CTX_set_dos_protection_cb -SSL_CTX_set_early_data_enabled -SSL_CTX_set_ex_data -SSL_CTX_set_false_start_allowed_without_alpn -SSL_CTX_set_grease_enabled -SSL_CTX_set_ignore_tls13_downgrade -SSL_CTX_set_info_callback -SSL_CTX_set_keylog_callback -SSL_CTX_set_max_cert_list -SSL_CTX_set_max_proto_version -SSL_CTX_set_max_send_fragment -SSL_CTX_set_min_proto_version -SSL_CTX_set_mode -SSL_CTX_set_msg_callback -SSL_CTX_set_msg_callback_arg -SSL_CTX_set_next_proto_select_cb -SSL_CTX_set_next_protos_advertised_cb -SSL_CTX_set_ocsp_response -SSL_CTX_set_options -SSL_CTX_set_private_key_method -SSL_CTX_set_psk_client_callback -SSL_CTX_set_psk_server_callback -SSL_CTX_set_purpose -SSL_CTX_set_quic_method -SSL_CTX_set_quiet_shutdown -SSL_CTX_set_read_ahead -SSL_CTX_set_retain_only_sha256_of_client_certs -SSL_CTX_set_reverify_on_resume -SSL_CTX_set_select_certificate_cb -SSL_CTX_set_session_cache_mode -SSL_CTX_set_session_id_context -SSL_CTX_set_session_psk_dhe_timeout -SSL_CTX_set_signed_cert_timestamp_list -SSL_CTX_set_signing_algorithm_prefs -SSL_CTX_set_srtp_profiles -SSL_CTX_set_strict_cipher_list -SSL_CTX_set_ticket_aead_method -SSL_CTX_set_timeout -SSL_CTX_set_tls_channel_id_enabled -SSL_CTX_set_tlsext_servername_arg -SSL_CTX_set_tlsext_servername_callback -SSL_CTX_set_tlsext_status_arg -SSL_CTX_set_tlsext_status_cb -SSL_CTX_set_tlsext_ticket_key_cb -SSL_CTX_set_tlsext_ticket_keys -SSL_CTX_set_tlsext_use_srtp -SSL_CTX_set_tmp_dh -SSL_CTX_set_tmp_dh_callback -SSL_CTX_set_tmp_ecdh -SSL_CTX_set_tmp_rsa -SSL_CTX_set_tmp_rsa_callback -SSL_CTX_set_trust -SSL_CTX_set_verify -SSL_CTX_set_verify_algorithm_prefs -SSL_CTX_set_verify_depth -SSL_CTX_up_ref -SSL_CTX_use_PrivateKey -SSL_CTX_use_PrivateKey_ASN1 -SSL_CTX_use_PrivateKey_file -SSL_CTX_use_RSAPrivateKey -SSL_CTX_use_RSAPrivateKey_ASN1 -SSL_CTX_use_RSAPrivateKey_file -SSL_CTX_use_certificate -SSL_CTX_use_certificate_ASN1 -SSL_CTX_use_certificate_chain_file -SSL_CTX_use_certificate_file -SSL_CTX_use_psk_identity_hint -SSL_SESSION_copy_without_early_data -SSL_SESSION_early_data_capable -SSL_SESSION_free -SSL_SESSION_from_bytes -SSL_SESSION_get0_cipher -SSL_SESSION_get0_id_context -SSL_SESSION_get0_ocsp_response -SSL_SESSION_get0_peer -SSL_SESSION_get0_peer_certificates -SSL_SESSION_get0_peer_sha256 -SSL_SESSION_get0_signed_cert_timestamp_list -SSL_SESSION_get0_ticket -SSL_SESSION_get_ex_data -SSL_SESSION_get_ex_new_index -SSL_SESSION_get_id -SSL_SESSION_get_master_key -SSL_SESSION_get_protocol_version -SSL_SESSION_get_ticket_lifetime_hint -SSL_SESSION_get_time -SSL_SESSION_get_timeout -SSL_SESSION_get_version -SSL_SESSION_has_peer_sha256 -SSL_SESSION_has_ticket -SSL_SESSION_is_resumable -SSL_SESSION_new -SSL_SESSION_set1_id -SSL_SESSION_set1_id_context -SSL_SESSION_set_ex_data -SSL_SESSION_set_protocol_version -SSL_SESSION_set_ticket -SSL_SESSION_set_time -SSL_SESSION_set_timeout -SSL_SESSION_should_be_single_use -SSL_SESSION_to_bytes -SSL_SESSION_to_bytes_for_ticket -SSL_SESSION_up_ref -SSL_accept -SSL_add0_chain_cert -SSL_add1_chain_cert -SSL_add_client_CA -SSL_add_file_cert_subjects_to_stack -SSL_alert_desc_string -SSL_alert_desc_string_long -SSL_alert_from_verify_result -SSL_alert_type_string -SSL_alert_type_string_long -SSL_cache_hit -SSL_certs_clear -SSL_check_private_key -SSL_clear -SSL_clear_chain_certs -SSL_clear_mode -SSL_clear_options -SSL_connect -SSL_cutthrough_complete -SSL_delegated_credential_used -SSL_do_handshake -SSL_dup_CA_list -SSL_early_callback_ctx_extension_get -SSL_early_data_accepted -SSL_enable_ocsp_stapling -SSL_enable_signed_cert_timestamps -SSL_enable_tls_channel_id -SSL_error_description -SSL_export_keying_material -SSL_free -SSL_generate_key_block -SSL_get0_alpn_selected -SSL_get0_certificate_types -SSL_get0_chain_certs -SSL_get0_next_proto_negotiated -SSL_get0_ocsp_response -SSL_get0_param -SSL_get0_peer_certificates -SSL_get0_peer_verify_algorithms -SSL_get0_server_requested_CAs -SSL_get0_session_id_context -SSL_get0_signed_cert_timestamp_list -SSL_get1_session -SSL_get_SSL_CTX -SSL_get_certificate -SSL_get_cipher_by_value -SSL_get_cipher_list -SSL_get_ciphers -SSL_get_client_CA_list -SSL_get_client_random -SSL_get_current_cipher -SSL_get_current_compression -SSL_get_current_expansion -SSL_get_curve_id -SSL_get_curve_name -SSL_get_default_timeout -SSL_get_early_data_reason -SSL_get_error -SSL_get_ex_data -SSL_get_ex_data_X509_STORE_CTX_idx -SSL_get_ex_new_index -SSL_get_extms_support -SSL_get_fd -SSL_get_finished -SSL_get_info_callback -SSL_get_ivs -SSL_get_key_block_len -SSL_get_max_cert_list -SSL_get_max_proto_version -SSL_get_min_proto_version -SSL_get_mode -SSL_get_negotiated_token_binding_param -SSL_get_options -SSL_get_peer_cert_chain -SSL_get_peer_certificate -SSL_get_peer_finished -SSL_get_peer_full_cert_chain -SSL_get_peer_quic_transport_params -SSL_get_peer_signature_algorithm -SSL_get_pending_cipher -SSL_get_privatekey -SSL_get_psk_identity -SSL_get_psk_identity_hint -SSL_get_quiet_shutdown -SSL_get_rbio -SSL_get_read_ahead -SSL_get_read_sequence -SSL_get_rfd -SSL_get_secure_renegotiation_support -SSL_get_selected_srtp_profile -SSL_get_server_random -SSL_get_server_tmp_key -SSL_get_servername -SSL_get_servername_type -SSL_get_session -SSL_get_shared_ciphers -SSL_get_shared_sigalgs -SSL_get_shutdown -SSL_get_signature_algorithm_digest -SSL_get_signature_algorithm_key_type -SSL_get_signature_algorithm_name -SSL_get_srtp_profiles -SSL_get_ticket_age_skew -SSL_get_tls_channel_id -SSL_get_tls_unique -SSL_get_tlsext_status_ocsp_resp -SSL_get_tlsext_status_type -SSL_get_verify_callback -SSL_get_verify_depth -SSL_get_verify_mode -SSL_get_verify_result -SSL_get_version -SSL_get_wbio -SSL_get_wfd -SSL_get_write_sequence -SSL_in_early_data -SSL_in_false_start -SSL_in_init -SSL_is_dtls -SSL_is_init_finished -SSL_is_server -SSL_is_signature_algorithm_rsa_pss -SSL_is_tls13_downgrade -SSL_is_token_binding_negotiated -SSL_key_update -SSL_library_init -SSL_load_client_CA_file -SSL_load_error_strings -SSL_magic_pending_session_ptr -SSL_max_seal_overhead -SSL_need_tmp_RSA -SSL_new -SSL_num_renegotiations -SSL_peek -SSL_pending -SSL_process_quic_post_handshake -SSL_process_tls13_new_session_ticket -SSL_provide_quic_data -SSL_quic_max_handshake_flight_len -SSL_quic_read_level -SSL_quic_write_level -SSL_read -SSL_renegotiate -SSL_renegotiate_pending -SSL_reset_early_data_reject -SSL_select_next_proto -SSL_send_fatal_alert -SSL_session_reused -SSL_set0_chain -SSL_set0_client_CAs -SSL_set0_rbio -SSL_set0_verify_cert_store -SSL_set0_wbio -SSL_set1_chain -SSL_set1_curves -SSL_set1_curves_list -SSL_set1_delegated_credential -SSL_set1_param -SSL_set1_sigalgs -SSL_set1_sigalgs_list -SSL_set1_tls_channel_id -SSL_set1_verify_cert_store -SSL_set_SSL_CTX -SSL_set_accept_state -SSL_set_alpn_protos -SSL_set_bio -SSL_set_cert_cb -SSL_set_chain_and_key -SSL_set_cipher_list -SSL_set_client_CA_list -SSL_set_connect_state -SSL_set_custom_verify -SSL_set_early_data_enabled -SSL_set_enforce_rsa_key_usage -SSL_set_ex_data -SSL_set_fd -SSL_set_ignore_tls13_downgrade -SSL_set_info_callback -SSL_set_jdk11_workaround -SSL_set_max_cert_list -SSL_set_max_proto_version -SSL_set_max_send_fragment -SSL_set_min_proto_version -SSL_set_mode -SSL_set_msg_callback -SSL_set_msg_callback_arg -SSL_set_mtu -SSL_set_ocsp_response -SSL_set_options -SSL_set_private_key_method -SSL_set_psk_client_callback -SSL_set_psk_server_callback -SSL_set_purpose -SSL_set_quic_early_data_context -SSL_set_quic_method -SSL_set_quic_transport_params -SSL_set_quiet_shutdown -SSL_set_read_ahead -SSL_set_renegotiate_mode -SSL_set_retain_only_sha256_of_client_certs -SSL_set_rfd -SSL_set_session -SSL_set_session_id_context -SSL_set_shed_handshake_config -SSL_set_shutdown -SSL_set_signed_cert_timestamp_list -SSL_set_signing_algorithm_prefs -SSL_set_srtp_profiles -SSL_set_state -SSL_set_strict_cipher_list -SSL_set_tls_channel_id_enabled -SSL_set_tlsext_host_name -SSL_set_tlsext_status_ocsp_resp -SSL_set_tlsext_status_type -SSL_set_tlsext_use_srtp -SSL_set_tmp_dh -SSL_set_tmp_dh_callback -SSL_set_tmp_ecdh -SSL_set_tmp_rsa -SSL_set_tmp_rsa_callback -SSL_set_token_binding_params -SSL_set_trust -SSL_set_verify -SSL_set_verify_algorithm_prefs -SSL_set_verify_depth -SSL_set_verify_result -SSL_set_wfd -SSL_shutdown -SSL_state -SSL_state_string -SSL_state_string_long -SSL_total_renegotiations -SSL_use_PrivateKey -SSL_use_PrivateKey_ASN1 -SSL_use_PrivateKey_file -SSL_use_RSAPrivateKey -SSL_use_RSAPrivateKey_ASN1 -SSL_use_RSAPrivateKey_file -SSL_use_certificate -SSL_use_certificate_ASN1 -SSL_use_certificate_file -SSL_use_psk_identity_hint -SSL_used_hello_retry_request -SSL_version -SSL_want -SSL_write -SSLeay -SSLeay_version -SSLv23_client_method -SSLv23_method -SSLv23_server_method -SXNETID_free -SXNETID_it -SXNETID_new -SXNET_add_id_INTEGER -SXNET_add_id_asc -SXNET_add_id_ulong -SXNET_free -SXNET_get_id_INTEGER -SXNET_get_id_asc -SXNET_get_id_ulong -SXNET_it -SXNET_new -TLS_client_method -TLS_method -TLS_server_method -TLS_with_buffers_method -TLSv1_1_client_method -TLSv1_1_method -TLSv1_1_server_method -TLSv1_2_client_method -TLSv1_2_method -TLSv1_2_server_method -TLSv1_client_method -TLSv1_method -TLSv1_server_method -TRUST_TOKEN_CLIENT_add_key -TRUST_TOKEN_CLIENT_begin_issuance -TRUST_TOKEN_CLIENT_begin_redemption -TRUST_TOKEN_CLIENT_finish_issuance -TRUST_TOKEN_CLIENT_finish_redemption -TRUST_TOKEN_CLIENT_free -TRUST_TOKEN_CLIENT_new -TRUST_TOKEN_CLIENT_set_srr_key -TRUST_TOKEN_ISSUER_add_key -TRUST_TOKEN_ISSUER_free -TRUST_TOKEN_ISSUER_issue -TRUST_TOKEN_ISSUER_new -TRUST_TOKEN_ISSUER_redeem -TRUST_TOKEN_ISSUER_set_metadata_key -TRUST_TOKEN_ISSUER_set_srr_key -TRUST_TOKEN_decode_private_metadata -TRUST_TOKEN_experiment_v0 -TRUST_TOKEN_experiment_v1 -TRUST_TOKEN_free -TRUST_TOKEN_generate_key -TRUST_TOKEN_new -USERNOTICE_free -USERNOTICE_it -USERNOTICE_new -UTF8_getc -UTF8_putc -X25519 -X25519_keypair -X25519_public_from_private -X509V3_EXT_CRL_add_nconf -X509V3_EXT_REQ_add_nconf -X509V3_EXT_add -X509V3_EXT_add_alias -X509V3_EXT_add_list -X509V3_EXT_add_nconf -X509V3_EXT_add_nconf_sk -X509V3_EXT_cleanup -X509V3_EXT_d2i -X509V3_EXT_free -X509V3_EXT_get -X509V3_EXT_get_nid -X509V3_EXT_i2d -X509V3_EXT_nconf -X509V3_EXT_nconf_nid -X509V3_EXT_print -X509V3_EXT_print_fp -X509V3_EXT_val_prn -X509V3_NAME_from_section -X509V3_add1_i2d -X509V3_add_standard_extensions -X509V3_add_value -X509V3_add_value_bool -X509V3_add_value_bool_nf -X509V3_add_value_int -X509V3_add_value_uchar -X509V3_conf_free -X509V3_extensions_print -X509V3_get_d2i -X509V3_get_section -X509V3_get_string -X509V3_get_value_bool -X509V3_get_value_int -X509V3_parse_list -X509V3_section_free -X509V3_set_ctx -X509V3_set_nconf -X509V3_string_free -X509_ALGORS_it -X509_ALGOR_cmp -X509_ALGOR_dup -X509_ALGOR_free -X509_ALGOR_get0 -X509_ALGOR_it -X509_ALGOR_new -X509_ALGOR_set0 -X509_ALGOR_set_md -X509_ATTRIBUTE_SET_it -X509_ATTRIBUTE_count -X509_ATTRIBUTE_create -X509_ATTRIBUTE_create_by_NID -X509_ATTRIBUTE_create_by_OBJ -X509_ATTRIBUTE_create_by_txt -X509_ATTRIBUTE_dup -X509_ATTRIBUTE_free -X509_ATTRIBUTE_get0_data -X509_ATTRIBUTE_get0_object -X509_ATTRIBUTE_get0_type -X509_ATTRIBUTE_it -X509_ATTRIBUTE_new -X509_ATTRIBUTE_set1_data -X509_ATTRIBUTE_set1_object -X509_CERT_AUX_free -X509_CERT_AUX_it -X509_CERT_AUX_new -X509_CERT_AUX_print -X509_CINF_free -X509_CINF_it -X509_CINF_new -X509_CRL_INFO_free -X509_CRL_INFO_it -X509_CRL_INFO_new -X509_CRL_METHOD_free -X509_CRL_METHOD_new -X509_CRL_add0_revoked -X509_CRL_add1_ext_i2d -X509_CRL_add_ext -X509_CRL_check_suiteb -X509_CRL_cmp -X509_CRL_delete_ext -X509_CRL_diff -X509_CRL_digest -X509_CRL_dup -X509_CRL_free -X509_CRL_get0_by_cert -X509_CRL_get0_by_serial -X509_CRL_get0_lastUpdate -X509_CRL_get0_nextUpdate -X509_CRL_get0_signature -X509_CRL_get_ext -X509_CRL_get_ext_by_NID -X509_CRL_get_ext_by_OBJ -X509_CRL_get_ext_by_critical -X509_CRL_get_ext_count -X509_CRL_get_ext_d2i -X509_CRL_get_meth_data -X509_CRL_get_signature_nid -X509_CRL_it -X509_CRL_match -X509_CRL_new -X509_CRL_print -X509_CRL_print_fp -X509_CRL_set_default_method -X509_CRL_set_issuer_name -X509_CRL_set_lastUpdate -X509_CRL_set_meth_data -X509_CRL_set_nextUpdate -X509_CRL_set_version -X509_CRL_sign -X509_CRL_sign_ctx -X509_CRL_sort -X509_CRL_up_ref -X509_CRL_verify -X509_EXTENSIONS_it -X509_EXTENSION_create_by_NID -X509_EXTENSION_create_by_OBJ -X509_EXTENSION_dup -X509_EXTENSION_free -X509_EXTENSION_get_critical -X509_EXTENSION_get_data -X509_EXTENSION_get_object -X509_EXTENSION_it -X509_EXTENSION_new -X509_EXTENSION_set_critical -X509_EXTENSION_set_data -X509_EXTENSION_set_object -X509_INFO_free -X509_INFO_new -X509_LOOKUP_by_alias -X509_LOOKUP_by_fingerprint -X509_LOOKUP_by_issuer_serial -X509_LOOKUP_by_subject -X509_LOOKUP_ctrl -X509_LOOKUP_file -X509_LOOKUP_free -X509_LOOKUP_hash_dir -X509_LOOKUP_init -X509_LOOKUP_new -X509_LOOKUP_shutdown -X509_NAME_ENTRIES_it -X509_NAME_ENTRY_create_by_NID -X509_NAME_ENTRY_create_by_OBJ -X509_NAME_ENTRY_create_by_txt -X509_NAME_ENTRY_dup -X509_NAME_ENTRY_free -X509_NAME_ENTRY_get_data -X509_NAME_ENTRY_get_object -X509_NAME_ENTRY_it -X509_NAME_ENTRY_new -X509_NAME_ENTRY_set -X509_NAME_ENTRY_set_data -X509_NAME_ENTRY_set_object -X509_NAME_INTERNAL_it -X509_NAME_add_entry -X509_NAME_add_entry_by_NID -X509_NAME_add_entry_by_OBJ -X509_NAME_add_entry_by_txt -X509_NAME_cmp -X509_NAME_delete_entry -X509_NAME_digest -X509_NAME_dup -X509_NAME_entry_count -X509_NAME_free -X509_NAME_get0_der -X509_NAME_get_entry -X509_NAME_get_index_by_NID -X509_NAME_get_index_by_OBJ -X509_NAME_get_text_by_NID -X509_NAME_get_text_by_OBJ -X509_NAME_hash -X509_NAME_hash_old -X509_NAME_it -X509_NAME_new -X509_NAME_oneline -X509_NAME_print -X509_NAME_print_ex -X509_NAME_print_ex_fp -X509_NAME_set -X509_OBJECT_free_contents -X509_OBJECT_get0_X509 -X509_OBJECT_get_type -X509_OBJECT_idx_by_subject -X509_OBJECT_retrieve_by_subject -X509_OBJECT_retrieve_match -X509_OBJECT_up_ref_count -X509_PKEY_free -X509_PKEY_new -X509_POLICY_NODE_print -X509_PUBKEY_free -X509_PUBKEY_get -X509_PUBKEY_get0_param -X509_PUBKEY_it -X509_PUBKEY_new -X509_PUBKEY_set -X509_PUBKEY_set0_param -X509_PURPOSE_add -X509_PURPOSE_cleanup -X509_PURPOSE_get0 -X509_PURPOSE_get0_name -X509_PURPOSE_get0_sname -X509_PURPOSE_get_by_id -X509_PURPOSE_get_by_sname -X509_PURPOSE_get_count -X509_PURPOSE_get_id -X509_PURPOSE_get_trust -X509_PURPOSE_set -X509_REQ_INFO_free -X509_REQ_INFO_it -X509_REQ_INFO_new -X509_REQ_add1_attr -X509_REQ_add1_attr_by_NID -X509_REQ_add1_attr_by_OBJ -X509_REQ_add1_attr_by_txt -X509_REQ_add_extensions -X509_REQ_add_extensions_nid -X509_REQ_check_private_key -X509_REQ_delete_attr -X509_REQ_digest -X509_REQ_dup -X509_REQ_extension_nid -X509_REQ_free -X509_REQ_get0_signature -X509_REQ_get1_email -X509_REQ_get_attr -X509_REQ_get_attr_by_NID -X509_REQ_get_attr_by_OBJ -X509_REQ_get_attr_count -X509_REQ_get_extension_nids -X509_REQ_get_extensions -X509_REQ_get_pubkey -X509_REQ_get_signature_nid -X509_REQ_it -X509_REQ_new -X509_REQ_print -X509_REQ_print_ex -X509_REQ_print_fp -X509_REQ_set_extension_nids -X509_REQ_set_pubkey -X509_REQ_set_subject_name -X509_REQ_set_version -X509_REQ_sign -X509_REQ_sign_ctx -X509_REQ_to_X509 -X509_REQ_verify -X509_REVOKED_add1_ext_i2d -X509_REVOKED_add_ext -X509_REVOKED_delete_ext -X509_REVOKED_dup -X509_REVOKED_free -X509_REVOKED_get0_revocationDate -X509_REVOKED_get0_serialNumber -X509_REVOKED_get_ext -X509_REVOKED_get_ext_by_NID -X509_REVOKED_get_ext_by_OBJ -X509_REVOKED_get_ext_by_critical -X509_REVOKED_get_ext_count -X509_REVOKED_get_ext_d2i -X509_REVOKED_it -X509_REVOKED_new -X509_REVOKED_set_revocationDate -X509_REVOKED_set_serialNumber -X509_SIG_free -X509_SIG_it -X509_SIG_new -X509_STORE_CTX_cleanup -X509_STORE_CTX_free -X509_STORE_CTX_get0_cert -X509_STORE_CTX_get0_chain -X509_STORE_CTX_get0_current_crl -X509_STORE_CTX_get0_current_issuer -X509_STORE_CTX_get0_param -X509_STORE_CTX_get0_parent_ctx -X509_STORE_CTX_get0_policy_tree -X509_STORE_CTX_get0_store -X509_STORE_CTX_get0_untrusted -X509_STORE_CTX_get1_chain -X509_STORE_CTX_get1_issuer -X509_STORE_CTX_get_chain -X509_STORE_CTX_get_current_cert -X509_STORE_CTX_get_error -X509_STORE_CTX_get_error_depth -X509_STORE_CTX_get_ex_data -X509_STORE_CTX_get_ex_new_index -X509_STORE_CTX_get_explicit_policy -X509_STORE_CTX_init -X509_STORE_CTX_new -X509_STORE_CTX_purpose_inherit -X509_STORE_CTX_set0_crls -X509_STORE_CTX_set0_param -X509_STORE_CTX_set_cert -X509_STORE_CTX_set_chain -X509_STORE_CTX_set_default -X509_STORE_CTX_set_depth -X509_STORE_CTX_set_error -X509_STORE_CTX_set_ex_data -X509_STORE_CTX_set_flags -X509_STORE_CTX_set_purpose -X509_STORE_CTX_set_time -X509_STORE_CTX_set_trust -X509_STORE_CTX_set_verify_cb -X509_STORE_CTX_trusted_stack -X509_STORE_CTX_zero -X509_STORE_add_cert -X509_STORE_add_crl -X509_STORE_add_lookup -X509_STORE_free -X509_STORE_get0_objects -X509_STORE_get0_param -X509_STORE_get1_certs -X509_STORE_get1_crls -X509_STORE_get_by_subject -X509_STORE_get_cert_crl -X509_STORE_get_check_crl -X509_STORE_get_check_issued -X509_STORE_get_check_revocation -X509_STORE_get_cleanup -X509_STORE_get_get_crl -X509_STORE_get_get_issuer -X509_STORE_get_lookup_certs -X509_STORE_get_lookup_crls -X509_STORE_get_verify -X509_STORE_get_verify_cb -X509_STORE_load_locations -X509_STORE_new -X509_STORE_set0_additional_untrusted -X509_STORE_set1_param -X509_STORE_set_cert_crl -X509_STORE_set_check_crl -X509_STORE_set_check_issued -X509_STORE_set_check_revocation -X509_STORE_set_cleanup -X509_STORE_set_default_paths -X509_STORE_set_depth -X509_STORE_set_flags -X509_STORE_set_get_crl -X509_STORE_set_get_issuer -X509_STORE_set_lookup_certs -X509_STORE_set_lookup_crls -X509_STORE_set_purpose -X509_STORE_set_trust -X509_STORE_set_verify -X509_STORE_set_verify_cb -X509_STORE_up_ref -X509_TRUST_add -X509_TRUST_cleanup -X509_TRUST_get0 -X509_TRUST_get0_name -X509_TRUST_get_by_id -X509_TRUST_get_count -X509_TRUST_get_flags -X509_TRUST_get_trust -X509_TRUST_set -X509_TRUST_set_default -X509_VAL_free -X509_VAL_it -X509_VAL_new -X509_VERIFY_PARAM_add0_policy -X509_VERIFY_PARAM_add0_table -X509_VERIFY_PARAM_add1_host -X509_VERIFY_PARAM_clear_flags -X509_VERIFY_PARAM_free -X509_VERIFY_PARAM_get0 -X509_VERIFY_PARAM_get0_name -X509_VERIFY_PARAM_get0_peername -X509_VERIFY_PARAM_get_count -X509_VERIFY_PARAM_get_depth -X509_VERIFY_PARAM_get_flags -X509_VERIFY_PARAM_inherit -X509_VERIFY_PARAM_lookup -X509_VERIFY_PARAM_new -X509_VERIFY_PARAM_set1 -X509_VERIFY_PARAM_set1_email -X509_VERIFY_PARAM_set1_host -X509_VERIFY_PARAM_set1_ip -X509_VERIFY_PARAM_set1_ip_asc -X509_VERIFY_PARAM_set1_name -X509_VERIFY_PARAM_set1_policies -X509_VERIFY_PARAM_set_depth -X509_VERIFY_PARAM_set_flags -X509_VERIFY_PARAM_set_hostflags -X509_VERIFY_PARAM_set_purpose -X509_VERIFY_PARAM_set_time -X509_VERIFY_PARAM_set_trust -X509_VERIFY_PARAM_table_cleanup -X509_add1_ext_i2d -X509_add1_reject_object -X509_add1_trust_object -X509_add_ext -X509_alias_get0 -X509_alias_set1 -X509_chain_check_suiteb -X509_chain_up_ref -X509_check_akid -X509_check_ca -X509_check_email -X509_check_host -X509_check_ip -X509_check_ip_asc -X509_check_issued -X509_check_private_key -X509_check_purpose -X509_check_trust -X509_cmp -X509_cmp_current_time -X509_cmp_time -X509_delete_ext -X509_digest -X509_dup -X509_email_free -X509_find_by_issuer_and_serial -X509_find_by_subject -X509_free -X509_get0_extensions -X509_get0_notAfter -X509_get0_notBefore -X509_get0_pubkey_bitstr -X509_get0_signature -X509_get0_tbs_sigalg -X509_get1_email -X509_get1_ocsp -X509_get_default_cert_area -X509_get_default_cert_dir -X509_get_default_cert_dir_env -X509_get_default_cert_file -X509_get_default_cert_file_env -X509_get_default_private_dir -X509_get_ex_data -X509_get_ex_new_index -X509_get_ext -X509_get_ext_by_NID -X509_get_ext_by_OBJ -X509_get_ext_by_critical -X509_get_ext_count -X509_get_ext_d2i -X509_get_extended_key_usage -X509_get_extension_flags -X509_get_issuer_name -X509_get_key_usage -X509_get_pubkey -X509_get_serialNumber -X509_get_signature_nid -X509_get_subject_name -X509_getm_notAfter -X509_getm_notBefore -X509_gmtime_adj -X509_issuer_and_serial_cmp -X509_issuer_and_serial_hash -X509_issuer_name_cmp -X509_issuer_name_hash -X509_issuer_name_hash_old -X509_it -X509_keyid_get0 -X509_keyid_set1 -X509_load_cert_crl_file -X509_load_cert_file -X509_load_crl_file -X509_new -X509_ocspid_print -X509_parse_from_buffer -X509_policy_check -X509_policy_level_get0_node -X509_policy_level_node_count -X509_policy_node_get0_parent -X509_policy_node_get0_policy -X509_policy_node_get0_qualifiers -X509_policy_tree_free -X509_policy_tree_get0_level -X509_policy_tree_get0_policies -X509_policy_tree_get0_user_policies -X509_policy_tree_level_count -X509_print -X509_print_ex -X509_print_ex_fp -X509_print_fp -X509_pubkey_digest -X509_reject_clear -X509_set_ex_data -X509_set_issuer_name -X509_set_notAfter -X509_set_notBefore -X509_set_pubkey -X509_set_serialNumber -X509_set_subject_name -X509_set_version -X509_sign -X509_sign_ctx -X509_signature_dump -X509_signature_print -X509_subject_name_cmp -X509_subject_name_hash -X509_subject_name_hash_old -X509_supported_extension -X509_time_adj -X509_time_adj_ex -X509_to_X509_REQ -X509_trust_clear -X509_up_ref -X509_verify -X509_verify_cert -X509_verify_cert_error_string -X509at_add1_attr -X509at_add1_attr_by_NID -X509at_add1_attr_by_OBJ -X509at_add1_attr_by_txt -X509at_delete_attr -X509at_get0_data_by_OBJ -X509at_get_attr -X509at_get_attr_by_NID -X509at_get_attr_by_OBJ -X509at_get_attr_count -X509v3_add_ext -X509v3_delete_ext -X509v3_get_ext -X509v3_get_ext_by_NID -X509v3_get_ext_by_OBJ -X509v3_get_ext_by_critical -X509v3_get_ext_count -a2i_GENERAL_NAME -a2i_IPADDRESS -a2i_IPADDRESS_NC -a2i_ipadd -abi_test_clobber_d0 -abi_test_clobber_d1 -abi_test_clobber_d10 -abi_test_clobber_d11 -abi_test_clobber_d12 -abi_test_clobber_d13 -abi_test_clobber_d14 -abi_test_clobber_d15 -abi_test_clobber_d2 -abi_test_clobber_d3 -abi_test_clobber_d4 -abi_test_clobber_d5 -abi_test_clobber_d6 -abi_test_clobber_d7 -abi_test_clobber_d8 -abi_test_clobber_d9 -abi_test_clobber_r0 -abi_test_clobber_r1 -abi_test_clobber_r10 -abi_test_clobber_r11 -abi_test_clobber_r12 -abi_test_clobber_r2 -abi_test_clobber_r3 -abi_test_clobber_r4 -abi_test_clobber_r5 -abi_test_clobber_r6 -abi_test_clobber_r7 -abi_test_clobber_r8 -abi_test_clobber_r9 -abi_test_trampoline -aes_ctr_set_key -aes_hw_cbc_encrypt -aes_hw_ctr32_encrypt_blocks -aes_hw_decrypt -aes_hw_encrypt -aes_hw_set_decrypt_key -aes_hw_set_encrypt_key -aes_nohw_cbc_encrypt -aes_nohw_ctr32_encrypt_blocks -aes_nohw_decrypt -aes_nohw_encrypt -aes_nohw_set_decrypt_key -aes_nohw_set_encrypt_key -asn1_do_adb -asn1_enc_free -asn1_enc_init -asn1_enc_restore -asn1_enc_save -asn1_ex_c2i -asn1_ex_i2c -asn1_generalizedtime_to_tm -asn1_get_choice_selector -asn1_get_field_ptr -asn1_item_combine_free -asn1_refcount_dec_and_test_zero -asn1_refcount_set_one -asn1_set_choice_selector -asn1_utctime_to_tm -bio_clear_socket_error -bio_fd_should_retry -bio_ip_and_port_to_socket_and_addr -bio_sock_error -bio_socket_nbio -bn_abs_sub_consttime -bn_add_words -bn_copy_words -bn_div_consttime -bn_expand -bn_fits_in_words -bn_from_montgomery_small -bn_in_range_words -bn_is_bit_set_words -bn_is_relatively_prime -bn_jacobi -bn_lcm_consttime -bn_less_than_montgomery_R -bn_less_than_words -bn_miller_rabin_init -bn_miller_rabin_iteration -bn_minimal_width -bn_mod_add_consttime -bn_mod_add_words -bn_mod_exp_base_2_consttime -bn_mod_exp_mont_small -bn_mod_inverse0_prime_mont_small -bn_mod_inverse_consttime -bn_mod_inverse_prime -bn_mod_inverse_secret_prime -bn_mod_lshift1_consttime -bn_mod_lshift_consttime -bn_mod_mul_montgomery_small -bn_mod_sub_consttime -bn_mod_sub_words -bn_mod_u16_consttime -bn_mont_n0 -bn_mul_add_words -bn_mul_comba4 -bn_mul_comba8 -bn_mul_consttime -bn_mul_mont -bn_mul_small -bn_mul_words -bn_odd_number_is_obviously_composite -bn_one_to_montgomery -bn_rand_range_words -bn_rand_secret_range -bn_reduce_once -bn_reduce_once_in_place -bn_resize_words -bn_rshift1_words -bn_rshift_secret_shift -bn_rshift_words -bn_select_words -bn_set_minimal_width -bn_set_words -bn_sqr_comba4 -bn_sqr_comba8 -bn_sqr_consttime -bn_sqr_small -bn_sqr_words -bn_sub_words -bn_to_montgomery_small -bn_uadd_consttime -bn_usub_consttime -bn_wexpand -boringssl_fips_self_test -bsaes_cbc_encrypt -bsaes_ctr32_encrypt_blocks -c2i_ASN1_BIT_STRING -c2i_ASN1_INTEGER -c2i_ASN1_OBJECT -cbb_add_latin1 -cbb_add_ucs2_be -cbb_add_utf32_be -cbb_add_utf8 -cbb_get_utf8_len -cbs_get_latin1 -cbs_get_ucs2_be -cbs_get_utf32_be -cbs_get_utf8 -d2i_ACCESS_DESCRIPTION -d2i_ASN1_BIT_STRING -d2i_ASN1_BMPSTRING -d2i_ASN1_BOOLEAN -d2i_ASN1_ENUMERATED -d2i_ASN1_GENERALIZEDTIME -d2i_ASN1_GENERALSTRING -d2i_ASN1_IA5STRING -d2i_ASN1_INTEGER -d2i_ASN1_NULL -d2i_ASN1_OBJECT -d2i_ASN1_OCTET_STRING -d2i_ASN1_PRINTABLE -d2i_ASN1_PRINTABLESTRING -d2i_ASN1_SEQUENCE_ANY -d2i_ASN1_SET_ANY -d2i_ASN1_T61STRING -d2i_ASN1_TIME -d2i_ASN1_TYPE -d2i_ASN1_UNIVERSALSTRING -d2i_ASN1_UTCTIME -d2i_ASN1_UTF8STRING -d2i_ASN1_VISIBLESTRING -d2i_AUTHORITY_INFO_ACCESS -d2i_AUTHORITY_KEYID -d2i_AutoPrivateKey -d2i_BASIC_CONSTRAINTS -d2i_CERTIFICATEPOLICIES -d2i_CRL_DIST_POINTS -d2i_DHparams -d2i_DHparams_bio -d2i_DIRECTORYSTRING -d2i_DISPLAYTEXT -d2i_DIST_POINT -d2i_DIST_POINT_NAME -d2i_DSAPrivateKey -d2i_DSAPrivateKey_bio -d2i_DSAPrivateKey_fp -d2i_DSAPublicKey -d2i_DSA_PUBKEY -d2i_DSA_PUBKEY_bio -d2i_DSA_PUBKEY_fp -d2i_DSA_SIG -d2i_DSAparams -d2i_ECDSA_SIG -d2i_ECParameters -d2i_ECPrivateKey -d2i_ECPrivateKey_bio -d2i_ECPrivateKey_fp -d2i_EC_PUBKEY -d2i_EC_PUBKEY_bio -d2i_EC_PUBKEY_fp -d2i_EDIPARTYNAME -d2i_EXTENDED_KEY_USAGE -d2i_GENERAL_NAME -d2i_GENERAL_NAMES -d2i_ISSUING_DIST_POINT -d2i_NETSCAPE_SPKAC -d2i_NETSCAPE_SPKI -d2i_NOTICEREF -d2i_OTHERNAME -d2i_PKCS12 -d2i_PKCS12_bio -d2i_PKCS12_fp -d2i_PKCS7 -d2i_PKCS7_bio -d2i_PKCS8PrivateKey_bio -d2i_PKCS8PrivateKey_fp -d2i_PKCS8_PRIV_KEY_INFO -d2i_PKCS8_PRIV_KEY_INFO_bio -d2i_PKCS8_PRIV_KEY_INFO_fp -d2i_PKCS8_bio -d2i_PKCS8_fp -d2i_PKEY_USAGE_PERIOD -d2i_POLICYINFO -d2i_POLICYQUALINFO -d2i_PROXY_CERT_INFO_EXTENSION -d2i_PROXY_POLICY -d2i_PUBKEY -d2i_PUBKEY_bio -d2i_PUBKEY_fp -d2i_PrivateKey -d2i_PrivateKey_bio -d2i_PrivateKey_fp -d2i_PublicKey -d2i_RSAPrivateKey -d2i_RSAPrivateKey_bio -d2i_RSAPrivateKey_fp -d2i_RSAPublicKey -d2i_RSAPublicKey_bio -d2i_RSAPublicKey_fp -d2i_RSA_PSS_PARAMS -d2i_RSA_PUBKEY -d2i_RSA_PUBKEY_bio -d2i_RSA_PUBKEY_fp -d2i_SSL_SESSION -d2i_SSL_SESSION_bio -d2i_SXNET -d2i_SXNETID -d2i_USERNOTICE -d2i_X509 -d2i_X509_ALGOR -d2i_X509_ALGORS -d2i_X509_ATTRIBUTE -d2i_X509_AUX -d2i_X509_CERT_AUX -d2i_X509_CINF -d2i_X509_CRL -d2i_X509_CRL_INFO -d2i_X509_CRL_bio -d2i_X509_CRL_fp -d2i_X509_EXTENSION -d2i_X509_EXTENSIONS -d2i_X509_NAME -d2i_X509_NAME_ENTRY -d2i_X509_PUBKEY -d2i_X509_REQ -d2i_X509_REQ_INFO -d2i_X509_REQ_bio -d2i_X509_REQ_fp -d2i_X509_REVOKED -d2i_X509_SIG -d2i_X509_VAL -d2i_X509_bio -d2i_X509_fp -dsa_asn1_meth -ec_GFp_mont_add -ec_GFp_mont_dbl -ec_GFp_mont_felem_from_bytes -ec_GFp_mont_felem_mul -ec_GFp_mont_felem_sqr -ec_GFp_mont_felem_to_bytes -ec_GFp_mont_group_finish -ec_GFp_mont_group_init -ec_GFp_mont_group_set_curve -ec_GFp_mont_init_precomp -ec_GFp_mont_mul -ec_GFp_mont_mul_base -ec_GFp_mont_mul_batch -ec_GFp_mont_mul_precomp -ec_GFp_mont_mul_public_batch -ec_GFp_nistp_recode_scalar_bits -ec_GFp_simple_cmp_x_coordinate -ec_GFp_simple_felem_from_bytes -ec_GFp_simple_felem_to_bytes -ec_GFp_simple_group_finish -ec_GFp_simple_group_get_curve -ec_GFp_simple_group_init -ec_GFp_simple_group_set_curve -ec_GFp_simple_invert -ec_GFp_simple_is_at_infinity -ec_GFp_simple_is_on_curve -ec_GFp_simple_point_copy -ec_GFp_simple_point_init -ec_GFp_simple_point_set_to_infinity -ec_GFp_simple_points_equal -ec_affine_jacobian_equal -ec_affine_select -ec_affine_to_jacobian -ec_asn1_meth -ec_bignum_to_felem -ec_bignum_to_scalar -ec_cmp_x_coordinate -ec_compute_wNAF -ec_felem_add -ec_felem_equal -ec_felem_from_bytes -ec_felem_neg -ec_felem_non_zero_mask -ec_felem_select -ec_felem_sub -ec_felem_to_bignum -ec_felem_to_bytes -ec_get_x_coordinate_as_bytes -ec_get_x_coordinate_as_scalar -ec_group_new -ec_hash_to_curve_p384_xmd_sha512_sswu_draft07 -ec_hash_to_curve_p521_xmd_sha512_sswu_draft06 -ec_hash_to_scalar_p384_xmd_sha512_draft07 -ec_hash_to_scalar_p521_xmd_sha512_draft06 -ec_init_precomp -ec_jacobian_to_affine -ec_jacobian_to_affine_batch -ec_pkey_meth -ec_point_from_uncompressed -ec_point_mul_scalar -ec_point_mul_scalar_base -ec_point_mul_scalar_batch -ec_point_mul_scalar_precomp -ec_point_mul_scalar_public -ec_point_mul_scalar_public_batch -ec_point_select -ec_point_set_affine_coordinates -ec_point_to_bytes -ec_precomp_select -ec_random_nonzero_scalar -ec_scalar_add -ec_scalar_equal_vartime -ec_scalar_from_bytes -ec_scalar_from_montgomery -ec_scalar_inv0_montgomery -ec_scalar_is_zero -ec_scalar_mul_montgomery -ec_scalar_neg -ec_scalar_reduce -ec_scalar_select -ec_scalar_sub -ec_scalar_to_bytes -ec_scalar_to_montgomery -ec_scalar_to_montgomery_inv_vartime -ec_set_to_safe_point -ec_simple_scalar_inv0_montgomery -ec_simple_scalar_to_montgomery_inv_vartime -ed25519_asn1_meth -ed25519_pkey_meth -gcm_ghash_neon -gcm_ghash_nohw -gcm_ghash_v8 -gcm_gmult_neon -gcm_gmult_nohw -gcm_gmult_v8 -gcm_init_neon -gcm_init_nohw -gcm_init_v8 -i2a_ACCESS_DESCRIPTION -i2a_ASN1_ENUMERATED -i2a_ASN1_INTEGER -i2a_ASN1_OBJECT -i2a_ASN1_STRING -i2c_ASN1_BIT_STRING -i2c_ASN1_INTEGER -i2d_ACCESS_DESCRIPTION -i2d_ASN1_BIT_STRING -i2d_ASN1_BMPSTRING -i2d_ASN1_BOOLEAN -i2d_ASN1_ENUMERATED -i2d_ASN1_GENERALIZEDTIME -i2d_ASN1_GENERALSTRING -i2d_ASN1_IA5STRING -i2d_ASN1_INTEGER -i2d_ASN1_NULL -i2d_ASN1_OBJECT -i2d_ASN1_OCTET_STRING -i2d_ASN1_PRINTABLE -i2d_ASN1_PRINTABLESTRING -i2d_ASN1_SEQUENCE_ANY -i2d_ASN1_SET_ANY -i2d_ASN1_T61STRING -i2d_ASN1_TIME -i2d_ASN1_TYPE -i2d_ASN1_UNIVERSALSTRING -i2d_ASN1_UTCTIME -i2d_ASN1_UTF8STRING -i2d_ASN1_VISIBLESTRING -i2d_AUTHORITY_INFO_ACCESS -i2d_AUTHORITY_KEYID -i2d_BASIC_CONSTRAINTS -i2d_CERTIFICATEPOLICIES -i2d_CRL_DIST_POINTS -i2d_DHparams -i2d_DHparams_bio -i2d_DIRECTORYSTRING -i2d_DISPLAYTEXT -i2d_DIST_POINT -i2d_DIST_POINT_NAME -i2d_DSAPrivateKey -i2d_DSAPrivateKey_bio -i2d_DSAPrivateKey_fp -i2d_DSAPublicKey -i2d_DSA_PUBKEY -i2d_DSA_PUBKEY_bio -i2d_DSA_PUBKEY_fp -i2d_DSA_SIG -i2d_DSAparams -i2d_ECDSA_SIG -i2d_ECParameters -i2d_ECPrivateKey -i2d_ECPrivateKey_bio -i2d_ECPrivateKey_fp -i2d_EC_PUBKEY -i2d_EC_PUBKEY_bio -i2d_EC_PUBKEY_fp -i2d_EDIPARTYNAME -i2d_EXTENDED_KEY_USAGE -i2d_GENERAL_NAME -i2d_GENERAL_NAMES -i2d_ISSUING_DIST_POINT -i2d_NETSCAPE_SPKAC -i2d_NETSCAPE_SPKI -i2d_NOTICEREF -i2d_OTHERNAME -i2d_PKCS12 -i2d_PKCS12_bio -i2d_PKCS12_fp -i2d_PKCS7 -i2d_PKCS7_bio -i2d_PKCS8PrivateKeyInfo_bio -i2d_PKCS8PrivateKeyInfo_fp -i2d_PKCS8PrivateKey_bio -i2d_PKCS8PrivateKey_fp -i2d_PKCS8PrivateKey_nid_bio -i2d_PKCS8PrivateKey_nid_fp -i2d_PKCS8_PRIV_KEY_INFO -i2d_PKCS8_PRIV_KEY_INFO_bio -i2d_PKCS8_PRIV_KEY_INFO_fp -i2d_PKCS8_bio -i2d_PKCS8_fp -i2d_PKEY_USAGE_PERIOD -i2d_POLICYINFO -i2d_POLICYQUALINFO -i2d_PROXY_CERT_INFO_EXTENSION -i2d_PROXY_POLICY -i2d_PUBKEY -i2d_PUBKEY_bio -i2d_PUBKEY_fp -i2d_PrivateKey -i2d_PrivateKey_bio -i2d_PrivateKey_fp -i2d_PublicKey -i2d_RSAPrivateKey -i2d_RSAPrivateKey_bio -i2d_RSAPrivateKey_fp -i2d_RSAPublicKey -i2d_RSAPublicKey_bio -i2d_RSAPublicKey_fp -i2d_RSA_PSS_PARAMS -i2d_RSA_PUBKEY -i2d_RSA_PUBKEY_bio -i2d_RSA_PUBKEY_fp -i2d_SSL_SESSION -i2d_SSL_SESSION_bio -i2d_SXNET -i2d_SXNETID -i2d_USERNOTICE -i2d_X509 -i2d_X509_ALGOR -i2d_X509_ALGORS -i2d_X509_ATTRIBUTE -i2d_X509_AUX -i2d_X509_CERT_AUX -i2d_X509_CINF -i2d_X509_CRL -i2d_X509_CRL_INFO -i2d_X509_CRL_bio -i2d_X509_CRL_fp -i2d_X509_EXTENSION -i2d_X509_EXTENSIONS -i2d_X509_NAME -i2d_X509_NAME_ENTRY -i2d_X509_PUBKEY -i2d_X509_REQ -i2d_X509_REQ_INFO -i2d_X509_REQ_bio -i2d_X509_REQ_fp -i2d_X509_REVOKED -i2d_X509_SIG -i2d_X509_VAL -i2d_X509_bio -i2d_X509_fp -i2d_re_X509_CRL_tbs -i2d_re_X509_REQ_tbs -i2d_re_X509_tbs -i2o_ECPublicKey -i2s_ASN1_ENUMERATED -i2s_ASN1_ENUMERATED_TABLE -i2s_ASN1_INTEGER -i2s_ASN1_OCTET_STRING -i2t_ASN1_OBJECT -i2v_ASN1_BIT_STRING -i2v_GENERAL_NAME -i2v_GENERAL_NAMES -kBoringSSLRSASqrtTwo -kBoringSSLRSASqrtTwoLen -kOpenSSLReasonStringData -kOpenSSLReasonValues -kOpenSSLReasonValuesLen -level_add_node -level_find_node -lh_delete -lh_doall_arg -lh_free -lh_insert -lh_new -lh_num_items -lh_retrieve -lh_retrieve_key -lh_strhash -md4_block_data_order -o2i_ECPublicKey -pkcs12_iterations_acceptable -pkcs12_key_gen -pkcs12_pbe_encrypt_init -pkcs7_bundle -pkcs7_parse_header -pkcs8_pbe_decrypt -pmbtoken_exp0_blind -pmbtoken_exp0_client_key_from_bytes -pmbtoken_exp0_generate_key -pmbtoken_exp0_issuer_key_from_bytes -pmbtoken_exp0_read -pmbtoken_exp0_sign -pmbtoken_exp0_unblind -pmbtoken_exp1_blind -pmbtoken_exp1_client_key_from_bytes -pmbtoken_exp1_generate_key -pmbtoken_exp1_get_h_for_testing -pmbtoken_exp1_issuer_key_from_bytes -pmbtoken_exp1_read -pmbtoken_exp1_sign -pmbtoken_exp1_unblind -policy_cache_find_data -policy_cache_free -policy_cache_set -policy_cache_set_mapping -policy_data_free -policy_data_new -policy_node_cmp_new -policy_node_free -policy_node_match -rand_fork_unsafe_buffering_enabled -rsa_asn1_meth -rsa_default_decrypt -rsa_default_private_transform -rsa_default_sign_raw -rsa_default_size -rsa_pkey_meth -s2i_ASN1_INTEGER -s2i_ASN1_OCTET_STRING -sha1_block_data_order -sha256_block_data_order -sha256_block_data_order_neon -sha512_block_data_order -sha512_block_data_order_neon -sk_CRYPTO_BUFFER_call_copy_func -sk_CRYPTO_BUFFER_call_free_func -sk_SSL_CIPHER_call_cmp_func -sk_X509_NAME_call_cmp_func -sk_X509_NAME_call_copy_func -sk_X509_NAME_call_free_func -sk_X509_call_free_func -sk_deep_copy -sk_delete -sk_delete_ptr -sk_dup -sk_find -sk_free -sk_insert -sk_is_sorted -sk_new -sk_new_null -sk_num -sk_pop -sk_pop_free -sk_pop_free_ex -sk_push -sk_set -sk_set_cmp_func -sk_shift -sk_sort -sk_value -sk_zero -tree_find_sk -v2i_ASN1_BIT_STRING -v2i_GENERAL_NAME -v2i_GENERAL_NAMES -v2i_GENERAL_NAME_ex -v3_akey_id -v3_alt -v3_bcons -v3_cpols -v3_crl_invdate -v3_crl_num -v3_crl_reason -v3_crld -v3_delta_crl -v3_ext_ku -v3_freshest_crl -v3_idp -v3_info -v3_inhibit_anyp -v3_key_usage -v3_name_constraints -v3_ns_ia5_list -v3_nscert -v3_ocsp_accresp -v3_ocsp_nocheck -v3_pci -v3_pkey_usage_period -v3_policy_constraints -v3_policy_mappings -v3_sinfo -v3_skey_id -v3_sxnet -vpaes_ctr32_encrypt_blocks -vpaes_decrypt -vpaes_decrypt_key_to_bsaes -vpaes_encrypt -vpaes_encrypt_key_to_bsaes -vpaes_set_decrypt_key -vpaes_set_encrypt_key -x25519_asn1_meth -x25519_ge_add -x25519_ge_frombytes_vartime -x25519_ge_p1p1_to_p2 -x25519_ge_p1p1_to_p3 -x25519_ge_p3_to_cached -x25519_ge_scalarmult -x25519_ge_scalarmult_base -x25519_ge_scalarmult_small_precomp -x25519_ge_sub -x25519_ge_tobytes -x25519_pkey_meth -x25519_sc_reduce -x509_digest_sign_algorithm -x509_digest_verify_init -x509_print_rsa_pss_params -x509_rsa_ctx_to_pss -x509_rsa_pss_to_ctx -x509v3_bytes_to_hex -x509v3_hex_to_bytes -x509v3_looks_like_dns_name -x509v3_name_cmp diff --git a/demo/demo_client.c b/demo/demo_client.c index 5f20d8216..c223d5ea4 100644 --- a/demo/demo_client.c +++ b/demo/demo_client.c @@ -24,8 +24,10 @@ #include "xqc_hq.h" -#define XQC_PACKET_TMP_BUF_LEN 1600 -#define MAX_BUF_SIZE (100*1024*1024) +#define XQC_PACKET_TMP_BUF_LEN 1600 +#define MAX_BUF_SIZE (100*1024*1024) +#define XQC_INTEROP_TLS_GROUPS "X25519:P-256:P-384:P-521" + typedef enum xqc_demo_cli_alpn_type_s { ALPN_HQ, @@ -138,9 +140,10 @@ typedef struct xqc_demo_cli_quic_config_s { int token_len; /* token len */ char token[XQC_MAX_TOKEN_LEN]; /* token buf */ - char *cipher_suites; /* cipher suites */ + char *cipher_suites; /* cipher suites */ uint8_t use_0rtt; /* 0-rtt switch, default turned off */ + uint64_t keyupdate_pkt_threshold; /* packet limit of a single 1-rtt key, 0 for unlimited */ } xqc_demo_cli_quic_config_t; @@ -867,7 +870,9 @@ xqc_demo_cli_h3_request_read_notify(xqc_h3_request_t *h3_request, xqc_request_no user_stream->recv_body_len += read; } while (read > 0 && !fin); - printf("xqc_h3_request_recv_body size %zd, fin:%d\n", read, fin); + if (read > 0) { + printf("xqc_h3_request_recv_body size %zd, fin:%d\n", read, fin); + } if (fin) { user_stream->recv_fin = 1; @@ -1070,7 +1075,7 @@ xqc_demo_cli_init_engine_ssl_config(xqc_engine_ssl_config_t* cfg, xqc_demo_cli_c cfg->ciphers = XQC_TLS_CIPHERS; } - cfg->groups = XQC_TLS_GROUPS; + cfg->groups = XQC_INTEROP_TLS_GROUPS; } void @@ -1114,21 +1119,6 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings, break; } -#if 0 - xqc_conn_settings_t cs = { - .pacing_on = args->net_cfg.pacing, - .ping_on = 0, - .cong_ctrl_callback = cong_ctrl, - .cc_params = { - .customize_on = 1, - .init_cwnd = 32, - }, - .so_sndbuf = 1024*1024, - .proto_version = XQC_VERSION_V1, - .spurious_loss_detect_on = 1, - }; - *settings = cs; -#endif memset(settings, 0, sizeof(xqc_conn_settings_t)); settings->pacing_on = args->net_cfg.pacing; settings->cong_ctrl_callback = cong_ctrl; @@ -1137,6 +1127,7 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings, settings->so_sndbuf = 1024*1024; settings->proto_version = XQC_VERSION_V1; settings->spurious_loss_detect_on = 1; + settings->keyupdate_pkt_threshold = args->quic_cfg.keyupdate_pkt_threshold; } /* set client args to default values */ @@ -1158,6 +1149,7 @@ xqc_demo_cli_init_args(xqc_demo_cli_client_args_t *args) /* quic cfg */ args->quic_cfg.alpn_type = ALPN_HQ; strncpy(args->quic_cfg.alpn, "hq-interop", sizeof(args->quic_cfg.alpn)); + args->quic_cfg.keyupdate_pkt_threshold = UINT64_MAX; } void @@ -1254,6 +1246,7 @@ xqc_demo_cli_usage(int argc, char *argv[]) " -U Url. \n" " -k key out path\n" " -K Client's life circle time\n" + " -u key update packet threshold\n" , prog); } @@ -1262,7 +1255,7 @@ void xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args) { int ch = 0; - while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:")) != -1) { + while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:u:")) != -1) { switch (ch) { /* server ip */ case 'a': @@ -1388,6 +1381,12 @@ xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args xqc_demo_cli_parse_urls(optarg, args); break; + /* key update packet threshold */ + case 'u': + printf("key update packet threshold: %s\n", optarg); + args->quic_cfg.keyupdate_pkt_threshold = atoi(optarg); + break; + default: printf("other option :%c\n", ch); xqc_demo_cli_usage(argc, argv); @@ -1653,6 +1652,25 @@ xqc_demo_cli_init_alpn_ctx(xqc_demo_cli_ctx_t *ctx) { int ret = 0; + xqc_hq_callbacks_t hq_cbs = { + .hqc_cbs = { + .conn_create_notify = xqc_demo_cli_hq_conn_create_notify, + .conn_close_notify = xqc_demo_cli_hq_conn_close_notify, + }, + .hqr_cbs = { + .req_close_notify = xqc_demo_cli_hq_req_close_notify, + .req_read_notify = xqc_demo_cli_hq_req_read_notify, + .req_write_notify = xqc_demo_cli_hq_req_write_notify, + } + }; + + /* init hq context */ + ret = xqc_hq_ctx_init(ctx->engine, &hq_cbs); + if (ret != XQC_OK) { + printf("init hq context error, ret: %d\n", ret); + return ret; + } + xqc_h3_callbacks_t h3_cbs = { .h3c_cbs = { .h3_conn_create_notify = xqc_demo_cli_h3_conn_create_notify, @@ -1674,25 +1692,6 @@ xqc_demo_cli_init_alpn_ctx(xqc_demo_cli_ctx_t *ctx) return ret; } - xqc_hq_callbacks_t hq_cbs = { - .hqc_cbs = { - .conn_create_notify = xqc_demo_cli_hq_conn_create_notify, - .conn_close_notify = xqc_demo_cli_hq_conn_close_notify, - }, - .hqr_cbs = { - .req_close_notify = xqc_demo_cli_hq_req_close_notify, - .req_read_notify = xqc_demo_cli_hq_req_read_notify, - .req_write_notify = xqc_demo_cli_hq_req_write_notify, - } - }; - - /* init hq context */ - ret = xqc_hq_ctx_init(ctx->engine, &hq_cbs); - if (ret != XQC_OK) { - printf("init hq context error, ret: %d\n", ret); - return ret; - } - return ret; } diff --git a/demo/demo_server.c b/demo/demo_server.c index a219d7646..643a13f8f 100644 --- a/demo/demo_server.c +++ b/demo/demo_server.c @@ -1311,6 +1311,26 @@ xqc_demo_svr_init_alpn_ctx(xqc_demo_svr_ctx_t *ctx) { int ret = 0; + xqc_hq_callbacks_t hq_cbs = { + .hqc_cbs = { + .conn_create_notify = xqc_demo_svr_hq_conn_create_notify, + .conn_close_notify = xqc_demo_svr_hq_conn_close_notify, + }, + .hqr_cbs = { + .req_create_notify = xqc_demo_svr_hq_req_create_notify, + .req_close_notify = xqc_demo_svr_hq_req_close_notify, + .req_read_notify = xqc_demo_svr_hq_req_read_notify, + .req_write_notify = xqc_demo_svr_hq_req_write_notify, + } + }; + + /* init hq context */ + ret = xqc_hq_ctx_init(ctx->engine, &hq_cbs); + if (ret != XQC_OK) { + printf("init hq context error, ret: %d\n", ret); + return ret; + } + xqc_h3_callbacks_t h3_cbs = { .h3c_cbs = { .h3_conn_create_notify = xqc_demo_svr_h3_conn_create_notify, @@ -1332,26 +1352,6 @@ xqc_demo_svr_init_alpn_ctx(xqc_demo_svr_ctx_t *ctx) return ret; } - xqc_hq_callbacks_t hq_cbs = { - .hqc_cbs = { - .conn_create_notify = xqc_demo_svr_hq_conn_create_notify, - .conn_close_notify = xqc_demo_svr_hq_conn_close_notify, - }, - .hqr_cbs = { - .req_create_notify = xqc_demo_svr_hq_req_create_notify, - .req_close_notify = xqc_demo_svr_hq_req_close_notify, - .req_read_notify = xqc_demo_svr_hq_req_read_notify, - .req_write_notify = xqc_demo_svr_hq_req_write_notify, - } - }; - - /* init hq context */ - ret = xqc_hq_ctx_init(ctx->engine, &hq_cbs); - if (ret != XQC_OK) { - printf("init hq context error, ret: %d\n", ret); - return ret; - } - return ret; } diff --git a/demo/xqc_hq_ctx.c b/demo/xqc_hq_ctx.c index 0a4f0a1e0..efd30465a 100644 --- a/demo/xqc_hq_ctx.c +++ b/demo/xqc_hq_ctx.c @@ -41,9 +41,8 @@ xqc_hq_ctx_init(xqc_engine_t *engine, xqc_hq_callbacks_t *hq_cbs) }; /* register ALPN and Application-Layer-Protocol callbacks */ - if (xqc_engine_register_alpn(engine, XQC_ALPN_HQ_29, XQC_ALPN_HQ_29_LEN, &ap_cbs) != XQC_OK - || xqc_engine_register_alpn(engine, XQC_ALPN_HQ_INTEROP, XQC_ALPN_HQ_INTEROP_LEN, &ap_cbs) - != XQC_OK) + if (xqc_engine_register_alpn(engine, XQC_ALPN_HQ_INTEROP, XQC_ALPN_HQ_INTEROP_LEN, &ap_cbs) != XQC_OK + || xqc_engine_register_alpn(engine, XQC_ALPN_HQ_29, XQC_ALPN_HQ_29_LEN, &ap_cbs) != XQC_OK) { xqc_hq_ctx_destroy(engine); return -XQC_EFATAL; diff --git a/docs/docs-zh/CONTRIBUTING-zh.md b/docs/docs-zh/CONTRIBUTING-zh.md index c4e7cf450..db4d77487 100644 --- a/docs/docs-zh/CONTRIBUTING-zh.md +++ b/docs/docs-zh/CONTRIBUTING-zh.md @@ -112,7 +112,7 @@ _类型_: _举例_: ```bash -[~]: Update CONTRIBUTING.md +[~] Update CONTRIBUTING.md ``` #### 测试 diff --git a/docs/docs-zh/Event_log-zh.md b/docs/docs-zh/Event_log-zh.md new file mode 100644 index 000000000..a647bf78f --- /dev/null +++ b/docs/docs-zh/Event_log-zh.md @@ -0,0 +1,728 @@ +# event_log 模块 + +## 模块介绍 + +event_log模块是log模块的扩展功能模块,目的是结合qlog规范定义的事件类型规范化日志打印。 +qlog规范:https://datatracker.ietf.org/doc/draft-marx-qlog-event-definitions-quic-h3/ + +## 模块使用 + +### 开启event_log功能 + +#### 编译时 + +在cmake编译xquic时添加“-DXQC_ENABLE_EVENT_LOG=1”将编译event_log相关功能,默认状态不编译。 + +#### 运行时 + +通过xqc_engine_create函数创建engine对象时,根据传入的xqc_config_t对象的cfg_log_event参数选择是否启用event_log功能,当cfg_log_event>0时开启。 + +### 使用event_log功能 + +#### 调用事件日志打印 + +在事件发生的位置调用xqc_log_event函数 + +```C +xqc_log_event(log, 事件类型, 事件相关参数); +``` + +> 其中log为xqc_log_t对象,编译时会根据事件类型检查传入的事件相关参数与事件的回调函数格式是否符合。 + +现有qlog事件相关参数如下(详见xqc_log_event_callback.h): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

事件类型

+
+

事件相关参数

+
+

CON_CONNECTION_STARTED

+
+

xqc_connection_t *conn, xqc_int_t local

+
+

CON_CONNECTION_CLOSED

+
+

xqc_connection_t *conn

+
+

CON_CONNECTION_ID_UPDATED

+
+

xqc_connection_t *conn

+
+

CON_CONNECTION_STATE_UPDATED

+
+

xqc_connection_t *conn

+
+

SEC_KEY_UPDATED

+
+

xqc_engine_ssl_config_t ssl_config, + xqc_int_t local

+
+

TRA_VERSION_INFORMATION

+
+

uint32_t local_count, uint32_t *local_version, + uint32_t remote_count, uint32_t *remote_version, uint32_t choose

+
+

TRA_ALPN_INFORMATION

+
+

size_t local_count, uint8_t *local_alpn, + size_t remote_count, const uint8_t *remote_alpn, size_t alpn_len, const + unsigned char *alpn

+
+

TRA_PARAMETERS_SET

+
+

xqc_connection_t *conn, xqc_int_t local

+
+

TRA_PACKET_SENT

+
+

xqc_packet_out_t *packet_out

+
+

TRA_PACKET_RECEIVED

+
+

xqc_packet_in_t *packet_in

+
+

TRA_PACKET_BUFFERED

+
+

xqc_packet_in_t *packet_in

+
+

TRA_PACKETS_ACKED

+
+

xqc_packet_in_t *packet_in, + xqc_packet_number_t high, xqc_packet_number_t low

+
+

TRA_DATAGRAMS_SENT

+
+

ssize_t size

+
+

TRA_DATAGRAMS_RECEIVED

+
+

ssize_t size

+
+

TRA_STREAM_STATE_UPDATED

+
+

xqc_stream_t *stream, xqc_int_t + stream_type, xqc_int_t state

+
+

TRA_FRAMES_PROCESSED

+
+

根据frame类型不同,传入参数不同

+
+

REC_PARAMETERS_SET

+
+

xqc_send_ctl_t *ctl

+
+

REC_METRICS_UPDATED

+
+

xqc_send_ctl_t *ctl

+
+

REC_CONGESTION_STATE_UPDATED

+
+

char *new_state

+
+

REC_LOSS_TIMER_UPDATED

+
+

xqc_send_ctl_t *ctl,

+

xqc_usec_t inter_time, + xqc_int_t type, xqc_int_t event

+
+

REC_PACKET_LOST

+
+

xqc_packet_out_t *packet_out

+
+

HTTP_PARAMETERS_SET

+
+

xqc_h3_conn_t *h3_conn, xqc_int_t local

+
+

HTTP_PARAMETERS_RESTORED

+
+

xqc_h3_conn_t *h3_conn

+
+

HTTP_STREAM_TYPE_SET

+
+

xqc_h3_stream_t *h3_stream, xqc_int_t + local

+
+

HTTP_FRAME_CREATED

+
+

根据frame类型不同,传入参数不同

+
+

HTTP_FRAME_PARSED

+
+

xqc_h3_stream_t *h3_stream

+
+

HTTP_SETTING_PARSED

+
+

uint64_t identifier, uint64_t value

+
+

QPACK_STATE_UPDATED

+
+

根据类型属于编码器/解码器,传入参数不同

+
+

QPACK_STREAM_STATE_UPDATED

+
+

xqc_h3_stream_t *h3_stream

+
+

QPACK_DYNAMIC_TABLE_UPDATED

+
+

根据动态表插入/删除,传入参数不同

+
+

QPACK_HEADERS_ENCODED

+
+

根据prefixheader,传入参数不同

+
+

QPACK_HEADERS_DECODED

+
+

根据prefixheader,传入参数不同

+
+

QPACK_INSTRUCTION_CREATED

+
+

根据指令不同,传入参数不同

+
+

QPACK_INSTRUCTION_PARSED

+
+

根据指令不同,传入参数不同

+
+

GEN_REPORT

+
+

report级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_FATAL

+
+

fatal级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_ERROR

+
+

error级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_WARN

+
+

warn级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_STATS

+
+

stats级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_INFO

+
+

info级别通用日志打印,类似printf传入格式化字符串和参数

+
+

GEN_DEBUG

+
+

debug级别通用日志打印,类似printf传入格式化字符串和参数

+
+ +#### 注册新事件 + +在已实现的qlog事件基础上可根据实现特点和需求注册自定义的事件,注册新事件方法如下: + +* 在xqc_log.h的xqc_log_type_t枚举类中添加事件名 + +```C +typedef enum { + /* connectivity event */ + CON_SERVER_LISTENING, + CON_CONNECTION_STARTED, + CON_CONNECTION_CLOSED, + CON_CONNECTION_ID_UPDATED, + CON_SPIN_BIM_UPDATED, + CON_CONNECTION_STATE_UPDATED, + + ... ... +} xqc_log_type_t; +``` + +* 在xqc_log.c的xqc_log_type_str函数中添加事件对应的事件名表示 + +```C +const char * +xqc_log_type_str(xqc_log_type_t type) +{ + static const char* event_type2str[] = { + [CON_SERVER_LISTENING] = "server_listening", + [CON_CONNECTION_STARTED] = "connection_started", + [CON_CONNECTION_CLOSED] = "connection_closed", + [CON_CONNECTION_ID_UPDATED] = "connection_id_updated", + [CON_SPIN_BIM_UPDATED] = "spin_bin_updated", + [CON_CONNECTION_STATE_UPDATED] = "connection_state_updated", + + ... ... + }; + return event_type2str[type]; +} +``` + +> 形如:\[事件类型\] = "事件名" + +* 在xqc_log.c的xqc_log_type_2_level函数中设置事件的日志级别 + +```C +xqc_log_level_t +xqc_log_type_2_level(xqc_log_type_t type) +{ + switch (type) { + case GEN_REPORT: + return XQC_LOG_REPORT; + case GEN_FATAL: + return XQC_LOG_FATAL; + case GEN_ERROR: + return XQC_LOG_ERROR; + case GEN_WARN: + return XQC_LOG_WARN; + + ... ... +} +``` + +* 在xqc_log_event_callback.h中定义日志的回调函数,回调函数格式为 + +```C +xqc_log_事件类型_callback(xqc_log_t *log, const char *func, ...) +``` + +> 传参的log和func为固定参数,可选参数部分为事件相关的参数 + +* 在xqc_log_event_callback.c中实现日志的回调函数,根据事件类型规范日志格式并调用xqc_log_implement函数(定义在xqc_log.h中,使用方式类似printf函数)打印 + +```C +xqc_log_implement(log, 事件类型, func, 日志格式, 打印参数); +``` + +### event_log日志分析 + +#### 日志格式 + +```text +[时间] [事件名] |scid:所属连接的scid|打印日志的函数名|打印日志内容| +``` + +> 事件的具体打印内容和格式详见xqc_log_event_callback.c文件 + +常用grep: +> 过滤特定事件:grep "\[事件名\]" +> +> 过滤特定连接:grep "|scid:所属连接的scid|" + +#### 后处理将日志转换为qlog格式 + +通过python等脚本语言将日志格式转变为qlog规范中定义的格式(.qlog) --- todo + +借助 [qvis](https://qvis.quictools.info/#/files) (一个针对qlog规范的可视化工具)解析.qlog文件,方便使用者分析学习xquic的传输过程。 diff --git a/docs/docs-zh/FAQ-zh.md b/docs/docs-zh/FAQ-zh.md new file mode 100644 index 000000000..00ccf9a93 --- /dev/null +++ b/docs/docs-zh/FAQ-zh.md @@ -0,0 +1,70 @@ +# FAQ + +> 支持的协议版本 + +* draft-29 +* version 1 + +> 依赖项 + +因需要 TLS 1.3 功能依赖 SSL 库,下面两者可二选一(都支持),由编译选项控制: +* BoringSSL +* BabaSSL + +如果需要跑 test client/test server 或者本地回归测试,需要安装: +* libevent +* CUnit + +> 编译方法 + +见 [QuickStart](https://github.com/alibaba/xquic#quickstart-guide) + +> XQUIC 还支持什么平台?其他平台如何编译? + +XQUIC 支持 Android、iOS、Linux 和 MacOS,编译方法参见 [Platforms](../Platforms.md)。 + +> 在各平台的编译产物大小 + +* Android + - 包含BoringSSL:v8a(64位) - 1.3MB,v7a(32位) - 947KB + - 不包含BoringSSL:v8a(64位) - 363KB, v7a(32位) - 275KB +* iOS + - 包含BoringSSL:arm64 - 1.13 MB, armv7 - 0.9MB + - 不包含BoringSSL:arm64 - 325KB,armv7 - 289KB + +> 为什么我编译出来包体积那么大? + +需要使用各个平台的 toolchain 进行压缩 +* Linux/MacOS 下可以通过运行 `strip libxquic.so` 命令进行压缩。 +* Android 可以使用交叉编译工具链压缩,例如: +``` +aarch64-linux-android-strip release/arm64-v8a/libxquic.so +arm-linux-androideabi-strip release/armeabi-v7a/libxquic.so +``` +* iOS 可以使用 Xcode 环境里安装的 strip 工具,例如: +``` +strip arm64/libxquic.a +``` + +> 基本功能支持情况 + +* 0-RTT +* 连接迁移(分支) +* ... + +其他功能支持情况,参考互通性验证:https://interop.seemann.io/ + +> 当前尚未支持 xxx 功能(例如 multipath),未来是否有计划支持? + +请先查询 [Milestones](https://github.com/alibaba/xquic/milestones) 中是否计划支持该功能,如果你想要的功能暂时不在我们的计划中,可以通过 Issue 提交 New Feature Request。 + +> QUIC-LB支持:负载分发与均衡 + +XQUIC是一个纯协议实现库,只包含协议栈能力,没有负载均衡功能。 +QUIC-LB草案主要是规约CID生成算法。 +XQUIC支持以cid generate callback形式由上层生成&设置CID; +上层未设置callback情况下,由XQUIC内部随机生成CID。 + +> 同一个 connection 的多个 stream 可以在多个线程中使用吗? + +XQUIC 不支持同一个连接跑在不同的线程上。建议用同一个线程处理相同xquic connection的socket IO和stream/request读写,如果业务必须在不同线程上处理不同stream/request,可以采用其他方式进行线程间通信,比如共享进程内存、unix socket,IO线程收到stream/request数据后转发给业务线程。 \ No newline at end of file diff --git a/docs/docs-zh/README-zh.md b/docs/docs-zh/README-zh.md index 6ecbb7dd6..b62c0be7b 100644 --- a/docs/docs-zh/README-zh.md +++ b/docs/docs-zh/README-zh.md @@ -84,8 +84,8 @@ sh ../scripts/xquic_test.sh ## 文档 -* 关于API的使用,详见 [API文档](../../docs/API.md). -* 关于平台支持的细节,详见 [平台文档](../../docs/Platforms.md). +* 关于API的使用,详见 [API文档](../../docs/API.md)。 +* 关于平台支持的细节,详见 [平台文档](../../docs/Platforms.md)。 * 关于 IETF QUIC Protocol 的中文翻译,详见翻译文档。 - 以下翻译均基于 draft-34,RFC的翻译工作正在进行中。 - [draft-ietf-quic-invariants-13-zh](../../docs/translation/draft-ietf-quic-invariants-13-zh.md) @@ -94,8 +94,9 @@ sh ../scripts/xquic_test.sh - [draft-ietf-quic-tls-34-zh](../../docs/translation/draft-ietf-quic-tls-34-zh.md) - [draft-ietf-quic-http-34-zh](../../docs/translation/draft-ietf-quic-http-34-zh.md) - [draft-ietf-quic-qpack-21-zh](../../docs/translation/draft-ietf-quic-qpack-21-zh.md) - -* 关于常见问题,参见 [FAQs](../../docs/FAQ.md). +* 关于event_log模块的使用, 详见 [Event_log module docs](./docs/docs-zh/Event_log-zh.md)。 +* 关于测试,参见 [测试文档](./docs/docs-zh/Testing-zh.md)。 +* 关于常见问题,参见 [FAQs](./docs/docs-zh/FAQ-zh.md) 和 [Trouble Shooting Guide](./docs/docs-zh/Troubleshooting-zh.md)。 ## Contributing diff --git a/docs/docs-zh/Testing-zh.md b/docs/docs-zh/Testing-zh.md new file mode 100644 index 000000000..aab8e660e --- /dev/null +++ b/docs/docs-zh/Testing-zh.md @@ -0,0 +1,74 @@ +# Testing XQUIC + +本文档主要描述了如何使用 test_client 和 test_server 进行测试。 + +## 运行步骤 + +在运行 test_server 之前,需要先生成证书: + +```bash +cd build +keyfile=server.key +certfile=server.crt +openssl req -newkey rsa:2048 -x509 -nodes -keyout "$keyfile" -new -out "$certfile" -subj /CN=test.xquic.com +``` + +运行 test_client 和 test_server: + +```bash +./test_server -l d > /dev/null & +./test_client -a 127.0.0.1 -p 8443 -s 1024000 -E +``` + +## 参数含义 + +以下参数都可以在 tests/test_client.c 和 tests/test_server.c 的 `usage()` 中找到对应说明,如本文档有更新滞后的情况,请以最新代码为准。 + +### test_client + +| Option | Usage | +| :----: | ---- | +| -a | Server addr. | +| -p | Server port. | +| -P | Number of Parallel requests per single connection. Default 1. | +| -n | Total number of requests to send. Defaults 1. | +| -c | Congestion Control Algorithm. r:reno b:bbr c:cubic B:bbr2 bbr+ bbr2+ | +| -C | Pacing on. | +| -t | Connection timeout. Default 3 seconds. | +| -T | Transport layer. No HTTP3. | +| -1 | Force 1RTT. | +| -s | Body size to send. | +| -w | Write received body to file. | +| -r | Read sending body from file. priority s > r | +| -l | Log level. e:error d:debug. | +| -E | Echo check on. Compare sent data with received data. | +| -d | Drop rate ‰. | +| -u | Url. default https://test.xquic.com/path/resource | +| -H | Header. eg. key:value | +| -h | Host & sni. eg. test.xquic.com | +| -G | GET on. Default is POST | +| -x | Test case ID | +| -N | No encryption | +| -6 | IPv6 | +| -V | Force cert verification. 0: don't allow self-signed cert. 1: allow self-signed cert. | +| -q | name-value pair num of request header, default and larger than 6 | +| -o | Output log file path, default ./clog | + +### test_server + +| Option | Usage | +| :----: | ---- | +| -p | Server port. | +| -e | Echo. Send received body. | +| -c | Congestion Control Algorithm. r:reno b:bbr c:cubic B:bbr2 bbr+ bbr2+ | +| -C | Pacing on. | +| -s | Body size to send. | +| -w | Write received body to file. | +| -r | Read sending body from file. priority e > s > r | +| -l | Log level. e:error d:debug. | +| -u | Url. default https://test.xquic.com/path/resource | +| -x | Test case ID | +| -6 | IPv6 | +| -b | batch | +| -S | server sid | +| -o | Output log file path, default ./slog | diff --git a/docs/docs-zh/Troubleshooting-zh.md b/docs/docs-zh/Troubleshooting-zh.md new file mode 100644 index 000000000..2c90f1196 --- /dev/null +++ b/docs/docs-zh/Troubleshooting-zh.md @@ -0,0 +1,26 @@ +# Trouble Shooting Guide + +> iOS 编译失败 + +类似 [Discussions #21](https://github.com/alibaba/xquic/discussions/21) 的问题,最新版本已经fix,请拉取最新代码。 + +> MacOS 编译失败 + +先检查是否添加了 `-DPLATFORM=mac` 参数。 + +> 首次运行 test_server 后,报错:error create engine + +需要先生成证书,见 [Testing](./Testing-zh.md)。 + +> 运行 test_client 时,更改 host of url 后报错,例如:[#67](https://github.com/alibaba/xquic/issues/67) +> +> ./test_client -u "https://aaa.test/1M" -G -a 127.0.0.1 -p 443 (success) +> +> ./test_client -u "https://bbb.test/1M" -G -a 127.0.0.1 -p 443 (failed) + +测试程序没有按照域名来保存文件,需要手动删除session ticket、传输参数、token + +``` +cd build +rm -f test_session tp_localhost xqc_token +``` \ No newline at end of file diff --git a/include/xquic/xqc_errno.h b/include/xquic/xqc_errno.h index 97ab82197..b81ed5cf4 100644 --- a/include/xquic/xqc_errno.h +++ b/include/xquic/xqc_errno.h @@ -169,6 +169,8 @@ typedef enum { XQC_TLS_DERIVE_KEY_ERROR = 741, XQC_TLS_DO_HANDSHAKE_ERROR = 742, XQC_TLS_POST_HANDSHAKE_ERROR = 743, + XQC_TLS_UPDATE_KEY_ERROR = 744, + XQC_TLS_DECRYPT_WHEN_KU_ERROR = 745, XQC_TLS_ERR_MAX, } xqc_tls_error_t; diff --git a/include/xquic/xqc_http3.h b/include/xquic/xqc_http3.h index d9490828f..82613a017 100644 --- a/include/xquic/xqc_http3.h +++ b/include/xquic/xqc_http3.h @@ -118,9 +118,16 @@ typedef struct xqc_http_headers_s { typedef struct xqc_request_stats_s { size_t send_body_size; size_t recv_body_size; - size_t send_header_size; /* compressed header size */ - size_t recv_header_size; /* compressed header size */ - int stream_err; /* QUIC layer error code, 0 for no error */ + size_t send_header_size; /* compressed header size */ + size_t recv_header_size; /* compressed header size */ + int stream_err; /* QUIC layer error code, 0 for no error */ + xqc_msec_t blocked_time; /* time of h3 stream being blocked */ + xqc_msec_t unblocked_time; /* time of h3 stream being unblocked */ + xqc_msec_t stream_fin_time; /* time of receiving transport fin */ + xqc_msec_t h3r_begin_time; /* time of creating request */ + xqc_msec_t h3r_end_time; /* time of request fin */ + xqc_msec_t h3r_header_begin_time; /* time of receiving HEADERS frame */ + xqc_msec_t h3r_header_end_time; /* time of finishing processing HEADERS frame */ } xqc_request_stats_t; diff --git a/include/xquic/xquic.h b/include/xquic/xquic.h index 368b59c0c..5038e8eae 100644 --- a/include/xquic/xquic.h +++ b/include/xquic/xquic.h @@ -140,6 +140,17 @@ typedef struct xqc_log_callbacks_s { typedef int (*xqc_server_accept_pt)(xqc_engine_t *engine, xqc_connection_t *conn, const xqc_cid_t *cid, void *user_data); +/** + * @brief connection refused callback. corresponding to xqc_server_accept_pt callback function. + * this function will be invoked when a QUIC connection is refused by xquic due to security + * considerations, applications SHALL link the connection's lifetime between itself and xquic, and + * free the context if it was created during xqc_server_accept_pt. + * + * @param user_data the user_data parameter of connection + */ +typedef void (*xqc_server_refuse_pt)(xqc_engine_t *engine, xqc_connection_t *conn, + const xqc_cid_t *cid, void *user_data); + /** * @brief engine can't find connection related to input udp packet, and return a STATELESS_RESET * packet, implementations shall send this buffer back to peer. this callback function is almost the @@ -189,7 +200,7 @@ typedef xqc_save_string_pt xqc_save_session_pt; * transport parameters are use when initiating 0-RTT connections to avoid violating the server's * restriction, it shall be remembered with the same storage requirements and strategy as token. * When initiating a new connection, transport parameters is part of xqc_conn_ssl_config_t parameter -*/ + */ typedef xqc_save_string_pt xqc_save_trans_param_pt; /** @@ -395,6 +406,11 @@ typedef struct xqc_transport_callbacks_s { */ xqc_server_accept_pt server_accept; + /** + * connection refused by xquic. REQUIRED only for server + */ + xqc_server_refuse_pt server_refuse; + /* stateless reset callback */ xqc_stateless_reset_pt stateless_reset; @@ -761,6 +777,8 @@ typedef struct xqc_conn_settings_s { xqc_msec_t init_idle_time_out; /* initial idle timeout interval, effective before handshake completion */ xqc_msec_t idle_time_out; /* idle timeout interval, effective after handshake completion */ int32_t spurious_loss_detect_on; + uint32_t anti_amplification_limit; /* limit of anti-amplification, default 3 */ + uint64_t keyupdate_pkt_threshold; /* packet limit of a single 1-rtt key, 0 for unlimited */ } xqc_conn_settings_t; diff --git a/scripts/case_test.sh b/scripts/case_test.sh index d8454a346..dbc655bb5 100755 --- a/scripts/case_test.sh +++ b/scripts/case_test.sh @@ -35,7 +35,6 @@ function case_print_result() { } - clear_log echo -e "stream read notify fail ...\c" ./test_client -s 1024000 -l d -t 1 -E -x 12 >> clog @@ -822,8 +821,8 @@ grep_err_log clear_log echo -e "stream concurrency flow control ...\c" -./test_client -s 1 -l e -t 1 -E -P 1025 -G >> clog -if [[ `grep ">>>>>>>> pass:1" clog|wc -l` -eq 1024 ]]; then +./test_client -s 1 -l e -t 1 -E -P 1025 -G > ccfc.log +if [[ `grep ">>>>>>>> pass:1" ccfc.log|wc -l` -eq 1024 ]]; then echo ">>>>>>>> pass:1" case_print_result "stream_concurrency_flow_control" "pass" else @@ -831,6 +830,7 @@ else case_print_result "stream_concurrency_flow_control" "fail" fi grep_err_log|grep -v stream +rm -f ccfc.log clear_log echo -e "1% loss ...\c" @@ -1145,6 +1145,41 @@ else echo "$errlog" fi +killall test_server +./test_server -l d -e > /dev/null & +sleep 1 + +clear_log +echo -e "key update ...\c" +./test_client -s 102400 -l d -E -x 40 >> clog +result=`grep ">>>>>>>> pass" clog` +svr_res=`grep "key phase changed to" slog` +cli_res=`grep "key phase changed to" clog` +errlog=`grep_err_log` +if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ] && [ "$svr_res" != "" ] && [ "$cli_res" != "" ]; then + echo ">>>>>>>> pass:1" + case_print_result "key_update" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "key_update" "fail" +fi +grep_err_log + +clear_log +echo -e "key update 0RTT...\c" +./test_client -s 102400 -l d -E -x 40 >> clog +result=`grep ">>>>>>>> pass" clog` +svr_res=`grep "key phase changed to" slog` +cli_res=`grep "key phase changed to" clog` +errlog=`grep_err_log` +if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ] && [ "$svr_res" != "" ] && [ "$cli_res" != "" ]; then + echo ">>>>>>>> pass:1" + case_print_result "key_update_0RTT" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "key_update_0RTT" "fail" +fi +grep_err_log killall test_server diff --git a/scripts/xquic_test.sh b/scripts/xquic_test.sh index e00806b52..c4274ba75 100644 --- a/scripts/xquic_test.sh +++ b/scripts/xquic_test.sh @@ -2,7 +2,6 @@ #!/bin/bash - function generate_cert() { if [[ ! -f "server.key" || ! -f "server.crt" ]]; then keyfile=server.key @@ -23,7 +22,7 @@ function install_cunit() { } function install_go() { - sudo yum -y install go + sudo yum -y install golang } function build_babassl() { diff --git a/src/common/utils/2d_hash/xqc_2d_hash_table.c b/src/common/utils/2d_hash/xqc_2d_hash_table.c index 5abb1785f..302929546 100644 --- a/src/common/utils/2d_hash/xqc_2d_hash_table.c +++ b/src/common/utils/2d_hash/xqc_2d_hash_table.c @@ -15,11 +15,10 @@ typedef struct xqc_2d_hash_node_s { /* hash of second dimension */ uint64_t hash2; - /* - * the pointer of data, 2d-hash of data can be same, - * but all inserted data shall be unique. - * when comparing two different data with xqc_2d_hash_table_data_cmp, - * non-zero MUST be returned + /* + * the pointer of data. among different nodes, hash values are allowd to be + * same, while the data shall be unique. when comparing two different nodes + * with xqc_2d_hash_table_data_cmp, non-zero MUST be returned. */ void *data; } xqc_2d_hash_node_t; @@ -207,10 +206,10 @@ xqc_2d_hash_lookup(xqc_2d_hash_table_t *ht, uint64_t h1, void *v1, size_t len1, ret_cmp = ret_cb; *data = node->data; - /* - * as we put data at the head of a list, - * the first found 2d-matched data is always newest, - * can't find a better data, break and return this value + /* + * as we put data at the head of a list, the first found + * 2d-matched data is always newest and better, break and + * take this node as comparison result */ if (ret_cb == XQC_2D_CMP_RES_2D) { break; diff --git a/src/common/utils/ringarray/xqc_ring_array.c b/src/common/utils/ringarray/xqc_ring_array.c index fc4b0cb83..fb989d3cd 100644 --- a/src/common/utils/ringarray/xqc_ring_array.c +++ b/src/common/utils/ringarray/xqc_ring_array.c @@ -73,10 +73,10 @@ xqc_rarray_check_range(xqc_rarray_t *ra, uint64_t offset) { uint64_t eoffset = (ra->offset + ra->count) & ra->mask; /* end offset of rarray */ if (ra->offset >= eoffset) { - /* - * input offset is always in range [0, capacity), - * if rollover, ra->offset equals to eoffset, - * only if offset not exceed capacity, it is always in range + /* + * input offset is always in range [0, capacity), if rollover, + * ra->offset equals to eoffset, only if offset not exceed capacity, + * it is always in range. */ return offset >= ra->offset || offset < eoffset; diff --git a/src/common/utils/ringmem/xqc_ring_mem.c b/src/common/utils/ringmem/xqc_ring_mem.c index 40c0aeb6c..911bb68d7 100644 --- a/src/common/utils/ringmem/xqc_ring_mem.c +++ b/src/common/utils/ringmem/xqc_ring_mem.c @@ -11,10 +11,6 @@ #include "xqc_ring_mem.h" -/* - * circular memory, maintains a linear memory block, and can be used to store objects with - * Irregular sizes as a queue, xqc_ring_mem_t will maintain the memory as FIFO order - */ typedef struct xqc_ring_mem_s { /* original memory */ uint8_t *buf; @@ -349,9 +345,9 @@ xqc_ring_mem_duplicate(xqc_ring_mem_t *rmem, xqc_ring_mem_idx_t ori_idx, size_t } else { /* - * impossible 2 truncation happened in one ring mem, - * so if duplicated memory block is truncated, - * the original memory block MUST be continuous + * it is impossible that 2 truncation exist in one ring mem. Hence, if + * the duplicated memory block is truncated, the original memory block + * will always be continuous. */ size_t first_blk_size = rmem->capacity - soffset_dup; memmove(rmem->buf + soffset_dup, rmem->buf + soffset_ori, first_blk_size); diff --git a/src/http3/frame/xqc_h3_frame.c b/src/http3/frame/xqc_h3_frame.c index ebb5cf8eb..561deaba9 100644 --- a/src/http3/frame/xqc_h3_frame.c +++ b/src/http3/frame/xqc_h3_frame.c @@ -139,6 +139,28 @@ xqc_h3_frm_parse_max_push_id(const unsigned char *p, size_t sz, xqc_h3_frame_t * return pos - p; } +ssize_t +xqc_h3_frm_parse_reserved(const unsigned char *p, size_t sz, + xqc_h3_frame_t *frame, xqc_bool_t *fin) +{ + const unsigned char *pos = p; + size_t read = 0; + + *fin = XQC_FALSE; + + /* skip until all payload read or all bytes consumed */ + read = xqc_min(frame->len - frame->consumed_len, sz); + pos += read; + frame->consumed_len += read; + + /* all bytes consumed */ + if (frame->len == frame->consumed_len) { + *fin = XQC_TRUE; + } + + return pos - p; +} + ssize_t xqc_h3_frm_parse(const unsigned char *p, size_t sz, xqc_h3_frame_pctx_t *pctx) { @@ -208,7 +230,8 @@ xqc_h3_frm_parse(const unsigned char *p, size_t sz, xqc_h3_frame_pctx_t *pctx) break; } default: { - return -XQC_H3_INVALID_FRAME_TYPE; + XQC_H3_DECODE_FRM(xqc_h3_frm_parse_reserved, pos, sz, pctx->frame, &fin); + break; } } diff --git a/src/http3/frame/xqc_h3_frame_defs.h b/src/http3/frame/xqc_h3_frame_defs.h index e0ac46d13..10f2aa939 100644 --- a/src/http3/frame/xqc_h3_frame_defs.h +++ b/src/http3/frame/xqc_h3_frame_defs.h @@ -16,7 +16,7 @@ typedef enum xqc_h3_frm_type_s { XQC_H3_FRM_PUSH_PROMISE = 0x05, XQC_H3_FRM_GOAWAY = 0x07, XQC_H3_FRM_MAX_PUSH_ID = 0x0d, - XQC_H3_FRM_UNKNOWN = 0xff, + XQC_H3_FRM_UNKNOWN = UINT64_MAX, } xqc_h3_frm_type_t; diff --git a/src/http3/qpack/dtable/xqc_dtable.c b/src/http3/qpack/dtable/xqc_dtable.c index 9a46848f4..c2a313002 100644 --- a/src/http3/qpack/dtable/xqc_dtable.c +++ b/src/http3/qpack/dtable/xqc_dtable.c @@ -344,9 +344,9 @@ xqc_dtable_make_space(xqc_dtable_t *dt, size_t space) } /* - * if free memory is smaller than space, continue to check if there are entries - * can be evicted to make space. if min_ref is unlimited, all entries can be - * evicted + * if there is not enough unused memory, continue to check if it is possible + * to make space by evicting entries. + * NOTICE: if min_ref is unlimited, all entries can be evicted. */ if (dt->capacity - dt->used < space && dt->min_ref != XQC_INVALID_INDEX) { xqc_dtable_entry_t *first_entry = xqc_rarray_front(dt->entries); diff --git a/src/http3/qpack/xqc_encoder.c b/src/http3/qpack/xqc_encoder.c index e46010c5d..6063f79a2 100644 --- a/src/http3/qpack/xqc_encoder.c +++ b/src/http3/qpack/xqc_encoder.c @@ -48,7 +48,7 @@ typedef struct xqc_encoder_s { size_t name_len_limit; /* - * dtable insertion limit for entry. + * dtable insertion limit for entry. * insert_limit_entry_size = insert_limit_entry * dtable_cap */ double entry_limit; diff --git a/src/http3/xqc_h3_conn.c b/src/http3/xqc_h3_conn.c index 56a25dce6..c349d2fab 100644 --- a/src/http3/xqc_h3_conn.c +++ b/src/http3/xqc_h3_conn.c @@ -349,6 +349,7 @@ xqc_h3_conn_destroy(xqc_h3_conn_t *h3_conn) xqc_int_t xqc_h3_conn_on_uni_stream_created(xqc_h3_conn_t *h3c, uint64_t stype) { + uint64_t cflag; static const uint64_t stype_2_flag_map[] = { [XQC_H3_STREAM_TYPE_CONTROL] = XQC_H3_CONN_FLAG_CONTROL_OPENED, [XQC_H3_STREAM_TYPE_PUSH] = XQC_H3_CONN_FLAG_PUSH_OPENED, @@ -357,12 +358,12 @@ xqc_h3_conn_on_uni_stream_created(xqc_h3_conn_t *h3c, uint64_t stype) }; /* check if control and qpack streams are already created */ - uint64_t cflag = stype_2_flag_map[stype]; /* stream creation flag */ switch (stype) { case XQC_H3_STREAM_TYPE_CONTROL: case XQC_H3_STREAM_TYPE_PUSH: case XQC_H3_STREAM_TYPE_QPACK_ENCODER: case XQC_H3_STREAM_TYPE_QPACK_DECODER: + cflag = stype_2_flag_map[stype]; /* stream creation flag */ /* if control/encoder/decoder stream has been created, close connection */ if (h3c->flags & cflag) { xqc_log(h3c->log, XQC_LOG_ERROR, @@ -376,6 +377,7 @@ xqc_h3_conn_on_uni_stream_created(xqc_h3_conn_t *h3c, uint64_t stype) break; default: + /* reserved stream type, do nothing */ break; } @@ -512,7 +514,9 @@ xqc_h3_conn_on_settings_entry_received(uint64_t identifier, uint64_t value, void break; default: - return XQC_ERROR; + xqc_log(h3c->log, XQC_LOG_INFO, "|ignore unknown setting|identifier%ui|value:%ui", + identifier, value); + break; } return XQC_OK; diff --git a/src/http3/xqc_h3_ctx.c b/src/http3/xqc_h3_ctx.c index 1916ea1ed..26e96071b 100644 --- a/src/http3/xqc_h3_ctx.c +++ b/src/http3/xqc_h3_ctx.c @@ -38,8 +38,8 @@ xqc_h3_ctx_init(xqc_engine_t *engine, xqc_h3_callbacks_t *h3_cbs) }; /* register ALPN and transport layer callbacks */ - if (xqc_engine_register_alpn(engine, XQC_ALPN_H3_29, XQC_ALPN_H3_29_LEN, &ap_cbs) != XQC_OK - || xqc_engine_register_alpn(engine, XQC_ALPN_H3, XQC_ALPN_H3_LEN, &ap_cbs) != XQC_OK) + if (xqc_engine_register_alpn(engine, XQC_ALPN_H3, XQC_ALPN_H3_LEN, &ap_cbs) != XQC_OK + || xqc_engine_register_alpn(engine, XQC_ALPN_H3_29, XQC_ALPN_H3_29_LEN, &ap_cbs) != XQC_OK) { xqc_h3_ctx_destroy(engine); return -XQC_EFATAL; diff --git a/src/http3/xqc_h3_defs.h b/src/http3/xqc_h3_defs.h index e31ba15e6..2cfc45e2c 100644 --- a/src/http3/xqc_h3_defs.h +++ b/src/http3/xqc_h3_defs.h @@ -22,17 +22,17 @@ extern const char* const xqc_h3_alpn[]; #define XQC_H3_MAX_FIELD_SECTION_SIZE (32 * 1024) /* max buf size for converting uppercase filed line name to lowercase */ -#define XQC_H3_HEADERS_LOWERCASE_BUF_SIZE 4096 +#define XQC_H3_HEADERS_LOWERCASE_BUF_SIZE 4096 -#define XQC_VAR_BUF_INIT_SIZE (256) +#define XQC_VAR_BUF_INIT_SIZE (256) -#define XQC_VAR_BUF_CUT_SIZE (16 * 1024) +#define XQC_VAR_BUF_CUT_SIZE (16 * 1024) -#define XQC_DATA_BUF_SIZE_4K (4096) +#define XQC_DATA_BUF_SIZE_4K (4096) -#define XQC_H3_STREAM_MAX_FRM_PAYLOAD (4096) +#define XQC_H3_STREAM_MAX_FRM_PAYLOAD (4096) -#define XQC_H3_MAX_BUFFER_COUNT_SIZE (100) +#define XQC_H3_MAX_BUFFER_COUNT_SIZE (100) /* setting options */ diff --git a/src/http3/xqc_h3_request.c b/src/http3/xqc_h3_request.c index 93797526a..97cc1f15a 100644 --- a/src/http3/xqc_h3_request.c +++ b/src/http3/xqc_h3_request.c @@ -7,6 +7,7 @@ #include "src/transport/xqc_engine.h" #include "src/http3/xqc_h3_conn.h" #include "src/http3/xqc_h3_ctx.h" +#include "src/common/xqc_time.h" xqc_h3_request_t * @@ -46,6 +47,20 @@ xqc_h3_request_create(xqc_engine_t *engine, const xqc_cid_t *cid, void *user_dat void xqc_h3_request_destroy(xqc_h3_request_t *h3_request) { + xqc_h3_stream_t *h3s = h3_request->h3_stream; + + /* print request statistic log */ + xqc_request_stats_t stats = xqc_h3_request_get_stats(h3_request); + xqc_log(h3_request->h3_stream->log, XQC_LOG_REPORT, "|stream_id:%ui|err:%ui" + "|rcvd_bdy_sz:%uz|snd_bdy_sz:%uz|rcvd_hdr_sz:%uz|snd_hdr_sz:%uz" + "|blkd_tm:%ui|nblkd_tm:%ui|strm_fin_tm:%ui|h3r_s_tm:%ui|h3r_e_tm:%ui" + "|h3r_hdr_s_tm:%ui|h3r_hdr_e_tm:%ui|", h3s->stream_id, + stats.stream_err, stats.recv_body_size, stats.send_body_size, + stats.recv_header_size, stats.send_header_size, + stats.blocked_time, stats.unblocked_time, stats.stream_fin_time, + stats.h3r_begin_time, stats.h3r_end_time, + stats.h3r_header_begin_time, stats.h3r_header_end_time); + if (h3_request->request_if->h3_request_close_notify) { h3_request->request_if->h3_request_close_notify(h3_request, h3_request->user_data); } @@ -129,6 +144,8 @@ xqc_h3_request_create_inner(xqc_h3_conn_t *h3_conn, xqc_h3_stream_t *h3_stream, h3_request->request_if->h3_request_create_notify(h3_request, h3_request->user_data); } + xqc_h3_request_begin(h3_request); + return h3_request; } @@ -136,12 +153,21 @@ xqc_request_stats_t xqc_h3_request_get_stats(xqc_h3_request_t *h3_request) { xqc_request_stats_t stats; - uint64_t conn_err = h3_request->h3_stream->h3c->conn->conn_err; - stats.recv_body_size = h3_request->body_recvd; - stats.send_body_size = h3_request->body_sent; - stats.recv_header_size = h3_request->header_recvd; - stats.send_header_size = h3_request->header_sent; - stats.stream_err = conn_err != 0 ? conn_err : (int)xqc_h3_stream_get_err(h3_request->h3_stream); + + uint64_t conn_err = h3_request->h3_stream->h3c->conn->conn_err; + stats.recv_body_size = h3_request->body_recvd; + stats.send_body_size = h3_request->body_sent; + stats.recv_header_size = h3_request->header_recvd; + stats.send_header_size = h3_request->header_sent; + stats.stream_err = conn_err != 0 ? conn_err : (int)xqc_h3_stream_get_err(h3_request->h3_stream); + stats.blocked_time = h3_request->blocked_time; + stats.unblocked_time = h3_request->unblocked_time; + stats.stream_fin_time = h3_request->stream_fin_time; + stats.h3r_begin_time = h3_request->h3r_begin_time; + stats.h3r_end_time = h3_request->h3r_end_time; + stats.h3r_header_begin_time = h3_request->h3r_header_begin_time; + stats.h3r_header_end_time = h3_request->h3r_header_end_time; + return stats; } @@ -358,6 +384,9 @@ xqc_h3_request_recv_headers(xqc_h3_request_t *h3_request, uint8_t *fin) /* if there is body or trailer exists, recv fin together with body or trailer */ *fin = (h3_request->read_flag == XQC_REQ_NOTIFY_READ_HEADER) ? h3_request->fin_flag : 0; + if (*fin) { + xqc_h3_request_end(h3_request); + } /* unset read flag */ h3_request->read_flag &= ~XQC_REQ_NOTIFY_READ_HEADER; @@ -372,6 +401,9 @@ xqc_h3_request_recv_headers(xqc_h3_request_t *h3_request, uint8_t *fin) h3_request->h3_stream->h3c->conn); *fin = h3_request->fin_flag; + if (*fin) { + xqc_h3_request_end(h3_request); + } /* unset read flag */ h3_request->read_flag &= ~XQC_REQ_NOTIFY_READ_TRAILER; @@ -425,6 +457,7 @@ xqc_h3_request_recv_body(xqc_h3_request_t *h3_request, unsigned char *recv_buf, *fin = h3_request->fin_flag; if (*fin) { h3_request->body_recvd_final_size = h3_request->body_recvd; + xqc_h3_request_end(h3_request); } } @@ -460,6 +493,8 @@ xqc_h3_request_on_recv_header(xqc_h3_request_t *h3r) headers = &h3r->h3_header[h3r->current_header]; + xqc_h3_request_header_end(h3r); + /* header is too large */ if (headers->total_len > h3r->h3_stream->h3c->local_h3_conn_settings.max_field_section_size) @@ -525,12 +560,12 @@ xqc_h3_request_on_recv_empty_fin(xqc_h3_request_t *h3r) } h3r->fin_flag = 1; + xqc_h3_request_end(h3r); - /* - * if read flag is not XQC_REQ_NOTIFY_READ_NULL, - * it means that there is header or content not received by application, - * shall not notify empty fin event, application will be noticed when - * receiving header and content + /* + * if read flag is not XQC_REQ_NOTIFY_READ_NULL, it means that there is header or content not + * received by application, shall not notify empty fin event, application will be noticed when + * receiving header and content */ if (h3r->read_flag != XQC_REQ_NOTIFY_READ_NULL) { return XQC_OK; @@ -572,5 +607,53 @@ xqc_h3_request_get_writing_headers(xqc_h3_request_t *h3r) return NULL; } + xqc_h3_request_header_begin(h3r); return &h3r->h3_header[h3r->current_header]; } + +#define XQC_H3_REQUEST_RECORD_TIME(a) \ + if ((a) == 0) { \ + (a) = xqc_monotonic_timestamp(); \ + } \ + +void +xqc_h3_request_blocked(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->blocked_time); +} + +void +xqc_h3_request_unblocked(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->unblocked_time); +} + +void +xqc_h3_request_header_begin(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->h3r_header_begin_time); +} + +void +xqc_h3_request_header_end(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->h3r_header_end_time); +} + +void +xqc_h3_request_stream_fin(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->stream_fin_time); +} + +void +xqc_h3_request_begin(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->h3r_begin_time); +} + +void +xqc_h3_request_end(xqc_h3_request_t *h3r) +{ + XQC_H3_REQUEST_RECORD_TIME(h3r->h3r_end_time); +} diff --git a/src/http3/xqc_h3_request.h b/src/http3/xqc_h3_request.h index 2b884117f..12a78f59a 100644 --- a/src/http3/xqc_h3_request.h +++ b/src/http3/xqc_h3_request.h @@ -46,6 +46,15 @@ typedef struct xqc_h3_request_s { size_t body_sent; size_t body_sent_final_size; + /* statistic */ + xqc_msec_t blocked_time; /* time of h3 stream being blocked */ + xqc_msec_t unblocked_time; /* time of h3 stream being unblocked */ + xqc_msec_t stream_fin_time; /* time of receiving transport fin */ + xqc_msec_t h3r_begin_time; /* time of creating request */ + xqc_msec_t h3r_end_time; /* time of request fin */ + xqc_msec_t h3r_header_begin_time; /* time of receiving HEADERS frame */ + xqc_msec_t h3r_header_end_time; /* time of finishing processing HEADERS frame */ + } xqc_h3_request_t; @@ -67,5 +76,12 @@ xqc_int_t xqc_h3_request_on_recv_empty_fin(xqc_h3_request_t *h3r); /* get headers for writing */ xqc_http_headers_t *xqc_h3_request_get_writing_headers(xqc_h3_request_t *h3r); +void xqc_h3_request_blocked(xqc_h3_request_t *h3r); +void xqc_h3_request_unblocked(xqc_h3_request_t *h3r); +void xqc_h3_request_header_begin(xqc_h3_request_t *h3r); +void xqc_h3_request_header_end(xqc_h3_request_t *h3r); +void xqc_h3_request_stream_fin(xqc_h3_request_t *h3r); +void xqc_h3_request_begin(xqc_h3_request_t *h3r); +void xqc_h3_request_end(xqc_h3_request_t *h3r); #endif /* _XQC_H3_REQUEST_H_INCLUDED_ */ diff --git a/src/http3/xqc_h3_stream.c b/src/http3/xqc_h3_stream.c index bbf01fb6a..8d226b3b6 100644 --- a/src/http3/xqc_h3_stream.c +++ b/src/http3/xqc_h3_stream.c @@ -536,8 +536,10 @@ xqc_h3_stream_process_control(xqc_h3_stream_t *h3s, unsigned char *data, size_t processed += read; if (pctx->state != XQC_H3_FRM_STATE_END && data_len != processed) { - xqc_log(h3c->log, XQC_LOG_ERROR, "|parse frame state error|state:%d||data_len:%zu|" - "processed:%zu|", pctx->state, data_len, processed); + xqc_log(h3c->log, XQC_LOG_ERROR, "|parse frame state error|state:%d" + "|data_len:%uz|processed:%uz|type:%xL|len:%uz|consumed:%uz", + pctx->state, data_len, processed, pctx->frame.type, + pctx->frame.len, pctx->frame.consumed_len); xqc_h3_frm_reset_pctx(pctx); return -XQC_H3_DECODE_ERROR; } @@ -587,10 +589,10 @@ xqc_h3_stream_process_control(xqc_h3_stream_t *h3s, unsigned char *data, size_t break; default: - xqc_log(h3c->log, XQC_LOG_ERROR, "|xqc_h3_stream_process_control error" - "|error frame type:%z|", pctx->frame.type); - xqc_h3_frm_reset_pctx(pctx); - return -H3_FRAME_UNEXPECTED; + /* ignore unknown h3 frame */ + xqc_log(h3c->log, XQC_LOG_INFO, "|ignore unknown frame|" + "type:%xL|", pctx->frame.type); + break; } xqc_log_event(h3s->log, HTTP_FRAME_PARSED, h3s); @@ -620,8 +622,8 @@ xqc_h3_stream_process_push(xqc_h3_stream_t *h3s, unsigned char *data, size_t dat processed += read; if (pctx->state != XQC_H3_FRM_STATE_END && data_len != processed) { - xqc_log(h3s->log, XQC_LOG_ERROR, "|parse frame state error|state:%d||data_len:%zu|" - "processed:%zu|", pctx->state, data_len, processed); + xqc_log(h3s->log, XQC_LOG_ERROR, "|parse frame state error|state:%d||data_len:%uz|" + "processed:%uz|", pctx->state, data_len, processed); xqc_h3_frm_reset_pctx(pctx); return -XQC_H3_DECODE_ERROR; } @@ -635,10 +637,9 @@ xqc_h3_stream_process_push(xqc_h3_stream_t *h3s, unsigned char *data, size_t dat /* PUSH related is not implemented yet */ break; default: - xqc_log(h3s->log, XQC_LOG_ERROR, "|xqc_h3_stream_process_push error|error" - " frame type:%z|", pctx->frame.type); - xqc_h3_frm_reset_pctx(pctx); - return -H3_FRAME_UNEXPECTED; + xqc_log(h3s->log, XQC_LOG_INFO, "|ignore unknown frame|" + "frame type:%xL|", pctx->frame.type); + break; } xqc_log_event(h3s->log, HTTP_FRAME_PARSED, h3s); xqc_h3_frm_reset_pctx(pctx); @@ -686,20 +687,20 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t /* process request bytes */ while (processed < data_len) { - xqc_log(h3s->log, XQC_LOG_DEBUG, "|parse frame|state:%d|data_len:%d|process:%d|", + xqc_log(h3s->log, XQC_LOG_DEBUG, "|parse frame|state:%d|data_len:%uz|process:%z|", pctx->state, data_len, processed); /* parse frame, mainly the type, length field */ ssize_t read = xqc_h3_frm_parse(data + processed, data_len - processed, pctx); if (read < 0) { - xqc_log(h3s->log, XQC_LOG_ERROR, "|parse frame error|ret:%d|state:%d|frame_type:%d|", + xqc_log(h3s->log, XQC_LOG_ERROR, "|parse frame error|ret:%z|state:%d|frame_type:%xL|", read, pctx->state, pctx->frame.type); xqc_h3_frm_reset_pctx(pctx); return read; } - xqc_log(h3s->log, XQC_LOG_DEBUG, "|parse frame success|frame_type:%d|read:%z|", - pctx->frame.type, read); + xqc_log(h3s->log, XQC_LOG_DEBUG, "|parse frame success|frame_type:%xL|len:%ui|read:%z|", + pctx->frame.type, pctx->frame.len, read); processed += read; xqc_bool_t fin = pctx->state == XQC_H3_FRM_STATE_END ? XQC_TRUE : XQC_FALSE; @@ -721,7 +722,7 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t hdrs, fin, &blocked); if (read < 0) { xqc_log(h3s->log, XQC_LOG_ERROR, "|xqc_h3_stream_process_request error" - "|error frame type:%z|", pctx->frame.type); + "|error frame type:%xL|", pctx->frame.type); xqc_h3_frm_reset_pctx(pctx); return -XQC_QPACK_SAVE_HEADERS_ERROR; } @@ -754,6 +755,8 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t return -XQC_H3_BLOCKED_STREAM_EXCEED; } + xqc_h3_request_blocked(h3s->h3r); + return processed; } else { @@ -765,6 +768,7 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t if (h3s->blocked_stream) { xqc_h3_conn_remove_blocked_stream(h3s->h3c, h3s->blocked_stream); h3s->blocked_stream = NULL; + xqc_h3_request_unblocked(h3s->h3r); } } } @@ -817,12 +821,16 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t h3s->h3r->fin_flag = fin_flag; } - /* notify DATA whenever there is data */ + /* + * when all bytes of DATA frame is read, notify to + * application to make sure it is notified before Trailer + */ ret = xqc_h3_request_on_recv_body(h3s->h3r); if (ret != XQC_OK) { xqc_log(h3s->log, XQC_LOG_ERROR, "|recv body error|%d|", ret); return ret; } + xqc_log(h3s->log, XQC_LOG_DEBUG, "|notify body on DATA frame end"); } break; @@ -831,10 +839,9 @@ xqc_h3_stream_process_request(xqc_h3_stream_t *h3s, unsigned char *data, size_t break; default: - xqc_log(h3s->log, XQC_LOG_ERROR, "|process request error|error " - "frame type:%z|", pctx->frame.type); - xqc_h3_frm_reset_pctx(pctx); - return -H3_FRAME_UNEXPECTED; + xqc_log(h3s->log, XQC_LOG_INFO, "|ignore unknown frame|" + "frame type:%xL|", pctx->frame.type); + break; } if (fin) { @@ -1043,7 +1050,6 @@ xqc_h3_stream_process_in(xqc_h3_stream_t *h3s, unsigned char *data, size_t data_ xqc_log(h3c->log, XQC_LOG_ERROR, "|h3_stream is not blocked|processed:%ui|" "data_len:%ui", processed, data_len); return XQC_ERROR; - } /* if blocked, store data in blocked buffer */ @@ -1138,6 +1144,11 @@ xqc_h3_stream_process_blocked_data(xqc_stream_t *stream, xqc_h3_stream_t *h3s, x if (*fin) { h3s->flags |= XQC_HTTP3_STREAM_FLAG_READ_EOF; + + if (h3s->type == XQC_H3_STREAM_TYPE_REQUEST) { + /* only request stream will be blocked */ + xqc_h3_request_stream_fin(h3s->h3r); + } } } while (buf->buf_len == buf->data_len && !*fin); @@ -1171,6 +1182,11 @@ xqc_h3_stream_process_data(xqc_stream_t *stream, xqc_h3_stream_t *h3s, xqc_bool_ if (*fin) { h3s->flags |= XQC_HTTP3_STREAM_FLAG_READ_EOF; + + if (h3s->type == XQC_H3_STREAM_TYPE_REQUEST) { + /* only request stream will be blocked */ + xqc_h3_request_stream_fin(h3s->h3r); + } } /* process h3 stream data */ @@ -1188,7 +1204,7 @@ xqc_h3_stream_process_data(xqc_stream_t *stream, xqc_h3_stream_t *h3s, xqc_bool_ } while (read == buff_size && !*fin); - if (*fin) { + if (*fin && h3s->type == XQC_H3_STREAM_TYPE_REQUEST) { h3s->h3r->fin_flag = *fin; } @@ -1234,6 +1250,18 @@ xqc_h3_stream_process_blocked_stream(xqc_h3_stream_t *h3s) } } + /* notify DATA to application ASAP */ + if (h3s->type == XQC_H3_STREAM_TYPE_REQUEST + && !xqc_list_empty(&h3s->h3r->body_buf)) + { + /* notify DATA whenever there is data */ + xqc_int_t ret = xqc_h3_request_on_recv_body(h3s->h3r); + if (ret != XQC_OK) { + xqc_log(h3s->log, XQC_LOG_ERROR, "|recv body error|%d|", ret); + return ret; + } + } + /* * Blocked h3 stream will be delayed to destroy when stream was closed while all bytes are read. * Hence, if the h3 stream is unblocked, h3 stream shall be destroyed after processing. @@ -1326,6 +1354,18 @@ xqc_h3_stream_read_notify(xqc_stream_t *stream, void *user_data) xqc_log(h3c->log, XQC_LOG_ERROR, "|xqc_h3_stream_process_data error|%d|", ret); return ret; } + + /* notify DATA to application ASAP */ + if (h3s->type == XQC_H3_STREAM_TYPE_REQUEST + && !xqc_list_empty(&h3s->h3r->body_buf)) + { + /* notify DATA whenever there is data */ + ret = xqc_h3_request_on_recv_body(h3s->h3r); + if (ret != XQC_OK) { + xqc_log(h3s->log, XQC_LOG_ERROR, "|recv body error|%d|", ret); + return ret; + } + } } xqc_log(h3c->log, XQC_LOG_DEBUG, "|success|stream_id:%ui|conn:%p|", diff --git a/src/http3/xqc_h3_stream.h b/src/http3/xqc_h3_stream.h index 4c18a1c14..b7bacfb8d 100644 --- a/src/http3/xqc_h3_stream.h +++ b/src/http3/xqc_h3_stream.h @@ -24,7 +24,7 @@ typedef enum { XQC_H3_STREAM_TYPE_REQUEST = 0x10, /* reserved stream type or others */ - XQC_H3_STREAM_TYPE_UNKNOWN = 0xFF, + XQC_H3_STREAM_TYPE_UNKNOWN = 0xFFFFFFFFFFFFFFFFull, } xqc_h3_stream_type_t; typedef enum { @@ -88,7 +88,11 @@ typedef struct xqc_h3_stream_s { /* http3 connection */ xqc_h3_conn_t *h3c; - /* bidi stream user interface, used to send/recv request contents */ + /* + * bidi stream user interface, used to send/recv request contents. h3r is + * available only in request streams, create or dereference in control or + * reserved streams is forbidden. + */ xqc_h3_request_t *h3r; /* stream type */ diff --git a/src/tls/xqc_crypto.c b/src/tls/xqc_crypto.c index ed8b1448e..11652f907 100644 --- a/src/tls/xqc_crypto.c +++ b/src/tls/xqc_crypto.c @@ -12,7 +12,6 @@ #define XQC_NONCE_LEN 16 #define XQC_HP_SAMPLELEN 16 #define XQC_HP_MASKLEN 5 -#define XQC_PKT_NUMLEN_MASK 0x03 #define XQC_FAKE_HP_MASK "\x00\x00\x00\x00\x00" #define XQC_FAKE_AEAD_OVERHEAD XQC_TLS_AEAD_OVERHEAD_MAX_LEN @@ -47,6 +46,21 @@ xqc_vec_assign(xqc_vec_t * vec, const uint8_t * data, size_t data_len) return XQC_OK; } +static inline void +xqc_ckm_init(xqc_crypto_km_t *ckm) +{ + xqc_vec_init(&ckm->secret); + xqc_vec_init(&ckm->key); + xqc_vec_init(&ckm->iv); +} + +static inline void +xqc_ckm_free(xqc_crypto_km_t *ckm) +{ + xqc_vec_free(&ckm->secret); + xqc_vec_free(&ckm->key); + xqc_vec_free(&ckm->iv); +} /* set aead suites, cipher suites and digest suites */ xqc_crypto_t * @@ -58,12 +72,15 @@ xqc_crypto_create(uint32_t cipher_id, xqc_log_t *log) } crypto->log = log; + crypto->key_phase = 0; + xqc_vec_init(&crypto->keys.tx_hp); xqc_vec_init(&crypto->keys.rx_hp); - xqc_vec_init(&crypto->keys.tx_ckm.key); - xqc_vec_init(&crypto->keys.tx_ckm.iv); - xqc_vec_init(&crypto->keys.rx_ckm.key); - xqc_vec_init(&crypto->keys.rx_ckm.iv); + + for (int i = 0; i < XQC_KEY_PHASE_CNT; i++) { + xqc_ckm_init(&crypto->keys.tx_ckm[i]); + xqc_ckm_init(&crypto->keys.rx_ckm[i]); + } switch (cipher_id) { /* TLS_AES_128_GCM_SHA256 */ @@ -109,10 +126,10 @@ xqc_crypto_destroy(xqc_crypto_t *crypto) xqc_vec_free(&crypto->keys.tx_hp); xqc_vec_free(&crypto->keys.rx_hp); - xqc_vec_free(&crypto->keys.tx_ckm.key); - xqc_vec_free(&crypto->keys.tx_ckm.iv); - xqc_vec_free(&crypto->keys.rx_ckm.key); - xqc_vec_free(&crypto->keys.rx_ckm.iv); + for (int i = 0; i < XQC_KEY_PHASE_CNT; i++) { + xqc_ckm_free(&crypto->keys.tx_ckm[i]); + xqc_ckm_free(&crypto->keys.rx_ckm[i]); + } xqc_free(crypto); } @@ -143,7 +160,7 @@ xqc_crypto_encrypt_header(xqc_crypto_t *crypto, xqc_pkt_type_t pkt_type, uint8_t size_t nwrite; /* packet number position and sample position */ - size_t pktno_len = (header[0] & XQC_PKT_NUMLEN_MASK) + 1; + size_t pktno_len = XQC_PACKET_SHORT_HEADER_PKTNO_LEN(header); uint8_t *sample = pktno + 4; /* hp cipher and key */ @@ -227,7 +244,7 @@ xqc_crypto_decrypt_header(xqc_crypto_t *crypto, xqc_pkt_type_t pkt_type, uint8_t } /* get length of packet number */ - size_t pktno_len = (header[0] & 0x03) + 1; + size_t pktno_len = XQC_PACKET_SHORT_HEADER_PKTNO_LEN(header); if (pktno + pktno_len > end) { xqc_log(crypto->log, XQC_LOG_ERROR, "|illegal pkt, pkt num exceed buffer"); return -XQC_EILLPKT; @@ -243,7 +260,7 @@ xqc_crypto_decrypt_header(xqc_crypto_t *crypto, xqc_pkt_type_t pkt_type, uint8_t xqc_int_t -xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, +xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, xqc_uint_t key_phase, uint8_t *header, size_t header_len, uint8_t *payload, size_t payload_len, uint8_t *dst, size_t dst_cap, size_t *dst_len) { @@ -252,12 +269,12 @@ xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, /* aead function and tx key */ xqc_pkt_protect_aead_t *pp_aead = &crypto->pp_aead; - xqc_crypto_km_t *ckm = &crypto->keys.tx_ckm; + xqc_crypto_km_t *ckm = &crypto->keys.tx_ckm[key_phase]; if (ckm->key.base == NULL || ckm->key.len == 0 || ckm->iv.base == NULL || ckm->iv.len == 0) { - xqc_log(crypto->log, XQC_LOG_ERROR, "|pp encrypt key NULL|"); - return -XQC_EENCRYPT; + xqc_log(crypto->log, XQC_LOG_ERROR, "|pp encrypt key NULL|key_phase:%ui|", key_phase); + return -XQC_TLS_ENCRYPT_DATA_ERROR; } /* generate nonce for aead encryption with original packet number */ @@ -282,7 +299,7 @@ xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, xqc_int_t -xqc_crypto_decrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, +xqc_crypto_decrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, xqc_uint_t key_phase, uint8_t *header, size_t header_len, uint8_t *payload, size_t payload_len, uint8_t *dst, size_t dst_cap, size_t *dst_len) { @@ -291,11 +308,11 @@ xqc_crypto_decrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, /* keys for decryption */ xqc_pkt_protect_aead_t *pp_aead = &crypto->pp_aead; - xqc_crypto_km_t *ckm = &crypto->keys.rx_ckm; + xqc_crypto_km_t *ckm = &crypto->keys.rx_ckm[key_phase]; if (ckm->key.base == NULL || ckm->key.len == 0 || ckm->iv.base == NULL || ckm->iv.len == 0) { - xqc_log(crypto->log, XQC_LOG_ERROR, "|decrypt key NULL|"); + xqc_log(crypto->log, XQC_LOG_ERROR, "|decrypt key NULL|key_phase:%ui|", key_phase); return -XQC_TLS_DECRYPT_DATA_ERROR; } @@ -432,12 +449,12 @@ xqc_crypto_derive_keys(xqc_crypto_t *crypto, const uint8_t *secret, size_t secre switch (type) { case XQC_KEY_TYPE_RX_READ: - p_ckm = &crypto->keys.rx_ckm; + p_ckm = &crypto->keys.rx_ckm[crypto->key_phase]; p_hp = &crypto->keys.rx_hp; break; case XQC_KEY_TYPE_TX_WRITE: - p_ckm = &crypto->keys.tx_ckm; + p_ckm = &crypto->keys.tx_ckm[crypto->key_phase]; p_hp = &crypto->keys.tx_hp; break; @@ -475,6 +492,29 @@ xqc_crypto_derive_keys(xqc_crypto_t *crypto, const uint8_t *secret, size_t secre return XQC_OK; } +xqc_int_t +xqc_crypto_save_application_traffic_secret_0(xqc_crypto_t *crypto, + const uint8_t *secret, size_t secretlen, xqc_key_type_t type) +{ + xqc_crypto_km_t *ckm; + switch (type) { + case XQC_KEY_TYPE_RX_READ: + ckm = &crypto->keys.rx_ckm[crypto->key_phase]; + break; + + case XQC_KEY_TYPE_TX_WRITE: + ckm = &crypto->keys.tx_ckm[crypto->key_phase]; + break; + + default: + xqc_log(crypto->log, XQC_LOG_ERROR, "|illegal crypto secret type|type:%d|", type); + return -XQC_TLS_INVALID_ARGUMENT; + } + + xqc_vec_assign(&ckm->secret, secret, secretlen); + return XQC_OK; +} + xqc_bool_t xqc_crypto_is_key_ready(xqc_crypto_t *crypto, xqc_key_type_t type) { @@ -482,11 +522,11 @@ xqc_crypto_is_key_ready(xqc_crypto_t *crypto, xqc_key_type_t type) xqc_vec_t *hp; if (type == XQC_KEY_TYPE_RX_READ) { - km = &crypto->keys.rx_ckm; + km = &crypto->keys.rx_ckm[crypto->key_phase]; hp = &crypto->keys.rx_hp; } else { - km = &crypto->keys.tx_ckm; + km = &crypto->keys.tx_ckm[crypto->key_phase]; hp = &crypto->keys.tx_hp; } @@ -550,3 +590,85 @@ xqc_crypto_aead_tag_len(xqc_crypto_t *crypto) { return crypto->pp_aead.taglen; } + +xqc_int_t +xqc_crypto_derive_updated_keys(xqc_crypto_t *crypto, xqc_key_type_t type) +{ + xqc_int_t ret; + + xqc_uint_t current_key_phase = crypto->key_phase; + xqc_uint_t updated_key_phase = current_key_phase ^ 1; + + xqc_crypto_km_t *current_ckm, *updated_ckm; + switch (type) { + case XQC_KEY_TYPE_RX_READ: + current_ckm = &crypto->keys.rx_ckm[current_key_phase]; + updated_ckm = &crypto->keys.rx_ckm[updated_key_phase]; + break; + + case XQC_KEY_TYPE_TX_WRITE: + current_ckm = &crypto->keys.tx_ckm[current_key_phase]; + updated_ckm = &crypto->keys.tx_ckm[updated_key_phase]; + break; + + default: + xqc_log(crypto->log, XQC_LOG_ERROR, "|illegal crypto secret type|type:%d|", type); + return -XQC_TLS_INVALID_ARGUMENT; + } + + + /* update application traffic secret */ + static uint8_t LABEL[] = "quic ku"; + uint8_t dest_buf[INITIAL_SECRET_MAX_LEN]; + + ret = xqc_hkdf_expand_label(dest_buf, INITIAL_SECRET_MAX_LEN, + current_ckm->secret.base, current_ckm->secret.len, + LABEL, xqc_lengthof(LABEL), &crypto->md); + if (ret != XQC_OK) { + return -XQC_TLS_UPDATE_KEY_ERROR; + } + xqc_vec_assign(&updated_ckm->secret, dest_buf, current_ckm->secret.len); + + + /* derive packet protection key with new secret */ + uint8_t key[XQC_MAX_KNP_LEN] = {0}, iv[XQC_MAX_KNP_LEN] = {0}; + size_t keycap = XQC_MAX_KNP_LEN, ivcap = XQC_MAX_KNP_LEN; + size_t keylen = 0, ivlen = 0; + + ret = xqc_crypto_derive_packet_protection_key(crypto, key, keycap, &keylen, + updated_ckm->secret.base, + updated_ckm->secret.len); + if (ret != XQC_OK || keylen <= 0) { + xqc_log(crypto->log, XQC_LOG_ERROR, + "|xqc_crypto_derive_packet_protection_key failed|ret:%d|", ret); + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + ret = xqc_crypto_derive_packet_protection_iv(crypto, iv, ivcap, &ivlen, + updated_ckm->secret.base, + updated_ckm->secret.len); + if (ret != XQC_OK || ivlen <= 0) { + xqc_log(crypto->log, XQC_LOG_ERROR, + "|xqc_crypto_derive_packet_protection_iv failed|ret:%d|", ret); + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + if (xqc_vec_assign(&updated_ckm->key, key, keylen) != XQC_OK) { + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + if (xqc_vec_assign(&updated_ckm->iv, iv, ivlen) != XQC_OK) { + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + return XQC_OK; +} + +void +xqc_crypto_discard_old_keys(xqc_crypto_t *crypto) +{ + xqc_uint_t discard_key_phase = crypto->key_phase ^ 1; + + xqc_ckm_free(&crypto->keys.rx_ckm[discard_key_phase]); + xqc_ckm_free(&crypto->keys.tx_ckm[discard_key_phase]); +} diff --git a/src/tls/xqc_crypto.h b/src/tls/xqc_crypto.h index c8eb6a0dc..38b456b36 100644 --- a/src/tls/xqc_crypto.h +++ b/src/tls/xqc_crypto.h @@ -106,11 +106,7 @@ typedef struct xqc_digest_s { #define xqc_digest_init_to_sha256(obj) ((obj)->digest = EVP_sha256()) #define xqc_digest_init_to_sha384(obj) ((obj)->digest = EVP_sha384()) -typedef enum { - XQC_CRYPTO_KM_FLAG_NONE, - XQC_CRYPTO_KM_FLAG_KEY_PHASE_ONE = 0x01, /* key phase bit is set */ -} xqc_crypto_km_flag; - +#define XQC_KEY_PHASE_CNT 2 typedef struct xqc_vec_s { uint8_t *base; /* pointer of data. */ @@ -121,13 +117,14 @@ typedef struct xqc_crypto_km_s { xqc_vec_t key; xqc_vec_t iv; - uint8_t flags; /* for key update */ + /* application traffic secrets, only use on 1-rtt, for key update */ + xqc_vec_t secret; } xqc_crypto_km_t; typedef struct xqc_crypto_keys_s { /* packet payload protect key */ - xqc_crypto_km_t rx_ckm; - xqc_crypto_km_t tx_ckm; + xqc_crypto_km_t rx_ckm[XQC_KEY_PHASE_CNT]; + xqc_crypto_km_t tx_ckm[XQC_KEY_PHASE_CNT]; /* packet header protect key */ xqc_vec_t rx_hp; @@ -152,6 +149,9 @@ typedef struct xqc_crypto_s { /* log handler */ xqc_log_t *log; + /* key phase, 1-RTT : 1 or 0, others is always 0 */ + xqc_uint_t key_phase; + } xqc_crypto_t; @@ -171,6 +171,12 @@ void xqc_crypto_destroy(xqc_crypto_t *crypto); xqc_int_t xqc_crypto_derive_keys(xqc_crypto_t *crypto, const uint8_t *secret, size_t secretlen, xqc_key_type_t type); +/** + * @brief save application traffic secret for key update + */ +xqc_int_t xqc_crypto_save_application_traffic_secret_0(xqc_crypto_t *crypto, + const uint8_t *secret, size_t secretlen, xqc_key_type_t type); + /** * @brief query is protection key is ready */ @@ -185,7 +191,7 @@ xqc_bool_t xqc_crypto_is_key_ready(xqc_crypto_t *crypto, xqc_key_type_t type); * @param dst_len written length * @return XQC_OK for success, others for failure */ -xqc_int_t xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, +xqc_int_t xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, xqc_uint_t key_phase, uint8_t *header, size_t header_len, uint8_t *payload, size_t payload_len, uint8_t *dst, size_t dst_cap, size_t *dst_len); @@ -200,7 +206,7 @@ xqc_int_t xqc_crypto_encrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, * @param dst_len length of decrypted payload * @return xqc_int_t */ -xqc_int_t xqc_crypto_decrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, +xqc_int_t xqc_crypto_decrypt_payload(xqc_crypto_t *crypto, uint64_t pktno, xqc_uint_t key_phase, uint8_t *header, size_t header_len, uint8_t *payload, size_t payload_len, uint8_t *dst, size_t dst_cap, size_t *dst_len); @@ -241,4 +247,16 @@ xqc_int_t xqc_crypto_derive_initial_secret( ssize_t xqc_crypto_aead_tag_len(xqc_crypto_t *crypto); + +/** + * @brief derive updated secrets and read/write keys on 1-RTT + */ +xqc_int_t xqc_crypto_derive_updated_keys(xqc_crypto_t *crypto, xqc_key_type_t type); + +/** + * @brief discard the old read and write keys on 1-RTT + */ +void xqc_crypto_discard_old_keys(xqc_crypto_t *crypto); + + #endif \ No newline at end of file diff --git a/src/tls/xqc_tls.c b/src/tls/xqc_tls.c index 98ca68726..a91069a70 100644 --- a/src/tls/xqc_tls.c +++ b/src/tls/xqc_tls.c @@ -62,6 +62,8 @@ typedef struct xqc_tls_s { /* quic version. used to decide protection salt */ xqc_proto_version_t version; + xqc_bool_t key_update_confirmed; + } xqc_tls_t; @@ -328,6 +330,7 @@ xqc_tls_create(xqc_tls_ctx_t *ctx, xqc_tls_config_t *cfg, xqc_log_t *log, void * tls->user_data = user_data; tls->cert_verify_flag = cfg->cert_verify_flag; tls->no_crypto = cfg->no_crypto_flag; + tls->key_update_confirmed = XQC_TRUE; /* init ssl with input config */ ret = xqc_tls_create_ssl(tls, cfg); @@ -600,8 +603,17 @@ xqc_tls_encrypt_payload(xqc_tls_t *tls, xqc_encrypt_level_t level, return -XQC_TLS_INVALID_STATE; } - return xqc_crypto_encrypt_payload(crypto, pktno, header, header_len, payload, payload_len, - dst, dst_cap, dst_len); + xqc_uint_t key_phase = 0; + if (level == XQC_ENC_LEV_1RTT) { + key_phase = XQC_PACKET_SHORT_HEADER_KEY_PHASE(header); + if (key_phase >= XQC_KEY_PHASE_CNT) { + xqc_log(tls->log, XQC_LOG_ERROR, "|illegal key phase|key_phase:%ui|", key_phase); + return -XQC_TLS_INVALID_STATE; + } + } + + return xqc_crypto_encrypt_payload(crypto, pktno, key_phase, header, header_len, + payload, payload_len, dst, dst_cap, dst_len); } xqc_int_t @@ -629,8 +641,17 @@ xqc_tls_decrypt_payload(xqc_tls_t *tls, xqc_encrypt_level_t level, return -XQC_TLS_INVALID_STATE; } - return xqc_crypto_decrypt_payload(crypto, pktno, header, header_len, payload, payload_len, - dst, dst_cap, dst_len); + xqc_uint_t key_phase = 0; + if (level == XQC_ENC_LEV_1RTT) { + key_phase = XQC_PACKET_SHORT_HEADER_KEY_PHASE(header); + if (key_phase >= XQC_KEY_PHASE_CNT) { + xqc_log(tls->log, XQC_LOG_ERROR, "|illegal key phase|key_phase:%ui|", key_phase); + return -XQC_TLS_INVALID_STATE; + } + } + + return xqc_crypto_decrypt_payload(crypto, pktno, key_phase, header, header_len, + payload, payload_len, dst, dst_cap, dst_len); } @@ -698,6 +719,49 @@ xqc_tls_set_no_crypto(xqc_tls_t *tls) tls->no_crypto = XQC_TRUE; } +void +xqc_tls_set_1rtt_key_phase(xqc_tls_t *tls, xqc_uint_t key_phase) +{ + tls->crypto[XQC_ENC_LEV_1RTT]->key_phase = key_phase; +} + +xqc_bool_t +xqc_tls_is_key_update_confirmed(xqc_tls_t *tls) +{ + return tls->key_update_confirmed; +} + +xqc_int_t +xqc_tls_update_1rtt_keys(xqc_tls_t *tls, xqc_key_type_t type) +{ + xqc_crypto_t *crypto = tls->crypto[XQC_ENC_LEV_1RTT]; + if (crypto == NULL) { + xqc_log(tls->log, XQC_LOG_ERROR, "|invalid state|1rtt crypto is null|"); + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + xqc_int_t ret = xqc_crypto_derive_updated_keys(crypto, type); + if (ret != XQC_OK) { + xqc_log(tls->log, XQC_LOG_ERROR, "|derive write keys error|"); + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + if (type == XQC_KEY_TYPE_RX_READ) { + tls->key_update_confirmed = XQC_FALSE; + + } else if (type == XQC_KEY_TYPE_TX_WRITE) { + tls->key_update_confirmed = XQC_TRUE; + } + + return XQC_OK; +} + +void +xqc_tls_discard_old_1rtt_keys(xqc_tls_t *tls) +{ + xqc_crypto_discard_old_keys(tls->crypto[XQC_ENC_LEV_1RTT]); +} + /** * ============================================================================ @@ -799,8 +863,7 @@ xqc_ssl_session_ticket_key_cb(SSL *ssl, uint8_t *key_name, uint8_t *iv, } else { /* * decrypt session ticket, returns -1 to abort the handshake, - * 0 if decrypting the ticket failed, - * and 1 or 2 on success + * 0 if decrypting the ticket failed, and 1 or 2 on success */ if (memcmp(key_name, key->name, 16) != 0) { xqc_log(tls->log, XQC_LOG_ERROR, "|ssl session ticket decrypt, key name not match|"); @@ -961,7 +1024,18 @@ xqc_tls_set_read_secret(SSL *ssl, enum ssl_encryption_level_t level, } } - /* derive and install write key */ + /* save application traffic secret */ + if (level == ssl_encryption_application) { + ret = xqc_crypto_save_application_traffic_secret_0(tls->crypto[level], secret, + secret_len, XQC_KEY_TYPE_RX_READ); + if (ret != XQC_OK) { + xqc_log(tls->log, XQC_LOG_ERROR, + "|save application traffic secret error|level:%d|ret:%d", level, ret); + return XQC_SSL_FAIL; + } + } + + /* derive and install read key */ xqc_crypto_t *crypto = tls->crypto[level]; ret = xqc_crypto_derive_keys(crypto, secret, secret_len, XQC_KEY_TYPE_RX_READ); if (ret != XQC_OK) { @@ -993,6 +1067,17 @@ xqc_tls_set_write_secret(SSL *ssl, enum ssl_encryption_level_t level, } } + /* save application traffic secret */ + if (level == ssl_encryption_application) { + ret = xqc_crypto_save_application_traffic_secret_0(tls->crypto[level], secret, + secret_len, XQC_KEY_TYPE_TX_WRITE); + if (ret != XQC_OK) { + xqc_log(tls->log, XQC_LOG_ERROR, + "|save application traffic secret error|level:%d|ret:%d", level, ret); + return XQC_SSL_FAIL; + } + } + /* derive and install write key */ xqc_crypto_t *crypto = tls->crypto[level]; ret = xqc_crypto_derive_keys(crypto, secret, secret_len, XQC_KEY_TYPE_TX_WRITE); diff --git a/src/tls/xqc_tls.h b/src/tls/xqc_tls.h index 419668ebe..e114a760f 100644 --- a/src/tls/xqc_tls.h +++ b/src/tls/xqc_tls.h @@ -164,4 +164,24 @@ ssize_t xqc_tls_aead_tag_len(xqc_tls_t *tls, xqc_encrypt_level_t level); */ void xqc_tls_set_no_crypto(xqc_tls_t *tls); +/** + * @brief update key phase on 1-RTT + */ +void xqc_tls_set_1rtt_key_phase(xqc_tls_t *tls, xqc_uint_t key_phase); + +/** + * @brief check if key update is waiting confirmed + */ +xqc_bool_t xqc_tls_is_key_update_confirmed(xqc_tls_t *tls); + +/** + * @brief derive updated read or write keys on 1-RTT + */ +xqc_int_t xqc_tls_update_1rtt_keys(xqc_tls_t *tls, xqc_key_type_t type); + +/** + * @brief discard the old read and write keys on 1-RTT + */ +void xqc_tls_discard_old_1rtt_keys(xqc_tls_t *tls); + #endif diff --git a/src/tls/xqc_tls_ctx.c b/src/tls/xqc_tls_ctx.c index 3bf1edad8..e5d9cd41f 100644 --- a/src/tls/xqc_tls_ctx.c +++ b/src/tls/xqc_tls_ctx.c @@ -410,9 +410,9 @@ xqc_tls_ctx_register_alpn(xqc_tls_ctx_t *ctx, const char *alpn, size_t alpn_len) return -XQC_EPARAM; } - if (alpn_len > ctx->alpn_list_sz - ctx->alpn_list_len) { + if (alpn_len + 1 > ctx->alpn_list_sz - ctx->alpn_list_len) { /* realloc buffer */ - size_t new_alpn_list_sz = 2 * (ctx->alpn_list_sz + alpn_len); + size_t new_alpn_list_sz = 2 * (ctx->alpn_list_sz + alpn_len) + 1; char *alpn_list_new = xqc_malloc(new_alpn_list_sz); ctx->alpn_list_sz = new_alpn_list_sz; diff --git a/src/transport/xqc_conn.c b/src/transport/xqc_conn.c index 6d7cc1121..abe863399 100644 --- a/src/transport/xqc_conn.c +++ b/src/transport/xqc_conn.c @@ -29,14 +29,16 @@ xqc_conn_settings_t default_conn_settings = { - .pacing_on = 0, - .ping_on = 0, - .so_sndbuf = 0, - .linger = {.linger_on = 0, .linger_timeout = 0}, - .proto_version = XQC_VERSION_V1, - .init_idle_time_out = XQC_CONN_INITIAL_IDLE_TIMEOUT, - .idle_time_out = XQC_CONN_DEFAULT_IDLE_TIMEOUT, - .spurious_loss_detect_on = 0, + .pacing_on = 0, + .ping_on = 0, + .so_sndbuf = 0, + .linger = {.linger_on = 0, .linger_timeout = 0}, + .proto_version = XQC_VERSION_V1, + .init_idle_time_out = XQC_CONN_INITIAL_IDLE_TIMEOUT, + .idle_time_out = XQC_CONN_DEFAULT_IDLE_TIMEOUT, + .spurious_loss_detect_on = 0, + .anti_amplification_limit = XQC_DEFAULT_ANTI_AMPLIFICATION_LIMIT, + .keyupdate_pkt_threshold = 0, }; void @@ -49,13 +51,24 @@ xqc_server_set_conn_settings(const xqc_conn_settings_t *settings) default_conn_settings.so_sndbuf = settings->so_sndbuf; default_conn_settings.linger = settings->linger; default_conn_settings.spurious_loss_detect_on = settings->spurious_loss_detect_on; + + if (settings->init_idle_time_out > 0) { + default_conn_settings.init_idle_time_out = settings->init_idle_time_out; + } + if (settings->idle_time_out > 0) { default_conn_settings.idle_time_out = settings->idle_time_out; } + if (settings->anti_amplification_limit > XQC_DEFAULT_ANTI_AMPLIFICATION_LIMIT) { + default_conn_settings.anti_amplification_limit = settings->anti_amplification_limit; + } + if (xqc_check_proto_version_valid(settings->proto_version)) { default_conn_settings.proto_version = settings->proto_version; } + + default_conn_settings.keyupdate_pkt_threshold = settings->keyupdate_pkt_threshold; } static const char * const xqc_conn_flag_to_str[XQC_CONN_FLAG_SHIFT_NUM] = { @@ -204,6 +217,19 @@ xqc_conn_init_flow_ctl(xqc_connection_t *conn) flow_ctl->fc_last_window_update_time = 0; } +static inline void +xqc_conn_init_key_update_ctx(xqc_connection_t *conn) +{ + xqc_key_update_ctx_t *ctx = &conn->key_update_ctx; + + ctx->cur_out_key_phase = 0; + ctx->next_in_key_phase = 0; + + ctx->first_sent_pktno = 0; + ctx->first_recv_pktno = 0; + ctx->enc_pkt_cnt = 0; +} + xqc_connection_t * xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, const xqc_conn_settings_t *settings, void *user_data, xqc_conn_type_t type) @@ -234,8 +260,13 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, xc->conn_settings.init_idle_time_out = XQC_CONN_INITIAL_IDLE_TIMEOUT; } + if (xc->conn_settings.anti_amplification_limit < XQC_DEFAULT_ANTI_AMPLIFICATION_LIMIT) { + xc->conn_settings.anti_amplification_limit = XQC_DEFAULT_ANTI_AMPLIFICATION_LIMIT; + } + xqc_conn_init_trans_settings(xc); xqc_conn_init_flow_ctl(xc); + xqc_conn_init_key_update_ctx(xc); xc->conn_pool = pool; @@ -494,7 +525,7 @@ xqc_conn_client_on_alpn(xqc_connection_t *conn, const unsigned char *alpn, size_ /* set quic callbacks to quic connection */ ret = xqc_engine_get_alpn_callbacks(conn->engine, alpn, alpn_len, &conn->app_proto_cbs); if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_ERROR, "|can't get application level|ret:%d", ret); + xqc_log(conn->log, XQC_LOG_ERROR, "|can't get application layer callback|ret:%d", ret); return ret; } @@ -510,7 +541,7 @@ xqc_conn_server_on_alpn(xqc_connection_t *conn, const unsigned char *alpn, size_ /* set quic callbacks to quic connection */ ret = xqc_engine_get_alpn_callbacks(conn->engine, alpn, alpn_len, &conn->app_proto_cbs); if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_ERROR, "|can't get application level|ret:%d", ret); + xqc_log(conn->log, XQC_LOG_ERROR, "|can't get application layer callback|ret:%d", ret); return ret; } @@ -544,7 +575,7 @@ xqc_conn_destroy(xqc_connection_t *xc) xqc_log(xc->log, XQC_LOG_REPORT, "|%p|srtt:%ui|retrans rate:%.4f|send_count:%ud|lost_count:%ud|tlp_count:%ud|" "spurious_loss_count:%ud|recv_count:%ud|has_0rtt:%d|0rtt_accept:%d|token_ok:%d|handshake_time:%ui|" - "first_send_delay:%ui|conn_persist:%ui|err:0x%xi|%s|", + "first_send_delay:%ui|conn_persist:%ui|keyupdate_cnt:%d|err:0x%xi|%s|", xc, xqc_send_ctl_get_srtt(xc->conn_send_ctl), xqc_send_ctl_get_retrans_rate(xc->conn_send_ctl), xc->conn_send_ctl->ctl_send_count, xc->conn_send_ctl->ctl_lost_count, xc->conn_send_ctl->ctl_tlp_count, xc->conn_send_ctl->ctl_spurious_loss_count, xc->conn_send_ctl->ctl_recv_count, @@ -553,7 +584,8 @@ xqc_conn_destroy(xqc_connection_t *xc) xc->conn_type == XQC_CONN_TYPE_SERVER ? (xc->conn_flag & XQC_CONN_FLAG_TOKEN_OK ? 1:0) : (-1), (xc->handshake_complete_time > xc->conn_create_time) ? (xc->handshake_complete_time - xc->conn_create_time) : 0, (xc->first_data_send_time > xc->conn_create_time) ? (xc->first_data_send_time - xc->conn_create_time) : 0, - xqc_monotonic_timestamp() - xc->conn_create_time, xc->conn_err, xqc_conn_addr_str(xc)); + xqc_monotonic_timestamp() - xc->conn_create_time, xc->key_update_ctx.key_update_cnt, + xc->conn_err, xqc_conn_addr_str(xc)); xqc_log_event(xc->log, CON_CONNECTION_CLOSED, xc); if (xc->conn_flag & XQC_CONN_FLAG_WAIT_WAKEUP) { @@ -571,10 +603,24 @@ xqc_conn_destroy(xqc_connection_t *xc) xqc_destroy_stream(stream); } - if (xc->app_proto_cbs.conn_cbs.conn_close_notify - && (xc->conn_flag & XQC_CONN_FLAG_UPPER_CONN_EXIST)) - { - xc->app_proto_cbs.conn_cbs.conn_close_notify(xc, &xc->scid_set.user_scid, xc->app_proto_user_data); + /* notify destruction */ + if (xc->conn_flag & XQC_CONN_FLAG_UPPER_CONN_EXIST) { + /* ALPN negotiated, notify close through application layer protocol callback function */ + if (xc->app_proto_cbs.conn_cbs.conn_close_notify) { + xc->app_proto_cbs.conn_cbs.conn_close_notify(xc, &xc->scid_set.user_scid, + xc->app_proto_user_data); + + } else if (xc->transport_cbs.server_refuse) { + /* ALPN context is not initialized, ClientHello has not been received */ + xc->transport_cbs.server_refuse(xc->engine, xc, &xc->scid_set.user_scid, xc->user_data); + xqc_log(xc->log, XQC_LOG_REPORT, + "|conn close notified by refuse|%s", xqc_conn_addr_str(xc)); + + } else { + xqc_log(xc->log, XQC_LOG_REPORT, + "|conn close event not notified|%s", xqc_conn_addr_str(xc)); + } + xc->conn_flag &= ~XQC_CONN_FLAG_UPPER_CONN_EXIST; } @@ -836,7 +882,8 @@ xqc_convert_pkt_0rtt_2_1rtt(xqc_connection_t *conn, xqc_packet_out_t *packet_out /* copy header */ packet_out->po_used_size = 0; int ret = xqc_gen_short_packet_header(packet_out, conn->dcid_set.current_dcid.cid_buf, - conn->dcid_set.current_dcid.cid_len, XQC_PKTNO_BITS, 0); + conn->dcid_set.current_dcid.cid_len, XQC_PKTNO_BITS, 0, + conn->key_update_ctx.cur_out_key_phase); packet_out->po_used_size = ret; /* copy frame directly */ @@ -1184,6 +1231,7 @@ xqc_process_packet_with_pn(xqc_connection_t *conn, xqc_packet_out_t *packet_out) packet_out->po_pkt.pkt_num = conn->conn_send_ctl->ctl_packet_number[packet_out->po_pkt.pkt_pns]; xqc_write_packet_number(packet_out->po_ppktno, packet_out->po_pkt.pkt_num, XQC_PKTNO_BITS); xqc_long_packet_update_length(packet_out); + xqc_short_packet_update_key_phase(packet_out, conn->key_update_ctx.cur_out_key_phase); /* encrypt packet body */ if (xqc_packet_encrypt(conn, packet_out) < 0) { @@ -2373,6 +2421,15 @@ xqc_conn_server_validate_address(xqc_connection_t *c, xqc_packet_in_t *pi) default: break; } + + /* + * loss detection timer might be unset when anti-amplification limit is reached, but receiving + * a handshake or receiving a packet with cid which was choosed by server, will remove the + * anti-amplification state, and loss detection timer shall be re-armed. + */ + if (c->conn_flag & XQC_CONN_FLAG_ADDR_VALIDATED) { + xqc_send_ctl_rearm_ld_timer(c->conn_send_ctl); + } } @@ -2646,6 +2703,35 @@ xqc_conn_try_retire_conn_id(xqc_connection_t *conn, uint64_t seq_num) return XQC_OK; } +xqc_int_t +xqc_conn_confirm_key_update(xqc_connection_t *conn) +{ + xqc_key_update_ctx_t *ctx = &conn->key_update_ctx; + + ctx->key_update_cnt++; + ctx->first_sent_pktno = conn->conn_send_ctl->ctl_packet_number[XQC_PNS_APP_DATA] + 1; + ctx->first_recv_pktno = UINT64_MAX; + ctx->cur_out_key_phase ^= 1; + ctx->next_in_key_phase ^= 1; + ctx->enc_pkt_cnt = 0; + + xqc_tls_set_1rtt_key_phase(conn->tls, ctx->cur_out_key_phase); + xqc_log(conn->log, XQC_LOG_DEBUG, "|key phase changed to %ui|", ctx->cur_out_key_phase); + + /* + * An endpoint SHOULD retain old read keys for no more than three times the PTO after having + * received a packet protected using the new keys. After this period, old read keys and their + * corresponding secrets SHOULD be discarded. + */ + xqc_usec_t now = xqc_monotonic_timestamp(); + xqc_usec_t pto = xqc_send_ctl_calc_pto(conn->conn_send_ctl); + if (!xqc_send_ctl_timer_is_set(conn->conn_send_ctl, XQC_TIMER_KEY_UPDATE)) { + xqc_send_ctl_timer_set(conn->conn_send_ctl, XQC_TIMER_KEY_UPDATE, now, 3 * pto); + } + + return XQC_OK; +} + /* check whether if the dcid is valid for the connection */ xqc_int_t @@ -3085,6 +3171,17 @@ xqc_settings_copy_from_transport_params(xqc_trans_settings_t *dest, dest->active_connection_id_limit = src->active_connection_id_limit; } +void +xqc_conn_update_flow_ctl_settings(xqc_connection_t *conn) +{ + xqc_conn_flow_ctl_t *flow_ctl = &conn->conn_flow_ctl; + xqc_trans_settings_t *remote_settings = &conn->remote_settings; + + flow_ctl->fc_max_data_can_send = remote_settings->max_data; + flow_ctl->fc_max_streams_bidi_can_send = remote_settings->max_streams_bidi; + flow_ctl->fc_max_streams_uni_can_send = remote_settings->max_streams_uni; +} + xqc_int_t xqc_conn_set_early_remote_transport_params(xqc_connection_t *conn, @@ -3095,7 +3192,7 @@ xqc_conn_set_early_remote_transport_params(xqc_connection_t *conn, } xqc_settings_copy_from_transport_params(&conn->remote_settings, params); - + xqc_conn_update_flow_ctl_settings(conn); return XQC_OK; } diff --git a/src/transport/xqc_conn.h b/src/transport/xqc_conn.h index 0067f3d86..da4db6831 100644 --- a/src/transport/xqc_conn.h +++ b/src/transport/xqc_conn.h @@ -201,6 +201,18 @@ typedef struct { char data[]; } xqc_hs_buffer_t; +typedef struct { + xqc_uint_t cur_out_key_phase; /* key phase used in current sent packets */ + xqc_uint_t next_in_key_phase; /* key phase expected in next received packets */ + xqc_uint_t key_update_cnt; /* number of key updates per connection */ + + /* for current out key phase */ + xqc_packet_number_t first_sent_pktno; /* lowest packet number sent with each key phase */ + xqc_packet_number_t first_recv_pktno; /* lowest packet number recv with each key phase */ + uint64_t enc_pkt_cnt; /* number of packet encrypt with each key phase */ + +} xqc_key_update_ctx_t; + struct xqc_connection_s { xqc_conn_settings_t conn_settings; @@ -304,6 +316,8 @@ struct xqc_connection_s { /* for limit the length of crypto_data */ size_t crypto_data_total_len; + /* for key update */ + xqc_key_update_ctx_t key_update_ctx; }; const char *xqc_conn_flag_2_str(xqc_conn_flag_t conn_flag); @@ -437,4 +451,6 @@ xqc_int_t xqc_conn_on_recv_retry(xqc_connection_t *conn); /* get idle timeout in milliseconds */ xqc_msec_t xqc_conn_get_idle_timeout(xqc_connection_t *conn); +xqc_int_t xqc_conn_confirm_key_update(xqc_connection_t *conn); + #endif /* _XQC_CONN_H_INCLUDED_ */ diff --git a/src/transport/xqc_defs.h b/src/transport/xqc_defs.h index a60ece0bb..a9b1e2738 100644 --- a/src/transport/xqc_defs.h +++ b/src/transport/xqc_defs.h @@ -54,6 +54,9 @@ extern const unsigned char xqc_proto_version_field[][XQC_PROTO_VERSION_LEN]; /* max alpn length */ -#define XQC_MAX_ALPN_LEN 255 +#define XQC_MAX_ALPN_LEN 255 + +/* limit of anti-amplification */ +#define XQC_DEFAULT_ANTI_AMPLIFICATION_LIMIT 3 #endif \ No newline at end of file diff --git a/src/transport/xqc_engine.c b/src/transport/xqc_engine.c index 69ab70a48..0376eeec1 100644 --- a/src/transport/xqc_engine.c +++ b/src/transport/xqc_engine.c @@ -663,7 +663,7 @@ xqc_engine_process_conn(xqc_connection_t *conn, xqc_usec_t now) XQC_CHECK_UNDECRYPT_PACKETS(); XQC_CHECK_IMMEDIATE_CLOSE(); - if (XQC_UNLIKELY(!xqc_list_empty(&conn->conn_send_ctl->ctl_buff_1rtt_packets) + if (XQC_UNLIKELY(!xqc_list_empty(&conn->conn_send_ctl->ctl_buff_1rtt_packets) && conn->conn_flag & XQC_CONN_FLAG_CAN_SEND_1RTT)) { xqc_conn_write_buffed_1rtt_packets(conn); } diff --git a/src/transport/xqc_pacing.c b/src/transport/xqc_pacing.c index a66a9f883..22cb30021 100644 --- a/src/transport/xqc_pacing.c +++ b/src/transport/xqc_pacing.c @@ -51,7 +51,8 @@ xqc_pacing_rate_calc(xqc_pacing_t *pacing) pacing_rate = cwnd * 1000000 / srtt; if (ctl->ctl_cong_callback->xqc_cong_ctl_in_slow_start - && ctl->ctl_cong_callback->xqc_cong_ctl_in_slow_start(ctl->ctl_cong)) { + && ctl->ctl_cong_callback->xqc_cong_ctl_in_slow_start(ctl->ctl_cong)) + { pacing_rate *= 2; } else { diff --git a/src/transport/xqc_packet.h b/src/transport/xqc_packet.h index 137217ba1..da63eca18 100644 --- a/src/transport/xqc_packet.h +++ b/src/transport/xqc_packet.h @@ -62,6 +62,8 @@ struct xqc_packet_s { #define XQC_PACKET_LONG_HEADER_PREFIX_LENGTH (1 + XQC_PACKET_VERSION_LENGTH) #define XQC_PACKET_INITIAL_MIN_LENGTH XQC_QUIC_MSS +#define XQC_PACKET_SHORT_HEADER_PKTNO_LEN(buf) ((buf[0] & 0x03) + 1) +#define XQC_PACKET_SHORT_HEADER_KEY_PHASE(buf) ((buf[0] & 0x04) >> 2) #define xqc_parse_uint16(p) ((p)[0] << 8 | (p)[1]) #define xqc_parse_uint32(p) ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) diff --git a/src/transport/xqc_packet_out.c b/src/transport/xqc_packet_out.c index 3b1724adc..da369f80b 100644 --- a/src/transport/xqc_packet_out.c +++ b/src/transport/xqc_packet_out.c @@ -144,7 +144,8 @@ xqc_write_packet_header(xqc_connection_t *conn, xqc_packet_out_t *packet_out) if (pkt_type == XQC_PTYPE_SHORT_HEADER && packet_out->po_used_size == 0) { ret = xqc_gen_short_packet_header(packet_out, conn->dcid_set.current_dcid.cid_buf, conn->dcid_set.current_dcid.cid_len, - XQC_PKTNO_BITS, packet_out->po_pkt.pkt_num); + XQC_PKTNO_BITS, packet_out->po_pkt.pkt_num, + conn->key_update_ctx.cur_out_key_phase); } else if (pkt_type != XQC_PTYPE_SHORT_HEADER && packet_out->po_used_size == 0) { ret = xqc_gen_long_packet_header(packet_out, diff --git a/src/transport/xqc_packet_parser.c b/src/transport/xqc_packet_parser.c index c3f9e1c28..3c64a2027 100644 --- a/src/transport/xqc_packet_parser.c +++ b/src/transport/xqc_packet_parser.c @@ -170,7 +170,7 @@ xqc_write_packet_number(unsigned char *buf, xqc_packet_number_t packet_number, u int xqc_gen_short_packet_header(xqc_packet_out_t *packet_out, unsigned char *dcid, unsigned int dcid_len, - unsigned char packet_number_bits, xqc_packet_number_t packet_number) + unsigned char packet_number_bits, xqc_packet_number_t packet_number, xqc_uint_t key_phase) { /* 0 1 2 3 @@ -189,7 +189,7 @@ xqc_gen_short_packet_header(xqc_packet_out_t *packet_out, unsigned char *dcid, u unsigned char spin_bit = 0x01; unsigned char reserved_bits = 0x00; - unsigned char key_phase_bit = 0x00; + unsigned char key_phase_bit = key_phase ? 0x01 : 0x00; unsigned int packet_number_len = xqc_packet_number_bits2len(packet_number_bits); unsigned int need = 1 + dcid_len + packet_number_len; @@ -259,13 +259,8 @@ xqc_packet_parse_short_header(xqc_connection_t *c, xqc_packet_in_t *packet_in) } xqc_uint_t spin_bit = (pos[0] & 0x20) >> 5; - xqc_uint_t reserved_bits = (pos[0] & 0x18) >> 3; - xqc_uint_t key_phase = (pos[0] & 0x04) >> 2; - xqc_uint_t packet_number_len = (pos[0] & 0x03) + 1; pos += 1; - - xqc_log(c->log, XQC_LOG_DEBUG, "|parse short header|spin_bit:%ud|reserved_bits:%ud|key_phase:%ud|packet_number_len:%ud|", - spin_bit, reserved_bits, key_phase, packet_number_len); + xqc_log(c->log, XQC_LOG_DEBUG, "|parse short header|spin_bit:%ud|", spin_bit); /* check dcid */ xqc_cid_set(&(packet->pkt_dcid), pos, cid_len); @@ -306,6 +301,17 @@ xqc_long_packet_update_length(xqc_packet_out_t *packet_out) } } +void +xqc_short_packet_update_key_phase(xqc_packet_out_t *packet_out, xqc_uint_t key_phase) +{ + if (packet_out->po_pkt.pkt_type == XQC_PTYPE_SHORT_HEADER) { + unsigned char key_phase_bit = key_phase ? 0x01 : 0x00; + unsigned char *dst_buf = packet_out->po_buf; + dst_buf[0] &= (~(1<<2)); /* clear up original key phase bit */ + dst_buf[0] |= (key_phase_bit << 2); /* set current updated key phase bit */ + } +} + void xqc_short_packet_update_dcid(xqc_packet_out_t *packet_out, xqc_connection_t *conn) { @@ -597,6 +603,35 @@ xqc_packet_encrypt_buf(xqc_connection_t *conn, xqc_packet_out_t *packet_out, return ret; } + /* update enc_pkt_cnt for current 1-rtt key & maybe initiate a key update */ + if (packet_out->po_pkt.pkt_type == XQC_PTYPE_SHORT_HEADER && level == XQC_ENC_LEV_1RTT) { + conn->key_update_ctx.enc_pkt_cnt++; + + if (conn->conn_settings.keyupdate_pkt_threshold > 0 + && conn->key_update_ctx.enc_pkt_cnt > conn->conn_settings.keyupdate_pkt_threshold + && conn->key_update_ctx.first_sent_pktno <= + conn->conn_send_ctl->ctl_largest_acked[XQC_PNS_APP_DATA]) + { + ret = xqc_tls_update_1rtt_keys(conn->tls, XQC_KEY_TYPE_RX_READ); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_tls_update_rx_keys error|"); + return ret; + } + + ret = xqc_tls_update_1rtt_keys(conn->tls, XQC_KEY_TYPE_TX_WRITE); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_tls_update_tx_keys error|"); + return ret; + } + + ret = xqc_conn_confirm_key_update(conn); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_conn_confirm_key_update error|"); + return ret; + } + } + } + return XQC_OK; } @@ -636,12 +671,12 @@ xqc_packet_decrypt(xqc_connection_t *conn, xqc_packet_in_t *packet_in) ret = xqc_tls_decrypt_header(conn->tls, level, packet_in->pi_pkt.pkt_type, header, pktno, end); if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_INFO, "|remove header protection error|ret:%d", ret); + xqc_log(conn->log, XQC_LOG_INFO, "|remove header protection error|ret:%d|", ret); return ret; } /* source buffer for payload decryption */ - size_t pktno_len = (header[0] & 0x03) + 1; + size_t pktno_len = XQC_PACKET_SHORT_HEADER_PKTNO_LEN(header); size_t header_len = packet_in->pi_pkt.pkt_num_offset + pktno_len; uint8_t *payload = header + header_len; size_t payload_len = packet_in->pi_pkt.length - pktno_len; @@ -656,18 +691,63 @@ xqc_packet_decrypt(xqc_connection_t *conn, xqc_packet_in_t *packet_in) packet_in->pi_pkt.pkt_num = xqc_packet_decode_packet_number(largest_pn, truncated_pn, pktno_len * 8); + /* check key phase, determine weather to update read keys */ + xqc_uint_t key_phase = XQC_PACKET_SHORT_HEADER_KEY_PHASE(header); + if (packet_in->pi_pkt.pkt_type == XQC_PTYPE_SHORT_HEADER && level == XQC_ENC_LEV_1RTT + && key_phase != conn->key_update_ctx.next_in_key_phase + && packet_in->pi_pkt.pkt_num > conn->key_update_ctx.first_recv_pktno + && xqc_tls_is_key_update_confirmed(conn->tls)) + { + ret = xqc_tls_update_1rtt_keys(conn->tls, XQC_KEY_TYPE_RX_READ); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_INFO, "|xqc_tls_update_rx_keys error|"); + return ret; + } + } + /* decrypt packet payload */ ret = xqc_tls_decrypt_payload(conn->tls, level, packet_in->pi_pkt.pkt_num, header, header_len, payload, payload_len, dst, dst_cap, &packet_in->decode_payload_len); if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_WARN, "|xqc_tls_decrypt_payload error|pkt_type|"); - return ret; + if (!xqc_tls_is_key_update_confirmed(conn->tls)) { + xqc_log(conn->log, XQC_LOG_WARN, "|xqc_tls_decrypt_payload error when keyupdate|"); + return -XQC_TLS_DECRYPT_WHEN_KU_ERROR; + + } else { + xqc_log(conn->log, XQC_LOG_WARN, "|xqc_tls_decrypt_payload error|"); + return ret; + } } packet_in->pos = dst; packet_in->last = dst + packet_in->decode_payload_len; + /* update write keys, apply key update */ + if (packet_in->pi_pkt.pkt_type == XQC_PTYPE_SHORT_HEADER && level == XQC_ENC_LEV_1RTT) { + + if (key_phase != conn->key_update_ctx.next_in_key_phase + && !xqc_tls_is_key_update_confirmed(conn->tls)) + { + ret = xqc_tls_update_1rtt_keys(conn->tls, XQC_KEY_TYPE_TX_WRITE); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_WARN, "|xqc_tls_update_tx_keys error|"); + return ret; + } + + ret = xqc_conn_confirm_key_update(conn); + if (ret != XQC_OK) { + xqc_log(conn->log, XQC_LOG_WARN, "|xqc_conn_confirm_key_update error|"); + return ret; + } + + } else if (key_phase == conn->key_update_ctx.next_in_key_phase + && packet_in->pi_pkt.pkt_num < conn->key_update_ctx.first_recv_pktno) + { + conn->key_update_ctx.first_recv_pktno = packet_in->pi_pkt.pkt_num; + } + } + return XQC_OK; } @@ -815,7 +895,7 @@ xqc_packet_parse_retry(xqc_connection_t *c, xqc_packet_in_t *packet_in) } if (c->conn_type != XQC_CONN_TYPE_CLIENT) { - return -XQC_EPROTO; + return -XQC_EILLPKT; } xqc_cid_t odcid; diff --git a/src/transport/xqc_packet_parser.h b/src/transport/xqc_packet_parser.h index d2150d44f..af58253f1 100644 --- a/src/transport/xqc_packet_parser.h +++ b/src/transport/xqc_packet_parser.h @@ -21,12 +21,14 @@ unsigned xqc_long_packet_header_size(unsigned char dcid_len, unsigned char scid_ int xqc_write_packet_number(unsigned char *buf, xqc_packet_number_t packet_number, unsigned char packet_number_bits); int xqc_gen_short_packet_header(xqc_packet_out_t *packet_out, unsigned char *dcid, unsigned int dcid_len, - unsigned char packet_number_bits, xqc_packet_number_t packet_number); + unsigned char packet_number_bits, xqc_packet_number_t packet_number, xqc_uint_t key_phase); xqc_int_t xqc_packet_parse_short_header(xqc_connection_t *c, xqc_packet_in_t *packet_in); void xqc_long_packet_update_length(xqc_packet_out_t *packet_out); +void xqc_short_packet_update_key_phase(xqc_packet_out_t *packet_out, xqc_uint_t key_phase); + void xqc_short_packet_update_dcid(xqc_packet_out_t *packet_out, xqc_connection_t *conn); int xqc_gen_long_packet_header(xqc_packet_out_t *packet_out, diff --git a/src/transport/xqc_send_ctl.c b/src/transport/xqc_send_ctl.c index e86ba6b4c..0f343f450 100644 --- a/src/transport/xqc_send_ctl.c +++ b/src/transport/xqc_send_ctl.c @@ -143,7 +143,8 @@ xqc_send_ctl_get_packet_out(xqc_send_ctl_t *ctl, unsigned need, xqc_pkt_type_t p xqc_list_for_each_reverse(pos, &ctl->ctl_send_packets) { packet_out = xqc_list_entry(pos, xqc_packet_out_t, po_list); if (packet_out->po_pkt.pkt_type == pkt_type - && packet_out->po_buf_size - packet_out->po_used_size >= need) { + && packet_out->po_buf_size - packet_out->po_used_size >= need) + { return packet_out; } } @@ -1049,24 +1050,20 @@ xqc_send_ctl_on_ack_received(xqc_send_ctl_t *ctl, xqc_ack_info_t *const ack_info xqc_log(ctl->ctl_conn->log, XQC_LOG_DEBUG, "|ctl_packets_used:%ud|ctl_packets_free:%ud|", ctl->ctl_packets_used, ctl->ctl_packets_free); - /* - * Update the RTT if the largest acknowledged is newly acked - * and at least one ack-eliciting was newly acked. - */ + if (XQC_IS_ACK_ELICITING(packet_out->po_frame_types)) { + has_ack_eliciting = 1; + } + if (packet_out->po_pkt.pkt_num == largest_ack - && XQC_IS_ACK_ELICITING(packet_out->po_frame_types)) + && packet_out->po_pkt.pkt_num == ctl->ctl_largest_acked[pns]) { - has_ack_eliciting = 1; update_rtt = 1; ctl->ctl_latest_rtt = ack_recv_time - ctl->ctl_largest_acked_sent_time[pns]; } } } - /* Nothing to do if there are no newly acked packets */ - if (!has_ack_eliciting) { - return XQC_OK; - } + update_rtt &= has_ack_eliciting; if (update_rtt) { xqc_send_ctl_update_rtt(ctl, &ctl->ctl_latest_rtt, ack_info->ack_delay); @@ -1713,7 +1710,9 @@ xqc_send_ctl_get_earliest_loss_time(xqc_send_ctl_t *ctl, xqc_pkt_num_space_t *pn xqc_usec_t time = ctl->ctl_loss_time[XQC_PNS_INIT]; *pns_ret = XQC_PNS_INIT; for (xqc_pkt_num_space_t pns = XQC_PNS_HSK; pns <= XQC_PNS_APP_DATA; ++pns) { - if (time == 0 || ctl->ctl_loss_time[pns] < time) { + if (ctl->ctl_loss_time[pns] != 0 + && (time == 0 || ctl->ctl_loss_time[pns] < time)) + { time = ctl->ctl_loss_time[pns]; *pns_ret = pns; } @@ -1749,12 +1748,24 @@ xqc_send_ctl_check_anti_amplification(xqc_connection_t *conn, size_t byte_cnt) && conn->conn_send_ctl->ctl_bytes_send > 0 && !(conn->conn_flag & XQC_CONN_FLAG_ADDR_VALIDATED)) { - limit = (conn->conn_send_ctl->ctl_bytes_send + byte_cnt >= 3 * conn->conn_send_ctl->ctl_bytes_recv); + limit = (conn->conn_send_ctl->ctl_bytes_send + byte_cnt + >= conn->conn_settings.anti_amplification_limit * conn->conn_send_ctl->ctl_bytes_recv); } return limit; } + +void +xqc_send_ctl_rearm_ld_timer(xqc_send_ctl_t *ctl) +{ + /* make sure the loss detection timer is armed */ + if (!xqc_send_ctl_timer_is_set(ctl, XQC_TIMER_LOSS_DETECTION)) { + xqc_send_ctl_set_loss_detection_timer(ctl); + } +} + + xqc_bool_t xqc_send_ctl_ack_received_in_pns(xqc_send_ctl_t *ctl, xqc_pkt_num_space_t pns) { @@ -1776,6 +1787,7 @@ static const char * const timer_type_2_str[XQC_TIMER_N] = { [XQC_TIMER_PING] = "PING", [XQC_TIMER_RETIRE_CID] = "RETIRE_CID", [XQC_TIMER_LINGER_CLOSE] = "LINGER_CLOSE", + [XQC_TIMER_KEY_UPDATE] = "KEY_UPDATE", }; const char * @@ -1984,6 +1996,15 @@ xqc_send_ctl_linger_close_timeout(xqc_send_ctl_timer_type type, xqc_usec_t now, } } +void +xqc_send_ctl_key_update_timeout(xqc_send_ctl_timer_type type, xqc_usec_t now, void *ctx) +{ + xqc_send_ctl_t *ctl = (xqc_send_ctl_t *) ctx; + xqc_connection_t *conn = ctl->ctl_conn; + + xqc_tls_discard_old_1rtt_keys(conn->tls); +} + /* timer callbacks end */ void @@ -2020,12 +2041,18 @@ xqc_send_ctl_timer_init(xqc_send_ctl_t *ctl) } else if (type == XQC_TIMER_PING) { timer->ctl_timer_callback = xqc_send_ctl_ping_timeout; timer->ctl_ctx = ctl; + } else if (type == XQC_TIMER_RETIRE_CID) { timer->ctl_timer_callback = xqc_send_ctl_retire_cid_timeout; timer->ctl_ctx = ctl; + } else if (type == XQC_TIMER_LINGER_CLOSE) { timer->ctl_timer_callback = xqc_send_ctl_linger_close_timeout; timer->ctl_ctx = ctl; + + } else if (type == XQC_TIMER_KEY_UPDATE) { + timer->ctl_timer_callback = xqc_send_ctl_key_update_timeout; + timer->ctl_ctx = ctl; } } } diff --git a/src/transport/xqc_send_ctl.h b/src/transport/xqc_send_ctl.h index e4c355673..f7be577ee 100644 --- a/src/transport/xqc_send_ctl.h +++ b/src/transport/xqc_send_ctl.h @@ -52,6 +52,7 @@ typedef enum { XQC_TIMER_PING, XQC_TIMER_RETIRE_CID, XQC_TIMER_LINGER_CLOSE, + XQC_TIMER_KEY_UPDATE, XQC_TIMER_N, } xqc_send_ctl_timer_type; @@ -295,6 +296,8 @@ float xqc_send_ctl_get_retrans_rate(xqc_send_ctl_t *ctl); */ xqc_bool_t xqc_send_ctl_check_anti_amplification(xqc_connection_t *conn, size_t byte_cnt); +void xqc_send_ctl_rearm_ld_timer(xqc_send_ctl_t *ctl); + xqc_bool_t xqc_send_ctl_ack_received_in_pns(xqc_send_ctl_t *ctl, xqc_pkt_num_space_t pns); diff --git a/src/transport/xqc_stream.c b/src/transport/xqc_stream.c index ae3597d2a..65b1beeee 100644 --- a/src/transport/xqc_stream.c +++ b/src/transport/xqc_stream.c @@ -121,7 +121,8 @@ xqc_stream_maybe_need_close(xqc_stream_t *stream) xqc_usec_t new_expire = 3 * xqc_send_ctl_calc_pto(ctl) + now; if ((ctl->ctl_timer[XQC_TIMER_STREAM_CLOSE].ctl_timer_is_set && new_expire < ctl->ctl_timer[XQC_TIMER_STREAM_CLOSE].ctl_expire_time) - || !ctl->ctl_timer[XQC_TIMER_STREAM_CLOSE].ctl_timer_is_set) { + || !ctl->ctl_timer[XQC_TIMER_STREAM_CLOSE].ctl_timer_is_set) + { xqc_send_ctl_timer_set(ctl, XQC_TIMER_STREAM_CLOSE, now, new_expire - now); } stream->stream_close_time = new_expire; @@ -1052,7 +1053,8 @@ xqc_stream_recv(xqc_stream_t *stream, unsigned char *recv_buf, size_t recv_buf_s } if (stream->stream_data_in.stream_length > 0 - && stream->stream_data_in.next_read_offset == stream->stream_data_in.stream_length) { + && stream->stream_data_in.next_read_offset == stream->stream_data_in.stream_length) + { *fin = 1; stream->stream_stats.peer_fin_read_time = xqc_monotonic_timestamp(); if (stream->stream_state_recv == XQC_RECV_STREAM_ST_DATA_RECVD) { @@ -1114,7 +1116,8 @@ xqc_stream_send(xqc_stream_t *stream, unsigned char *send_data, size_t send_data if (!(conn->conn_flag & XQC_CONN_FLAG_CAN_SEND_1RTT)) { if ((conn->conn_type == XQC_CONN_TYPE_CLIENT) && (conn->conn_state == XQC_CONN_STATE_CLIENT_INITIAL_SENT) - && support_0rtt) { + && support_0rtt) + { pkt_type = XQC_PTYPE_0RTT; conn->conn_flag |= XQC_CONN_FLAG_HAS_0RTT; stream->stream_flag |= XQC_STREAM_FLAG_HAS_0RTT; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 90729753f..b0cf44ca8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,11 +48,11 @@ if(HAVE_CUNIT) target_include_directories(run_tests PRIVATE ${CUNIT_INCLUDE_DIRS}) target_link_libraries(run_tests xquic-static + ${CUNIT_LIBRARIES} + ${SSL_LIB_PATH} m dl pthread - ${CUNIT_LIBRARIES} - ${SSL_LIB_PATH} ) add_test(run_tests run_tests) diff --git a/tests/test_client.c b/tests/test_client.c index fdce36d62..25c1cef3b 100644 --- a/tests/test_client.c +++ b/tests/test_client.c @@ -71,6 +71,7 @@ typedef struct user_stream_s { xqc_msec_t first_frame_time; /* first frame download time */ xqc_msec_t last_read_time; int abnormal_count; + int body_read_notify_cnt; } user_stream_t; typedef struct user_conn_s { @@ -1485,8 +1486,15 @@ xqc_client_request_close_notify(xqc_h3_request_t *h3_request, void *user_data) if (g_echo_check) { int pass = 0; if (user_stream->recv_fin && user_stream->send_body_len == user_stream->recv_body_len - && memcmp(user_stream->send_body, user_stream->recv_body, user_stream->send_body_len) == 0) { + && memcmp(user_stream->send_body, user_stream->recv_body, user_stream->send_body_len) == 0) + { pass = 1; + + /* large data read once for all */ + if (user_stream->send_body_len >= 1024 * 1024 && user_stream->body_read_notify_cnt == 1) { + pass = 0; + printf("large body received once for all"); + } } printf(">>>>>>>> pass:%d\n", pass); } @@ -1811,6 +1819,7 @@ xqc_client_write_log(xqc_log_level_t lvl, const void *buf, size_t count, void *e printf("xqc_client_write_log err\n"); return; } + int write_len = write(ctx->log_fd, log_buf, log_len); if (write_len < 0) { printf("write log failed, errno: %d\n", errno); @@ -1860,6 +1869,7 @@ xqc_keylog_cb(const char *line, void *user_data) printf("write keys failed, errno: %d\n", errno); return; } + write_len = write(ctx->keylog_fd, "\n", 1); if (write_len < 0) { printf("write keys failed, errno: %d\n", errno); @@ -2152,6 +2162,7 @@ int main(int argc, char *argv[]) { //.so_sndbuf = 1024*1024, .proto_version = XQC_VERSION_V1, .spurious_loss_detect_on = 0, + .keyupdate_pkt_threshold = 0, }; xqc_config_t config; @@ -2187,6 +2198,11 @@ int main(int argc, char *argv[]) { conn_settings.spurious_loss_detect_on = 1; } + /* test key update */ + if (g_test_case == 40) { + conn_settings.keyupdate_pkt_threshold = 30; + } + eb = event_base_new(); ctx.ev_engine = event_new(eb, -1, 0, xqc_client_engine_callback, &ctx); diff --git a/tests/test_server.c b/tests/test_server.c index 2f1436e83..c6687a84d 100644 --- a/tests/test_server.c +++ b/tests/test_server.c @@ -1078,6 +1078,7 @@ xqc_server_write_log(xqc_log_level_t lvl, const void *buf, size_t count, void *e printf("xqc_server_write_log err\n"); return; } + int write_len = write(ctx->log_fd, log_buf, log_len); if (write_len < 0) { printf("xqc_server_write_log write failed, errno: %d\n", errno); @@ -1127,6 +1128,7 @@ xqc_keylog_cb(const char *line, void *user_data) printf("write keys failed, errno: %d\n", errno); return; } + write_len = write(ctx->keylog_fd, "\n", 1); if (write_len < 0) { printf("write keys failed, errno: %d\n", errno); diff --git a/tests/unittest/xqc_h3_test.c b/tests/unittest/xqc_h3_test.c index 658c9f016..b2de25ccb 100644 --- a/tests/unittest/xqc_h3_test.c +++ b/tests/unittest/xqc_h3_test.c @@ -153,6 +153,20 @@ xqc_test_frame() CU_ASSERT(buf->consumed_len == buf->data_len); xqc_h3_frm_reset_pctx(&pctx); + /* reserved frame type with 10 bytes */ + char reserved_frame[] = "\xcf\x25\x7c\x52\x89\x59\xd7\xba\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + size_t reserved_frame_len = sizeof(reserved_frame) - 1; + size_t reserved_consumed_len = 0; + for (size_t i = 0; i < reserved_frame_len; i++) { + processed = xqc_h3_frm_parse(reserved_frame + reserved_consumed_len, 1, &pctx); + CU_ASSERT(processed > 0); + reserved_consumed_len += processed; + } + CU_ASSERT(pctx.state == XQC_H3_FRM_STATE_END); + CU_ASSERT(reserved_consumed_len == reserved_frame_len); + CU_ASSERT(pctx.frame.type == 0xf257c528959d7ba) + xqc_h3_frm_reset_pctx(&pctx); + xqc_var_buf_free(buf); } diff --git a/tests/unittest/xqc_recv_record_test.c b/tests/unittest/xqc_recv_record_test.c index 9cae0227b..fe1dc412f 100644 --- a/tests/unittest/xqc_recv_record_test.c +++ b/tests/unittest/xqc_recv_record_test.c @@ -28,7 +28,7 @@ xqc_test_recv_record() //printf("low:%llu, high=%llu\n", pnode->pktno_range.low, pnode->pktno_range.high); } - //printf("largest=%llu\n", xqc_recv_record_largest(&record)); + /* printf("largest=%llu\n", xqc_recv_record_largest(&record)); */ CU_ASSERT(10 == xqc_recv_record_largest(&record)); diff --git a/xqc_build.sh b/xqc_build.sh index 473f06444..55640e241 100755 --- a/xqc_build.sh +++ b/xqc_build.sh @@ -46,8 +46,6 @@ if [ x"$platform" == xios ] ; then configures="-DSSL_TYPE=${ssl_type} -DSSL_PATH=${ssl_path} -DSSL_LIB_PATH=${ssl_lib_path} - -DBORINGSSL_PREFIX=bs - -DBORINGSSL_PREFIX_SYMBOLS=$cur_dir/bssl_symbols.txt -DDEPLOYMENT_TARGET=10.0 -DCMAKE_BUILD_TYPE=Minsizerel -DXQC_ENABLE_TESTING=OFF