-/* $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.
*
/* 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
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);
-/* $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.
*
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)
{
*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_)
{