Dual DTLS version methods.
Add new methods DTLS_*_method() which support both DTLS 1.0 and DTLS 1.2 and
pick the highest version the peer supports during negotiation.
As with SSL/TLS options can change this behaviour specifically
SSL_OP_NO_DTLSv1 and SSL_OP_NO_DTLSv1_2.
(cherry picked from commit c6913eeb76
)
Conflicts:
CHANGES
This commit is contained in:
parent
b60b9e7afe
commit
65a87d3cc3
@ -912,6 +912,11 @@ static char *jpake_secret = NULL;
|
|||||||
meth=TLSv1_client_method();
|
meth=TLSv1_client_method();
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_DTLS1
|
#ifndef OPENSSL_NO_DTLS1
|
||||||
|
else if (strcmp(*argv,"-dtls") == 0)
|
||||||
|
{
|
||||||
|
meth=DTLS_client_method();
|
||||||
|
socket_type=SOCK_DGRAM;
|
||||||
|
}
|
||||||
else if (strcmp(*argv,"-dtls1") == 0)
|
else if (strcmp(*argv,"-dtls1") == 0)
|
||||||
{
|
{
|
||||||
meth=DTLSv1_client_method();
|
meth=DTLSv1_client_method();
|
||||||
|
@ -1369,6 +1369,11 @@ int MAIN(int argc, char *argv[])
|
|||||||
{ meth=TLSv1_2_server_method(); }
|
{ meth=TLSv1_2_server_method(); }
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_DTLS1
|
#ifndef OPENSSL_NO_DTLS1
|
||||||
|
else if (strcmp(*argv,"-dtls") == 0)
|
||||||
|
{
|
||||||
|
meth=DTLS_server_method();
|
||||||
|
socket_type = SOCK_DGRAM;
|
||||||
|
}
|
||||||
else if (strcmp(*argv,"-dtls1") == 0)
|
else if (strcmp(*argv,"-dtls1") == 0)
|
||||||
{
|
{
|
||||||
meth=DTLSv1_server_method();
|
meth=DTLSv1_server_method();
|
||||||
|
@ -155,6 +155,13 @@ IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
|
|||||||
dtls1_get_client_method,
|
dtls1_get_client_method,
|
||||||
DTLSv1_2_enc_data)
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
|
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
|
||||||
|
DTLS_client_method,
|
||||||
|
ssl_undefined_function,
|
||||||
|
dtls1_connect,
|
||||||
|
dtls1_get_client_method,
|
||||||
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
int dtls1_connect(SSL *s)
|
int dtls1_connect(SSL *s)
|
||||||
{
|
{
|
||||||
BUF_MEM *buf=NULL;
|
BUF_MEM *buf=NULL;
|
||||||
@ -785,12 +792,14 @@ static int dtls1_get_hello_verify(SSL *s)
|
|||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
unsigned int cookie_len;
|
unsigned int cookie_len;
|
||||||
|
|
||||||
|
s->first_packet = 1;
|
||||||
n=s->method->ssl_get_message(s,
|
n=s->method->ssl_get_message(s,
|
||||||
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
|
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
|
||||||
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B,
|
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B,
|
||||||
-1,
|
-1,
|
||||||
s->max_cert_list,
|
s->max_cert_list,
|
||||||
&ok);
|
&ok);
|
||||||
|
s->first_packet = 0;
|
||||||
|
|
||||||
if (!ok) return((int)n);
|
if (!ok) return((int)n);
|
||||||
|
|
||||||
@ -802,14 +811,16 @@ static int dtls1_get_hello_verify(SSL *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = (unsigned char *)s->init_msg;
|
data = (unsigned char *)s->init_msg;
|
||||||
|
#if 0
|
||||||
if ((data[0] != (s->version>>8)) || (data[1] != (s->version&0xff)))
|
if (s->method->version != DTLS_ANY_VERSION &&
|
||||||
|
((data[0] != (s->version>>8)) || (data[1] != (s->version&0xff))))
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY,SSL_R_WRONG_SSL_VERSION);
|
SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY,SSL_R_WRONG_SSL_VERSION);
|
||||||
s->version=(s->version&0xff00)|data[1];
|
s->version=(s->version&0xff00)|data[1];
|
||||||
al = SSL_AD_PROTOCOL_VERSION;
|
al = SSL_AD_PROTOCOL_VERSION;
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
data+=2;
|
data+=2;
|
||||||
|
|
||||||
cookie_len = *(data++);
|
cookie_len = *(data++);
|
||||||
|
@ -267,6 +267,8 @@ void dtls1_clear(SSL *s)
|
|||||||
ssl3_clear(s);
|
ssl3_clear(s);
|
||||||
if (s->options & SSL_OP_CISCO_ANYCONNECT)
|
if (s->options & SSL_OP_CISCO_ANYCONNECT)
|
||||||
s->version=DTLS1_BAD_VER;
|
s->version=DTLS1_BAD_VER;
|
||||||
|
else if (s->method->version == DTLS_ANY_VERSION)
|
||||||
|
s->version=DTLS1_2_VERSION;
|
||||||
else
|
else
|
||||||
s->version=s->method->version;
|
s->version=s->method->version;
|
||||||
}
|
}
|
||||||
@ -522,5 +524,3 @@ static int dtls1_handshake_write(SSL *s)
|
|||||||
{
|
{
|
||||||
return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
|
return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,3 +86,10 @@ IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
|
|||||||
dtls1_get_method,
|
dtls1_get_method,
|
||||||
DTLSv1_2_enc_data)
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
|
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
|
||||||
|
DTLS_method,
|
||||||
|
dtls1_accept,
|
||||||
|
dtls1_connect,
|
||||||
|
dtls1_get_method,
|
||||||
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
|
19
ssl/d1_pkt.c
19
ssl/d1_pkt.c
@ -1552,9 +1552,22 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
|
|||||||
|
|
||||||
*(p++)=type&0xff;
|
*(p++)=type&0xff;
|
||||||
wr->type=type;
|
wr->type=type;
|
||||||
|
/* Special case: for hello verify request, client version 1.0 and
|
||||||
*(p++)=(s->version>>8);
|
* we haven't decided which version to use yet send back using
|
||||||
*(p++)=s->version&0xff;
|
* version 1.0 header: otherwise some clients will ignore it.
|
||||||
|
*/
|
||||||
|
if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B
|
||||||
|
&& s->method->version == DTLS_ANY_VERSION
|
||||||
|
&& s->client_version == DTLS1_VERSION)
|
||||||
|
{
|
||||||
|
*(p++)=DTLS1_VERSION>>8;
|
||||||
|
*(p++)=DTLS1_VERSION&0xff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(p++)=s->version>>8;
|
||||||
|
*(p++)=s->version&0xff;
|
||||||
|
}
|
||||||
|
|
||||||
/* field where we are to write out packet epoch, seq num and len */
|
/* field where we are to write out packet epoch, seq num and len */
|
||||||
pseq=p;
|
pseq=p;
|
||||||
|
@ -153,6 +153,13 @@ IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
|
|||||||
dtls1_get_server_method,
|
dtls1_get_server_method,
|
||||||
DTLSv1_2_enc_data)
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
|
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
|
||||||
|
DTLS_server_method,
|
||||||
|
dtls1_accept,
|
||||||
|
ssl_undefined_function,
|
||||||
|
dtls1_get_server_method,
|
||||||
|
DTLSv1_2_enc_data)
|
||||||
|
|
||||||
int dtls1_accept(SSL *s)
|
int dtls1_accept(SSL *s)
|
||||||
{
|
{
|
||||||
BUF_MEM *buf;
|
BUF_MEM *buf;
|
||||||
@ -885,8 +892,9 @@ int dtls1_send_hello_verify_request(SSL *s)
|
|||||||
buf = (unsigned char *)s->init_buf->data;
|
buf = (unsigned char *)s->init_buf->data;
|
||||||
|
|
||||||
msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
|
msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
|
||||||
*(p++) = s->version >> 8;
|
/* Always use DTLS 1.0 version: see RFC 6347 */
|
||||||
*(p++) = s->version & 0xFF;
|
*(p++) = DTLS1_VERSION >> 8;
|
||||||
|
*(p++) = DTLS1_VERSION & 0xFF;
|
||||||
|
|
||||||
if (s->ctx->app_gen_cookie_cb == NULL ||
|
if (s->ctx->app_gen_cookie_cb == NULL ||
|
||||||
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
|
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
|
||||||
|
@ -86,6 +86,8 @@ extern "C" {
|
|||||||
#define DTLS1_VERSION 0xFEFF
|
#define DTLS1_VERSION 0xFEFF
|
||||||
#define DTLS1_BAD_VER 0x0100
|
#define DTLS1_BAD_VER 0x0100
|
||||||
#define DTLS1_2_VERSION 0xFEFD
|
#define DTLS1_2_VERSION 0xFEFD
|
||||||
|
/* Special value for method supporting multiple versions */
|
||||||
|
#define DTLS_ANY_VERSION 0x1FFFF
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* this alert description is not specified anywhere... */
|
/* this alert description is not specified anywhere... */
|
||||||
|
@ -694,6 +694,36 @@ int ssl3_client_hello(SSL *s)
|
|||||||
if (!ssl_get_new_session(s,0))
|
if (!ssl_get_new_session(s,0))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (s->method->version == DTLS_ANY_VERSION)
|
||||||
|
{
|
||||||
|
/* Determine which DTLS version to use */
|
||||||
|
int options = s->options;
|
||||||
|
/* If DTLS 1.2 disabled correct the version number */
|
||||||
|
if (options & SSL_OP_NO_DTLSv1_2)
|
||||||
|
{
|
||||||
|
/* Disabling all versions is silly: return an
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
if (options & SSL_OP_NO_DTLSv1)
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_WRONG_SSL_VERSION);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Update method so we don't use any DTLS 1.2
|
||||||
|
* features.
|
||||||
|
*/
|
||||||
|
s->method = DTLSv1_client_method();
|
||||||
|
s->version = DTLS1_VERSION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We only support one version: update method */
|
||||||
|
if (options & SSL_OP_NO_DTLSv1)
|
||||||
|
s->method = DTLSv1_2_client_method();
|
||||||
|
s->version = DTLS1_2_VERSION;
|
||||||
|
}
|
||||||
|
s->client_version = s->version;
|
||||||
|
}
|
||||||
/* else use the pre-loaded session */
|
/* else use the pre-loaded session */
|
||||||
|
|
||||||
p=s->s3->client_random;
|
p=s->s3->client_random;
|
||||||
@ -721,6 +751,7 @@ int ssl3_client_hello(SSL *s)
|
|||||||
Time=(unsigned long)time(NULL); /* Time */
|
Time=(unsigned long)time(NULL); /* Time */
|
||||||
l2n(Time,p);
|
l2n(Time,p);
|
||||||
RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
|
RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the message type and length last */
|
/* Do the message type and length last */
|
||||||
@ -873,6 +904,11 @@ int ssl3_get_server_hello(SSL *s)
|
|||||||
#ifndef OPENSSL_NO_COMP
|
#ifndef OPENSSL_NO_COMP
|
||||||
SSL_COMP *comp;
|
SSL_COMP *comp;
|
||||||
#endif
|
#endif
|
||||||
|
/* Hello verify request and/or server hello version may not
|
||||||
|
* match so set first packet if we're negotiating version.
|
||||||
|
*/
|
||||||
|
if (s->method->version == DTLS_ANY_VERSION)
|
||||||
|
s->first_packet = 1;
|
||||||
|
|
||||||
n=s->method->ssl_get_message(s,
|
n=s->method->ssl_get_message(s,
|
||||||
SSL3_ST_CR_SRVR_HELLO_A,
|
SSL3_ST_CR_SRVR_HELLO_A,
|
||||||
@ -885,6 +921,7 @@ int ssl3_get_server_hello(SSL *s)
|
|||||||
|
|
||||||
if (SSL_IS_DTLS(s))
|
if (SSL_IS_DTLS(s))
|
||||||
{
|
{
|
||||||
|
s->first_packet = 0;
|
||||||
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
|
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
|
||||||
{
|
{
|
||||||
if ( s->d1->send_cookie == 0)
|
if ( s->d1->send_cookie == 0)
|
||||||
@ -909,6 +946,21 @@ int ssl3_get_server_hello(SSL *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d=p=(unsigned char *)s->init_msg;
|
d=p=(unsigned char *)s->init_msg;
|
||||||
|
if (s->method->version == DTLS_ANY_VERSION)
|
||||||
|
{
|
||||||
|
/* Work out correct protocol version to use */
|
||||||
|
int hversion = (p[0] << 8)|p[1];
|
||||||
|
int options = s->options;
|
||||||
|
if (hversion == DTLS1_2_VERSION
|
||||||
|
&& !(options & SSL_OP_NO_DTLSv1_2))
|
||||||
|
s->method = DTLSv1_2_client_method();
|
||||||
|
else if (hversion == DTLS1_VERSION
|
||||||
|
&& !(options & SSL_OP_NO_DTLSv1))
|
||||||
|
s->method = DTLSv1_client_method();
|
||||||
|
else
|
||||||
|
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
|
||||||
|
s->version = s->client_version = s->method->version;
|
||||||
|
}
|
||||||
|
|
||||||
if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
|
if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
|
||||||
{
|
{
|
||||||
|
@ -968,8 +968,9 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
s->client_version=(((int)p[0])<<8)|(int)p[1];
|
s->client_version=(((int)p[0])<<8)|(int)p[1];
|
||||||
p+=2;
|
p+=2;
|
||||||
|
|
||||||
if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
|
if ((SSL_IS_DTLS(s) && s->client_version > s->version
|
||||||
(s->version != DTLS1_VERSION && s->client_version < s->version))
|
&& s->method->version != DTLS_ANY_VERSION) ||
|
||||||
|
(!SSL_IS_DTLS(s) && s->client_version < s->version))
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
|
||||||
if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
|
if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
|
||||||
@ -1087,6 +1088,30 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p += cookie_len;
|
p += cookie_len;
|
||||||
|
if (s->method->version == DTLS_ANY_VERSION)
|
||||||
|
{
|
||||||
|
/* Select version to use */
|
||||||
|
if (s->client_version <= DTLS1_2_VERSION &&
|
||||||
|
!(s->options & SSL_OP_NO_DTLSv1_2))
|
||||||
|
{
|
||||||
|
s->version = DTLS1_2_VERSION;
|
||||||
|
s->method = DTLSv1_2_server_method();
|
||||||
|
}
|
||||||
|
else if (s->client_version <= DTLS1_VERSION &&
|
||||||
|
!(s->options & SSL_OP_NO_DTLSv1))
|
||||||
|
{
|
||||||
|
s->version = DTLS1_VERSION;
|
||||||
|
s->method = DTLSv1_server_method();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
|
||||||
|
s->version = s->client_version;
|
||||||
|
al = SSL_AD_PROTOCOL_VERSION;
|
||||||
|
goto f_err;
|
||||||
|
}
|
||||||
|
s->session->ssl_version = s->version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n2s(p,i);
|
n2s(p,i);
|
||||||
|
@ -668,6 +668,9 @@ struct ssl_session_st
|
|||||||
#define SSL_OP_NO_TLSv1_2 0x08000000L
|
#define SSL_OP_NO_TLSv1_2 0x08000000L
|
||||||
#define SSL_OP_NO_TLSv1_1 0x10000000L
|
#define SSL_OP_NO_TLSv1_1 0x10000000L
|
||||||
|
|
||||||
|
#define SSL_OP_NO_DTLSv1 0x04000000L
|
||||||
|
#define SSL_OP_NO_DTLSv1_2 0x08000000L
|
||||||
|
|
||||||
#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\
|
#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\
|
||||||
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
|
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
|
||||||
|
|
||||||
@ -2209,6 +2212,10 @@ const SSL_METHOD *DTLSv1_2_method(void); /* DTLSv1.2 */
|
|||||||
const SSL_METHOD *DTLSv1_2_server_method(void); /* DTLSv1.2 */
|
const SSL_METHOD *DTLSv1_2_server_method(void); /* DTLSv1.2 */
|
||||||
const SSL_METHOD *DTLSv1_2_client_method(void); /* DTLSv1.2 */
|
const SSL_METHOD *DTLSv1_2_client_method(void); /* DTLSv1.2 */
|
||||||
|
|
||||||
|
const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
|
||||||
|
const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
|
||||||
|
const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */
|
||||||
|
|
||||||
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
|
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
|
||||||
|
|
||||||
int SSL_do_handshake(SSL *s);
|
int SSL_do_handshake(SSL *s);
|
||||||
|
Loading…
Reference in New Issue
Block a user