aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2012-06-27 16:44:58 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2012-06-27 16:44:58 +0000
commit2b8b5455829304396e38200c205612c4dc57c052 (patch)
treecc5cd6657453d80b7eafb3ba5cc4ef4fd66c176f /ssl
parentfd3744ddb062b70bb370acec340acbac23f0bd98 (diff)
downloadsrc-2b8b5455829304396e38200c205612c4dc57c052.tar.gz
src-2b8b5455829304396e38200c205612c4dc57c052.zip
Import OpenSSL 0.9.8x.vendor/openssl/0.9.8x
Notes
Notes: svn path=/vendor-crypto/openssl/dist/; revision=237653 svn path=/vendor-crypto/openssl/0.9.8x/; revision=237654; tag=vendor/openssl/0.9.8x
Diffstat (limited to 'ssl')
-rw-r--r--ssl/bio_ssl.c4
-rw-r--r--ssl/d1_both.c55
-rw-r--r--ssl/d1_clnt.c8
-rw-r--r--ssl/d1_enc.c8
-rw-r--r--ssl/d1_lib.c130
-rw-r--r--ssl/d1_pkt.c58
-rw-r--r--ssl/d1_srvr.c32
-rw-r--r--ssl/s2_srvr.c5
-rw-r--r--ssl/s3_clnt.c6
-rw-r--r--ssl/s3_enc.c3
-rw-r--r--ssl/s3_lib.c7
-rw-r--r--ssl/s3_srvr.c33
-rw-r--r--ssl/ssl.h3
-rw-r--r--ssl/ssl3.h11
-rw-r--r--ssl/ssl_ciph.c1
-rw-r--r--ssl/ssl_err.c5
-rw-r--r--ssl/ssl_lib.c5
-rw-r--r--ssl/ssl_locl.h2
-rw-r--r--ssl/t1_lib.c14
19 files changed, 279 insertions, 111 deletions
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
index 420deb7fc966..f0a031c71d6b 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -348,7 +348,11 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_C_SET_SSL:
if (ssl != NULL)
+ {
ssl_free(b);
+ if (!ssl_new(b))
+ return 0;
+ }
b->shutdown=(int)num;
ssl=(SSL *)ptr;
((BIO_SSL *)b->ptr)->ssl=ssl;
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 920fb1ff2493..4481c5505112 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -153,12 +153,11 @@
#endif
static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
-static unsigned char bitmask_end_values[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
+static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
/* XDTLS: figure out the right values */
static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
-static unsigned int dtls1_min_mtu(void);
static unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
unsigned long frag_len);
@@ -228,14 +227,14 @@ int dtls1_do_write(SSL *s, int type)
unsigned int len, frag_off, mac_size, blocksize;
/* AHA! Figure out the MTU, and stick to the right size */
- if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
+ if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
{
s->d1->mtu =
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
/* I've seen the kernel return bogus numbers when it doesn't know
* (initial write), so just make sure we have a reasonable number */
- if ( s->d1->mtu < dtls1_min_mtu())
+ if (s->d1->mtu < dtls1_min_mtu())
{
s->d1->mtu = 0;
s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
@@ -264,11 +263,10 @@ int dtls1_do_write(SSL *s, int type)
return ret;
mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
}
-
- OPENSSL_assert(mtu > 0); /* should have something reasonable now */
-
#endif
+ OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */
+
if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
OPENSSL_assert(s->init_num ==
(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
@@ -464,20 +462,9 @@ again:
memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
- s->d1->handshake_read_seq++;
- /* we just read a handshake message from the other side:
- * this means that we don't need to retransmit of the
- * buffered messages.
- * XDTLS: may be able clear out this
- * buffer a little sooner (i.e if an out-of-order
- * handshake message/record is received at the record
- * layer.
- * XDTLS: exception is that the server needs to
- * know that change cipher spec and finished messages
- * have been received by the client before clearing this
- * buffer. this can simply be done by waiting for the
- * first data segment, but is there a better way? */
- dtls1_clear_record_buffer(s);
+ /* Don't change sequence numbers while listening */
+ if (!s->d1->listen)
+ s->d1->handshake_read_seq++;
s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
return s->init_num;
@@ -806,16 +793,24 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
*ok = 0;
return i;
}
- OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);
+ /* Handshake fails if message header is incomplete */
+ if (i != DTLS1_HM_HEADER_LENGTH)
+ {
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
/* parse the message fragment header */
dtls1_get_message_header(wire, &msg_hdr);
/*
* if this is a future (or stale) message it gets buffered
- * (or dropped)--no further processing at this time
+ * (or dropped)--no further processing at this time
+ * While listening, we accept seq 1 (ClientHello with cookie)
+ * although we're still expecting seq 0 (ClientHello)
*/
- if ( msg_hdr.seq != s->d1->handshake_read_seq)
+ if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1))
return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
len = msg_hdr.msg_len;
@@ -876,7 +871,12 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
/* XDTLS: an incorrectly formatted fragment should cause the
* handshake to fail */
- OPENSSL_assert(i == (int)frag_len);
+ if (i != (int)frag_len)
+ {
+ al=SSL3_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER);
+ goto f_err;
+ }
*ok = 1;
@@ -1326,7 +1326,8 @@ unsigned char *
dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
unsigned long len, unsigned long frag_off, unsigned long frag_len)
{
- if ( frag_off == 0)
+ /* Don't change sequence numbers while listening */
+ if (frag_off == 0 && !s->d1->listen)
{
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
s->d1->next_handshake_write_seq++;
@@ -1379,7 +1380,7 @@ dtls1_write_message_header(SSL *s, unsigned char *p)
return p;
}
-static unsigned int
+unsigned int
dtls1_min_mtu(void)
{
return (g_probable_mtu[(sizeof(g_probable_mtu) /
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 0aa77ee51d50..ac24bfb35ed8 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -257,7 +257,6 @@ int dtls1_connect(SSL *s)
if (ret <= 0) goto end;
else
{
- dtls1_stop_timer(s);
if (s->hit)
s->state=SSL3_ST_CR_FINISHED_A;
else
@@ -350,6 +349,7 @@ int dtls1_connect(SSL *s)
case SSL3_ST_CR_SRVR_DONE_B:
ret=ssl3_get_server_done(s);
if (ret <= 0) goto end;
+ dtls1_stop_timer(s);
if (s->s3->tmp.cert_req)
s->state=SSL3_ST_CW_CERT_A;
else
@@ -403,7 +403,8 @@ int dtls1_connect(SSL *s)
case SSL3_ST_CW_CHANGE_A:
case SSL3_ST_CW_CHANGE_B:
- dtls1_start_timer(s);
+ if (!s->hit)
+ dtls1_start_timer(s);
ret=dtls1_send_change_cipher_spec(s,
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
@@ -438,7 +439,8 @@ int dtls1_connect(SSL *s)
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
- dtls1_start_timer(s);
+ if (!s->hit)
+ dtls1_start_timer(s);
ret=dtls1_send_finished(s,
SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
s->method->ssl3_enc->client_finished_label,
diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c
index 4a6c9090314d..baa75f9186b2 100644
--- a/ssl/d1_enc.c
+++ b/ssl/d1_enc.c
@@ -220,11 +220,7 @@ int dtls1_enc(SSL *s, int send)
if (!send)
{
if (l == 0 || l%bs != 0)
- {
- SSLerr(SSL_F_DTLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
- return 0;
- }
+ return -1;
}
EVP_Cipher(ds,rec->data,rec->input,l);
@@ -253,7 +249,7 @@ int dtls1_enc(SSL *s, int send)
}
/* TLS 1.0 does not bound the number of padding bytes by the block size.
* All of them must have value 'padding_length'. */
- if (i > (int)rec->length)
+ if (i + bs > (int)rec->length)
{
/* Incorrect padding. SSLerr() and ssl3_alert are done
* by caller: we don't want to reveal whether this is
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 54e16403e6e5..3d27e3085818 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -145,26 +145,33 @@ int dtls1_new(SSL *s)
return(1);
}
-void dtls1_free(SSL *s)
+static void dtls1_clear_queues(SSL *s)
{
pitem *item = NULL;
hm_fragment *frag = NULL;
-
- ssl3_free(s);
+ DTLS1_RECORD_DATA *rdata;
while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
{
+ rdata = (DTLS1_RECORD_DATA *) item->data;
+ if (rdata->rbuf.buf)
+ {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
OPENSSL_free(item->data);
pitem_free(item);
}
- pqueue_free(s->d1->unprocessed_rcds.q);
while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
{
+ rdata = (DTLS1_RECORD_DATA *) item->data;
+ if (rdata->rbuf.buf)
+ {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
OPENSSL_free(item->data);
pitem_free(item);
}
- pqueue_free(s->d1->processed_rcds.q);
while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
{
@@ -173,7 +180,6 @@ void dtls1_free(SSL *s)
OPENSSL_free(frag);
pitem_free(item);
}
- pqueue_free(s->d1->buffered_messages);
while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
{
@@ -182,15 +188,26 @@ void dtls1_free(SSL *s)
OPENSSL_free(frag);
pitem_free(item);
}
- pqueue_free(s->d1->sent_messages);
while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
- {
+ {
frag = (hm_fragment *)item->data;
OPENSSL_free(frag->fragment);
OPENSSL_free(frag);
pitem_free(item);
+ }
}
+
+void dtls1_free(SSL *s)
+ {
+ ssl3_free(s);
+
+ dtls1_clear_queues(s);
+
+ pqueue_free(s->d1->unprocessed_rcds.q);
+ pqueue_free(s->d1->processed_rcds.q);
+ pqueue_free(s->d1->buffered_messages);
+ pqueue_free(s->d1->sent_messages);
pqueue_free(s->d1->buffered_app_data.q);
pq_64bit_free(&(s->d1->bitmap.map));
@@ -204,6 +221,61 @@ void dtls1_free(SSL *s)
void dtls1_clear(SSL *s)
{
+ pqueue unprocessed_rcds;
+ pqueue processed_rcds;
+ pqueue buffered_messages;
+ pqueue sent_messages;
+ pqueue buffered_app_data;
+ unsigned int mtu;
+
+ if (s->d1)
+ {
+ unprocessed_rcds = s->d1->unprocessed_rcds.q;
+ processed_rcds = s->d1->processed_rcds.q;
+ buffered_messages = s->d1->buffered_messages;
+ sent_messages = s->d1->sent_messages;
+ buffered_app_data = s->d1->buffered_app_data.q;
+ mtu = s->d1->mtu;
+
+ dtls1_clear_queues(s);
+
+ pq_64bit_free(&(s->d1->bitmap.map));
+ pq_64bit_free(&(s->d1->bitmap.max_seq_num));
+
+ pq_64bit_free(&(s->d1->next_bitmap.map));
+ pq_64bit_free(&(s->d1->next_bitmap.max_seq_num));
+
+ memset(s->d1, 0, sizeof(*(s->d1)));
+
+ if (s->server)
+ {
+ s->d1->cookie_len = sizeof(s->d1->cookie);
+ }
+
+ if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
+ {
+ s->d1->mtu = mtu;
+ }
+
+ s->d1->unprocessed_rcds.q = unprocessed_rcds;
+ s->d1->processed_rcds.q = processed_rcds;
+ s->d1->buffered_messages = buffered_messages;
+ s->d1->sent_messages = sent_messages;
+ s->d1->buffered_app_data.q = buffered_app_data;
+
+#if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST)
+ s->d1->bitmap.length=64;
+#else
+ s->d1->bitmap.length=sizeof(s->d1->bitmap.map) * 8;
+#endif
+ pq_64bit_init(&(s->d1->bitmap.map));
+ pq_64bit_init(&(s->d1->bitmap.max_seq_num));
+
+ s->d1->next_bitmap.length = s->d1->bitmap.length;
+ pq_64bit_init(&(s->d1->next_bitmap.map));
+ pq_64bit_init(&(s->d1->next_bitmap.max_seq_num));
+ }
+
ssl3_clear(s);
if (s->options & SSL_OP_CISCO_ANYCONNECT)
s->version=DTLS1_BAD_VER;
@@ -349,35 +421,51 @@ void dtls1_double_timeout(SSL *s)
void dtls1_stop_timer(SSL *s)
{
/* Reset everything */
+ memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
s->d1->timeout_duration = 1;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
+ /* Clear retransmission buffer */
+ dtls1_clear_record_buffer(s);
}
-int dtls1_handle_timeout(SSL *s)
+int dtls1_check_timeout_num(SSL *s)
{
- DTLS1_STATE *state;
+ s->d1->timeout.num_alerts++;
- /* if no timer is expired, don't do anything */
- if (!dtls1_is_timer_expired(s))
+ /* Reduce MTU after 2 unsuccessful retransmissions */
+ if (s->d1->timeout.num_alerts > 2)
{
- return 0;
+ s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
}
- dtls1_double_timeout(s);
- state = s->d1;
- state->timeout.num_alerts++;
- if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
+ if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
{
/* fail the connection, enough alerts have been sent */
- SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
+ SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM,SSL_R_READ_TIMEOUT_EXPIRED);
+ return -1;
+ }
+
+ return 0;
+ }
+
+int dtls1_handle_timeout(SSL *s)
+ {
+ /* if no timer is expired, don't do anything */
+ if (!dtls1_is_timer_expired(s))
+ {
return 0;
}
- state->timeout.read_timeouts++;
- if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
+ dtls1_double_timeout(s);
+
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+
+ s->d1->timeout.read_timeouts++;
+ if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
{
- state->timeout.read_timeouts = 1;
+ s->d1->timeout.read_timeouts = 1;
}
dtls1_start_timer(s);
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 3f19077af111..65b1ef28cdeb 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -139,7 +139,6 @@ static int dtls1_process_record(SSL *s);
#if PQ_64BIT_IS_INTEGER
static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num);
#endif
-static void dtls1_clear_timeouts(SSL *s);
/* copy buffered record into SSL structure */
static int
@@ -335,6 +334,8 @@ dtls1_process_record(SSL *s)
SSL3_RECORD *rr;
unsigned int mac_size;
unsigned char md[EVP_MAX_MD_SIZE];
+ int decryption_failed_or_bad_record_mac = 0;
+ unsigned char *mac = NULL;
rr= &(s->s3->rrec);
@@ -369,12 +370,10 @@ dtls1_process_record(SSL *s)
enc_err = s->method->ssl3_enc->enc(s,0);
if (enc_err <= 0)
{
- if (enc_err == 0)
- /* SSLerr() and ssl3_send_alert() have been called */
- goto err;
-
- /* otherwise enc_err == -1 */
- goto err;
+ /* To minimize information leaked via timing, we will always
+ * perform all computations before discarding the message.
+ */
+ decryption_failed_or_bad_record_mac = 1;
}
#ifdef TLS_DEBUG
@@ -400,28 +399,32 @@ if ( (sess == NULL) ||
SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
goto f_err;
#else
- goto err;
+ decryption_failed_or_bad_record_mac = 1;
#endif
}
/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
- if (rr->length < mac_size)
+ if (rr->length >= mac_size)
{
-#if 0 /* OK only for stream ciphers */
- al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
- goto f_err;
-#else
- goto err;
-#endif
+ rr->length -= mac_size;
+ mac = &rr->data[rr->length];
}
- rr->length-=mac_size;
+ else
+ rr->length = 0;
s->method->ssl3_enc->mac(s,md,0);
- if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
+ if (mac == NULL || memcmp(md, mac, mac_size) != 0)
{
- goto err;
+ decryption_failed_or_bad_record_mac = 1;
}
}
+ if (decryption_failed_or_bad_record_mac)
+ {
+ /* decryption failed, silently discard message */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto err;
+ }
+
/* r->length is now just compressed */
if (s->expand != NULL)
{
@@ -615,10 +618,12 @@ again:
/* If this record is from the next epoch (either HM or ALERT),
* and a handshake is currently in progress, buffer it since it
- * cannot be processed at this time. */
+ * cannot be processed at this time. However, do not buffer
+ * anything while listening.
+ */
if (is_next_epoch)
{
- if (SSL_in_init(s) || s->in_handshake)
+ if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen)
{
dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num);
}
@@ -634,7 +639,6 @@ again:
goto again; /* get another record */
}
- dtls1_clear_timeouts(s); /* done waiting */
return(1);
}
@@ -1103,6 +1107,9 @@ start:
*/
if (msg_hdr.type == SSL3_MT_FINISHED)
{
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+
dtls1_retransmit_buffered_messages(s);
rr->length = 0;
goto start;
@@ -1806,10 +1813,3 @@ bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num)
return _num;
}
#endif
-
-
-static void
-dtls1_clear_timeouts(SSL *s)
- {
- memset(&(s->d1->timeout), 0x00, sizeof(struct dtls1_timeout_st));
- }
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 5b313664dd12..2efaa19ddc50 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -148,6 +148,7 @@ int dtls1_accept(SSL *s)
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int ret= -1;
int new_state,state,skip=0;
+ int listen;
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
@@ -157,11 +158,15 @@ int dtls1_accept(SSL *s)
cb=s->info_callback;
else if (s->ctx->info_callback != NULL)
cb=s->ctx->info_callback;
+
+ listen = s->d1->listen;
/* init things to blank */
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+ s->d1->listen = listen;
+
if (s->cert == NULL)
{
SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
@@ -271,11 +276,23 @@ int dtls1_accept(SSL *s)
s->init_num=0;
+ /* Reflect ClientHello sequence to remain stateless while listening */
+ if (listen)
+ {
+ memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence));
+ }
+
/* If we're just listening, stop here */
- if (s->d1->listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
ret = 2;
s->d1->listen = 0;
+ /* Set expected sequence numbers
+ * to continue the handshake.
+ */
+ s->d1->handshake_read_seq = 2;
+ s->d1->handshake_write_seq = 1;
+ s->d1->next_handshake_write_seq = 1;
goto end;
}
@@ -284,7 +301,6 @@ int dtls1_accept(SSL *s)
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
- dtls1_start_timer(s);
ret = dtls1_send_hello_verify_request(s);
if ( ret <= 0) goto end;
s->state=SSL3_ST_SW_FLUSH;
@@ -457,15 +473,16 @@ int dtls1_accept(SSL *s)
ret = ssl3_check_client_hello(s);
if (ret <= 0)
goto end;
- dtls1_stop_timer(s);
if (ret == 2)
+ {
+ dtls1_stop_timer(s);
s->state = SSL3_ST_SR_CLNT_HELLO_C;
+ }
else {
/* could be sent for a DH cert, even if we
* have not asked for it :-) */
ret=ssl3_get_client_certificate(s);
if (ret <= 0) goto end;
- dtls1_stop_timer(s);
s->init_num=0;
s->state=SSL3_ST_SR_KEY_EXCH_A;
}
@@ -475,7 +492,6 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SR_KEY_EXCH_B:
ret=ssl3_get_client_key_exchange(s);
if (ret <= 0) goto end;
- dtls1_stop_timer(s);
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
@@ -497,7 +513,6 @@ int dtls1_accept(SSL *s)
/* we should decide if we expected this one */
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
- dtls1_stop_timer(s);
s->state=SSL3_ST_SR_FINISHED_A;
s->init_num=0;
@@ -713,9 +728,6 @@ int dtls1_send_hello_verify_request(SSL *s)
/* number of bytes to write */
s->init_num=p-buf;
s->init_off=0;
-
- /* buffer the message to handle re-xmits */
- dtls1_buffer_message(s, 0);
}
/* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
@@ -736,7 +748,7 @@ int dtls1_send_server_hello(SSL *s)
p=s->s3->server_random;
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+ RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
/* Do the message type and length last */
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
index eeffe2549248..c87d84499e76 100644
--- a/ssl/s2_srvr.c
+++ b/ssl/s2_srvr.c
@@ -403,13 +403,14 @@ static int get_client_master_key(SSL *s)
p+=3;
n2s(p,i); s->s2->tmp.clear=i;
n2s(p,i); s->s2->tmp.enc=i;
- n2s(p,i); s->session->key_arg_length=i;
- if(s->session->key_arg_length > SSL_MAX_KEY_ARG_LENGTH)
+ n2s(p,i);
+ if(i > SSL_MAX_KEY_ARG_LENGTH)
{
ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_KEY_ARG_TOO_LONG);
return -1;
}
+ s->session->key_arg_length=i;
s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B;
}
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index a7cb7a1ebf30..2c9fb87f528d 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -878,7 +878,7 @@ int ssl3_get_server_hello(SSL *s)
/* wrong packet length */
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
- goto err;
+ goto f_err;
}
return(1);
@@ -1713,7 +1713,7 @@ int ssl3_get_new_session_ticket(SSL *s)
if (n < 6)
{
/* need at least ticket_lifetime_hint + ticket length */
- al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
@@ -1724,7 +1724,7 @@ int ssl3_get_new_session_ticket(SSL *s)
/* ticket_lifetime_hint + ticket_length + ticket */
if (ticklen + 6 != n)
{
- al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 1539a4ce1c54..759231d9d4c0 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -479,6 +479,9 @@ int ssl3_enc(SSL *s, int send)
/* we need to add 'i-1' padding bytes */
l+=i;
+ /* the last of these zero bytes will be overwritten
+ * with the padding length. */
+ memset(&rec->input[rec->length], 0, i);
rec->length+=i;
rec->input[l-1]=(i-1);
}
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 8fa4ab02c367..a40621822b37 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1722,11 +1722,17 @@ void ssl3_clear(SSL *s)
}
#ifndef OPENSSL_NO_DH
if (s->s3->tmp.dh != NULL)
+ {
DH_free(s->s3->tmp.dh);
+ s->s3->tmp.dh = NULL;
+ }
#endif
#ifndef OPENSSL_NO_ECDH
if (s->s3->tmp.ecdh != NULL)
+ {
EC_KEY_free(s->s3->tmp.ecdh);
+ s->s3->tmp.ecdh = NULL;
+ }
#endif
rp = s->s3->rbuf.buf;
@@ -2635,4 +2641,3 @@ need to go to SSL_ST_ACCEPT.
}
return(ret);
}
-
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index e2d570f80f0a..5ada1f155070 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -235,6 +235,7 @@ int ssl3_accept(SSL *s)
}
s->init_num=0;
+ s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
if (s->state != SSL_ST_RENEGOTIATE)
{
@@ -709,10 +710,15 @@ int ssl3_check_client_hello(SSL *s)
s->s3->tmp.reuse_message = 1;
if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
{
+ /* We only allow the client to restart the handshake once per
+ * negotiation. */
+ if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
+ {
+ SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
+ return -1;
+ }
/* Throw away what we have done so far in the current handshake,
- * which will now be aborted. (A full SSL_clear would be too much.)
- * I hope that tmp.dh is the only thing that may need to be cleared
- * when a handshake is not completed ... */
+ * which will now be aborted. (A full SSL_clear would be too much.) */
#ifndef OPENSSL_NO_DH
if (s->s3->tmp.dh != NULL)
{
@@ -720,6 +726,14 @@ int ssl3_check_client_hello(SSL *s)
s->s3->tmp.dh = NULL;
}
#endif
+#ifndef OPENSSL_NO_ECDH
+ if (s->s3->tmp.ecdh != NULL)
+ {
+ EC_KEY_free(s->s3->tmp.ecdh);
+ s->s3->tmp.ecdh = NULL;
+ }
+#endif
+ s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
return 2;
}
return 1;
@@ -1329,7 +1343,6 @@ int ssl3_send_server_key_exchange(SSL *s)
if (s->s3->tmp.dh != NULL)
{
- DH_free(dh);
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1390,7 +1403,6 @@ int ssl3_send_server_key_exchange(SSL *s)
if (s->s3->tmp.ecdh != NULL)
{
- EC_KEY_free(s->s3->tmp.ecdh);
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1401,12 +1413,11 @@ int ssl3_send_server_key_exchange(SSL *s)
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
goto err;
}
- if (!EC_KEY_up_ref(ecdhp))
+ if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
goto err;
}
- ecdh = ecdhp;
s->s3->tmp.ecdh=ecdh;
if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
@@ -1560,6 +1571,7 @@ int ssl3_send_server_key_exchange(SSL *s)
(unsigned char *)encodedPoint,
encodedlen);
OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
p += encodedlen;
}
#endif
@@ -1949,6 +1961,7 @@ int ssl3_get_client_key_exchange(SSL *s)
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ BN_clear_free(pub);
goto err;
}
@@ -2262,6 +2275,12 @@ int ssl3_get_client_key_exchange(SSL *s)
/* Get encoded point length */
i = *p;
p += 1;
+ if (n != 1 + i)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_EC_LIB);
+ goto err;
+ }
if (EC_POINT_oct2point(group,
clnt_ecpoint, p, i, bn_ctx) == 0)
{
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 7d4e46e9163a..eb50e14efd6f 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1682,6 +1682,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_DTLS1_ACCEPT 246
#define SSL_F_DTLS1_ADD_CERT_TO_BUF 280
#define SSL_F_DTLS1_BUFFER_RECORD 247
+#define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 293
#define SSL_F_DTLS1_CLIENT_HELLO 248
#define SSL_F_DTLS1_CONNECT 249
#define SSL_F_DTLS1_ENC 250
@@ -1739,6 +1740,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL3_CALLBACK_CTRL 233
#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129
#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130
+#define SSL_F_SSL3_CHECK_CLIENT_HELLO 292
#define SSL_F_SSL3_CLIENT_HELLO 131
#define SSL_F_SSL3_CONNECT 132
#define SSL_F_SSL3_CTRL 213
@@ -1974,6 +1976,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_MISSING_TMP_RSA_KEY 172
#define SSL_R_MISSING_TMP_RSA_PKEY 173
#define SSL_R_MISSING_VERIFY_MESSAGE 174
+#define SSL_R_MULTIPLE_SGC_RESTARTS 325
#define SSL_R_NON_SSLV2_INITIAL_PACKET 175
#define SSL_R_NO_CERTIFICATES_RETURNED 176
#define SSL_R_NO_CERTIFICATE_ASSIGNED 177
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 2f579c253bc8..b9a85effa005 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -333,6 +333,17 @@ typedef struct ssl3_buffer_st
#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002
#define SSL3_FLAGS_POP_BUFFER 0x0004
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
+
+/* SSL3_FLAGS_SGC_RESTART_DONE is set when we
+ * restart a handshake because of MS SGC and so prevents us
+ * from restarting the handshake in a loop. It's reset on a
+ * renegotiation, so effectively limits the client to one restart
+ * per negotiation. This limits the possibility of a DDoS
+ * attack where the client handshakes in a loop using SGC to
+ * restart. Servers which permit renegotiation can still be
+ * effected, but we can't prevent that.
+ */
+#define SSL3_FLAGS_SGC_RESTART_DONE 0x0040
typedef struct ssl3_state_st
{
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index a34680ee8502..a54c06ffb7d3 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -303,6 +303,7 @@ static void load_builtin_compressions(void)
sk_SSL_COMP_push(ssl_comp_methods,comp);
}
}
+ sk_SSL_COMP_sort(ssl_comp_methods);
}
MemCheck_on();
}
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 7eb52026e78a..20895ee903af 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/* ssl/ssl_err.c */
/* ====================================================================
- * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -80,6 +80,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_DTLS1_ACCEPT), "DTLS1_ACCEPT"},
{ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF), "DTLS1_ADD_CERT_TO_BUF"},
{ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD), "DTLS1_BUFFER_RECORD"},
+{ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM), "DTLS1_CHECK_TIMEOUT_NUM"},
{ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO), "DTLS1_CLIENT_HELLO"},
{ERR_FUNC(SSL_F_DTLS1_CONNECT), "DTLS1_CONNECT"},
{ERR_FUNC(SSL_F_DTLS1_ENC), "DTLS1_ENC"},
@@ -137,6 +138,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL), "SSL3_CALLBACK_CTRL"},
{ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE), "SSL3_CHANGE_CIPHER_STATE"},
{ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM), "SSL3_CHECK_CERT_AND_ALGORITHM"},
+{ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO), "SSL3_CHECK_CLIENT_HELLO"},
{ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO), "SSL3_CLIENT_HELLO"},
{ERR_FUNC(SSL_F_SSL3_CONNECT), "SSL3_CONNECT"},
{ERR_FUNC(SSL_F_SSL3_CTRL), "SSL3_CTRL"},
@@ -375,6 +377,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY) ,"missing tmp rsa key"},
{ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY) ,"missing tmp rsa pkey"},
{ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
+{ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"},
{ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
{ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
{ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index b6b8e6038aa6..23de3151bf63 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1000,6 +1000,11 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
+#ifndef OPENSSL_NO_DTLS1
+ if (larg < (long)dtls1_min_mtu())
+ return 0;
+#endif
+
if (SSL_version(s) == DTLS1_VERSION ||
SSL_version(s) == DTLS1_BAD_VER)
{
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index e305db43ff8d..3d581f1f2fe4 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -870,6 +870,7 @@ void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
void dtls1_reset_seq_numbers(SSL *s, int rw);
long dtls1_default_timeout(void);
struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
+int dtls1_check_timeout_num(SSL *s);
int dtls1_handle_timeout(SSL *s);
SSL_CIPHER *dtls1_get_cipher(unsigned int u);
void dtls1_start_timer(SSL *s);
@@ -877,6 +878,7 @@ 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);
+unsigned int dtls1_min_mtu(void);
/* some client-only functions */
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 0cc8320e1789..cc97258ae536 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -521,6 +521,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
}
n2s(data, idsize);
dsize -= 2 + idsize;
+ size -= 2 + idsize;
if (dsize < 0)
{
*al = SSL_AD_DECODE_ERROR;
@@ -559,9 +560,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
}
/* Read in request_extensions */
+ if (size < 2)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
n2s(data,dsize);
size -= 2;
- if (dsize > size)
+ if (dsize != size)
{
*al = SSL_AD_DECODE_ERROR;
return 0;
@@ -569,6 +575,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
sdata = data;
if (dsize > 0)
{
+ if (s->tlsext_ocsp_exts)
+ {
+ sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+ X509_EXTENSION_free);
+ }
+
s->tlsext_ocsp_exts =
d2i_X509_EXTENSIONS(NULL,
&sdata, dsize);