mirror of
https://github.com/openssl/openssl.git
synced 2025-04-24 20:51:14 +08:00
Multi-Stream API
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19769)
This commit is contained in:
parent
aef2496127
commit
e4c2988dc5
@ -87,6 +87,9 @@ Notes:
|
||||
- †9: QUIC always uses AES-128-GCM initially. We need to determine when and
|
||||
what ciphers we report as being in use.
|
||||
- †10: Not supporting async for now.
|
||||
- †11: Since these functions only configure cipher suite lists used for TLSv1.2,
|
||||
which is never used for QUIC, they do not require changes, and we can allow
|
||||
applications to configure these lists freely, as they will be ignored.
|
||||
|
||||
| API Item | Cat. | Sema. | Appl. | Impl. Req. | Status |
|
||||
|----------|----------|-----------|---------------|----------------|--------|
|
||||
@ -140,7 +143,7 @@ Notes:
|
||||
| `SSL_CTX_up_ref` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_CTX_free` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_new` | Object | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_dup` | Object | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_dup` | Object | 🟩U | 🟩A | 🟥FC | 🟢Done |
|
||||
| `SSL_up_ref` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_free` | Object | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_is_dtls` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
@ -153,28 +156,27 @@ Notes:
|
||||
| **⇒ Method Manipulation** | |
|
||||
| `SSL_CTX_get_ssl_method` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_get_ssl_method` | Object | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_CTX_set_ssl_method` | Object | 🟥TBD | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_set_ssl_method` | Object | 🟥TBD | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_set_ssl_method` | Object | 🟥TBD | 🟩A | 🟧QSI | 🟢Done |
|
||||
| **⇒ SRTP** | |
|
||||
| `SSL_get_selected_srtp_profile` | HL | 🟩U | 🟥FC | 🟨C\* | 🟡TODO |
|
||||
| `SSL_get_srtp_profiles` | HL | 🟩U | 🟥FC | 🟨C\* | 🟡TODO |
|
||||
| `SSL_CTX_set_tlsext_use_srtp` | HL | 🟩U | 🟥FC | 🟨C\* | 🟡TODO |
|
||||
| `SSL_set_tlsext_use_srtp` | HL | 🟩U | 🟥FC | 🟨C\* | 🟡TODO |
|
||||
| `SSL_get_selected_srtp_profile` | HL | 🟩U | 🟧NO | 🟨C\* | 🟢Done |
|
||||
| `SSL_get_srtp_profiles` | HL | 🟩U | 🟧NO | 🟨C\* | 🟢Done |
|
||||
| `SSL_CTX_set_tlsext_use_srtp` | HL | 🟩U | 🟥FC | 🟨C\* | 🟢Done |
|
||||
| `SSL_set_tlsext_use_srtp` | HL | 🟩U | 🟥FC | 🟩NC\* | 🟢Done |
|
||||
| **⇒ Ciphersuite Configuration** | |
|
||||
| `SSL_CTX_set_cipher_list` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_CTX_set_ciphersuites` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_CTX_get_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_set_ciphersuites` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_get1_supported_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_bytes_to_cipher_list` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_get_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_get_cipher_list` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_set_cipher_list` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟡TODO |
|
||||
| `SSL_CTX_set_cipher_list` | HL | 🟩U | 🟩A | 🟩NC\* †11 | 🟢Done |
|
||||
| `SSL_CTX_set_ciphersuites` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟢Done |
|
||||
| `SSL_CTX_get_ciphers` | HL | 🟩U | 🟩A |🟩NC\* | 🟢Done |
|
||||
| `SSL_set_ciphersuites` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_get1_supported_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †1 | 🟢Done |
|
||||
| `SSL_bytes_to_cipher_list` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_get_ciphers` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_get_cipher_list` | HL | 🟩U | 🟩A | 🟩NC\* †11 | 🟢Done |
|
||||
| `SSL_set_cipher_list` | HL | 🟩U | 🟩A | 🟩NC\* †11 | 🟢Done |
|
||||
| **⇒ Negotiated Ciphersuite Queries** | |
|
||||
| `SSL_get_current_cipher` | HL | 🟩U | 🟩A | 🟨C\* †9 | 🟠Design TBD |
|
||||
| `SSL_get_pending_cipher` | HL | 🟩U | 🟩A | 🟨C\* †9 | 🟠Design TBD |
|
||||
| `SSL_get_shared_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †9 | 🟠Design TBD |
|
||||
| `SSL_get_client_ciphers` | HL | 🟩U | 🟩A | 🟨C\* †9 | 🟠Design TBD |
|
||||
| `SSL_get_current_cipher` | HL | 🟩U | 🟩A |🟩NC\* †9 | 🟢Done |
|
||||
| `SSL_get_pending_cipher` | HL | 🟩U | 🟩A | 🟩NC\* †9 | 🟢Done |
|
||||
| `SSL_get_shared_ciphers` | HL | 🟩U | 🟩A | 🟩NC\* †9 | 🟢Done |
|
||||
| `SSL_get_client_ciphers` | HL | 🟩U | 🟩A | 🟩NC\* †9 | 🟢Done |
|
||||
| `SSL_get_current_compression` | HL | 🟩U | 🟩A | 🟩HLNC | 🟢Done |
|
||||
| `SSL_get_current_expansion` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_get_shared_sigalgs` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
@ -191,9 +193,9 @@ Notes:
|
||||
| `SSL_get0_alpn_selected` | HL | 🟩U | 🟩A | 🟨C\* †2 | 🟡TODO |
|
||||
| `SSL_CTX_set_alpn_protos` | HL | 🟩U | 🟩A | 🟨C\* †2 | 🟡TODO |
|
||||
| **⇒ NPN** | †3 |
|
||||
| `SSL_CTX_set_next_proto_select_cb` | HL | 🟩U | 🟥FC | 🟨C\* †3 | 🟡TODO |
|
||||
| `SSL_CTX_set_next_protos_advertised_cb` | HL | 🟩U | 🟥FC | 🟨C\* †3 | 🟡TODO |
|
||||
| `SSL_get0_next_proto_negotiated` | HL | 🟩U | 🟥FC | 🟨C\* †3 | 🟡TODO |
|
||||
| `SSL_CTX_set_next_proto_select_cb` | HL | 🟩U | 🟥FC | 🟨C\* †3 | 🟢Done |
|
||||
| `SSL_CTX_set_next_protos_advertised_cb` | HL | 🟩U | 🟥FC | 🟨C\* †3 | 🟢Done |
|
||||
| `SSL_get0_next_proto_negotiated` | HL | 🟩U | 🟥FC | 🟩NC\* †3 | 🟢Done |
|
||||
| **⇒ Narrow Waist Interface** | †4 |
|
||||
| `SSL_CTX_ctrl` | Object | 🟩U | 🟩A | 🟩NC\* †4 | 🟢Done |
|
||||
| `SSL_ctrl` | Object | 🟩U | 🟩A | 🟩NC\* †4 | 🟢Done |
|
||||
@ -394,11 +396,11 @@ Notes:
|
||||
| `SSL_renegotiate_abbreviated` | HL | 🟩U | 🟥FC | 🟩NC\* †5 | 🟢Done |
|
||||
| `SSL_renegotiate_pending` | HL | 🟩U | 🟧NO | 🟩NC\* †5 | 🟢Done |
|
||||
| **⇒ Options** | |
|
||||
| `SSL_CTX_clear_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_CTX_set_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_CTX_clear_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_CTX_set_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_CTX_get_options` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_clear_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_set_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_clear_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_set_options` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_get_options` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| **⇒ Configuration** | |
|
||||
| `SSL_CONF_CTX_new` | Global | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
@ -519,7 +521,7 @@ Notes:
|
||||
| `SSL_set_num_tickets` | HL | 🟩U | 🟩A | 🟩NC\* †7 | 🟢Done |
|
||||
| `SSL_CTX_get_num_tickets` | HL | 🟩U | 🟩A | 🟩NC\* †7 | 🟢Done |
|
||||
| `SSL_CTX_set_num_tickets` | HL | 🟩U | 🟩A | 🟩NC\* †7 | 🟢Done |
|
||||
| `SSL_new_session_ticket` | HL | 🟩U | 🟩A | 🟨C\* | 🟡TODO |
|
||||
| `SSL_new_session_ticket` | HL | 🟩U | 🟩A | 🟩NC\* †7 | 🟢Done |
|
||||
| `SSL_set_session_ticket_ext` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_set_session_ticket_ext_cb` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_CTX_set_tlsext_ticket_key_evp_cb` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
@ -559,9 +561,9 @@ Notes:
|
||||
| `SSL_CTX_use_serverinfo_ex` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_CTX_use_serverinfo_file` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| **⇒ Post-Handshake Authentication** | |
|
||||
| `SSL_verify_client_post_handshake` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟡TODO |
|
||||
| `SSL_CTX_set_post_handshake_auth` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟡TODO |
|
||||
| `SSL_set_post_handshake_auth` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟡TODO |
|
||||
| `SSL_verify_client_post_handshake` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟢Done |
|
||||
| `SSL_CTX_set_post_handshake_auth` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟢Done |
|
||||
| `SSL_set_post_handshake_auth` | HL | 🟩U | 🟥FC | 🟨C* †8 | 🟢Done |
|
||||
| **⇒ DH Parameters** | |
|
||||
| `SSL_CTX_set_dh_auto` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_set_dh_auto` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
@ -576,23 +578,23 @@ Notes:
|
||||
| `SSL_in_before` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_is_init_finished` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_get_state` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_rstate_string` | HL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_rstate_string_long` | HL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_state_string` | HL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_state_string_long` | HL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_rstate_string` | HL | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_rstate_string_long` | HL | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_state_string` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_state_string_long` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| **⇒ Data Path and CSSM** | |
|
||||
| `SSL_set_connect_state` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_set_accept_state` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_is_server` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_is_server` | CSSM | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_peek` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_peek_ex` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_read` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_read_ex` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_write` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_write_ex` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_sendfile` | ADP | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_pending` | ADP | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_has_pending` | ADP | TBD | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_sendfile` | ADP | 🟩U | 🟥FC | 🟩NC\* | 🟢Done |
|
||||
| `SSL_pending` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_has_pending` | ADP | TBD | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_accept` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_connect` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_do_handshake` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
@ -605,15 +607,15 @@ Notes:
|
||||
| `SSL_get_rfd` | NDP | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_get_wfd` | NDP | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_get_fd` | NDP | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_set_rfd` | NDP | 🟧C | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_set_wfd` | NDP | 🟧C | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_set_fd` | NDP | 🟩U | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_key_update` | RL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_get_key_update_type` | RL | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_clear` (connection) | CSSM | TBD | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_set_rfd` | NDP | 🟧C | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_set_wfd` | NDP | 🟧C | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_set_fd` | NDP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_key_update` | RL | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_get_key_update_type` | RL | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_clear` (connection) | CSSM | TBD | 🟩A | 🟥FC | 🟢Done |
|
||||
| `SSL_clear` (stream) | CSSM | TBD | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
| `SSL_shutdown` | CSSM | 🟧C | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_want` | ADP | 🟧C | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_want` | ADP | 🟧C | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `BIO_new_ssl_connect` | Global | 🟩U | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `BIO_new_buffer_ssl_connect` | Global | 🟩U | 🟦U | 🟧QSI | 🟡TODO |
|
||||
| `SSL_get_shutdown` | CSSM | 🟩U | 🟩A | 🟧QSI | 🟠Design TBD |
|
||||
@ -632,17 +634,31 @@ Notes:
|
||||
| `SSL_shutdown_ex` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_stream_conclude` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_stream_reset` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_state` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_error_code` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_read_state` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_write_state` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_read_error_code` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_write_error_code` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_conn_close_info` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| **⇒ New APIs for Multi-Stream** | |
|
||||
| `SSL_get0_connection` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_is_connection` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_id` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_stream_type` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_new_stream` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_accept_stream` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_get_accept_stream_queue_len` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_set_default_stream_mode` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_set_incoming_stream_reject_policy` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_detach_stream` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| `SSL_attach_stream` | CSSM | 🟦N | 🟩A | 🟥QSA | 🟡TODO |
|
||||
| **⇒ Currently Not Supported** | |
|
||||
| `SSL_copy_session_id` | Special | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `BIO_ssl_copy_session_id` | Special | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_quiet_shutdown` | CSSM | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_quiet_shutdown` | CSSM | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_quiet_shutdown` | CSSM | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_quiet_shutdown` | CSSM | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_ssl_version` | HL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_copy_session_id` | Special | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `BIO_ssl_copy_session_id` | Special | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_set_quiet_shutdown` | CSSM | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `SSL_CTX_get_quiet_shutdown` | CSSM | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `SSL_set_quiet_shutdown` | CSSM | 🟩U | 🟥FC | 🟨C | 🟢Done |
|
||||
| `SSL_get_quiet_shutdown` | CSSM | 🟩U | 🟧NO | 🟨C | 🟢Done |
|
||||
| `SSL_CTX_set_ssl_version` | HL | 🟩U | 🟥FC | 🟨C | 🟢Done |
|
||||
| **⇒ Async** | |
|
||||
| `SSL_CTX_set_async_callback` | Async | 🟩U | 🟧NO | 🟩NC* †10 | 🟢Done |
|
||||
| `SSL_set_async_callback` | Async | 🟩U | 🟧NO | 🟩NC* †10 | 🟢Done |
|
||||
@ -653,67 +669,67 @@ Notes:
|
||||
| `SSL_get_all_async_fds` | Async | 🟩U | 🟧NO | 🟩NC* †10 | 🟢Done |
|
||||
| `SSL_get_changed_async_fds` | Async | 🟩U | 🟧NO | 🟩NC* †10 | 🟢Done |
|
||||
| **⇒ Readahead** | |
|
||||
| `SSL_CTX_get_default_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_default_read_buffer_len` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_default_read_buffer_len` | RL | 🟩U | 🟧NO | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_default_read_ahead` | RL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_get_read_ahead` | RL | 🟩U | 🟧NO | 🟩NC* |🟢Done |
|
||||
| `SSL_CTX_set_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* |🟢Done |
|
||||
| `SSL_get_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* |🟢Done |
|
||||
| `SSL_set_read_ahead` | RL | 🟩U | 🟧NO | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_set_default_read_buffer_len` | RL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_default_read_buffer_len` | RL | 🟩U | 🟧NO | 🟨C* | 🟢Done |
|
||||
| **⇒ Record Padding and Fragmentation** | |
|
||||
| `SSL_CTX_set_record_padding_callback` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_record_padding_callback` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_block_padding` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_block_padding` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_tlsext_max_fragment_length` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_tlsext_max_fragment_length` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_record_padding_callback` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_record_padding_callback` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_get_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_set_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_get_record_padding_callback_arg` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_record_padding_callback_arg` | RL | 🟩U | 🟥FC |🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_set_block_padding` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_block_padding` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_set_tlsext_max_fragment_length` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_tlsext_max_fragment_length` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| **⇒ Stateless/HelloRetryRequest** | |
|
||||
| `SSL_stateless` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_stateless_cookie_generate_cb` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_stateless_cookie_verify_cb` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_stateless` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_set_stateless_cookie_generate_cb` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_set_stateless_cookie_verify_cb` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| **⇒ Early Data/0-RTT** | |
|
||||
| `SSL_CTX_set_allow_early_data_cb` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_allow_early_data_cb` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_get_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_set_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_read_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_write_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_get_early_data_status` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTX_set_allow_early_data_cb` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_allow_early_data_cb` | 0-RTT | 🟩U | 🟥FC | 🟨C* |🟢Done |
|
||||
| `SSL_CTX_get_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_set_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_get_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_recv_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTX_get_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTX_set_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_get_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_set_max_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_read_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_write_early_data` | 0-RTT | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_get_early_data_status` | 0-RTT | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| **⇒ Miscellaneous** | |
|
||||
| `DTLSv1_listen` | RL | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `DTLS_set_timer_cb` | NDP | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `DTLS_get_data_mtu` | NDP | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `SSL_get_ex_data_X509_STORE_CTX_idx` | Global | 🟩U | 🟦U | 🟩NC | 🟢Done |
|
||||
| `BIO_ssl_shutdown` | Global | 🟩U | 🟩A | 🟩NC | 🟢Done |
|
||||
| `SSL_alloc_buffers` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_free_buffers` | HL | 🟩U | 🟩A | 🟨C\* | 🟠Design TBD |
|
||||
| `SSL_alloc_buffers` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_free_buffers` | HL | 🟩U | 🟩A | 🟨C\* | 🟢Done |
|
||||
| `SSL_trace` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| `SSL_set_debug` | HL | 🟩U | 🟩A | 🟩NC\* | 🟢Done |
|
||||
| **⇒ Controls** | |
|
||||
| `SSL_CTRL_MODE` | Special | 🟩U | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_CTRL_CLEAR_MODE` | Special | 🟩U | 🟩A | 🟧QSI | 🟡TODO |
|
||||
| `SSL_CTRL_MODE` | Special | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_CTRL_CLEAR_MODE` | Special | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS` | HL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_NUM_RENEGOTIATIONS` | HL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_TOTAL_RENEGOTIATIONS` | HL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_RI_SUPPORT` | HL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_READ_AHEAD` | HL | 🟩U | 🟧NO | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_SET_READ_AHEAD` | HL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_MAX_PIPELINES` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_MAX_SEND_FRAGMENT` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_SPLIT_SEND_FRAGMENT` | RL | 🟩U | 🟥FC | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_READ_AHEAD` | HL | 🟩U | 🟥FC | 🟨C* |🟢Done |
|
||||
| `SSL_CTRL_SET_MAX_PIPELINES` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTRL_SET_MAX_SEND_FRAGMENT` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTRL_SET_SPLIT_SEND_FRAGMENT` | RL | 🟩U | 🟥FC | 🟨C* | 🟢Done |
|
||||
| `SSL_CTRL_SET_MTU` | RL | 🟩U | 🟥FC | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_SET_MAX_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_MIN_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟨C* | 🟡TODO |
|
||||
| `SSL_CTRL_SET_MAX_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟨C* | 🟢Done |
|
||||
| `SSL_CTRL_SET_MIN_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_MAX_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_GET_MIN_PROTO_VERSION` | HL | 🟩U | 🟩A | 🟩NC* | 🟢Done |
|
||||
| `SSL_CTRL_BUILD_CERT_CHAIN` | HL | 🟩U | 🟩A | 🟩NC* | 🟢Done |
|
||||
@ -810,5 +826,170 @@ Notes:
|
||||
| `SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER` | ADP | 🟩U | 🟩A | 🟧QSI | 🟢Done |
|
||||
| `SSL_MODE_RELEASE_BUFFERS` | ADP | 🟩U | 🟧NO | 🟩NC | 🟢Done |
|
||||
| `SSL_MODE_ASYNC` | ADP | 🟩U | 🟧NO | 🟩NC | 🟢Done |
|
||||
| `SSL_MODE_AUTO_RETRY` | ADP | TBD | TBD | TBD | 🔴Pending Triage |
|
||||
| `SSL_MODE_SEND_FALLBACK_SCSV` | HL | 🟩U | 🟩A | 🟨C\* | 🟡TODO |
|
||||
| `SSL_MODE_AUTO_RETRY` | ADP | 🟩U | 🟧NO | 🟩NC | 🟢Done |
|
||||
| `SSL_MODE_SEND_FALLBACK_SCSV` | HL | 🟩U | 🟩U | 🟩NC | 🟢Done |
|
||||
|
||||
Q&A For TLS-Related Calls
|
||||
-------------------------
|
||||
|
||||
### What should `SSL_get_current_cipher`, `SSL_get_pending_cipher`, etc. do?
|
||||
|
||||
QUIC always uses AES-128-GCM for Initial packets. At this time the handshake
|
||||
layer has not negotiated a ciphersuite so it has no “current” cipher. We could
|
||||
return AES-128-GCM here, but it seems reasonable to just return NULL as the
|
||||
encryption is mostly for protection against accidential modification and not
|
||||
“real” encryption. From the perspective of the Handshake layer encryption is not
|
||||
active yet. An application using QUIC can always interpret NULL as meaning
|
||||
AES-128-GCM is being used if needed as this is implied by using QUIC.
|
||||
|
||||
### What should `SSL_CTX_set_cipher_list` do?
|
||||
|
||||
Since this function configures the cipher list for TLSv1.2 and below only, there
|
||||
is no need to restrict it as TLSv1.3 is required for QUIC. For the sake of
|
||||
application compatibility, applications can still configure the TLSv1.2 cipher
|
||||
list; it will always be ignored.
|
||||
|
||||
### What should `SSL_get_current_cipher` and similar do?
|
||||
|
||||
QUIC always uses AES-128-GCM encryption initially, so we could either return
|
||||
AES-128-GCM where the handshake has not yet negotiated another algorithm or
|
||||
return NULL here.
|
||||
|
||||
A. We return NULL here, because it allows applications to detect if a
|
||||
ciphersuite has been negotiated and NULL can be used to infer that Initial
|
||||
encryption is still being used. This also minimises the changes needed to the
|
||||
implementation.
|
||||
|
||||
### What SSL options should be supported?
|
||||
|
||||
Options we explicitly want to support:
|
||||
|
||||
- `SSL_OP_CIPHER_SERVER_PREFERENCE`
|
||||
- `SSL_OP_DISABLE_TLSEXT_CA_NAMES`
|
||||
- `SSL_OP_NO_TX_CERTIFICATE_COMPRESSION`
|
||||
- `SSL_OP_NO_RX_CERTIFICATE_COMPRESSION`
|
||||
- `SSL_OP_PRIORITIZE_CHACHA`
|
||||
- `SSL_OP_NO_TICKET`
|
||||
|
||||
Options we do not yet support but could support in the future, currently no-ops:
|
||||
|
||||
- `SSL_OP_CLEANSE_PLAINTEXT`
|
||||
- `SSL_OP_NO_QUERY_MTU`
|
||||
- `SSL_OP_NO_ANTI_REPLAY`
|
||||
|
||||
The following options must be explicitly forbidden:
|
||||
|
||||
- `SSL_OP_NO_TLSv1_3` — TLSv1.3 is required for QUIC
|
||||
- `SSL_OP_ENABLE_MIDDLEBOX_COMPAT` — forbidden by QUIC RFCs
|
||||
- `SSL_OP_ENABLE_KTLS` — not currently supported for QUIC
|
||||
- `SSL_OP_SAFARI_ECDHE_ECDSA_BUG`
|
||||
- `SSL_OP_TLSEXT_PADDING`
|
||||
- `SSL_OP_TLS_ROLLBACK_BUG`
|
||||
- `SSL_OP_IGNORE_UNEXPECTED_EOF`
|
||||
- `SSL_OP_ALLOW_NO_DHE_KEX`
|
||||
|
||||
The following options are ignored for TLSv1.3 or otherwise not applicable and
|
||||
may therefore be settable but ignored. We take this approach on the grounds
|
||||
that it is harmless and applications might want to see that options have been
|
||||
correctly set for protocols unrelated to QUIC.
|
||||
|
||||
- `SSL_OP_CRYPTOPRO_TLSEXT_BUG`
|
||||
- `SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS`
|
||||
- `SSL_OP_ALLOW_CLIENT_RENEGOTIATION`
|
||||
- `SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION`
|
||||
- `SSL_OP_CISCO_ANYCONNECT`
|
||||
- `SSL_OP_COOKIE_EXCHANGE`
|
||||
- `SSL_OP_LEGACY_SERVER_CONNECT`
|
||||
- `SSL_OP_NO_COMPRESSION`
|
||||
- `SSL_OP_NO_ENCRYPT_THEN_MAC`
|
||||
- `SSL_OP_NO_EXTENDED_MASTER_SECRET`
|
||||
- `SSL_OP_NO_RENEGOTIATION`
|
||||
- `SSL_OP_NO_RESSION_RESUMPTION_ON_NEGOTIATION`
|
||||
- `SSL_OP_NO_SSLv3`
|
||||
- `SSL_OP_NO_TLSv1`
|
||||
- `SSL_OP_NO_TLSv1_1`
|
||||
- `SSL_OP_NO_TLSv1_2`
|
||||
- `SSL_OP_NO_DTLSv1`
|
||||
- `SSL_OP_NO_DTLSv1_2`
|
||||
|
||||
### What should `SSL_rstate_string` and `SSL_state_string` do?
|
||||
|
||||
SSL_state_string is highly handshake layer specific, so it makes sense to just
|
||||
forward to the handshake layer.
|
||||
|
||||
SSL_rstate_string is record layer specific. A cursory evaluation of usage via
|
||||
GitHub code search did not appear to identify much usage of this function other
|
||||
than for debug output; i.e., there seems to be little usage of this in a way
|
||||
that depends on the output for the purposes of control flow. Since there is not
|
||||
really any direct correspondence to the QUIC record layer, we conservatively
|
||||
define the output of this function as "unknown".
|
||||
|
||||
TODO: forbid NPN
|
||||
TODO: enforce TLSv1.3
|
||||
TODO: forbid PHA - DONE
|
||||
TODO: forbid middlebox compat mode in a deeper way?
|
||||
TODO: new_session_ticket doesn't need modifying as such, but ticket machinery
|
||||
will
|
||||
|
||||
### What should `SSL_pending` and `SSL_has_pending` do?
|
||||
|
||||
`SSL_pending` traditionally yields the number of bytes buffered inside a SSL
|
||||
object available for immediate reading. For QUIC, we can just make this report
|
||||
the current size of the receive stream buffer.
|
||||
|
||||
`SSL_has_pending` returns a boolean value indicating whether there is processed
|
||||
or unprocessed incoming data pending. There is no direct correspondence to
|
||||
QUIC, so there are various implementation options:
|
||||
|
||||
- `SSL_pending() > 0`
|
||||
- `SSL_pending() > 0 || pending URXEs or RXEs exist`
|
||||
|
||||
The latter can probably be viewed as more of a direct correspondence to the
|
||||
design intent of the API, so we go with this.
|
||||
|
||||
### What should `SSL_alloc_buffers` and `SSL_free_buffers` do?
|
||||
|
||||
These do not really correspond to our internal architecture for QUIC. Since
|
||||
internal buffers are always available, `SSL_alloc_buffers` can simply always
|
||||
return 1. `SSL_free_buffers` can always return 0, as though the buffers are in
|
||||
use, which they generally will be.
|
||||
|
||||
### What should `SSL_key_update` and `SSL_get_key_update_type`?
|
||||
|
||||
`SSL_key_update` can trigger a TX record layer key update, which will cause the
|
||||
peer to respond with a key update in turn. The update occurs asynchronously
|
||||
at next transmission, not immediately.
|
||||
|
||||
`SSL_get_key_update_type` returns an enumerated value which is only relevant to
|
||||
the TLSv1.3 protocol; for QUIC, it will always return `SSL_KEY_UPDATE_NONE`.
|
||||
|
||||
### What should `SSL_MODE_AUTO_RETRY` do?
|
||||
|
||||
The absence of `SSL_MODE_AUTO_RETRY` causes `SSL_read`/`SSL_write` on a normal
|
||||
TLS connection to potentially return due to internal handshake message
|
||||
processing. This does not really make sense for our QUIC implementation,
|
||||
therefore we always act as though `SSL_MODE_AUTO_RETRY` is on, and this mode is
|
||||
ignored.
|
||||
|
||||
### What should `SSL_MODE_SEND_FALLBACK_SCSV` do?
|
||||
|
||||
This is not relevant to QUIC because this functionality relates to protocol
|
||||
version downgrade attack protection and QUIC only supports TLSv1.3. Thus,
|
||||
it is ignored.
|
||||
|
||||
### What should `SSL_CTX_set_ssl_version` do?
|
||||
|
||||
This is a deprecated function, so it needn't be supported for QUIC. Fail closed.
|
||||
|
||||
### What should `SSL_set_ssl_method` do?
|
||||
|
||||
For now we can avoid supporting this for QUIC. Supporting this would be rather
|
||||
hairy.
|
||||
|
||||
### What should `SSL_set_shutdown` do?
|
||||
|
||||
TBD.
|
||||
|
||||
### What should `SSL_dup` and `SSL_clear` do?
|
||||
|
||||
These may be tricky to support. Currently they are blocked.
|
||||
|
@ -29,7 +29,7 @@ designs and the relevant design decisions.
|
||||
- [`SSL_get_[rw]fd`](#-ssl-get--rw-fd-)
|
||||
- [`SSL_CTRL_MODE`, `SSL_CTRL_CLEAR_MODE`](#-ssl-ctrl-mode----ssl-ctrl-clear-mode-)
|
||||
- [SSL Modes](#ssl-modes)
|
||||
+ [New APIs](#new-apis)
|
||||
+ [New APIs for Single-Stream Operation](#new-apis-for-single-stream-operation)
|
||||
- [`SSL_tick`](#-ssl-tick-)
|
||||
- [`SSL_get_tick_timeout`](#-ssl-get-tick-timeout-)
|
||||
- [`SSL_set_blocking_mode`, `SSL_get_blocking_mode`](#-ssl-set-blocking-mode----ssl-get-blocking-mode-)
|
||||
@ -41,8 +41,23 @@ designs and the relevant design decisions.
|
||||
- [`SSL_stream_conclude`](#-ssl-stream-conclude-)
|
||||
- [`SSL_stream_reset`](#-ssl-stream-reset-)
|
||||
- [`SSL_get_stream_state`](#-ssl-get-stream-state-)
|
||||
- [`SSL_get_stream_error_code`](#-ssl-get-stream-error-code-)
|
||||
- [`SSL_get_stream_read_error_code`, `SSL_get_stream_write_error_code`](#-ssl-get-stream-read-error-code----ssl-get-stream-write-error-code-)
|
||||
- [`SSL_get_conn_close_info`](#-ssl-get-conn-close-info-)
|
||||
+ [New APIs for Multi-Stream Operation](#new-apis-for-multi-stream-operation)
|
||||
- [Notes on Multi-Threaded Operation](#notes-on-multi-threaded-operation)
|
||||
- [Notes on Blocking](#notes-on-blocking)
|
||||
- [Notes on Application-Level Polling](#notes-on-application-level-polling)
|
||||
- [`SSL_get0_connection`](#-ssl-get0-connection-)
|
||||
- [`SSL_is_connection`](#-ssl-is-connection-)
|
||||
- [`SSL_get_stream_type`](#-ssl-get-stream-type-)
|
||||
- [`SSL_get_stream_id`](#-ssl-get-stream-id-)
|
||||
- [`SSL_new_stream`](#-ssl-new-stream-)
|
||||
- [`SSL_accept_stream`](#-ssl-accept-stream-)
|
||||
- [`SSL_get_accept_stream_queue_len`](#-ssl-get-accept-stream-queue-len-)
|
||||
- [`SSL_set_incoming_stream_reject_policy`](#-ssl-set-incoming-stream-reject-policy-)
|
||||
- [`SSL_set_default_stream_mode`](#-ssl-set-default-stream-mode-)
|
||||
- [`SSL_detach_stream`](#-ssl-detach-stream-)
|
||||
- [`SSL_attach_stream`](#-ssl-attach-stream-)
|
||||
+ [Future APIs](#future-apis)
|
||||
* [BIO Objects](#bio-objects)
|
||||
+ [Existing APIs](#existing-apis-1)
|
||||
@ -50,7 +65,7 @@ designs and the relevant design decisions.
|
||||
- [`BIO_new_bio_pair`](#-bio-new-bio-pair-)
|
||||
- [Interactions with `BIO_f_buffer`](#interactions-with--bio-f-buffer-)
|
||||
- [MTU Signalling](#mtu-signalling)
|
||||
+ [New APIs](#new-apis-1)
|
||||
+ [New APIs](#new-apis)
|
||||
- [`BIO_sendmmsg` and `BIO_recvmmsg`](#-bio-sendmmsg--and--bio-recvmmsg-)
|
||||
- [Truncation Mode](#truncation-mode)
|
||||
- [Capability Negotiation](#capability-negotiation)
|
||||
@ -60,7 +75,6 @@ designs and the relevant design decisions.
|
||||
- [`BIO_s_dgram_mem`](#-bio-s-dgram-mem-)
|
||||
- [`BIO_err_is_non_fatal`](#-bio-err-is-non-fatal-)
|
||||
* [Q & A](#q---a)
|
||||
* [Implementation Status](#implementation-status)
|
||||
|
||||
Overview and Implementation Status
|
||||
----------------------------------
|
||||
@ -150,6 +164,9 @@ Each API listed below has an information table with the following fields:
|
||||
|
||||
- **CS:** Not handshake-layer related. Can be used on any QUIC SSL object.
|
||||
|
||||
- **S**: Requires a QUIC stream SSL object or a QUIC connection SSL object
|
||||
with a default stream attached.
|
||||
|
||||
### Existing APIs
|
||||
|
||||
#### `SSL_set_connect_state`
|
||||
@ -411,7 +428,7 @@ Should not require any changes.
|
||||
|
||||
- `SSL_MODE_ASYNC`: TBD.
|
||||
|
||||
### New APIs
|
||||
### New APIs for Single-Stream Operation
|
||||
|
||||
TBD: Should any of these be implemented as ctrls rather than actual functions?
|
||||
|
||||
@ -721,6 +738,22 @@ no-ops. This is considered a success case.
|
||||
* stream.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_NONE 0
|
||||
|
||||
/*
|
||||
* The read or write part of the stream is still available and has not been
|
||||
* terminated in a normal or non-normal manner.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_OK 1
|
||||
|
||||
/*
|
||||
* The stream is a unidirectional stream and this direction cannot be used; for
|
||||
* example, a remotely initiated unidirectional stream where
|
||||
* SSL_get_stream_write_state is called, or a locally initiated unidirectional
|
||||
* stream where SSL_get_stream_read_state is
|
||||
called.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_WRONG_DIR 2
|
||||
|
||||
/*
|
||||
* The read or write part of the stream has been finished in a normal manner.
|
||||
*
|
||||
@ -732,17 +765,32 @@ no-ops. This is considered a success case.
|
||||
* already indicated the end of the stream by calling SSL_stream_conclude,
|
||||
* and that future calls to SSL_write will fail.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_FINISHED 1
|
||||
#define SSL_STREAM_STATE_FINISHED 3
|
||||
|
||||
/*
|
||||
* The stream was reset by the local party.
|
||||
*
|
||||
* For SSL_get_stream_read_state, this means that the stream was aborted using a
|
||||
* locally transmitted STOP_SENDING frame. Attempts to read from the stream via
|
||||
* SSL_read will fail, though SSL_read may allow any residual data waiting to
|
||||
* be read to be read first.
|
||||
*
|
||||
* For SSL_get_stream_write_state, this means that the stream was aborted
|
||||
* using a locally transmitted RESET_STREAM frame. Attempts to write to
|
||||
* the stream will fail.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_RESET_LOCAL 2
|
||||
#define SSL_STREAM_STATE_RESET_LOCAL 4
|
||||
|
||||
/*
|
||||
* The stream was reset by the remote party.
|
||||
*
|
||||
* For SSL_get_stream_read_state, this means the peer sent a STREAM_RESET
|
||||
* frame for the stream.
|
||||
*
|
||||
* For SSL_get_stream_write_state, this means the peer sent a STOP_SENDING
|
||||
* frame for the stream.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_RESET_REMOTE 3
|
||||
#define SSL_STREAM_STATE_RESET_REMOTE 5
|
||||
|
||||
/*
|
||||
* The underlying connection supporting the stream has closed or otherwise
|
||||
@ -755,7 +803,7 @@ no-ops. This is considered a success case.
|
||||
* For SSL_get_stream_write_state, this means that attempts to write to the
|
||||
* stream will fail.
|
||||
*/
|
||||
#define SSL_STREAM_STATE_CONN_CLOSED 4
|
||||
#define SSL_STREAM_STATE_CONN_CLOSED 6
|
||||
|
||||
int SSL_get_stream_read_state(SSL *ssl);
|
||||
int SSL_get_stream_write_state(SSL *ssl);
|
||||
@ -765,22 +813,31 @@ This API allows the current state of a stream to be queried. This allows an
|
||||
application to determine whether a stream is still usable and why a stream has
|
||||
reached an error state.
|
||||
|
||||
#### `SSL_get_stream_error_code`
|
||||
#### `SSL_get_stream_read_error_code`, `SSL_get_stream_write_error_code`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | S |
|
||||
|
||||
```c
|
||||
int SSL_get_stream_error_code(SSL *ssl, uint64_t *app_error_code);
|
||||
int SSL_get_stream_read_error_code(SSL *ssl, uint64_t *app_error_code);
|
||||
int SSL_get_stream_write_error_code(SSL *ssl, uint64_t *app_error_code);
|
||||
```
|
||||
|
||||
`SSL_get_stream_read_error_code` gets the error code for the read part of the
|
||||
stream.
|
||||
|
||||
`SSL_get_stream_write_error_code` gets the error code for the write part of
|
||||
the stream.
|
||||
|
||||
If a stream has been terminated normally, returns 0.
|
||||
|
||||
If a stream has been terminated non-normally, returns 1 and writes the
|
||||
applicable application error code to `*app_error_code`.
|
||||
|
||||
If a stream is still healthy, returns -1.
|
||||
If a stream is still healthy, or was healthy at the time the connection was
|
||||
closed, or the respective part of the stream does not exist (e.g. for a
|
||||
unidirectional stream), returns -1.
|
||||
|
||||
#### `SSL_get_conn_close_info`
|
||||
|
||||
@ -804,7 +861,8 @@ int SSL_get_conn_close_info(SSL *ssl,
|
||||
|
||||
If a connection is still healthy, returns 0. Otherwise, fills `*info` with
|
||||
information about the error causing connection termination and returns 1.
|
||||
`info_len` must be set to `sizeof(*info)`.
|
||||
`info_len` must be set to `sizeof(*info)`. Returns -1 if called on a non-QUIC
|
||||
SSL object or if the connection status cannot be determined.
|
||||
|
||||
`info->reason` is set to point to a buffer containing a reason string. The
|
||||
buffer is valid for the lifetime of the SSL object. The reason string will
|
||||
@ -818,6 +876,340 @@ reason string in bytes.
|
||||
if it was initiated by the application. The namespace of `info->error_code` is
|
||||
determined by this parameter.
|
||||
|
||||
### New APIs for Multi-Stream Operation
|
||||
|
||||
The above new APIs are built on constructively to facilitate multi-stream
|
||||
operation.
|
||||
|
||||
The concept of a QUIC stream SSL object is introduced. A QUIC SSL object is
|
||||
either a QUIC connection SSL object or a QUIC stream SSL object. A QUIC stream
|
||||
SSL object belongs to a QUIC connection SSL object. A QUIC connection SSL object
|
||||
may or may not have an associated default stream. There may only be at most one
|
||||
default stream for a QUIC connection SSL object. Reading or writing application
|
||||
data to a QUIC connection SSL object with a default stream is equivalent to
|
||||
reading or writing to that stream. It is an error to attempt to read or write
|
||||
application data, or perform other stream-specific operations, on a QUIC
|
||||
connection SSL object without a default stream associated.
|
||||
|
||||
#### Notes on Multi-Threaded Operation
|
||||
|
||||
Initially these APIs will not be thread safe over the same connection, but in
|
||||
the longer term we intend to support multiple threads using different QUIC
|
||||
stream SSL objects on different threads over the same connection without the
|
||||
application having to do any locking. This is referred to as multi-stream
|
||||
multi-thread (MSMT) operation. Only APIs explicitly denoted below will
|
||||
eventually be MSMT-safe.
|
||||
|
||||
#### Notes on Blocking
|
||||
|
||||
The blocking mode can be configured on each SSL object individually. When a QUIC
|
||||
stream SSL object is created it inherits its blocking state from the currently
|
||||
configured blocking state of the QUIC connection SSL object at the time the
|
||||
stream is created. This can be changed independently. For example, a QUIC
|
||||
connection SSL object can be in blocking mode to allow for blocking
|
||||
`SSL_accept_stream` calls, yet have some or all QUIC stream SSL objects be in
|
||||
non-blocking mode concurrently.
|
||||
|
||||
#### Notes on Application-Level Polling
|
||||
|
||||
An API may be added in the future to allow applications to poll multiple QUIC
|
||||
connection SSL objects efficiently for new stream and stream readability events.
|
||||
This is not yet urgent but will be more relevant for concurrent server
|
||||
applications.
|
||||
|
||||
#### `SSL_get0_connection`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | CS |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Get the SSL object representing the connection associated with this object.
|
||||
*
|
||||
* If the SSL object represents a non-QUIC method or a QUIC connection, this
|
||||
* returns the same object passed.
|
||||
*
|
||||
* If the SSL object represents a QUIC stream returns the QUIC connection
|
||||
* object.
|
||||
*/
|
||||
SSL *SSL_get0_connection(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_is_connection`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | CS |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Returns 1 if the object represents a connection. This always returns 1 for
|
||||
* non-QUIC methods, but returns 0 for SSL objects for QUIC streams which are
|
||||
* not also the QUIC connection object.
|
||||
*
|
||||
* This is exactly equivalent to (SSL_get0_connection(ssl) == ssl).
|
||||
*/
|
||||
int SSL_is_connection(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_get_stream_type`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | S |
|
||||
|
||||
```c
|
||||
/*
|
||||
* If the object represents a stream, returns a SSL_STREAM_TYPE value
|
||||
* designating whether the stream can be used for transmission, reception,
|
||||
* or both.
|
||||
*
|
||||
* This always returns SSL_STREAM_TYPE_BIDI for non-QUIC methods.
|
||||
*
|
||||
* It returns SSL_STREAM_TYPE_NONE for a QUIC connection object if it
|
||||
* does not have a default stream.
|
||||
*/
|
||||
#define SSL_STREAM_TYPE_NONE 0
|
||||
#define SSL_STREAM_TYPE_READ 1
|
||||
#define SSL_STREAM_TYPE_WRITE 2
|
||||
#define SSL_STREAM_TYPE_BIDI (SSL_STREAM_TYPE_READ | SSL_STREAM_TYPE_WRITE)
|
||||
__owur int SSL_get_stream_type(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_get_stream_id`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | S |
|
||||
|
||||
```c
|
||||
/*
|
||||
* QUIC: Returns the unique stream ID for the stream, an integer in range [0, 2**62-1],
|
||||
* or UINT64_MAX if the stream ID is not available. If called on a QUIC
|
||||
* connection, returns the unique stream ID for the default stream if there is
|
||||
* one, and otherwise returns UINT64_MAX.
|
||||
*
|
||||
* TLS, DTLS: Returns UINT64_MAX.
|
||||
*/
|
||||
__owur uint64_t SSL_get_stream_id(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_new_stream`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Create a new SSL object representing a single additional stream.
|
||||
*
|
||||
* There is no need to call SSL_connect on the resulting object, and
|
||||
* any such call is a no-op.
|
||||
*
|
||||
* For QUIC:
|
||||
* Creates a new stream. Must be called only on a QUIC connection SSL object.
|
||||
* Can be used on client or server. If the SSL_STREAM_FLAG_UNI flag is set,
|
||||
* the created stream is unidirectional, otherwise it is bidirectional.
|
||||
*
|
||||
* To be MSMT-safe.
|
||||
*
|
||||
* For TLS and DTLS SSL objects:
|
||||
* Always fails.
|
||||
*/
|
||||
#define SSL_STREAM_FLAG_UNI 1
|
||||
|
||||
SSL *SSL_new_stream(SSL *ssl, uint64_t flags);
|
||||
```
|
||||
|
||||
#### `SSL_accept_stream`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | Yes | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Create a new SSL object representing an additional stream which was created
|
||||
* by the peer.
|
||||
*
|
||||
* There is no need to call SSL_accept on the resulting object, and
|
||||
* any such call is a no-op.
|
||||
*
|
||||
* For QUIC:
|
||||
* Must be called only on a QUIC connection SSL object. Fails if called on a
|
||||
* stream object. Checks if a new stream has been created by the peer. If it
|
||||
* has, creates a new SSL object to represent it and returns it. Otherwise,
|
||||
* returns NULL. If multiple streams are available to be accepted, the oldest
|
||||
* stream (that is, the stream with the lowest stream ID) is accepted.
|
||||
*
|
||||
* For all other methods:
|
||||
* Returns NULL.
|
||||
*
|
||||
* The flags argument is unused and should be set to zero.
|
||||
*
|
||||
* To be MSMT-safe (i.e., can be called from multiple threads).
|
||||
*
|
||||
* If the QUIC connection SSL object is configured in blocking mode, this
|
||||
* function will block unless the SSL_ACCEPT_STREAM_NO_BLOCK flag is passed.
|
||||
*
|
||||
* This function returns NULL if the effective incoming stream reject policy is
|
||||
* `REJECT`.
|
||||
*/
|
||||
#define SSL_ACCEPT_STREAM_NO_BLOCK 1
|
||||
|
||||
SSL *SSL_accept_stream(SSL *ssl, uint64_t flags);
|
||||
```
|
||||
|
||||
#### `SSL_get_accept_stream_queue_len`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Determine the number of streams waiting to be returned on a subsequent call
|
||||
* to SSL_accept_stream. If this returns a non-zero value, the next call to
|
||||
* SSL_accept_stream (on any thread) is guaranteed to work. Returns 0 for
|
||||
* non-QUIC objects, or for QUIC stream objects.
|
||||
*
|
||||
* To be MSMT-safe.
|
||||
*/
|
||||
size_t SSL_get_accept_stream_queue_len(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_set_incoming_stream_reject_policy`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Sets the policy for incoming streams. If `policy` is `AUTO` (the default):
|
||||
*
|
||||
* - if `SSL_detach_stream` has been used, this is equivalent to `ACCEPT`;
|
||||
*
|
||||
* - otherwise, if the default stream mode is
|
||||
* `SSL_DEFAULT_STREAM_MODE_AUTO_BIDI` or
|
||||
* `SSL_DEFAULT_STREAM_MODE_AUTO_UNI`, this is equivalent to `REJECT`;
|
||||
*
|
||||
* - otherwise, this is equivalent to `ACCEPT`.
|
||||
*
|
||||
* If configured to `ACCEPT`, incoming streams are placed on the accept queue
|
||||
* for application consumption. `aec` is ignored in this case.
|
||||
*
|
||||
* If configured to `REJECT`, incoming streams automatically have both their
|
||||
* receiving and sending parts handled via non-normal termination. `aec` is an
|
||||
* application error code used for the `STOP_SENDING` and `RESET_STREAM` frames
|
||||
* used for the purposes of this termination. The default AEC value used if this
|
||||
* function is never called is 0.
|
||||
*/
|
||||
#define SSL_INCOMING_STREAM_REJECT_POLICY_AUTO 0
|
||||
#define SSL_INCOMING_STREAM_REJECT_POLICY_ACCEPT 1
|
||||
#define SSL_INCOMING_STREAM_REJECT_POLICY_REJECT 2
|
||||
|
||||
int SSL_set_incoming_stream_reject_policy(SSL *ssl, int policy, uint64_t aec);
|
||||
```
|
||||
|
||||
#### `SSL_set_default_stream_mode`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Used to control single stream operation. Calling this function determines the
|
||||
* nature of the default stream which will automatically be created on the QUIC
|
||||
* connection SSL object.
|
||||
*
|
||||
* The default mode is `SSL_DEFAULT_STREAM_MODE_AUTO_BIDI`.
|
||||
*
|
||||
* The modes are as follows:
|
||||
*
|
||||
* - `SSL_DEFAULT_STREAM_MODE_NONE`: No default stream will ever be created.
|
||||
* The application is assumed to understand multi-stream operation.
|
||||
* Remotely-initiated streams are placed in the accept queue for application
|
||||
* consumption. `SSL_read` and `SSL_write` calls must be made on a QUIC
|
||||
* stream SSL object, not the QUIC connection SSL object, as no default
|
||||
* stream will be associated with it.
|
||||
*
|
||||
* - `SSL_DEFAULT_STREAM_MODE_AUTO_BIDI`: "First stream wins" mode of
|
||||
* operation for single-stream usage. If `SSL_write` is called before the
|
||||
* peer opens a remotely-initiated stream, a locally-initiated bidirectional
|
||||
* stream is created and bound as the default stream. If the peer opens a
|
||||
* remotely-initiated stream before the local application calls `SSL_write`
|
||||
* (with `len > 0`) for the first time, that stream is bound as the default
|
||||
* stream, which may be bidirectional or unidirectional; if it is
|
||||
* unidirectional, calls to `SSL_write` will fail. Attempts to create
|
||||
* additional streams by the peer are automatically rejected unless
|
||||
* the application opts in (API TBD).
|
||||
*
|
||||
* - `SSL_DEFAULT_STREAM_MODE_AUTO_UNI`: "First stream wins" mode of
|
||||
* operation for single-stream usage, with a unidirectional stream. This
|
||||
* functions identically to `SSL_DEFAULT_STREAM_MODE_AUTO_BIDI`, but if the
|
||||
* local application calls `SSL_write` prior to the peer creating a
|
||||
* remotely-initiated stream, a unidirectional TX-only stream is created and
|
||||
* bound as the default stream. Thereafter, calls to `SSL_read` will fail.
|
||||
* If the peer creates a remotely-initiated stream prior to the first call
|
||||
* to `SSL_write` (with `len > 0`), that stream will be bound as the default
|
||||
* stream; note that a bidirectional stream may be bound in this case.
|
||||
* Attempts to create additional streams by the peer are automatically
|
||||
* rejected unless the application opts in (API TBD).
|
||||
*
|
||||
* This function must be called before a default stream object is created, for
|
||||
* example before initiating a connection. If the function is too late to have
|
||||
* an effect, this function fails and returns 0. To switch to multi-stream
|
||||
* operation after a default stream has been created, use `SSL_detach_stream`.
|
||||
*/
|
||||
#define SSL_DEFAULT_STREAM_MODE_NONE 0
|
||||
#define SSL_DEFAULT_STREAM_MODE_AUTO_BIDI 1
|
||||
#define SSL_DEFAULT_STREAM_MODE_AUTO_UNI 2
|
||||
|
||||
__owur int SSL_set_default_stream_mode(SSL *ssl, uint32_t mode);
|
||||
```
|
||||
|
||||
#### `SSL_detach_stream`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Detaches a default stream from a QUIC connection object. If the
|
||||
* QUIC connection object does not contain a default stream, returns NULL.
|
||||
* After calling this, calling SSL_get_stream_type on the connection object
|
||||
* returns SSL_STREAM_TYPE_NONE. Always returns NULL for non-QUIC connections.
|
||||
*
|
||||
* Calling this function automatically inhibits default stream creation;
|
||||
* though, after calling this function, a QUIC connection SSL object will no
|
||||
* longer have a stream attached to it, calling SSL_read or SSL_write on
|
||||
* that QUIC connection SSL object will not automatically create a new
|
||||
* default stream. Default stream creation only occurs at most a single time per
|
||||
* connection.
|
||||
*/
|
||||
SSL *SSL_detach_stream(SSL *ssl);
|
||||
```
|
||||
|
||||
#### `SSL_attach_stream`
|
||||
|
||||
| Semantics | `SSL_get_error` | Can Tick? | CSHL |
|
||||
| --------- | ------------- | --------- | ------------- |
|
||||
| New | Never | No | C |
|
||||
|
||||
```c
|
||||
/*
|
||||
* Attaches a default stream to a QUIC connection object. If the conn object is
|
||||
* not a QUIC connection object, or already has a default stream, this function
|
||||
* fails. The stream must belong to the same connection, or this function fails.
|
||||
*/
|
||||
__owur int SSL_attach_stream(SSL *conn, SSL *stream);
|
||||
```
|
||||
|
||||
### Future APIs
|
||||
|
||||
A custom poller interface may be provided in the future. For more information,
|
||||
@ -1192,3 +1584,119 @@ calls.
|
||||
**Q. How should `STOP_SENDING` be supported?**
|
||||
|
||||
TODO: Determine how `STOP_SENDING` should be supported.
|
||||
|
||||
**Q. Can data be received on a locally initiated bidirectional stream before any
|
||||
data is sent on that stream?**
|
||||
|
||||
This is an interesting question without a clear answer to be found in the QUIC
|
||||
RFCs. A close reading of RFC 9000 suggests that the answer is, in principle,
|
||||
yes; however the RFC also grants explicit permission to make design choices in
|
||||
implementations which would preclude this:
|
||||
|
||||
>An implementation might choose to defer allocating a stream ID to a stream until
|
||||
>it sends the first STREAM frame and enters this state, which can allow for
|
||||
>better stream prioritization.
|
||||
|
||||
If an ID has not been allocated to a stream, obviously incoming data cannot be
|
||||
addressed to it. However, supposing that an implementation does not do this,
|
||||
RFC 9000 seems basically clear that it is valid for an application to create a
|
||||
stream locally, then receive data on it before sending anything:
|
||||
|
||||
>The sending part of a stream that the endpoint initiates (types 0 and 2 for
|
||||
>clients, 1 and 3 for servers) is opened by the application. The "Ready"
|
||||
>state represents a newly created stream that is able to accept data from the
|
||||
>application.
|
||||
>
|
||||
>[...]
|
||||
>
|
||||
>For a bidirectional stream, the receiving part enters the "Recv" state when
|
||||
>the sending part initiated by the endpoint (type 0 for a client, type 1 for
|
||||
>a server) enters the "Ready" state.
|
||||
|
||||
A peer is not generally notified of the creation of a stream which has not sent
|
||||
any data yet, since the creation of a stream is signalled only implicitly via
|
||||
the transmission of data in `STREAM` frames. However, a zero-length STREAM frame
|
||||
could presumably be used to effect such a notification. RFC 9000 contains no
|
||||
specific discussion of this possibility but does not preclude it. As such, in
|
||||
order to receive data on a locally-initiated bidirectional stream before sending
|
||||
any data on that stream, it would be necessary to either
|
||||
|
||||
- Use a QUIC implementation which signals a bidirectional stream which has
|
||||
not yet sent any data via a zero-length stream frame, or
|
||||
|
||||
- Use an application protocol which can inform the peer of the stream ID
|
||||
of the created stream in some application protocol-specific way.
|
||||
This is somewhat less plausible because it would require an API between
|
||||
the application and its QUIC library to inform the QUIC library
|
||||
that the peer has in fact created a stream with a given ID and to
|
||||
take its word for it. This is unlikely to be commonly available, especially as
|
||||
application errors in usage of such an API would lead to internal
|
||||
inconsistencies in QUIC connection state.
|
||||
|
||||
Of course this discussion is somewhat esoteric as it is unclear why an
|
||||
application would want to create a locally-initiated stream and then have the
|
||||
peer transmit on it first, rather than simply use a remotely-initiated stream.
|
||||
Thus this discussion of this edge case is more of a curiosity, however for
|
||||
completeness it needs to be thought about in the API design.
|
||||
|
||||
**Q. How should single-stream operation support locally and remotely-initiated
|
||||
streams?**
|
||||
|
||||
Note that the ID of a stream depends on whether it is bidirectional and whether
|
||||
it is initiated by the client or server. Therefore, in single stream operation,
|
||||
it is necessary to know whether single-stream QUIC is being used with
|
||||
client-initiated or server-initiated stream initiation, and whether a
|
||||
bidirectional or unidirectional stream is being used; otherwise, we do not know
|
||||
which stream ID to bind to.
|
||||
|
||||
The object of single stream operation is to support simple uses cases for simple
|
||||
applications. There seems no need to support esoteric usage of streams such as
|
||||
receiving first on a locally initiated stream here, thus we avoid supporting
|
||||
this to simplify the API.
|
||||
|
||||
As such, an application which calls `SSL_write` on a QUIC connection SSL object
|
||||
before it calls `SSL_read` by definition is using a locally-initiated stream,
|
||||
and an application which does the opposite is using a remotely-initiated stream.
|
||||
We can use the ordering of initial calls to `SSL_read` and `SSL_write` to infer
|
||||
the desired stream type.
|
||||
|
||||
Supporting locally-initiated streams (`SSL_write` called first) is simple;
|
||||
we automatically create the stream and queue data for transmission.
|
||||
|
||||
Supporting remotely-initiated streams (`SSL_read` called first) is a little
|
||||
stranger. We could create the stream with the correct ID when cued to by the
|
||||
initial call to `SSL_read` implying use of a remotely-initiated stream. However,
|
||||
this would mean we are creating state tracking a remotely-initiated stream
|
||||
before the peer has signalled it. This would work in the happy case where the
|
||||
client is connected to a compatible server but may result in strange
|
||||
inconsistencies of QUIC internal state if a client is accidentially connected to
|
||||
an incompatible peer. Since the peer ought to be the authority on the streams it
|
||||
creates, this seems like an undesirable approach.
|
||||
|
||||
Ergo, creation of a default remotely-initiated stream needs to be deferred
|
||||
until the *peer* signals such a stream.
|
||||
|
||||
This leads naturally to a "first stream wins" model of implementation:
|
||||
|
||||
- When a QUIC connection SSL object is created, default stream mode is
|
||||
enabled, meaning that a default stream will be bound to the QUIC connection
|
||||
SSL object at the earliest available opportunity. However, no default
|
||||
stream is bound yet.
|
||||
|
||||
- One of the following events happened — whichever happens first wins:
|
||||
|
||||
- The local application calls `SSL_write()` (`len > 0`). A locally-initiated
|
||||
stream with ordinal 0 is created. The stream is bidirectional by default but
|
||||
this can be changed. This stream is bound as the default stream.
|
||||
|
||||
- The peer creates a stream. This stream is bound as the default stream.
|
||||
|
||||
If the local application calls `SSL_read()` before either of the above
|
||||
occur, `SSL_read()` fails as though no data is available until one
|
||||
of the above events occurs.
|
||||
|
||||
Once one of the above events occurs, any additional stream created by the peer
|
||||
is automatically terminated using both `STOP_SENDING` and `STREAM_RESET` frames
|
||||
(to terminate both the receiving and sending parts respectively) and there is no
|
||||
API-visible effect to the local application (unless the application explicitly
|
||||
opts into supporting additional streams).
|
||||
|
Loading…
x
Reference in New Issue
Block a user