-/* $OpenBSD: s3_lib.c,v 1.230 2022/06/29 08:37:18 tb Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.231 2022/06/29 17:39:20 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
free(s->s3->alpn_selected);
+ freezero(s->s3->peer_quic_transport_params,
+ s->s3->peer_quic_transport_params_len);
+
freezero(s->s3, sizeof(*s->s3));
s->s3 = NULL;
s->s3->alpn_selected = NULL;
s->s3->alpn_selected_len = 0;
+ freezero(s->s3->peer_quic_transport_params,
+ s->s3->peer_quic_transport_params_len);
+ s->s3->peer_quic_transport_params = NULL;
+ s->s3->peer_quic_transport_params_len = 0;
+
memset(s->s3, 0, sizeof(*s->s3));
s->s3->rbuf.buf = rp;
-/* $OpenBSD: ssl.h,v 1.217 2022/06/28 20:57:33 tb Exp $ */
+/* $OpenBSD: ssl.h,v 1.218 2022/06/29 17:39:20 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int SSL_CTX_get_security_level(const SSL_CTX *ctx);
#endif /* LIBRESSL_INTERNAL */
+#ifdef LIBRESSL_INTERNAL
+/*
+ * SSL_set_quic_transport_params configures |ssl| to send |params| (of length
+ * |params_len|) in the quic_transport_parameters extension in either the
+ * ClientHello or EncryptedExtensions handshake message. This extension will
+ * only be sent if the TLS version is at least 1.3, and for a server, only if
+ * the client sent the extension. The buffer pointed to by |params| only need be
+ * valid for the duration of the call to this function. This function returns 1
+ *on success and 0 on failure.
+ */
+int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
+ size_t params_len);
+
+/*
+ * SSL_get_peer_quic_transport_params provides the caller with the value of the
+ * quic_transport_parameters extension sent by the peer. A pointer to the buffer
+ * containing the TransportParameters will be put in |*out_params|, and its
+ * length in |*params_len|. This buffer will be valid for the lifetime of the
+ * |SSL|. If no params were received from the peer, |*out_params_len| will be 0.
+ */
+void SSL_get_peer_quic_transport_params(const SSL *ssl,
+ const uint8_t **out_params, size_t *out_params_len);
+#endif
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
-/* $OpenBSD: ssl_lib.c,v 1.292 2022/06/29 08:39:08 tb Exp $ */
+/* $OpenBSD: ssl_lib.c,v 1.293 2022/06/29 17:39:20 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
free(s->internal->alpn_client_proto_list);
+ free(s->internal->quic_transport_params);
+
#ifndef OPENSSL_NO_SRTP
sk_SRTP_PROTECTION_PROFILE_free(s->internal->srtp_profiles);
#endif
return (SSL_CIPHER *)OBJ_bsearch_(key, base, num, sizeof(SSL_CIPHER),
ssl_cipher_id_cmp_BSEARCH_CMP_FN);
}
+
+int
+SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
+ size_t params_len)
+{
+ freezero(ssl->internal->quic_transport_params,
+ ssl->internal->quic_transport_params_len);
+ ssl->internal->quic_transport_params = NULL;
+ ssl->internal->quic_transport_params_len = 0;
+
+ if ((ssl->internal->quic_transport_params = malloc(params_len)) == NULL)
+ return 0;
+
+ memcpy(ssl->internal->quic_transport_params, params, params_len);
+ ssl->internal->quic_transport_params_len = params_len;
+
+ return 1;
+}
+
+void
+SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params,
+ size_t *out_params_len)
+{
+ *out_params = ssl->s3->peer_quic_transport_params;
+ *out_params_len = ssl->s3->peer_quic_transport_params_len;
+}
-/* $OpenBSD: ssl_locl.h,v 1.401 2022/06/29 12:03:38 tb Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.402 2022/06/29 17:39:20 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
unsigned char *alpn_client_proto_list;
unsigned int alpn_client_proto_list_len;
+ /* QUIC transport params we will send */
+ uint8_t *quic_transport_params;
+ size_t quic_transport_params_len;
+
/* XXX Callbacks */
/* true when we are actually in SSL_accept() or SSL_connect() */
*/
unsigned char *alpn_selected;
size_t alpn_selected_len;
+
+ /* Contains the QUIC transport params received from our peer. */
+ uint8_t *peer_quic_transport_params;
+ size_t peer_quic_transport_params_len;
} SSL3_STATE;
/*
-/* $OpenBSD: ssl_tlsext.c,v 1.114 2022/06/29 07:53:58 tb Exp $ */
+/* $OpenBSD: ssl_tlsext.c,v 1.115 2022/06/29 17:39:20 beck Exp $ */
/*
* Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
return CBS_skip(cbs, CBS_len(cbs));
}
+/*
+ * QUIC transport parameters extension.
+ */
+
+int
+tlsext_quic_transport_parameters_client_needs(SSL *s, uint16_t msg_type)
+{
+ return (s->internal->quic_transport_params_len > 0 &&
+ s->s3->hs.our_max_tls_version >= TLS1_3_VERSION);
+}
+
+int
+tlsext_quic_transport_parameters_client_build(SSL *s, uint16_t msg_type,
+ CBB *cbb)
+{
+ CBB contents;
+
+ if (!CBB_add_u16_length_prefixed(cbb, &contents))
+ return 0;
+
+ if (!CBB_add_bytes(&contents, s->internal->quic_transport_params,
+ s->internal->quic_transport_params_len))
+ return 0;
+
+ if (!CBB_flush(cbb))
+ return 0;
+
+ return 1;
+}
+
+int
+tlsext_quic_transport_parameters_client_parse(SSL *s, uint16_t msg_type,
+ CBS *cbs, int *alert)
+{
+ CBS transport_data;
+
+ /* QUIC requires TLS 1.3. */
+ if (ssl_effective_tls_version(s) < TLS1_3_VERSION) {
+ *alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ if (!CBS_get_u16_length_prefixed(cbs, &transport_data))
+ return 0;
+
+ if (!CBS_stow(&transport_data, &s->s3->peer_quic_transport_params,
+ &s->s3->peer_quic_transport_params_len))
+ return 0;
+
+ return 1;
+}
+
+int
+tlsext_quic_transport_parameters_server_needs(SSL *s, uint16_t msg_type)
+{
+ return s->internal->quic_transport_params_len > 0;
+}
+
+int
+tlsext_quic_transport_parameters_server_build(SSL *s, uint16_t msg_type,
+ CBB *cbb)
+{
+ CBB contents;
+
+ if (!CBB_add_u16_length_prefixed(cbb, &contents))
+ return 0;
+
+ if (!CBB_add_bytes(&contents, s->internal->quic_transport_params,
+ s->internal->quic_transport_params_len))
+ return 0;
+
+ if (!CBB_flush(cbb))
+ return 0;
+
+ return 1;
+}
+
+int
+tlsext_quic_transport_parameters_server_parse(SSL *s, uint16_t msg_type,
+ CBS *cbs, int *alert)
+{
+ CBS transport_data;
+
+ /*
+ * Ignore this extension if we don't have configured quic transport data
+ * or if we are not TLS 1.3.
+ */
+ if (s->internal->quic_transport_params_len == 0 ||
+ ssl_effective_tls_version(s) < TLS1_3_VERSION) {
+ if (!CBS_skip(cbs, CBS_len(cbs))) {
+ *alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ return 1;
+ }
+
+ if (!CBS_get_u16_length_prefixed(cbs, &transport_data))
+ return 0;
+
+ if (!CBS_stow(&transport_data, &s->s3->peer_quic_transport_params,
+ &s->s3->peer_quic_transport_params_len))
+ return 0;
+
+ return 1;
+}
+
struct tls_extension_funcs {
int (*needs)(SSL *s, uint16_t msg_type);
int (*build)(SSL *s, uint16_t msg_type, CBB *cbb);
},
},
#endif /* OPENSSL_NO_SRTP */
+ {
+ .type = TLSEXT_TYPE_quic_transport_parameters,
+ .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH,
+ .client = {
+ .needs = tlsext_quic_transport_parameters_client_needs,
+ .build = tlsext_quic_transport_parameters_client_build,
+ .parse = tlsext_quic_transport_parameters_client_parse,
+ },
+ .server = {
+ .needs = tlsext_quic_transport_parameters_server_needs,
+ .build = tlsext_quic_transport_parameters_server_build,
+ .parse = tlsext_quic_transport_parameters_server_parse,
+ },
+ },
{
.type = TLSEXT_TYPE_psk_key_exchange_modes,
.messages = SSL_TLSEXT_MSG_CH,
-/* $OpenBSD: ssl_tlsext.h,v 1.29 2022/06/03 13:31:49 tb Exp $ */
+/* $OpenBSD: ssl_tlsext.h,v 1.30 2022/06/29 17:39:20 beck Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
int tlsext_srtp_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
#endif
+int tlsext_quic_transport_parameters_client_needs(SSL *s, uint16_t msg_type);
+int tlsext_quic_transport_parameters_client_build(SSL *s, uint16_t msg_type,
+ CBB *cbb);
+int tlsext_quic_transport_parameters_client_parse(SSL *s, uint16_t msg_type,
+ CBS *cbs, int *alert);
+int tlsext_quic_transport_parameters_server_needs(SSL *s, uint16_t msg_type);
+int tlsext_quic_transport_parameters_server_build(SSL *s, uint16_t msg_type,
+ CBB *cbb);
+int tlsext_quic_transport_parameters_server_parse(SSL *s, uint16_t msg_type,
+ CBS *cbs, int *alert);
+
int tlsext_client_build(SSL *s, uint16_t msg_type, CBB *cbb);
int tlsext_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
-/* $OpenBSD: tls1.h,v 1.52 2022/06/28 20:36:55 tb Exp $ */
+/* $OpenBSD: tls1.h,v 1.53 2022/06/29 17:39:20 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
/* ExtensionType value from RFC 7685. */
#define TLSEXT_TYPE_padding 21
+/* ExtensionType value from draft-ietf-quic-tls */
+#define TLSEXT_TYPE_quic_transport_parameters 26
+
/* ExtensionType value from RFC 4507. */
#define TLSEXT_TYPE_session_ticket 35
-/* $OpenBSD: tlsexttest.c,v 1.63 2022/06/06 06:11:04 tb Exp $ */
+/* $OpenBSD: tlsexttest.c,v 1.64 2022/06/29 17:39:21 beck Exp $ */
/*
* Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
return (failure);
}
+
+/*
+ * QUIC transport parameters extenstion - RFC 90210 :)
+ */
+
+#define TEST_QUIC_TRANSPORT_DATA "0123456789abcdef"
+
+static unsigned char tlsext_quic_transport_data[] = {
+ 0x00, 0x10, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64,
+ 0x65, 0x66,
+};
+
+static int
+test_tlsext_quic_transport_parameters_client(void)
+{
+ unsigned char *data = NULL;
+ SSL_CTX *ssl_ctx = NULL;
+ SSL *ssl = NULL;
+ int failure;
+ size_t dlen;
+ CBB cbb;
+ CBS cbs;
+ int alert;
+ const uint8_t *out_bytes;
+ size_t out_bytes_len;
+
+ failure = 1;
+
+ if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL)
+ errx(1, "failed to create SSL_CTX");
+ if ((ssl = SSL_new(ssl_ctx)) == NULL)
+ errx(1, "failed to create SSL");
+
+ CBB_init(&cbb, 0);
+
+ if (tlsext_quic_transport_parameters_client_needs(ssl,
+ SSL_TLSEXT_MSG_CH)) {
+ FAIL("client should not need QUIC\n");
+ goto err;
+ }
+
+ if (!SSL_set_quic_transport_params(ssl,
+ TEST_QUIC_TRANSPORT_DATA, strlen(TEST_QUIC_TRANSPORT_DATA))) {
+ FAIL("client failed to set QUIC parametes\n");
+ goto err;
+ }
+
+ if (tlsext_quic_transport_parameters_client_needs(ssl,
+ SSL_TLSEXT_MSG_CH)) {
+ FAIL("client should not need QUIC\n");
+ goto err;
+ }
+
+ ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION;
+ ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION;
+
+ if (!tlsext_quic_transport_parameters_client_needs(ssl,
+ SSL_TLSEXT_MSG_CH)) {
+ FAIL("client should not need QUIC\n");
+ goto err;
+ }
+
+ if (!tlsext_quic_transport_parameters_client_build(ssl,
+ SSL_TLSEXT_MSG_CH, &cbb)) {
+ FAIL("client failed to build QUIC\n");
+ goto err;
+ }
+
+ if (!CBB_finish(&cbb, &data, &dlen)) {
+ FAIL("failed to finish CBB");
+ goto err;
+ }
+
+ if (dlen != sizeof(tlsext_quic_transport_data)) {
+ FAIL("got client QUIC with length %zu, "
+ "want length %zu\n", dlen,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ if (memcmp(data, tlsext_quic_transport_data, dlen) != 0) {
+ FAIL("client QUIC differs:\n");
+ fprintf(stderr, "received:\n");
+ hexdump(data, dlen);
+ fprintf(stderr, "test data:\n");
+ hexdump(tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ CBS_init(&cbs, tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+
+ if (!tlsext_quic_transport_parameters_server_parse(ssl,
+ SSL_TLSEXT_MSG_SH, &cbs, &alert)) {
+ FAIL("server_parse of QUIC from server failed\n");
+ goto err;
+ }
+ if (CBS_len(&cbs) != 0) {
+ FAIL("extension data remaining\n");
+ goto err;
+ }
+
+ SSL_get_peer_quic_transport_params(ssl, &out_bytes, &out_bytes_len);
+
+ if (out_bytes_len != strlen(TEST_QUIC_TRANSPORT_DATA)) {
+ FAIL("server_parse QUIC length differs, got %zu want %zu\n",
+ out_bytes_len,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ if (memcmp(out_bytes, TEST_QUIC_TRANSPORT_DATA,
+ out_bytes_len) != 0) {
+ FAIL("server_parse QUIC differs from sent:\n");
+ fprintf(stderr, "received:\n");
+ hexdump(data, dlen);
+ fprintf(stderr, "test data:\n");
+ hexdump(tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ failure = 0;
+
+ err:
+ CBB_cleanup(&cbb);
+ SSL_CTX_free(ssl_ctx);
+ SSL_free(ssl);
+ free(data);
+
+ return (failure);
+}
+
+static int
+test_tlsext_quic_transport_parameters_server(void)
+{
+ unsigned char *data = NULL;
+ SSL_CTX *ssl_ctx = NULL;
+ SSL *ssl = NULL;
+ int failure;
+ size_t dlen;
+ int alert;
+ CBB cbb;
+ CBS cbs;
+ const uint8_t *out_bytes;
+ size_t out_bytes_len;
+
+ failure = 1;
+
+ CBB_init(&cbb, 0);
+
+ if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL)
+ errx(1, "failed to create SSL_CTX");
+ if ((ssl = SSL_new(ssl_ctx)) == NULL)
+ errx(1, "failed to create SSL");
+
+ if (tlsext_quic_transport_parameters_server_needs(ssl, SSL_TLSEXT_MSG_SH)) {
+ FAIL("server should not need QUIC\n");
+ goto err;
+ }
+
+ if (!SSL_set_quic_transport_params(ssl,
+ TEST_QUIC_TRANSPORT_DATA, strlen(TEST_QUIC_TRANSPORT_DATA))) {
+ FAIL("server failed to set QUIC parametes\n");
+ goto err;
+ }
+
+ if (!tlsext_quic_transport_parameters_server_needs(ssl, SSL_TLSEXT_MSG_SH)) {
+ FAIL("server should need QUIC\n");
+ goto err;
+ }
+
+ if (!tlsext_quic_transport_parameters_server_build(ssl,
+ SSL_TLSEXT_MSG_SH, &cbb)) {
+ FAIL("server failed to build QUIC\n");
+ goto err;
+ }
+
+ if (!CBB_finish(&cbb, &data, &dlen))
+ errx(1, "failed to finish CBB");
+
+ if (dlen != sizeof(tlsext_quic_transport_data)) {
+ FAIL("got server QUIC with length %zu, "
+ "want length %zu\n", dlen,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ if (memcmp(data, tlsext_quic_transport_data, dlen) != 0) {
+ FAIL("saved server QUIC differs:\n");
+ fprintf(stderr, "received:\n");
+ hexdump(data, dlen);
+ fprintf(stderr, "test data:\n");
+ hexdump(tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ CBS_init(&cbs, tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+
+ if (tlsext_quic_transport_parameters_client_parse(ssl,
+ SSL_TLSEXT_MSG_SH, &cbs, &alert)) {
+ FAIL("QUIC parse should have failed!\n");
+ goto err;
+ }
+
+ ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION;
+ ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION;
+
+ if (!tlsext_quic_transport_parameters_client_parse(ssl,
+ SSL_TLSEXT_MSG_SH, &cbs, &alert)) {
+ FAIL("client_parse of QUIC from server failed\n");
+ goto err;
+ }
+ if (CBS_len(&cbs) != 0) {
+ FAIL("extension data remaining\n");
+ goto err;
+ }
+
+ SSL_get_peer_quic_transport_params(ssl, &out_bytes, &out_bytes_len);
+
+ if (out_bytes_len != strlen(TEST_QUIC_TRANSPORT_DATA)) {
+ FAIL("client QUIC length differs, got %zu want %zu\n",
+ out_bytes_len,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ if (memcmp(out_bytes, TEST_QUIC_TRANSPORT_DATA,
+ out_bytes_len) != 0) {
+ FAIL("client QUIC differs from sent:\n");
+ fprintf(stderr, "received:\n");
+ hexdump(data, dlen);
+ fprintf(stderr, "test data:\n");
+ hexdump(tlsext_quic_transport_data,
+ sizeof(tlsext_quic_transport_data));
+ goto err;
+ }
+
+ failure = 0;
+
+ err:
+ CBB_cleanup(&cbb);
+ SSL_CTX_free(ssl_ctx);
+ SSL_free(ssl);
+ free(data);
+
+ return (failure);
+}
+
static unsigned char tls_ocsp_client_default[] = {
0x01, 0x00, 0x00, 0x00, 0x00
};
failed |= test_tlsext_valid_hostnames();
+ failed |= test_tlsext_quic_transport_parameters_client();
+ failed |= test_tlsext_quic_transport_parameters_server();
+
return (failed);
}