From af994640675381673cd3f4653cf6b53022b491c8 Mon Sep 17 00:00:00 2001 From: jsing Date: Sun, 21 Aug 2022 19:42:15 +0000 Subject: [PATCH] Provide the remaining QUIC API. While more work is still required, this is sufficient to get ngtcp2 to compile with QUIC and for curl to be able to make HTTP/3 requests. ok tb@ --- lib/libssl/ssl.h | 44 +++++++++++++++++- lib/libssl/ssl_lib.c | 107 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/lib/libssl/ssl.h b/lib/libssl/ssl.h index be116de7757..caee3d60d9c 100644 --- a/lib/libssl/ssl.h +++ b/lib/libssl/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.226 2022/08/21 19:32:38 jsing Exp $ */ +/* $OpenBSD: ssl.h,v 1.227 2022/08/21 19:42:15 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1742,6 +1742,41 @@ int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method); /* SSL_is_quic returns true if an SSL has been configured for use with QUIC. */ int SSL_is_quic(const SSL *ssl); +/* + * SSL_quic_max_handshake_flight_len returns returns the maximum number of bytes + * that may be received at the given encryption level. This function should be + * used to limit buffering in the QUIC implementation. See RFC 9000 section 7.5. + */ +size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, + enum ssl_encryption_level_t level); + +/* + * SSL_quic_read_level returns the current read encryption level. + */ +enum ssl_encryption_level_t SSL_quic_read_level(const SSL *ssl); + +/* + * SSL_quic_write_level returns the current write encryption level. + */ +enum ssl_encryption_level_t SSL_quic_write_level(const SSL *ssl); + +/* + * SSL_provide_quic_data provides data from QUIC at a particular encryption + * level |level|. It returns one on success and zero on error. Note this + * function will return zero if the handshake is not expecting data from |level| + * at this time. The QUIC implementation should then close the connection with + * an error. + */ +int SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len); + +/* + * SSL_process_quic_post_handshake processes any data that QUIC has provided + * after the handshake has completed. This includes NewSessionTicket messages + * sent by the server. It returns one on success and zero on error. + */ +int SSL_process_quic_post_handshake(SSL *ssl); + /* * SSL_set_quic_transport_params configures |ssl| to send |params| (of length * |params_len|) in the quic_transport_parameters extension in either the @@ -1763,6 +1798,13 @@ int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params, void SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params, size_t *out_params_len); +/* + * SSL_set_quic_use_legacy_codepoint configures whether to use the legacy QUIC + * extension codepoint 0xffa5 as opposed to the official value 57. This is + * unsupported in LibreSSL. + */ +void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy); + #endif void ERR_load_SSL_strings(void); diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c index f0f0150d19c..c0ca19c7c18 100644 --- a/lib/libssl/ssl_lib.c +++ b/lib/libssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.303 2022/08/21 19:32:38 jsing Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.304 2022/08/21 19:42:15 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -2607,6 +2607,105 @@ SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method) return 1; } +size_t +SSL_quic_max_handshake_flight_len(const SSL *ssl, + enum ssl_encryption_level_t level) +{ + size_t flight_len; + + /* Limit flights to 16K when there are no large certificate messages. */ + flight_len = 16384; + + switch (level) { + case ssl_encryption_initial: + return flight_len; + + case ssl_encryption_early_data: + /* QUIC does not send EndOfEarlyData. */ + return 0; + + case ssl_encryption_handshake: + if (ssl->server) { + /* + * Servers may receive Certificate message if configured + * to request client certificates. + */ + if ((SSL_get_verify_mode(ssl) & SSL_VERIFY_PEER) != 0 && + ssl->internal->max_cert_list > flight_len) + flight_len = ssl->internal->max_cert_list; + } else { + /* + * Clients may receive both Certificate message and a + * CertificateRequest message. + */ + if (ssl->internal->max_cert_list * 2 > flight_len) + flight_len = ssl->internal->max_cert_list * 2; + } + return flight_len; + case ssl_encryption_application: + /* + * Note there is not actually a bound on the number of + * NewSessionTickets one may send in a row. This level may need + * more involved flow control. + */ + return flight_len; + } + + return 0; +} + +enum ssl_encryption_level_t +SSL_quic_read_level(const SSL *ssl) +{ + return ssl->s3->hs.tls13.quic_read_level; +} + +enum ssl_encryption_level_t +SSL_quic_write_level(const SSL *ssl) +{ + return ssl->s3->hs.tls13.quic_write_level; +} + +int +SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len) +{ + if (!SSL_is_quic(ssl)) { + SSLerror(ssl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (level != SSL_quic_read_level(ssl)) { + SSLerror(ssl, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); + return 0; + } + + if (ssl->s3->hs.tls13.quic_read_buffer == NULL) { + ssl->s3->hs.tls13.quic_read_buffer = tls_buffer_new(0); + if (ssl->s3->hs.tls13.quic_read_buffer == NULL) { + SSLerror(ssl, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + /* XXX - note that this does not currently downsize. */ + tls_buffer_set_capacity_limit(ssl->s3->hs.tls13.quic_read_buffer, + SSL_quic_max_handshake_flight_len(ssl, level)); + + /* + * XXX - an append that fails due to exceeding capacity should set + * SSL_R_EXCESSIVE_MESSAGE_SIZE. + */ + return tls_buffer_append(ssl->s3->hs.tls13.quic_read_buffer, data, len); +} + +int +SSL_process_quic_post_handshake(SSL *ssl) +{ + /* XXX - this needs to run PHH received. */ + return 1; +} + int SSL_do_handshake(SSL *s) { @@ -3371,6 +3470,12 @@ SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params, *out_params_len = ssl->s3->peer_quic_transport_params_len; } +void +SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy) +{ + /* Not supported. */ +} + static int ssl_cipher_id_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) { -- 2.20.1