summaryrefslogtreecommitdiffstats
path: root/src/ssl/t1_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/t1_lib.c')
-rw-r--r--src/ssl/t1_lib.c109
1 files changed, 65 insertions, 44 deletions
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index a6c48f1..f30e8eb 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -122,7 +122,6 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/rand.h>
-#include <openssl/type_check.h>
#include "internal.h"
@@ -309,7 +308,7 @@ char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) {
return 1;
}
-int SSL_early_callback_ctx_extension_get(
+char SSL_early_callback_ctx_extension_get(
const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
const uint8_t **out_data, size_t *out_len) {
CBS extensions;
@@ -1206,7 +1205,7 @@ static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert,
static int ext_ticket_parse_clienthello(SSL *ssl, uint8_t *out_alert, CBS *contents) {
/* This function isn't used because the ticket extension from the client is
- * handled in ssl_session.c. */
+ * handled in ssl_sess.c. */
return 1;
}
@@ -1375,7 +1374,6 @@ static void ext_npn_init(SSL *ssl) {
static int ext_npn_add_clienthello(SSL *ssl, CBB *out) {
if (ssl->s3->initial_handshake_complete ||
ssl->ctx->next_proto_select_cb == NULL ||
- (ssl->options & SSL_OP_DISABLE_NPN) ||
SSL_IS_DTLS(ssl)) {
return 1;
}
@@ -1400,7 +1398,6 @@ static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
assert(!ssl->s3->initial_handshake_complete);
assert(!SSL_IS_DTLS(ssl));
assert(ssl->ctx->next_proto_select_cb != NULL);
- assert(!(ssl->options & SSL_OP_DISABLE_NPN));
if (ssl->s3->alpn_selected != NULL) {
/* NPN and ALPN may not be negotiated in the same connection. */
@@ -2231,50 +2228,55 @@ int SSL_extension_supported(unsigned extension_value) {
tls_extension_find(&index, extension_value) != NULL;
}
-int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) {
+/* header_len is the length of the ClientHello header written so far, used to
+ * compute padding. It does not include the record header. Pass 0 if no padding
+ * is to be done. */
+uint8_t *ssl_add_clienthello_tlsext(SSL *s, uint8_t *const buf,
+ uint8_t *const limit, size_t header_len) {
/* don't add extensions for SSLv3 unless doing secure renegotiation */
- if (ssl->client_version == SSL3_VERSION &&
- !ssl->s3->send_connection_binding) {
- return 1;
+ if (s->client_version == SSL3_VERSION && !s->s3->send_connection_binding) {
+ return buf;
}
- size_t orig_len = CBB_len(out);
- CBB extensions;
- if (!CBB_add_u16_length_prefixed(out, &extensions)) {
+ CBB cbb, extensions;
+ CBB_zero(&cbb);
+ if (!CBB_init_fixed(&cbb, buf, limit - buf) ||
+ !CBB_add_u16_length_prefixed(&cbb, &extensions)) {
goto err;
}
- ssl->s3->tmp.extensions.sent = 0;
- ssl->s3->tmp.custom_extensions.sent = 0;
+ s->s3->tmp.extensions.sent = 0;
+ s->s3->tmp.custom_extensions.sent = 0;
size_t i;
for (i = 0; i < kNumExtensions; i++) {
if (kExtensions[i].init != NULL) {
- kExtensions[i].init(ssl);
+ kExtensions[i].init(s);
}
}
for (i = 0; i < kNumExtensions; i++) {
const size_t len_before = CBB_len(&extensions);
- if (!kExtensions[i].add_clienthello(ssl, &extensions)) {
+ if (!kExtensions[i].add_clienthello(s, &extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
goto err;
}
if (CBB_len(&extensions) != len_before) {
- ssl->s3->tmp.extensions.sent |= (1u << i);
+ s->s3->tmp.extensions.sent |= (1u << i);
}
}
- if (!custom_ext_add_clienthello(ssl, &extensions)) {
+ if (!custom_ext_add_clienthello(s, &extensions)) {
goto err;
}
- if (!SSL_IS_DTLS(ssl)) {
- header_len += CBB_len(&extensions) - orig_len;
+ if (header_len > 0) {
+ header_len += CBB_len(&extensions);
if (header_len > 0xff && header_len < 0x200) {
- /* Add padding to workaround bugs in F5 terminators. See RFC 7685.
+ /* Add padding to workaround bugs in F5 terminators. See
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03
*
* NB: because this code works out the length of all existing extensions
* it MUST always appear last. */
@@ -2299,58 +2301,80 @@ int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) {
}
}
+ if (!CBB_flush(&cbb)) {
+ goto err;
+ }
+
+ uint8_t *ret = buf;
+ const size_t cbb_len = CBB_len(&cbb);
/* If only two bytes have been written then the extensions are actually empty
* and those two bytes are the zero length. In that case, we don't bother
* sending the extensions length. */
- if (CBB_len(&extensions) - orig_len == 2) {
- CBB_discard_child(out);
+ if (cbb_len > 2) {
+ ret += cbb_len;
}
- return CBB_flush(out);
+ CBB_cleanup(&cbb);
+ return ret;
err:
+ CBB_cleanup(&cbb);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return NULL;
}
-int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out) {
- const size_t orig_len = CBB_len(out);
+uint8_t *ssl_add_serverhello_tlsext(SSL *s, uint8_t *const buf,
+ uint8_t *const limit) {
+ /* don't add extensions for SSLv3, unless doing secure renegotiation */
+ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) {
+ return buf;
+ }
- CBB extensions;
- if (!CBB_add_u16_length_prefixed(out, &extensions)) {
+ CBB cbb, extensions;
+ CBB_zero(&cbb);
+ if (!CBB_init_fixed(&cbb, buf, limit - buf) ||
+ !CBB_add_u16_length_prefixed(&cbb, &extensions)) {
goto err;
}
unsigned i;
for (i = 0; i < kNumExtensions; i++) {
- if (!(ssl->s3->tmp.extensions.received & (1u << i))) {
+ if (!(s->s3->tmp.extensions.received & (1u << i))) {
/* Don't send extensions that were not received. */
continue;
}
- if (!kExtensions[i].add_serverhello(ssl, &extensions)) {
+ if (!kExtensions[i].add_serverhello(s, &extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
goto err;
}
}
- if (!custom_ext_add_serverhello(ssl, &extensions)) {
+ if (!custom_ext_add_serverhello(s, &extensions)) {
goto err;
}
+ if (!CBB_flush(&cbb)) {
+ goto err;
+ }
+
+ uint8_t *ret = buf;
+ const size_t cbb_len = CBB_len(&cbb);
/* If only two bytes have been written then the extensions are actually empty
* and those two bytes are the zero length. In that case, we don't bother
* sending the extensions length. */
- if (CBB_len(&extensions) - orig_len == 2) {
- CBB_discard_child(out);
+ if (cbb_len > 2) {
+ ret += cbb_len;
}
- return CBB_flush(out);
+ CBB_cleanup(&cbb);
+ return ret;
err:
+ CBB_cleanup(&cbb);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return NULL;
}
static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) {
@@ -2389,12 +2413,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) {
return 0;
}
- /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat
- * ambiguous. Ignore all but the renegotiation_info extension. */
- if (s->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) {
- continue;
- }
-
unsigned ext_index;
const struct tls_extension *const ext =
tls_extension_find(&ext_index, type);
@@ -2450,10 +2468,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs) {
return 1;
}
-OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits);
-
static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) {
uint32_t received = 0;
+ assert(kNumExtensions <= sizeof(received) * 8);
if (CBS_len(cbs) != 0) {
/* Decode the extensions block and check it is valid. */
@@ -2588,6 +2605,10 @@ static int ssl_check_serverhello_tlsext(SSL *s) {
int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs) {
int alert = -1;
+ if (s->version < SSL3_VERSION) {
+ return 1;
+ }
+
if (ssl_scan_serverhello_tlsext(s, cbs, &alert) <= 0) {
ssl3_send_alert(s, SSL3_AL_FATAL, alert);
return 0;