openssl/openssl-1.0.0-beta4-dtls-reneg.patch
Tomáš Mráz 2d6ef07fa3 - upstream fix compression handling on session resumption
- various null checks and other small fixes from upstream
- upstream changes for the renegotiation info according to the latest draft
2010-01-07 22:43:57 +00:00

572 lines
16 KiB
Diff

diff -up openssl-1.0.0-beta4/ssl/d1_both.c.dtls-reneg openssl-1.0.0-beta4/ssl/d1_both.c
--- openssl-1.0.0-beta4/ssl/d1_both.c.dtls-reneg 2009-11-02 14:37:17.000000000 +0100
+++ openssl-1.0.0-beta4/ssl/d1_both.c 2010-01-07 17:35:19.000000000 +0100
@@ -764,6 +764,24 @@ int dtls1_send_finished(SSL *s, int a, i
p+=i;
l=i;
+ /* Copy the finished so we can use it for
+ * renegotiation checks
+ */
+ if(s->type == SSL_ST_CONNECT)
+ {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished,
+ s->s3->tmp.finish_md, i);
+ s->s3->previous_client_finished_len=i;
+ }
+ else
+ {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished,
+ s->s3->tmp.finish_md, i);
+ s->s3->previous_server_finished_len=i;
+ }
+
#ifdef OPENSSL_SYS_WIN16
/* MSVC 1.5 does not clear the top bytes of the word unless
* I do this.
diff -up openssl-1.0.0-beta4/ssl/d1_clnt.c.dtls-reneg openssl-1.0.0-beta4/ssl/d1_clnt.c
--- openssl-1.0.0-beta4/ssl/d1_clnt.c.dtls-reneg 2009-07-24 13:52:32.000000000 +0200
+++ openssl-1.0.0-beta4/ssl/d1_clnt.c 2010-01-07 17:44:55.000000000 +0100
@@ -286,16 +286,44 @@ int dtls1_connect(SSL *s)
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+ ret=ssl3_check_finished(s);
+ if (ret <= 0) goto end;
+ if (ret == 2)
+ {
+ s->hit = 1;
+ if (s->tlsext_ticket_expected)
+ s->state=SSL3_ST_CR_SESSION_TICKET_A;
+ else
+ s->state=SSL3_ST_CR_FINISHED_A;
+ s->init_num=0;
+ break;
+ }
+#endif
/* Check if it is anon DH or PSK */
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
!(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_status_expected)
+ s->state=SSL3_ST_CR_CERT_STATUS_A;
+ else
+ s->state=SSL3_ST_CR_KEY_EXCH_A;
+ }
+ else
+ {
+ skip = 1;
+ s->state=SSL3_ST_CR_KEY_EXCH_A;
+ }
+#else
}
else
skip=1;
+
s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
s->init_num=0;
break;
@@ -437,11 +465,36 @@ int dtls1_connect(SSL *s)
}
else
{
+#ifndef OPENSSL_NO_TLSEXT
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected)
+ s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+ else
+#endif
+
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
}
s->init_num=0;
break;
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_CR_SESSION_TICKET_A:
+ case SSL3_ST_CR_SESSION_TICKET_B:
+ ret=ssl3_get_new_session_ticket(s);
+ if (ret <= 0) goto end;
+ s->state=SSL3_ST_CR_FINISHED_A;
+ s->init_num=0;
+ break;
+
+ case SSL3_ST_CR_CERT_STATUS_A:
+ case SSL3_ST_CR_CERT_STATUS_B:
+ ret=ssl3_get_cert_status(s);
+ if (ret <= 0) goto end;
+ s->state=SSL3_ST_CR_KEY_EXCH_A;
+ s->init_num=0;
+ break;
+#endif
+
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
s->d1->change_cipher_spec_ok = 1;
@@ -554,8 +607,14 @@ int dtls1_client_hello(SSL *s)
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
{
+ SSL_SESSION *sess = s->session;
if ((s->session == NULL) ||
(s->session->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+ !sess->session_id_length ||
+#else
+ (!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
(s->session->not_resumable))
{
if (!ssl_get_new_session(s,0))
@@ -635,7 +694,15 @@ int dtls1_client_hello(SSL *s)
*(p++)=comp->id;
}
*(p++)=0; /* Add the NULL method */
-
+
+#ifndef OPENSSL_NO_TLSEXT
+ if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ {
+ SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+#endif
+
l=(p-d);
d=buf;
diff -up openssl-1.0.0-beta4/ssl/d1_lib.c.dtls-reneg openssl-1.0.0-beta4/ssl/d1_lib.c
diff -up openssl-1.0.0-beta4/ssl/d1_srvr.c.dtls-reneg openssl-1.0.0-beta4/ssl/d1_srvr.c
--- openssl-1.0.0-beta4/ssl/d1_srvr.c.dtls-reneg 2009-09-09 19:05:42.000000000 +0200
+++ openssl-1.0.0-beta4/ssl/d1_srvr.c 2010-01-07 17:44:55.000000000 +0100
@@ -305,8 +305,18 @@ int dtls1_accept(SSL *s)
ret=dtls1_send_server_hello(s);
if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
if (s->hit)
- s->state=SSL3_ST_SW_CHANGE_A;
+ {
+ if (s->tlsext_ticket_expected)
+ s->state=SSL3_ST_SW_SESSION_TICKET_A;
+ else
+ s->state=SSL3_ST_SW_CHANGE_A;
+ }
+#else
+ if (s->hit)
+ s->state=SSL3_ST_SW_CHANGE_A;
+#endif
else
s->state=SSL3_ST_SW_CERT_A;
s->init_num=0;
@@ -321,10 +331,24 @@ int dtls1_accept(SSL *s)
dtls1_start_timer(s);
ret=dtls1_send_server_certificate(s);
if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_status_expected)
+ s->state=SSL3_ST_SW_CERT_STATUS_A;
+ else
+ s->state=SSL3_ST_SW_KEY_EXCH_A;
+ }
+ else
+ {
+ skip = 1;
+ s->state=SSL3_ST_SW_KEY_EXCH_A;
+ }
+#else
}
else
skip=1;
+
s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
s->init_num=0;
break;
@@ -519,11 +543,34 @@ int dtls1_accept(SSL *s)
dtls1_stop_timer(s);
if (s->hit)
s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (s->tlsext_ticket_expected)
+ s->state=SSL3_ST_SW_SESSION_TICKET_A;
+#endif
else
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_SW_SESSION_TICKET_A:
+ case SSL3_ST_SW_SESSION_TICKET_B:
+ ret=dtls1_send_newsession_ticket(s);
+ if (ret <= 0) goto end;
+ s->state=SSL3_ST_SW_CHANGE_A;
+ s->init_num=0;
+ break;
+
+ case SSL3_ST_SW_CERT_STATUS_A:
+ case SSL3_ST_SW_CERT_STATUS_B:
+ ret=ssl3_send_cert_status(s);
+ if (ret <= 0) goto end;
+ s->state=SSL3_ST_SW_KEY_EXCH_A;
+ s->init_num=0;
+ break;
+
+#endif
+
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
@@ -749,6 +796,8 @@ int dtls1_send_server_hello(SSL *s)
p+=sl;
/* put the cipher */
+ if (s->s3->tmp.new_cipher == NULL)
+ return -1;
i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
p+=i;
@@ -762,6 +811,14 @@ int dtls1_send_server_hello(SSL *s)
*(p++)=s->s3->tmp.new_compression->id;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+#endif
+
/* do the header */
l=(p-d);
d=buf;
@@ -1384,3 +1441,114 @@ int dtls1_send_server_certificate(SSL *s
/* SSL3_ST_SW_CERT_B */
return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
}
+
+#ifndef OPENSSL_NO_TLSEXT
+int dtls1_send_newsession_ticket(SSL *s)
+ {
+ if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+ {
+ unsigned char *p, *senc, *macstart;
+ int len, slen;
+ unsigned int hlen, msg_len;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+ SSL_CTX *tctx = s->initial_ctx;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char key_name[16];
+
+ /* get session encoding length */
+ slen = i2d_SSL_SESSION(s->session, NULL);
+ /* Some length values are 16 bits, so forget it if session is
+ * too long
+ */
+ if (slen > 0xFF00)
+ return -1;
+ /* Grow buffer if need be: the length calculation is as
+ * follows 12 (DTLS handshake message header) +
+ * 4 (ticket lifetime hint) + 2 (ticket length) +
+ * 16 (key name) + max_iv_len (iv length) +
+ * session_length + max_enc_block_size (max encrypted session
+ * length) + max_md_size (HMAC).
+ */
+ if (!BUF_MEM_grow(s->init_buf,
+ DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH +
+ EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
+ return -1;
+ senc = OPENSSL_malloc(slen);
+ if (!senc)
+ return -1;
+ p = senc;
+ i2d_SSL_SESSION(s->session, &p);
+
+ p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]);
+ EVP_CIPHER_CTX_init(&ctx);
+ HMAC_CTX_init(&hctx);
+ /* Initialize HMAC and cipher contexts. If callback present
+ * it does all the work otherwise use generated values
+ * from parent ctx.
+ */
+ if (tctx->tlsext_ticket_key_cb)
+ {
+ if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+ &hctx, 1) < 0)
+ {
+ OPENSSL_free(senc);
+ return -1;
+ }
+ }
+ else
+ {
+ RAND_pseudo_bytes(iv, 16);
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key, iv);
+ HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+ tlsext_tick_md(), NULL);
+ memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ }
+ l2n(s->session->tlsext_tick_lifetime_hint, p);
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, key_name, 16);
+ p += 16;
+ /* output IV */
+ memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+ p += EVP_CIPHER_CTX_iv_length(&ctx);
+ /* Encrypt session data */
+ EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+ p += len;
+ EVP_EncryptFinal(&ctx, p, &len);
+ p += len;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ HMAC_Update(&hctx, macstart, p - macstart);
+ HMAC_Final(&hctx, p, &hlen);
+ HMAC_CTX_cleanup(&hctx);
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data written */
+ /* Total length */
+ len = p - (unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]);
+ p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4;
+ s2n(len - 18, p); /* Ticket length */
+
+ /* number of bytes to write */
+ s->init_num= len;
+ s->state=SSL3_ST_SW_SESSION_TICKET_B;
+ s->init_off=0;
+ OPENSSL_free(senc);
+
+ /* XDTLS: set message header ? */
+ msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
+ dtls1_set_message_header(s, (void *)s->init_buf->data,
+ SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len);
+
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 0);
+ }
+
+ /* SSL3_ST_SW_SESSION_TICKET_B */
+ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+ }
+#endif
diff -up openssl-1.0.0-beta4/ssl/ssl_locl.h.dtls-reneg openssl-1.0.0-beta4/ssl/ssl_locl.h
--- openssl-1.0.0-beta4/ssl/ssl_locl.h.dtls-reneg 2009-11-23 08:36:03.000000000 +0100
+++ openssl-1.0.0-beta4/ssl/ssl_locl.h 2010-01-07 17:44:55.000000000 +0100
@@ -933,7 +933,7 @@ void dtls1_start_timer(SSL *s);
void dtls1_stop_timer(SSL *s);
int dtls1_is_timer_expired(SSL *s);
void dtls1_double_timeout(SSL *s);
-
+int dtls1_send_newsession_ticket(SSL *s);
/* some client-only functions */
int ssl3_client_hello(SSL *s);
@@ -949,6 +949,9 @@ int ssl3_send_client_key_exchange(SSL *s
int ssl3_get_key_exchange(SSL *s);
int ssl3_get_server_certificate(SSL *s);
int ssl3_check_cert_and_algorithm(SSL *s);
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_check_finished(SSL *s);
+#endif
int dtls1_client_hello(SSL *s);
int dtls1_send_client_certificate(SSL *s);
@@ -1030,6 +1033,7 @@ int ssl_prepare_clienthello_tlsext(SSL *
int ssl_prepare_serverhello_tlsext(SSL *s);
int ssl_check_clienthello_tlsext(SSL *s);
int ssl_check_serverhello_tlsext(SSL *s);
+
#ifdef OPENSSL_NO_SHA256
#define tlsext_tick_md EVP_sha1
#else
diff -up openssl-1.0.0-beta4/ssl/s3_clnt.c.dtls-reneg openssl-1.0.0-beta4/ssl/s3_clnt.c
--- openssl-1.0.0-beta4/ssl/s3_clnt.c.dtls-reneg 2009-11-23 08:36:04.000000000 +0100
+++ openssl-1.0.0-beta4/ssl/s3_clnt.c 2010-01-07 17:44:55.000000000 +0100
@@ -170,9 +170,6 @@
static const SSL_METHOD *ssl3_get_client_method(int ver);
static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
-#ifndef OPENSSL_NO_TLSEXT
-static int ssl3_check_finished(SSL *s);
-#endif
static const SSL_METHOD *ssl3_get_client_method(int ver)
{
@@ -1827,6 +1824,7 @@ int ssl3_get_new_session_ticket(SSL *s)
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
+
p=d=(unsigned char *)s->init_msg;
n2l(p, s->session->tlsext_tick_lifetime_hint);
n2s(p, ticklen);
@@ -2991,7 +2989,7 @@ err:
*/
#ifndef OPENSSL_NO_TLSEXT
-static int ssl3_check_finished(SSL *s)
+int ssl3_check_finished(SSL *s)
{
int ok;
long n;
diff -up openssl-1.0.0-beta4/ssl/t1_lib.c.dtls-reneg openssl-1.0.0-beta4/ssl/t1_lib.c
--- openssl-1.0.0-beta4/ssl/t1_lib.c.dtls-reneg 2009-11-23 08:36:04.000000000 +0100
+++ openssl-1.0.0-beta4/ssl/t1_lib.c 2010-01-07 17:44:55.000000000 +0100
@@ -340,7 +340,8 @@ unsigned char *ssl_add_clienthello_tlsex
}
#ifndef OPENSSL_NO_EC
- if (s->tlsext_ecpointformatlist != NULL)
+ if (s->tlsext_ecpointformatlist != NULL &&
+ s->version != DTLS1_VERSION)
{
/* Add TLS extension ECPointFormats to the ClientHello message */
long lenmax;
@@ -359,7 +360,8 @@ unsigned char *ssl_add_clienthello_tlsex
memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
ret+=s->tlsext_ecpointformatlist_length;
}
- if (s->tlsext_ellipticcurvelist != NULL)
+ if (s->tlsext_ellipticcurvelist != NULL &&
+ s->version != DTLS1_VERSION)
{
/* Add TLS extension EllipticCurves to the ClientHello message */
long lenmax;
@@ -423,7 +425,8 @@ unsigned char *ssl_add_clienthello_tlsex
skip_ext:
#ifdef TLSEXT_TYPE_opaque_prf_input
- if (s->s3->client_opaque_prf_input != NULL)
+ if (s->s3->client_opaque_prf_input != NULL &&
+ s->version != DTLS1_VERSION)
{
size_t col = s->s3->client_opaque_prf_input_len;
@@ -440,7 +443,8 @@ unsigned char *ssl_add_clienthello_tlsex
}
#endif
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
+ s->version != DTLS1_VERSION)
{
int i;
long extlen, idlen, itmp;
@@ -515,7 +519,7 @@ unsigned char *ssl_add_serverhello_tlsex
s2n(0,ret);
}
- if(s->s3->send_connection_binding)
+ if(s->s3->send_connection_binding)
{
int el;
@@ -540,7 +544,8 @@ unsigned char *ssl_add_serverhello_tlsex
}
#ifndef OPENSSL_NO_EC
- if (s->tlsext_ecpointformatlist != NULL)
+ if (s->tlsext_ecpointformatlist != NULL &&
+ s->version != DTLS1_VERSION)
{
/* Add TLS extension ECPointFormats to the ServerHello message */
long lenmax;
@@ -579,7 +584,8 @@ unsigned char *ssl_add_serverhello_tlsex
}
#ifdef TLSEXT_TYPE_opaque_prf_input
- if (s->s3->server_opaque_prf_input != NULL)
+ if (s->s3->server_opaque_prf_input != NULL &&
+ s->version != DTLS1_VERSION)
{
size_t sol = s->s3->server_opaque_prf_input_len;
@@ -757,7 +763,8 @@ int ssl_parse_clienthello_tlsext(SSL *s,
}
#ifndef OPENSSL_NO_EC
- else if (type == TLSEXT_TYPE_ec_point_formats)
+ else if (type == TLSEXT_TYPE_ec_point_formats &&
+ s->version != DTLS1_VERSION)
{
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
@@ -784,7 +791,8 @@ int ssl_parse_clienthello_tlsext(SSL *s,
fprintf(stderr,"\n");
#endif
}
- else if (type == TLSEXT_TYPE_elliptic_curves)
+ else if (type == TLSEXT_TYPE_elliptic_curves &&
+ s->version != DTLS1_VERSION)
{
unsigned char *sdata = data;
int ellipticcurvelist_length = (*(sdata++) << 8);
@@ -814,7 +822,8 @@ int ssl_parse_clienthello_tlsext(SSL *s,
}
#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_opaque_prf_input
- else if (type == TLSEXT_TYPE_opaque_prf_input)
+ else if (type == TLSEXT_TYPE_opaque_prf_input &&
+ s->version != DTLS1_VERSION)
{
unsigned char *sdata = data;
@@ -858,8 +867,8 @@ int ssl_parse_clienthello_tlsext(SSL *s,
return 0;
renegotiate_seen = 1;
}
- else if (type == TLSEXT_TYPE_status_request
- && s->ctx->tlsext_status_cb)
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
{
if (size < 5)
@@ -1027,7 +1036,8 @@ int ssl_parse_serverhello_tlsext(SSL *s,
}
#ifndef OPENSSL_NO_EC
- else if (type == TLSEXT_TYPE_ec_point_formats)
+ else if (type == TLSEXT_TYPE_ec_point_formats &&
+ s->version != DTLS1_VERSION)
{
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
@@ -1073,7 +1083,8 @@ int ssl_parse_serverhello_tlsext(SSL *s,
s->tlsext_ticket_expected = 1;
}
#ifdef TLSEXT_TYPE_opaque_prf_input
- else if (type == TLSEXT_TYPE_opaque_prf_input)
+ else if (type == TLSEXT_TYPE_opaque_prf_input &&
+ s->version != DTLS1_VERSION)
{
unsigned char *sdata = data;
@@ -1103,7 +1114,8 @@ int ssl_parse_serverhello_tlsext(SSL *s,
}
}
#endif
- else if (type == TLSEXT_TYPE_status_request)
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION)
{
/* MUST be empty and only sent if we've requested
* a status request message.