int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { unsigned int ecpointformats_len; PACKET ecptformatlist; if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { ecpointformats_len = PACKET_remaining(&ecptformatlist); s->session->ext.ecpointformats_len = 0; OPENSSL_free(s->session->ext.ecpointformats); s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len); if (s->session->ext.ecpointformats == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } s->session->ext.ecpointformats_len = ecpointformats_len; if (!PACKET_copy_bytes(&ecptformatlist, s->session->ext.ecpointformats, ecpointformats_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, int *al) { unsigned int ecpointformatlist_length; PACKET ecptformatlist; if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { ecpointformatlist_length = PACKET_remaining(&ecptformatlist); s->session->tlsext_ecpointformatlist_length = 0; OPENSSL_free(s->session->tlsext_ecpointformatlist); s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length); if (s->session->tlsext_ecpointformatlist == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length; if (!PACKET_copy_bytes(&ecptformatlist, s->session->tlsext_ecpointformatlist, ecpointformatlist_length)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
/* * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. */ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 PACKET psk_kex_modes; unsigned int mode; if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) || PACKET_remaining(&psk_kex_modes) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, SSL_R_BAD_EXTENSION); return 0; } while (PACKET_get_1(&psk_kex_modes, &mode)) { if (mode == TLSEXT_KEX_MODE_KE_DHE) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; else if (mode == TLSEXT_KEX_MODE_KE && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; } #endif return 1; }
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET srp_I; if (!PACKET_as_length_prefixed_1(pkt, &srp_I) || PACKET_contains_zero_byte(&srp_I)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SRP, SSL_R_BAD_EXTENSION); return 0; } /* * TODO(openssl-team): currently, we re-authenticate the user * upon resumption. Instead, we MUST ignore the login. */ if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
static int test_PACKET_as_length_prefixed_1() { unsigned char buf1[BUF_LEN]; const size_t len = 16; unsigned int i; PACKET pkt, exact_pkt, subpkt = {0}; buf1[0] = len; for (i = 1; i < BUF_LEN; i++) buf1[i] = (i * 2) & 0xff; if (!TEST_true(PACKET_buf_init(&pkt, buf1, BUF_LEN)) || !TEST_true(PACKET_buf_init(&exact_pkt, buf1, len + 1)) || !TEST_false(PACKET_as_length_prefixed_1(&pkt, &subpkt)) || !TEST_size_t_eq(PACKET_remaining(&pkt), BUF_LEN) || !TEST_true(PACKET_as_length_prefixed_1(&exact_pkt, &subpkt) || !TEST_size_t_eq(PACKET_remaining(&exact_pkt), 0) || !TEST_size_t_eq(PACKET_remaining(&subpkt), len))) return 0; return 1; }
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, int *al) { PACKET ec_point_format_list; if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) || PACKET_remaining(&ec_point_format_list) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { if (!PACKET_memdup(&ec_point_format_list, &s->session->tlsext_ecpointformatlist, &s->session->tlsext_ecpointformatlist_length)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } } return 1; }
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, int *al) { PACKET srp_I; if (!PACKET_as_length_prefixed_1(pkt, &srp_I) || PACKET_contains_zero_byte(&srp_I)) { *al = SSL_AD_DECODE_ERROR; return 0; } /* * TODO(openssl-team): currently, we re-authenticate the user * upon resumption. Instead, we MUST ignore the login. */ if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET ec_point_format_list; if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) || PACKET_remaining(&ec_point_format_list) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { if (!PACKET_memdup(&ec_point_format_list, &s->session->ext.ecpointformats, &s->session->ext.ecpointformats_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
/* * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. * If a failure occurs then |*al| is set to an appropriate alert value. */ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 PACKET psk_kex_modes; unsigned int mode; if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) || PACKET_remaining(&psk_kex_modes) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } while (PACKET_get_1(&psk_kex_modes, &mode)) { if (mode == TLSEXT_KEX_MODE_KE_DHE) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; else if (mode == TLSEXT_KEX_MODE_KE) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; } #endif return 1; }
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET ec_point_format_list; if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) || PACKET_remaining(&ec_point_format_list) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit) { if (!PACKET_memdup(&ec_point_format_list, &s->session->ext.ecpointformats, &s->session->ext.ecpointformats_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
/* * ssl_choose_server_version - Choose server (D)TLS version. Called when the * client HELLO is received to select the final server protocol version and * the version specific method. * * @s: server SSL handle. * * Returns 0 on success or an SSL error reason number on failure. */ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello) { /*- * With version-flexible methods we have an initial state with: * * s->method->version == (D)TLS_ANY_VERSION, * s->version == (D)TLS_MAX_VERSION. * * So we detect version-flexible methods via the method version, not the * handle version. */ int server_version = s->method->version; int client_version = hello->legacy_version; const version_info *vent; const version_info *table; int disabled = 0; RAW_EXTENSION *suppversions; s->client_version = client_version; switch (server_version) { default: /* * TODO(TLS1.3): This check will fail if someone attempts to do * renegotiation in TLS1.3 at the moment. We need to ensure we disable * renegotiation for TLS1.3 */ if (version_cmp(s, client_version, s->version) < 0) return SSL_R_WRONG_SSL_VERSION; /* * If this SSL handle is not from a version flexible method we don't * (and never did) check min/max FIPS or Suite B constraints. Hope * that's OK. It is up to the caller to not choose fixed protocol * versions they don't want. If not, then easy to fix, just return * ssl_method_error(s, s->method) */ return 0; case TLS_ANY_VERSION: table = tls_version_table; break; case DTLS_ANY_VERSION: table = dtls_version_table; break; } suppversions = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_supported_versions); if (suppversions != NULL && !SSL_IS_DTLS(s)) { unsigned int candidate_vers = 0; unsigned int best_vers = 0; const SSL_METHOD *best_method = NULL; PACKET versionslist; if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) { /* Trailing or invalid data? */ return SSL_R_LENGTH_MISMATCH; } while (PACKET_get_net_2(&versionslist, &candidate_vers)) { /* TODO(TLS1.3): Remove this before release */ if (candidate_vers == TLS1_3_VERSION_DRAFT) candidate_vers = TLS1_3_VERSION; /* * TODO(TLS1.3): There is some discussion on the TLS list about * wheter to ignore versions <TLS1.2 in supported_versions. At the * moment we honour them if present. To be reviewed later */ if (version_cmp(s, candidate_vers, best_vers) <= 0) continue; for (vent = table; vent->version != 0 && vent->version != (int)candidate_vers; ++vent) continue; if (vent->version != 0 && vent->smeth != NULL) { const SSL_METHOD *method; method = vent->smeth(); if (ssl_method_error(s, method) == 0) { best_vers = candidate_vers; best_method = method; } } } if (PACKET_remaining(&versionslist) != 0) { /* Trailing data? */ return SSL_R_LENGTH_MISMATCH; } if (best_vers > 0) { s->version = best_vers; s->method = best_method; return 0; } return SSL_R_UNSUPPORTED_PROTOCOL; } /* * If the supported versions extension isn't present, then the highest * version we can negotiate is TLSv1.2 */ if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0) client_version = TLS1_2_VERSION; /* * No supported versions extension, so we just use the version supplied in * the ClientHello. */ for (vent = table; vent->version != 0; ++vent) { const SSL_METHOD *method; if (vent->smeth == NULL || version_cmp(s, client_version, vent->version) < 0) continue; method = vent->smeth(); if (ssl_method_error(s, method) == 0) { s->version = vent->version; s->method = method; return 0; } disabled = 1; } return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW; }