Commit 09c2bc5f6c for openssl.org
commit 09c2bc5f6c107ce97c396f2b7cc9118646085a0f
Author: Kurt Roeckx <kurt@roeckx.be>
Date: Tue Jul 15 11:38:21 2025 +0200
Remove support for SSLv2 Client Hello
Drop support for the SSLv2 Client Hello. We allowed that a client send
an SSLv2 compatible Client Hello.
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Alicja Kario <hkario@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28041)
diff --git a/CHANGES.md b/CHANGES.md
index 067a2b0752..ff960d0dcc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -32,6 +32,15 @@ OpenSSL 4.0
### Changes between 3.6 and 4.0 [xx XXX xxxx]
+ * Remove support for an SSLv2 Client Hello. When a client wanted to support
+ both SSLv2 and higher versions like SSLv3 or even TLSv1, it needed to
+ send an SSLv2 Client Hello. SSLv2 support itself was removed in version
+ 1.1.0, but there was still compatibility code for clients sending an SSLv2
+ Client Hello. Since we no longer support SSLv2 Client Hello,
+ SSL_client_hello_isv2() is now deprecated and always returns 0.
+
+ *Kurt Roeckx*
+
* Added "ML-DSA-MU" digest algorithm support.
*Shane Lontis*
diff --git a/NEWS.md b/NEWS.md
index f966d8cfda..30542709ce 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -36,6 +36,8 @@ OpenSSL 4.0
* The crypto-mdebug-backtrace configuration option has been entirely removed.
+ * Support for the SSLv2 Client Hello was removed
+
OpenSSL 3.6
-----------
diff --git a/doc/man3/SSL_CTX_set_client_hello_cb.pod b/doc/man3/SSL_CTX_set_client_hello_cb.pod
index 6367c68a62..41defadf30 100644
--- a/doc/man3/SSL_CTX_set_client_hello_cb.pod
+++ b/doc/man3/SSL_CTX_set_client_hello_cb.pod
@@ -9,7 +9,6 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_
typedef int (*SSL_client_hello_cb_fn)(SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn *f,
void *arg);
- int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
@@ -23,6 +22,12 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_
int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
size_t *outlen);
+The following functions have been deprecated since OpenSSL 4.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int SSL_client_hello_isv2(SSL *s);
+
=head1 DESCRIPTION
SSL_CTX_set_client_hello_cb() sets the callback function, which is automatically
@@ -40,14 +45,9 @@ function, the ClientHello callback will be called again, and, if it returns
success, normal handshake processing will continue from that point.
SSL_client_hello_isv2() indicates whether the ClientHello was carried in a
-SSLv2 record and is in the SSLv2 format. The SSLv2 format has substantial
-differences from the normal SSLv3 format, including using three bytes per
-cipher suite, and not allowing extensions. Additionally, the SSLv2 format
-'challenge' field is exposed via SSL_client_hello_get0_random(), padded to
-SSL3_RANDOM_SIZE bytes with zeros if needed. For SSLv2 format ClientHellos,
-SSL_client_hello_get0_compression_methods() returns a dummy list that only includes
-the null compression method, since the SSLv2 format does not include a
-mechanism by which to negotiate compression.
+SSLv2 record and is in the SSLv2 format.
+Support for the SSLv2 format was removed in 4.0 and this function
+will always return 0.
SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), and
@@ -117,7 +117,7 @@ The application's supplied ClientHello callback returns
SSL_CLIENT_HELLO_SUCCESS on success, SSL_CLIENT_HELLO_ERROR on failure, and
SSL_CLIENT_HELLO_RETRY to suspend processing.
-SSL_client_hello_isv2() returns 1 for SSLv2-format ClientHellos and 0 otherwise.
+SSL_client_hello_isv2() returns 0.
SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), and
diff --git a/doc/man3/SSL_get_ciphers.pod b/doc/man3/SSL_get_ciphers.pod
index add0fc4cd0..307f27e52d 100644
--- a/doc/man3/SSL_get_ciphers.pod
+++ b/doc/man3/SSL_get_ciphers.pod
@@ -51,12 +51,13 @@ list received from the client on B<ssl>. If B<ssl> is NULL, no ciphers are
available, or B<ssl> is not operating in server mode, NULL is returned.
SSL_bytes_to_cipher_list() treats the supplied B<len> octets in B<bytes>
-as a wire-protocol cipher suite specification (in the three-octet-per-cipher
-SSLv2 wire format if B<isv2format> is nonzero; otherwise the two-octet
-SSLv3/TLS wire format), and parses the cipher suites supported by the library
+as a wire-protocol cipher suite specification in the two-octet
+SSLv3/TLS wire format, and parses the cipher suites supported by the library
into the returned stacks of SSL_CIPHER objects sk and Signalling Cipher-Suite
-Values scsvs. Unsupported cipher suites are ignored. Returns 1 on success
-and 0 on failure.
+Values scsvs.
+The B<isv2format> is no longer supported and should always be set to 0.
+Unsupported cipher suites are ignored.
+Returns 1 on success and 0 on failure.
SSL_get_cipher_list() returns a pointer to the name of the SSL_CIPHER
listed for B<ssl> with B<priority>. If B<ssl> is NULL, no ciphers are
diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in
index 7882b8bc67..83d72e6fa8 100644
--- a/include/openssl/ssl.h.in
+++ b/include/openssl/ssl.h.in
@@ -1922,7 +1922,9 @@ typedef int (*SSL_new_pending_conn_cb_fn)(SSL_CTX *ctx, SSL *new_ssl,
void SSL_CTX_set_new_pending_conn_cb(SSL_CTX *c, SSL_new_pending_conn_cb_fn cb,
void *arg);
-int SSL_client_hello_isv2(SSL *s);
+#ifndef OPENSSL_NO_DEPRECATED_4_0
+OSSL_DEPRECATEDIN_4_0 int SSL_client_hello_isv2(SSL *s);
+#endif
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index f4b249bf32..670b03ab0b 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1122,17 +1122,6 @@ start:
}
}
-/*
- * Returns true if the current rrec was sent in SSLv2 backwards compatible
- * format and false otherwise.
- */
-int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl)
-{
- if (SSL_CONNECTION_IS_DTLS(rl->s))
- return 0;
- return rl->tlsrecs[0].version == SSL2_VERSION;
-}
-
static OSSL_FUNC_rlayer_msg_callback_fn rlayer_msg_callback_wrapper;
static void rlayer_msg_callback_wrapper(int write_p, int version,
int content_type, const void *buf,
diff --git a/ssl/record/record.h b/ssl/record/record.h
index 8e7b883845..23c15f3b41 100644
--- a/ssl/record/record.h
+++ b/ssl/record/record.h
@@ -140,7 +140,6 @@ int RECORD_LAYER_reset(RECORD_LAYER *rl);
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl);
int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl);
int RECORD_LAYER_write_pending(const RECORD_LAYER *rl);
-int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl);
__owur size_t ssl3_pending(const SSL *s);
__owur int ssl3_write_bytes(SSL *s, uint8_t type, const void *buf, size_t len,
size_t *written);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index e82ac8c040..43ca1e46d7 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -6732,17 +6732,12 @@ void SSL_CTX_set_new_pending_conn_cb(SSL_CTX *c, SSL_new_pending_conn_cb_fn cb,
c->new_pending_conn_arg = arg;
}
+#ifndef OPENSSL_NO_DEPRECATED_4_0
int SSL_client_hello_isv2(SSL *s)
{
- const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
-
- if (sc == NULL)
- return 0;
-
- if (sc->clienthello == NULL)
- return 0;
- return sc->clienthello->isv2;
+ return 0;
}
+#endif
unsigned int SSL_client_hello_get0_legacy_version(SSL *s)
{
@@ -7045,20 +7040,14 @@ int ssl_log_secret(SSL_CONNECTION *sc,
secret_len);
}
-#define SSLV2_CIPHER_LEN 3
-
-int ssl_cache_cipherlist(SSL_CONNECTION *s, PACKET *cipher_suites, int sslv2format)
+int ssl_cache_cipherlist(SSL_CONNECTION *s, PACKET *cipher_suites)
{
- int n;
-
- n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
-
if (PACKET_remaining(cipher_suites) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_NO_CIPHERS_SPECIFIED);
return 0;
}
- if (PACKET_remaining(cipher_suites) % n != 0) {
+ if (PACKET_remaining(cipher_suites) % TLS_CIPHER_LEN != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return 0;
}
@@ -7067,45 +7056,8 @@ int ssl_cache_cipherlist(SSL_CONNECTION *s, PACKET *cipher_suites, int sslv2form
s->s3.tmp.ciphers_raw = NULL;
s->s3.tmp.ciphers_rawlen = 0;
- if (sslv2format) {
- size_t numciphers = PACKET_remaining(cipher_suites) / n;
- PACKET sslv2ciphers = *cipher_suites;
- unsigned int leadbyte;
- unsigned char *raw;
-
- /*
- * We store the raw ciphers list in SSLv3+ format so we need to do some
- * preprocessing to convert the list first. If there are any SSLv2 only
- * ciphersuites with a non-zero leading byte then we are going to
- * slightly over allocate because we won't store those. But that isn't a
- * problem.
- */
- raw = OPENSSL_malloc_array(numciphers, TLS_CIPHER_LEN);
- s->s3.tmp.ciphers_raw = raw;
- if (raw == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
- return 0;
- }
- for (s->s3.tmp.ciphers_rawlen = 0;
- PACKET_remaining(&sslv2ciphers) > 0;
- raw += TLS_CIPHER_LEN) {
- if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
- || (leadbyte == 0
- && !PACKET_copy_bytes(&sslv2ciphers, raw,
- TLS_CIPHER_LEN))
- || (leadbyte != 0
- && !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_PACKET);
- OPENSSL_free(s->s3.tmp.ciphers_raw);
- s->s3.tmp.ciphers_raw = NULL;
- s->s3.tmp.ciphers_rawlen = 0;
- return 0;
- }
- if (leadbyte == 0)
- s->s3.tmp.ciphers_rawlen += TLS_CIPHER_LEN;
- }
- } else if (!PACKET_memdup(cipher_suites, &s->s3.tmp.ciphers_raw,
- &s->s3.tmp.ciphers_rawlen)) {
+ if (!PACKET_memdup(cipher_suites, &s->s3.tmp.ciphers_raw,
+ &s->s3.tmp.ciphers_rawlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -7119,27 +7071,24 @@ int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
PACKET pkt;
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
- if (sc == NULL)
+ if (sc == NULL || isv2format)
return 0;
if (!PACKET_buf_init(&pkt, bytes, len))
return 0;
- return ossl_bytes_to_cipher_list(sc, &pkt, sk, scsvs, isv2format, 0);
+ return ossl_bytes_to_cipher_list(sc, &pkt, sk, scsvs, 0);
}
int ossl_bytes_to_cipher_list(SSL_CONNECTION *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **skp,
STACK_OF(SSL_CIPHER) **scsvs_out,
- int sslv2format, int fatal)
+ int fatal)
{
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *sk = NULL;
STACK_OF(SSL_CIPHER) *scsvs = NULL;
- int n;
- /* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */
- unsigned char cipher[SSLV2_CIPHER_LEN];
-
- n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
+ int n = TLS_CIPHER_LEN;
+ unsigned char cipher[TLS_CIPHER_LEN];
if (PACKET_remaining(cipher_suites) == 0) {
if (fatal)
@@ -7169,16 +7118,7 @@ int ossl_bytes_to_cipher_list(SSL_CONNECTION *s, PACKET *cipher_suites,
}
while (PACKET_copy_bytes(cipher_suites, cipher, n)) {
- /*
- * SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the
- * first byte set to zero, while true SSLv2 ciphers have a non-zero
- * first byte. We don't support any true SSLv2 ciphers, so skip them.
- */
- if (sslv2format && cipher[0] != '\0')
- continue;
-
- /* For SSLv2-compat, ignore leading 0-byte. */
- c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher, 1);
+ c = ssl_get_cipher_by_char(s, cipher, 1);
if (c != NULL) {
if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) || (!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) {
if (fatal)
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 994bfb7943..606fded111 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -639,7 +639,6 @@ typedef struct raw_extension_st {
} RAW_EXTENSION;
typedef struct {
- unsigned int isv2;
unsigned int legacy_version;
unsigned char random[SSL3_RANDOM_SIZE];
size_t session_id_len;
@@ -2506,11 +2505,10 @@ __owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_CTX *ctx,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str,
CERT *c);
-__owur int ssl_cache_cipherlist(SSL_CONNECTION *s, PACKET *cipher_suites,
- int sslv2format);
+__owur int ssl_cache_cipherlist(SSL_CONNECTION *s, PACKET *cipher_suites);
__owur int ossl_bytes_to_cipher_list(SSL_CONNECTION *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **skp,
- STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
+ STACK_OF(SSL_CIPHER) **scsvs,
int fatal);
void ssl_update_cache(SSL_CONNECTION *s, int mode);
__owur int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 9e0c853c0d..3e3d00a8be 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1595,32 +1595,16 @@ int tls_get_message_header(SSL_CONNECTION *s, int *mt)
*mt = *p;
s->s3.tmp.message_type = *(p++);
- if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
- /*
- * Only happens with SSLv3+ in an SSLv2 backward compatible
- * ClientHello
- *
- * Total message size is the remaining record bytes to read
- * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
- */
- l = s->rlayer.tlsrecs[0].length + SSL3_HM_HEADER_LENGTH;
- s->s3.tmp.message_size = l;
-
- s->init_msg = s->init_buf->data;
- s->init_num = SSL3_HM_HEADER_LENGTH;
- } else {
- n2l3(p, l);
- /* BUF_MEM_grow takes an 'int' parameter */
- if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return 0;
- }
- s->s3.tmp.message_size = l;
-
- s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
- s->init_num = 0;
+ n2l3(p, l);
+ /* BUF_MEM_grow takes an 'int' parameter */
+ if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return 0;
}
+ s->s3.tmp.message_size = l;
+
+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
+ s->init_num = 0;
return 1;
}
@@ -1663,48 +1647,35 @@ int tls_get_message_body(SSL_CONNECTION *s, size_t *len)
return 0;
}
- /* Feed this message into MAC computation. */
- if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
- if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
- }
- if (s->msg_callback)
- s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
- (size_t)s->init_num, ussl, s->msg_callback_arg);
- } else {
- /*
- * We defer feeding in the HRR until later. We'll do it as part of
- * processing the message
- * The TLsv1.3 handshake transcript stops at the ClientFinished
- * message.
- */
+ /*
+ * We defer feeding in the HRR until later. We'll do it as part of
+ * processing the message
+ * The TLsv1.3 handshake transcript stops at the ClientFinished
+ * message.
+ */
#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
- /* KeyUpdate and NewSessionTicket do not need to be added */
- if (!SSL_CONNECTION_IS_TLS13(s)
- || (s->s3.tmp.message_type != SSL3_MT_NEWSESSION_TICKET
- && s->s3.tmp.message_type != SSL3_MT_KEY_UPDATE)) {
- if (s->s3.tmp.message_type != SSL3_MT_SERVER_HELLO
- || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
- || memcmp(hrrrandom,
- s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
- SSL3_RANDOM_SIZE)
- != 0) {
- if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num + SSL3_HM_HEADER_LENGTH)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
- }
+ /* KeyUpdate and NewSessionTicket do not need to be added */
+ if (!SSL_CONNECTION_IS_TLS13(s)
+ || (s->s3.tmp.message_type != SSL3_MT_NEWSESSION_TICKET
+ && s->s3.tmp.message_type != SSL3_MT_KEY_UPDATE)) {
+ if (s->s3.tmp.message_type != SSL3_MT_SERVER_HELLO
+ || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
+ || memcmp(hrrrandom,
+ s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
+ SSL3_RANDOM_SIZE)
+ != 0) {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
}
}
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
- (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, ussl,
- s->msg_callback_arg);
}
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
+ (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, ussl,
+ s->msg_callback_arg);
*len = s->init_num;
return 1;
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index db99d49706..bdb46716ef 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1627,7 +1627,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
{
/* |cookie| will only be initialized for DTLS. */
PACKET session_id, compression, extensions, cookie;
- static const unsigned char null_compression = 0;
CLIENTHELLO_MSG *clienthello = NULL;
/* Check if this is actually an unexpected renegotiation ClientHello */
@@ -1657,156 +1656,65 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
/*
* First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
*/
- clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
PACKET_null_init(&cookie);
- if (clienthello->isv2) {
- unsigned int mt;
-
- if (!SSL_IS_FIRST_HANDSHAKE(s)
- || s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
- goto err;
- }
-
- /*-
- * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
- * header is sent directly on the wire, not wrapped as a TLS
- * record. Our record layer just processes the message length and passes
- * the rest right through. Its format is:
- * Byte Content
- * 0-1 msg_length - decoded by the record layer
- * 2 msg_type - s->init_msg points here
- * 3-4 version
- * 5-6 cipher_spec_length
- * 7-8 session_id_length
- * 9-10 challenge_length
- * ... ...
- */
-
- if (!PACKET_get_1(pkt, &mt)
- || mt != SSL2_MT_CLIENT_HELLO) {
- /*
- * Should never happen. We should have tested this in the record
- * layer in order to have determined that this is an SSLv2 record
- * in the first place
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
goto err;
}
- /* Parse the message and load client random. */
- if (clienthello->isv2) {
- /*
- * Handle an SSLv2 backwards compatible ClientHello
- * Note, this is only for SSLv3+ using the backward compatible format.
- * Real SSLv2 is not supported, and is rejected below.
- */
- unsigned int ciphersuite_len, session_id_len, challenge_len;
- PACKET challenge;
-
- if (!PACKET_get_net_2(pkt, &ciphersuite_len)
- || !PACKET_get_net_2(pkt, &session_id_len)
- || !PACKET_get_net_2(pkt, &challenge_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
- goto err;
- }
-
- if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
+ if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
+ || !PACKET_get_length_prefixed_1(pkt, &session_id)
+ || !PACKET_copy_all(&session_id, clienthello->session_id,
+ SSL_MAX_SSL_SESSION_ID_LENGTH,
+ &clienthello->session_id_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
- if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
- ciphersuite_len)
- || !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
- || !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
- /* No extensions. */
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
+ if (SSL_CONNECTION_IS_DTLS(s)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
- clienthello->session_id_len = session_id_len;
-
- /* Load the client random and compression list. We use SSL3_RANDOM_SIZE
- * here rather than sizeof(clienthello->random) because that is the limit
- * for SSLv3 and it is fixed. It won't change even if
- * sizeof(clienthello->random) does.
- */
- challenge_len = challenge_len > SSL3_RANDOM_SIZE
- ? SSL3_RANDOM_SIZE
- : challenge_len;
- memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
- if (!PACKET_copy_bytes(&challenge,
- clienthello->random + SSL3_RANDOM_SIZE - challenge_len, challenge_len)
- /* Advertise only null compression. */
- || !PACKET_buf_init(&compression, &null_compression, 1)) {
+ if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
+ DTLS1_COOKIE_LENGTH,
+ &clienthello->dtls_cookie_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
-
- PACKET_null_init(&clienthello->extensions);
- } else {
- /* Regular ClientHello. */
- if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
- || !PACKET_get_length_prefixed_1(pkt, &session_id)
- || !PACKET_copy_all(&session_id, clienthello->session_id,
- SSL_MAX_SSL_SESSION_ID_LENGTH,
- &clienthello->session_id_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (SSL_CONNECTION_IS_DTLS(s)) {
- if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
- sizeof(clienthello->dtls_cookie),
- &clienthello->dtls_cookie_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /*
- * If we require cookies and this ClientHello doesn't contain one,
- * just return since we do not want to allocate any memory yet.
- * So check cookie length...
- */
- if (SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE) {
- if (clienthello->dtls_cookie_len == 0) {
- OPENSSL_free(clienthello);
- return MSG_PROCESS_FINISHED_READING;
- }
+ /*
+ * If we require cookies and this ClientHello doesn't contain one,
+ * just return since we do not want to allocate any memory yet.
+ * So check cookie length...
+ */
+ if (SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE) {
+ if (clienthello->dtls_cookie_len == 0) {
+ OPENSSL_free(clienthello);
+ return MSG_PROCESS_FINISHED_READING;
}
}
+ }
- if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
+ if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
- if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* Could be empty. */
+ if (PACKET_remaining(pkt) == 0) {
+ PACKET_null_init(&clienthello->extensions);
+ } else {
+ if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
+ || PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
-
- /* Could be empty. */
- if (PACKET_remaining(pkt) == 0) {
- PACKET_null_init(&clienthello->extensions);
- } else {
- if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- }
}
if (!PACKET_copy_all(&compression, clienthello->compressions,
@@ -1874,23 +1782,6 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s)
/* Set up the client_random */
memcpy(s->s3.client_random, clienthello->random, SSL3_RANDOM_SIZE);
- /* Choose the version */
-
- if (clienthello->isv2) {
- if (clienthello->legacy_version == SSL2_VERSION
- || (clienthello->legacy_version & 0xff00)
- != (SSL3_VERSION_MAJOR << 8)) {
- /*
- * This is real SSLv2 or something completely unknown. We don't
- * support it.
- */
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNKNOWN_PROTOCOL);
- goto err;
- }
- /* SSLv3/TLS */
- s->client_version = clienthello->legacy_version;
- }
-
/* Choose the server SSL/TLS/DTLS version. */
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
@@ -1936,10 +1827,8 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s)
s->hit = 0;
- if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
- clienthello->isv2)
- || !ossl_bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers,
- &scsvs, clienthello->isv2, 1)) {
+ if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites)
+ || !ossl_bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs, 1)) {
/* SSLfatal() already called */
goto err;
}
@@ -2017,7 +1906,7 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s)
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be
* ignored.
*/
- if (clienthello->isv2 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
+ if (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)) {
if (!ssl_get_new_session(s, 1)) {
/* SSLfatal() already called */
goto err;
diff --git a/test/cipherbytes_test.c b/test/cipherbytes_test.c
index 3e73781cfe..981a9cc13b 100644
--- a/test/cipherbytes_test.c
+++ b/test/cipherbytes_test.c
@@ -66,38 +66,6 @@ err:
return ret;
}
-static int test_v2(void)
-{
- STACK_OF(SSL_CIPHER) *sk, *scsv;
- /* ECDHE-ECDSA-AES256GCM, SSL2_RC4_1238_WITH_MD5,
- * ECDHE-ECDSA-CHACHA20-POLY1305 */
- const unsigned char bytes[] = { 0x00, 0x00, 0x35, 0x01, 0x00, 0x80,
- 0x00, 0x00, 0x33 };
- int ret = 0;
-
- if (!TEST_true(SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes), 1,
- &sk, &scsv))
- || !TEST_ptr(sk)
- || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 2)
- || !TEST_ptr(scsv)
- || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 0))
- goto err;
- if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
- "AES256-SHA")
- != 0
- || strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 1)),
- "DHE-RSA-AES128-SHA")
- != 0)
- goto err;
-
- ret = 1;
-
-err:
- sk_SSL_CIPHER_free(sk);
- sk_SSL_CIPHER_free(scsv);
- return ret;
-}
-
static int test_v3(void)
{
STACK_OF(SSL_CIPHER) *sk = NULL, *scsv = NULL;
@@ -139,7 +107,6 @@ int setup_tests(void)
ADD_TEST(test_empty);
ADD_TEST(test_unsupported);
- ADD_TEST(test_v2);
ADD_TEST(test_v3);
return 1;
}
diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t
index fe26564d50..4f90929560 100644
--- a/test/recipes/70-test_sslrecords.t
+++ b/test/recipes/70-test_sslrecords.t
@@ -33,20 +33,19 @@ my $inject_recs_num = undef;
my $content_type = undef;
my $boundary_test_type = undef;
my $fatal_alert = undef; # set by filters at expected fatal alerts
-my $sslv2testtype = undef;
my $proxy_start_success = 0;
-plan tests => 44;
+plan tests => 34;
SKIP: {
- skip "TLS 1.2 is disabled", 22 if disabled("tls1_2");
+ skip "TLS 1.2 is disabled", 17 if disabled("tls1_2");
# Run tests with TLS
run_tests(0);
}
SKIP: {
- skip "DTLS 1.2 is disabled", 22 if disabled("dtls1_2");
- skip "DTLSProxy does not work on Windows", 22 if $^O =~ /^(MSWin32)$/;
+ skip "DTLS 1.2 is disabled", 17 if disabled("dtls1_2");
+ skip "DTLSProxy does not work on Windows", 17 if $^O =~ /^(MSWin32)$/;
run_tests(1);
}
@@ -107,7 +106,7 @@ sub run_tests
"In context empty records test".($run_test_as_dtls == 1) ? " for DTLS" : " for TLS");
SKIP: {
- skip "Record tests not intended for dtls", 7 if $run_test_as_dtls == 1;
+ skip "Record tests not intended for dtls", 2 if $run_test_as_dtls == 1;
#Test 3: Injecting too many in context empty records should fail
$fatal_alert = 0;
$proxy->clear();
@@ -128,76 +127,10 @@ sub run_tests
$proxy->clientflags("-no_tls1_3");
$proxy->start();
ok($fatal_alert, "Fragmented alert records test");
-
- #Run some SSLv2 ClientHello tests
-
- use constant {
- TLSV1_2_IN_SSLV2 => 0,
- SSLV2_IN_SSLV2 => 1,
- FRAGMENTED_IN_TLSV1_2 => 2,
- FRAGMENTED_IN_SSLV2 => 3,
- ALERT_BEFORE_SSLV2 => 4
- };
-
- # The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
- # because in a SSLv2 ClientHello we can't send extensions to indicate
- # which signature algorithm we want to use, and the default is SHA1.
-
- #Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
- $sslv2testtype = TLSV1_2_IN_SSLV2;
- $proxy->clear();
- $proxy->filter(\&add_sslv2_filter);
- $proxy->serverflags("-tls1_2");
- $proxy->clientflags("-no_tls1_3 -legacy_renegotiation");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
-
- #Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
- # support this so it should fail. We actually treat it as an unknown
- # protocol so we don't even send an alert in this case.
- $sslv2testtype = SSLV2_IN_SSLV2;
- $proxy->clear();
- $proxy->serverflags("-tls1_2");
- $proxy->clientflags("-no_tls1_3");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok(TLSProxy::Message->fail(), "SSLv2 in SSLv2 ClientHello test");
-
- #Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
- # at all, but it gives us confidence that Test 8 fails for the right
- # reasons
- $sslv2testtype = FRAGMENTED_IN_TLSV1_2;
- $proxy->clear();
- $proxy->serverflags("-tls1_2");
- $proxy->clientflags("-no_tls1_3");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
-
- #Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
- # record; and another TLS1.2 record. This isn't allowed so should fail
- $sslv2testtype = FRAGMENTED_IN_SSLV2;
- $proxy->clear();
- $proxy->serverflags("-tls1_2");
- $proxy->clientflags("-no_tls1_3");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
-
- #Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
- # fail because an SSLv2 ClientHello must be the first record.
- $sslv2testtype = ALERT_BEFORE_SSLV2;
- $proxy->clear();
- $proxy->serverflags("-tls1_2");
- $proxy->clientflags("-no_tls1_3");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
}
#Unrecognised record type tests
- #Test 10: Sending an unrecognised record type in TLS1.2 should fail
+ #Test 5: Sending an unrecognised record type in TLS1.2 should fail
$fatal_alert = 0;
$proxy->clear();
if ($run_test_as_dtls == 1) {
@@ -220,7 +153,7 @@ sub run_tests
skip "TLSv1.1 or DTLSv1 disabled", 1 if ($run_test_as_dtls == 0 && disabled("tls1_1"))
|| ($run_test_as_dtls == 1 && disabled("dtls1"));
- #Test 11: Sending an unrecognised record type in TLS1.1 should fail
+ #Test 6: Sending an unrecognised record type in TLS1.1 should fail
$fatal_alert = 0;
$proxy->clear();
if ($run_test_as_dtls == 1) {
@@ -239,7 +172,7 @@ sub run_tests
SKIP: {
skip "Record tests not intended for dtls", 10 if $run_test_as_dtls == 1;
- #Test 12: Sending a different record version in TLS1.2 should fail
+ #Test 7: Sending a different record version in TLS1.2 should fail
$fatal_alert = 0;
$proxy->clear();
$proxy->clientflags("-tls1_2");
@@ -252,20 +185,20 @@ sub run_tests
skip "TLSv1.3 disabled", 9
if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
- #Test 13: Sending a different record version in TLS1.3 should fail
+ #Test 8: Sending a different record version in TLS1.3 should fail
$proxy->clear();
$proxy->filter(\&change_version);
$proxy->start();
ok(TLSProxy::Message->fail(), "Changed record version in TLS1.3");
- #Test 14: Sending an unrecognised record type in TLS1.3 should fail
+ #Test 9: Sending an unrecognised record type in TLS1.3 should fail
$fatal_alert = 0;
$proxy->clear();
$proxy->filter(\&add_unknown_record_type);
$proxy->start();
ok($fatal_alert, "Unrecognised record type in TLS1.3");
- #Test 15: Sending an outer record type other than app data once encrypted
+ #Test 10: Sending an outer record type other than app data once encrypted
#should fail
$fatal_alert = 0;
$proxy->clear();
@@ -281,7 +214,7 @@ sub run_tests
NO_DATA_BETWEEN_KEY_UPDATE => 4,
};
- #Test 16: Sending a ServerHello which doesn't end on a record boundary
+ #Test 11: Sending a ServerHello which doesn't end on a record boundary
# should fail
$fatal_alert = 0;
$proxy->clear();
@@ -290,7 +223,7 @@ sub run_tests
$proxy->start();
ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
- #Test 17: Sending a Finished which doesn't end on a record boundary
+ #Test 12: Sending a Finished which doesn't end on a record boundary
# should fail
$fatal_alert = 0;
$proxy->clear();
@@ -298,7 +231,7 @@ sub run_tests
$proxy->start();
ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
- #Test 18: Sending a KeyUpdate which doesn't end on a record boundary
+ #Test 13: Sending a KeyUpdate which doesn't end on a record boundary
# should fail
$fatal_alert = 0;
$proxy->clear();
@@ -306,7 +239,7 @@ sub run_tests
$proxy->start();
ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
- #Test 19: Sending application data in the middle of a fragmented KeyUpdate
+ #Test 14: Sending application data in the middle of a fragmented KeyUpdate
# should fail. Strictly speaking this is not a record boundary test
# but we use the same filter.
$fatal_alert = 0;
@@ -315,7 +248,7 @@ sub run_tests
$proxy->start();
ok($fatal_alert, "Data between KeyUpdate");
- #Test 20: Fragmented KeyUpdate. This should succeed. Strictly speaking this
+ #Test 15: Fragmented KeyUpdate. This should succeed. Strictly speaking this
# is not a record boundary test but we use the same filter.
$proxy->clear();
$boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE;
@@ -325,7 +258,7 @@ sub run_tests
SKIP: {
skip "EC disabled", 1 if disabled("ec");
- #Test 21: Force an HRR and change the "real" ServerHello to have a protocol
+ #Test 16: Force an HRR and change the "real" ServerHello to have a protocol
# record version of 0x0301 (TLSv1.0). At this point we have already
# decided that we are doing TLSv1.3 but are still using plaintext
# records. The server should be sending a record version of 0x303
@@ -342,7 +275,7 @@ sub run_tests
SKIP: {
skip "DTLS only record tests", 1 if $run_test_as_dtls != 1;
- #Test 22: We should ignore empty app data records
+ #Test 17: We should ignore empty app data records
$proxy->clear();
$proxy->filter(\&empty_app_data);
$proxy->start();
@@ -452,153 +385,6 @@ sub add_frag_alert_filter
push @{$records}, $record;
}
-sub add_sslv2_filter
-{
- my $proxy = shift;
- my $clienthello;
- my $record;
-
- # We're only interested in the initial ClientHello
- if ($proxy->flight != 0) {
- return;
- }
-
- # Ditch the real ClientHello - we're going to replace it with our own
- shift @{$proxy->record_list};
-
- if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
- my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
- TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
- my $alertlen = length $alert;
- $record = TLSProxy::Record->new(
- 0,
- TLSProxy::Record::RT_ALERT,
- TLSProxy::Record::VERS_TLS_1_2,
- $alertlen,
- 0,
- $alertlen,
- $alertlen,
- $alert,
- $alert
- );
-
- push @{$proxy->record_list}, $record;
- }
-
- if ($sslv2testtype == ALERT_BEFORE_SSLV2
- || $sslv2testtype == TLSV1_2_IN_SSLV2
- || $sslv2testtype == SSLV2_IN_SSLV2) {
- # This is an SSLv2 format ClientHello
- $clienthello =
- pack "C44",
- 0x01, # ClientHello
- 0x03, 0x03, #TLSv1.2
- 0x00, 0x03, # Ciphersuites len
- 0x00, 0x00, # Session id len
- 0x00, 0x20, # Challenge len
- 0x00, 0x00, 0x2f, #AES128-SHA
- 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
- 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
- 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
-
- if ($sslv2testtype == SSLV2_IN_SSLV2) {
- # Set the version to "real" SSLv2
- vec($clienthello, 1, 8) = 0x00;
- vec($clienthello, 2, 8) = 0x02;
- }
-
- my $chlen = length $clienthello;
-
- $record = TLSProxy::Record->new(
- 0,
- TLSProxy::Record::RT_HANDSHAKE,
- TLSProxy::Record::VERS_TLS_1_2,
- $chlen,
- 1, #SSLv2
- $chlen,
- $chlen,
- $clienthello,
- $clienthello
- );
-
- push @{$proxy->record_list}, $record;
- } else {
- # For this test we're using a real TLS ClientHello
- $clienthello =
- pack "C49",
- 0x01, # ClientHello
- 0x00, 0x00, 0x2D, # Message length
- 0x03, 0x03, # TLSv1.2
- 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
- 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
- 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
- 0x00, # Session id len
- 0x00, 0x04, # Ciphersuites len
- 0x00, 0x2f, # AES128-SHA
- 0x00, 0xff, # Empty reneg info SCSV
- 0x01, # Compression methods len
- 0x00, # Null compression
- 0x00, 0x00; # Extensions len
-
- # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
- # We deliberately split the second record prior to the Challenge/Random
- # and set the first byte of the random to 1. This makes the second SSLv2
- # record look like an SSLv2 ClientHello
- my $frag1 = substr $clienthello, 0, 6;
- my $frag2 = substr $clienthello, 6, 32;
- my $frag3 = substr $clienthello, 38;
-
- my $fraglen = length $frag1;
- $record = TLSProxy::Record->new(
- 0,
- TLSProxy::Record::RT_HANDSHAKE,
- TLSProxy::Record::VERS_TLS_1_2,
- $fraglen,
- 0,
- $fraglen,
- $fraglen,
- $frag1,
- $frag1
- );
- push @{$proxy->record_list}, $record;
-
- $fraglen = length $frag2;
- my $recvers;
- if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
- $recvers = 1;
- } else {
- $recvers = 0;
- }
- $record = TLSProxy::Record->new(
- 0,
- TLSProxy::Record::RT_HANDSHAKE,
- TLSProxy::Record::VERS_TLS_1_2,
- $fraglen,
- $recvers,
- $fraglen,
- $fraglen,
- $frag2,
- $frag2
- );
- push @{$proxy->record_list}, $record;
-
- $fraglen = length $frag3;
- $record = TLSProxy::Record->new(
- 0,
- TLSProxy::Record::RT_HANDSHAKE,
- TLSProxy::Record::VERS_TLS_1_2,
- $fraglen,
- 0,
- $fraglen,
- $fraglen,
- $frag3,
- $frag3
- );
- push @{$proxy->record_list}, $record;
- }
-
-}
-
sub add_unknown_record_type
{
my $proxy = shift;
diff --git a/util/libssl.num b/util/libssl.num
index d43e75f4d5..f8ca36f67d 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -298,7 +298,7 @@ SSL_get_srp_username ? 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_3_0
SSL_get_srp_userinfo ? 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_3_0,SRP
SSL_CTX_set_client_hello_cb ? 4_0_0 EXIST::FUNCTION:
SSL_CTX_set_new_pending_conn_cb ? 4_0_0 EXIST::FUNCTION:
-SSL_client_hello_isv2 ? 4_0_0 EXIST::FUNCTION:
+SSL_client_hello_isv2 ? 4_0_0 EXIST::FUNCTION:DEPRECATEDIN_4_0
SSL_client_hello_get0_legacy_version ? 4_0_0 EXIST::FUNCTION:
SSL_client_hello_get0_random ? 4_0_0 EXIST::FUNCTION:
SSL_client_hello_get0_session_id ? 4_0_0 EXIST::FUNCTION: