diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/d1_both.c | 22 | ||||
-rw-r--r-- | ssl/d1_lib.c | 10 | ||||
-rw-r--r-- | ssl/d1_pkt.c | 11 | ||||
-rw-r--r-- | ssl/d1_srvr.c | 3 | ||||
-rw-r--r-- | ssl/s23_clnt.c | 97 | ||||
-rw-r--r-- | ssl/s3_cbc.c | 129 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 11 | ||||
-rw-r--r-- | ssl/s3_enc.c | 6 | ||||
-rw-r--r-- | ssl/s3_lib.c | 12 | ||||
-rw-r--r-- | ssl/s3_pkt.c | 36 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 9 | ||||
-rw-r--r-- | ssl/ssl.h | 12 | ||||
-rw-r--r-- | ssl/ssl3.h | 10 | ||||
-rw-r--r-- | ssl/ssl_err.c | 5 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 12 | ||||
-rw-r--r-- | ssl/ssl_stat.c | 24 | ||||
-rw-r--r-- | ssl/ssltest.c | 8 | ||||
-rw-r--r-- | ssl/t1_enc.c | 12 | ||||
-rw-r--r-- | ssl/t1_lib.c | 88 | ||||
-rw-r--r-- | ssl/tls1.h | 14 |
20 files changed, 404 insertions, 127 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 4481c55051123..61867b3e33692 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -313,9 +313,10 @@ int dtls1_do_write(SSL *s, int type) s->init_off -= DTLS1_HM_HEADER_LENGTH; s->init_num += DTLS1_HM_HEADER_LENGTH; - /* write atleast DTLS1_HM_HEADER_LENGTH bytes */ - if ( len <= DTLS1_HM_HEADER_LENGTH) - len += DTLS1_HM_HEADER_LENGTH; + if ( s->init_num > curr_mtu) + len = curr_mtu; + else + len = s->init_num; } dtls1_fix_message_header(s, frag_off, @@ -620,7 +621,16 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) frag->msg_header.frag_off = 0; } else + { frag = (hm_fragment*) item->data; + if (frag->msg_header.msg_len != msg_hdr->msg_len) + { + item = NULL; + frag = NULL; + goto err; + } + } + /* If message is already reassembled, this must be a * retransmit and can be dropped. @@ -667,8 +677,8 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) if (item == NULL) { - goto err; i = -1; + goto err; } pqueue_insert(s->d1->buffered_messages, item); @@ -777,6 +787,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) int i,al; struct hm_header_st msg_hdr; + redo: /* see if we have the required fragment already */ if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok) { @@ -835,8 +846,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) s->msg_callback_arg); s->init_num = 0; - return dtls1_get_message_fragment(s, st1, stn, - max, ok); + goto redo; } else /* Incorrectly formated Hello request */ { diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 3d27e3085818b..c872cb6594511 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -191,9 +191,12 @@ static void dtls1_clear_queues(SSL *s) while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { - frag = (hm_fragment *)item->data; - OPENSSL_free(frag->fragment); - OPENSSL_free(frag); + rdata = (DTLS1_RECORD_DATA *) item->data; + if (rdata->rbuf.buf) + { + OPENSSL_free(rdata->rbuf.buf); + } + OPENSSL_free(item->data); pitem_free(item); } } @@ -217,6 +220,7 @@ void dtls1_free(SSL *s) pq_64bit_free(&(s->d1->next_bitmap.max_seq_num)); OPENSSL_free(s->d1); + s->d1 = NULL; } void dtls1_clear(SSL *s) diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 9db44c95f9bd8..d12604e6573eb 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -362,7 +362,6 @@ dtls1_process_record(SSL *s) /* decrypt in place in 'rr->input' */ rr->data=rr->input; - orig_len=rr->length; enc_err = s->method->ssl3_enc->enc(s,0); /* enc_err is: @@ -394,6 +393,9 @@ printf("\n"); mac_size=EVP_MD_size(s->read_hash); OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); + /* kludge: *_cbc_remove_padding passes padding length in rr->type */ + orig_len = rr->length+((unsigned int)rr->type>>8); + /* orig_len is the length of the record before any padding was * removed. This is public information, as is the MAC in use, * therefore we can safely process the record in a different @@ -772,6 +774,12 @@ start: } } + if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) + { + rr->length = 0; + goto start; + } + /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, @@ -938,6 +946,7 @@ start: !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && !s->s3->renegotiate) { + s->d1->handshake_read_seq++; ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 2efaa19ddc503..c0246c94eae87 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -246,10 +246,11 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; + dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret=dtls1_send_hello_request(s); if (ret <= 0) goto end; - s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; + s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index c6b9142c909ca..830eff0f511a1 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -509,7 +509,7 @@ static int ssl23_get_server_hello(SSL *s) /* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */ s->s2->ssl2_rollback=1; - /* setup the 5 bytes we have read so we get them from + /* setup the 7 bytes we have read so we get them from * the sslv2 buffer */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; @@ -525,27 +525,13 @@ static int ssl23_get_server_hello(SSL *s) s->handshake_func=s->method->ssl_connect; #endif } - else if ((p[0] == SSL3_RT_HANDSHAKE) && - (p[1] == SSL3_VERSION_MAJOR) && - ((p[2] == SSL3_VERSION_MINOR) || - (p[2] == TLS1_VERSION_MINOR)) && - (p[5] == SSL3_MT_SERVER_HELLO)) + else if (p[1] == SSL3_VERSION_MAJOR && + ((p[2] == SSL3_VERSION_MINOR) || + (p[2] == TLS1_VERSION_MINOR)) && + ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) || + (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) { - /* we have sslv3 or tls1 */ - - if (!ssl_init_wbio_buffer(s,1)) goto err; - - /* we are in this state */ - s->state=SSL3_ST_CR_SRVR_HELLO_A; - - /* put the 5 bytes we have read into the input buffer - * for SSLv3 */ - s->rstate=SSL_ST_READ_HEADER; - s->packet_length=n; - s->packet= &(s->s3->rbuf.buf[0]); - memcpy(s->packet,buf,n); - s->s3->rbuf.left=n; - s->s3->rbuf.offset=0; + /* we have sslv3 or tls1 (server hello or alert) */ if ((p[2] == SSL3_VERSION_MINOR) && !(s->options & SSL_OP_NO_SSLv3)) @@ -572,35 +558,52 @@ static int ssl23_get_server_hello(SSL *s) SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); goto err; } - - s->handshake_func=s->method->ssl_connect; - } - else if ((p[0] == SSL3_RT_ALERT) && - (p[1] == SSL3_VERSION_MAJOR) && - ((p[2] == SSL3_VERSION_MINOR) || - (p[2] == TLS1_VERSION_MINOR)) && - (p[3] == 0) && - (p[4] == 2)) - { - void (*cb)(const SSL *ssl,int type,int val)=NULL; - int j; - - /* An alert */ - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; - - i=p[5]; - if (cb != NULL) + + if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) { - j=(i<<8)|p[6]; - cb(s,SSL_CB_READ_ALERT,j); + /* fatal alert */ + + void (*cb)(const SSL *ssl,int type,int val)=NULL; + int j; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + i=p[5]; + if (cb != NULL) + { + j=(i<<8)|p[6]; + cb(s,SSL_CB_READ_ALERT,j); + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg); + + s->rwstate=SSL_NOTHING; + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); + goto err; } - s->rwstate=SSL_NOTHING; - SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); - goto err; + if (!ssl_init_wbio_buffer(s,1)) goto err; + + /* we are in this state */ + s->state=SSL3_ST_CR_SRVR_HELLO_A; + + /* put the 7 bytes we have read into the input buffer + * for SSLv3 */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + if (s->s3->rbuf.buf == NULL) + if (!ssl3_setup_buffers(s)) + goto err; + s->packet= &(s->s3->rbuf.buf[0]); + memcpy(s->packet,buf,n); + s->s3->rbuf.left=n; + s->s3->rbuf.offset=0; + + s->handshake_func=s->method->ssl_connect; } else { diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 28722e14f8682..9f57fc9a622f1 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -76,6 +76,13 @@ #define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) #define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) +/* constant_time_lt returns 0xff if a<b and 0x00 otherwise. */ +static unsigned constant_time_lt(unsigned a, unsigned b) + { + a -= b; + return DUPLICATE_MSB_TO_ALL(a); + } + /* constant_time_ge returns 0xff if a>=b and 0x00 otherwise. */ static unsigned constant_time_ge(unsigned a, unsigned b) { @@ -84,7 +91,7 @@ static unsigned constant_time_ge(unsigned a, unsigned b) } /* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */ -static unsigned char constant_time_eq_8(unsigned char a, unsigned char b) +static unsigned char constant_time_eq_8(unsigned a, unsigned b) { unsigned c = a ^ b; c--; @@ -139,14 +146,21 @@ int tls1_cbc_remove_padding(const SSL* s, unsigned mac_size) { unsigned padding_length, good, to_check, i; - const char has_explicit_iv = s->version == DTLS1_VERSION; - const unsigned overhead = 1 /* padding length byte */ + - mac_size + - (has_explicit_iv ? block_size : 0); - - /* These lengths are all public so we can test them in non-constant - * time. */ - if (overhead > rec->length) + const unsigned overhead = 1 /* padding length byte */ + mac_size; + /* Check if version requires explicit IV */ + if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) + { + /* These lengths are all public so we can test them in + * non-constant time. + */ + if (overhead + block_size > rec->length) + return 0; + /* We can now safely skip explicit IV */ + rec->data += block_size; + rec->input += block_size; + rec->length -= block_size; + } + else if (overhead > rec->length) return 0; padding_length = rec->data[rec->length-1]; @@ -208,28 +222,9 @@ int tls1_cbc_remove_padding(const SSL* s, rec->length -= padding_length; rec->type |= padding_length<<8; /* kludge: pass padding length */ - /* We can always safely skip the explicit IV. We check at the beginning - * of this function that the record has at least enough space for the - * IV, MAC and padding length byte. (These can be checked in - * non-constant time because it's all public information.) So, if the - * padding was invalid, then we didn't change |rec->length| and this is - * safe. If the padding was valid then we know that we have at least - * overhead+padding_length bytes of space and so this is still safe - * because overhead accounts for the explicit IV. */ - if (has_explicit_iv) - { - rec->data += block_size; - rec->input += block_size; - rec->length -= block_size; - } - return (int)((good & 1) | (~good & -1)); } -#if defined(_M_AMD64) || defined(__x86_64__) -#define CBC_MAC_ROTATE_IN_PLACE -#endif - /* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in * constant time (independent of the concrete value of rec->length, which may * vary within a 256-byte window). @@ -243,15 +238,18 @@ int tls1_cbc_remove_padding(const SSL* s, * * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into - * a single cache-line, then the variable memory accesses don't actually affect - * the timing. This has been tested to be true on Intel amd64 chips. + * a single or pair of cache-lines, then the variable memory accesses don't + * actually affect the timing. CPUs with smaller cache-lines [if any] are + * not multi-core and are not considered vulnerable to cache-timing attacks. */ +#define CBC_MAC_ROTATE_IN_PLACE + void ssl3_cbc_copy_mac(unsigned char* out, const SSL3_RECORD *rec, unsigned md_size,unsigned orig_len) { #if defined(CBC_MAC_ROTATE_IN_PLACE) - unsigned char rotated_mac_buf[EVP_MAX_MD_SIZE*2]; + unsigned char rotated_mac_buf[64+EVP_MAX_MD_SIZE]; unsigned char *rotated_mac; #else unsigned char rotated_mac[EVP_MAX_MD_SIZE]; @@ -271,7 +269,7 @@ void ssl3_cbc_copy_mac(unsigned char* out, OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); #if defined(CBC_MAC_ROTATE_IN_PLACE) - rotated_mac = (unsigned char*) (((intptr_t)(rotated_mac_buf + 64)) & ~63); + rotated_mac = rotated_mac_buf + ((0-(size_t)rotated_mac_buf)&63); #endif /* This information is public so it's safe to branch based on it. */ @@ -289,16 +287,13 @@ void ssl3_cbc_copy_mac(unsigned char* out, rotate_offset = (div_spoiler + mac_start - scan_start) % md_size; memset(rotated_mac, 0, md_size); - for (i = scan_start; i < orig_len;) + for (i = scan_start, j = 0; i < orig_len; i++) { - for (j = 0; j < md_size && i < orig_len; i++, j++) - { - unsigned char mac_started = constant_time_ge(i, mac_start); - unsigned char mac_ended = constant_time_ge(i, mac_end); - unsigned char b = 0; - b = rec->data[i]; - rotated_mac[j] |= b & mac_started & ~mac_ended; - } + unsigned char mac_started = constant_time_ge(i, mac_start); + unsigned char mac_ended = constant_time_ge(i, mac_end); + unsigned char b = rec->data[i]; + rotated_mac[j++] |= b & mac_started & ~mac_ended; + j &= constant_time_lt(j,md_size); } /* Now rotate the MAC */ @@ -306,30 +301,43 @@ void ssl3_cbc_copy_mac(unsigned char* out, j = 0; for (i = 0; i < md_size; i++) { - unsigned char offset = (div_spoiler + rotate_offset + i) % md_size; - out[j++] = rotated_mac[offset]; + /* in case cache-line is 32 bytes, touch second line */ + ((volatile unsigned char *)rotated_mac)[rotate_offset^32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt(rotate_offset,md_size); } #else memset(out, 0, md_size); + rotate_offset = md_size - rotate_offset; + rotate_offset &= constant_time_lt(rotate_offset,md_size); for (i = 0; i < md_size; i++) { - unsigned char offset = (div_spoiler + md_size - rotate_offset + i) % md_size; for (j = 0; j < md_size; j++) - out[j] |= rotated_mac[i] & constant_time_eq_8(j, offset); + out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset); + rotate_offset++; + rotate_offset &= constant_time_lt(rotate_offset,md_size); } #endif } +/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. */ +#define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + /* These functions serialize the state of a hash and thus perform the standard * "final" operation without adding the padding and length that such a function * typically does. */ static void tls1_md5_final_raw(void* ctx, unsigned char *md_out) { MD5_CTX *md5 = ctx; - l2n(md5->A, md_out); - l2n(md5->B, md_out); - l2n(md5->C, md_out); - l2n(md5->D, md_out); + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); } static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) @@ -449,6 +457,7 @@ void ssl3_cbc_digest_record( /* mdLengthSize is the number of bytes in the length field that terminates * the hash. */ unsigned md_length_size = 8; + char length_is_big_endian = 1; /* This is a, hopefully redundant, check that allows us to forget about * many possible overflows later in this function. */ @@ -462,6 +471,7 @@ void ssl3_cbc_digest_record( md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; md_size = 16; sslv3_pad_length = 48; + length_is_big_endian = 0; break; case NID_sha1: SHA1_Init((SHA_CTX*)md_state.c); @@ -602,11 +612,22 @@ void ssl3_cbc_digest_record( md_transform(md_state.c, hmac_pad); } - memset(length_bytes,0,md_length_size-4); - length_bytes[md_length_size-4] = (unsigned char)(bits>>24); - length_bytes[md_length_size-3] = (unsigned char)(bits>>16); - length_bytes[md_length_size-2] = (unsigned char)(bits>>8); - length_bytes[md_length_size-1] = (unsigned char)bits; + if (length_is_big_endian) + { + memset(length_bytes,0,md_length_size-4); + length_bytes[md_length_size-4] = (unsigned char)(bits>>24); + length_bytes[md_length_size-3] = (unsigned char)(bits>>16); + length_bytes[md_length_size-2] = (unsigned char)(bits>>8); + length_bytes[md_length_size-1] = (unsigned char)bits; + } + else + { + memset(length_bytes,0,md_length_size); + length_bytes[md_length_size-5] = (unsigned char)(bits>>24); + length_bytes[md_length_size-6] = (unsigned char)(bits>>16); + length_bytes[md_length_size-7] = (unsigned char)(bits>>8); + length_bytes[md_length_size-8] = (unsigned char)bits; + } if (k > 0) { diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index a17beb8a3bf8a..06fb2754f0a9f 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -491,6 +491,7 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; @@ -777,6 +778,7 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); goto f_err; } + s->s3->flags |= SSL3_FLAGS_CCS_OK; s->hit=1; } else /* a miss or crap from the other end */ @@ -893,7 +895,9 @@ int ssl3_get_server_hello(SSL *s) return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); +#ifndef OPENSSL_NO_TLSEXT err: +#endif return(-1); } @@ -2170,6 +2174,13 @@ int ssl3_send_client_key_exchange(SSL *s) int ecdh_clnt_cert = 0; int field_size = 0; + if (s->session->sess_cert == NULL) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + /* Did we send out the client's * ECDH share for use in premaster * computation as part of client certificate? diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 5d8f8ae52a150..736bfacc69437 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -758,6 +758,12 @@ int ssl3_alert_code(int code) case SSL_AD_INTERNAL_ERROR: return(SSL3_AD_HANDSHAKE_FAILURE); case SSL_AD_USER_CANCELLED: return(SSL3_AD_HANDSHAKE_FAILURE); case SSL_AD_NO_RENEGOTIATION: return(-1); /* Don't send it :-) */ + case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE); + case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE); + case SSL_AD_UNRECOGNIZED_NAME: return(SSL3_AD_HANDSHAKE_FAILURE); + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE); + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE); + case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); default: return(-1); } } diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index a40621822b37d..fc723a00a9759 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1734,6 +1734,11 @@ void ssl3_clear(SSL *s) s->s3->tmp.ecdh = NULL; } #endif +#ifndef OPENSSL_NO_TLSEXT +#ifndef OPENSSL_NO_EC + s->s3->is_probably_safari = 0; +#endif /* !OPENSSL_NO_EC */ +#endif /* !OPENSSL_NO_TLSEXT */ rp = s->s3->rbuf.buf; wp = s->s3->wbuf.buf; @@ -2398,6 +2403,13 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, j=sk_SSL_CIPHER_find(allow,c); if (j >= 0) { +#if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_TLSEXT) + if ((alg & SSL_kECDHE) && (alg & SSL_aECDSA) && s->s3->is_probably_safari) + { + if (!ret) ret=sk_SSL_CIPHER_value(allow,j); + continue; + } +#endif ret=sk_SSL_CIPHER_value(allow,j); break; } diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 707738be94c46..c087fee093b4b 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -351,7 +351,6 @@ again: /* decrypt in place in 'rr->input' */ rr->data=rr->input; - orig_len=rr->length; enc_err = s->method->ssl3_enc->enc(s,0); /* enc_err is: @@ -382,6 +381,9 @@ printf("\n"); mac_size=EVP_MD_size(s->read_hash); OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); + /* kludge: *_cbc_remove_padding passes padding length in rr->type */ + orig_len = rr->length+((unsigned int)rr->type>>8); + /* orig_len is the length of the record before any padding was * removed. This is public information, as is the MAC in use, * therefore we can safely process the record in a different @@ -527,10 +529,11 @@ int ssl3_do_compress(SSL *ssl) int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { const unsigned char *buf=buf_; - unsigned int tot,n,nw; - int i; + unsigned int n,nw; + int i,tot; s->rwstate=SSL_NOTHING; + OPENSSL_assert(s->s3->wnum < INT_MAX); tot=s->s3->wnum; s->s3->wnum=0; @@ -545,6 +548,22 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) } } + /* ensure that if we end up with a smaller value of data to write + * out than the the original len from a write which didn't complete + * for non-blocking I/O and also somehow ended up avoiding + * the check for this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as + * it must never be possible to end up with (len-tot) as a large + * number that will then promptly send beyond the end of the users + * buffer ... so we trap and report the error in a way the user + * will notice + */ + if (len < tot) + { + SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_BAD_LENGTH); + return(-1); + } + + n=(len-tot); for (;;) { @@ -1147,6 +1166,15 @@ start: goto f_err; } + if (!(s->s3->flags & SSL3_FLAGS_CCS_OK)) + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY); + goto f_err; + } + + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + rr->length=0; if (s->msg_callback) @@ -1278,7 +1306,7 @@ int ssl3_do_change_cipher_spec(SSL *s) if (s->s3->tmp.key_block == NULL) { - if (s->session == NULL) + if (s->session == NULL || s->session->master_key_length == 0) { /* might happen if dtls1_read_bytes() calls this */ SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY); diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index e49fc959c417e..fcc97f374f56b 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -523,6 +523,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; @@ -533,6 +534,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; @@ -1131,6 +1133,7 @@ int ssl3_get_client_hello(SSL *s) * s->tmp.new_cipher - the new cipher to use. */ +#ifndef OPENSSL_NO_TLSEXT /* Handles TLS extensions that we couldn't check earlier */ if (s->version >= SSL3_VERSION) { @@ -1140,6 +1143,7 @@ int ssl3_get_client_hello(SSL *s) goto err; } } +#endif if (ret < 0) ret=1; if (0) @@ -1760,6 +1764,11 @@ int ssl3_send_certificate_request(SSL *s) s->init_num=n+4; s->init_off=0; #ifdef NETSCAPE_HANG_BUG + if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) + { + SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); + goto err; + } p=(unsigned char *)s->init_buf->data + s->init_num; /* do the header */ diff --git a/ssl/ssl.h b/ssl/ssl.h index d6bbc449ddf44..5f2a04e83dbdf 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -490,11 +490,14 @@ typedef struct ssl_session_st #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L -#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L /* no effect since 0.9.7h and 0.9.8b */ +#define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040L #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L #define SSL_OP_TLS_D5_BUG 0x00000100L #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L +/* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */ +#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0 + /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added * in OpenSSL 0.9.6d. Usually (depending on the application protocol) * the workaround is not needed. Unfortunately some broken SSL/TLS @@ -1204,6 +1207,8 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE #define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */ #define SSL_ERROR_NONE 0 #define SSL_ERROR_SSL 1 @@ -2074,6 +2079,11 @@ void ERR_load_SSL_strings(void); #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 #define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 diff --git a/ssl/ssl3.h b/ssl/ssl3.h index b9a85effa0058..de5e559a59df3 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -333,6 +333,7 @@ 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 +#define SSL3_FLAGS_CCS_OK 0x0080 /* SSL3_FLAGS_SGC_RESTART_DONE is set when we * restart a handshake because of MS SGC and so prevents us @@ -460,6 +461,15 @@ typedef struct ssl3_state_st unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; unsigned char previous_server_finished_len; int send_connection_binding; /* TODOEKR */ + +#ifndef OPENSSL_NO_TLSEXT +#ifndef OPENSSL_NO_EC + /* This is set to true if we believe that this is a version of Safari + * running on OS X 10.6 or newer. We wish to know this because Safari + * on 10.8 .. 10.8.3 has broken ECDHE-ECDSA support. */ + char is_probably_safari; +#endif /* !OPENSSL_NO_EC */ +#endif /* !OPENSSL_NO_TLSEXT */ } SSL3_STATE; diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 60e7e9d16c041..9e28dfddf1037 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -475,6 +475,11 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"}, {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"}, {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"}, +{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"}, +{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"}, +{ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"}, +{ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"}, +{ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"}, {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"}, {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"}, {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 8b6b601cabd88..47a0c7c4eaa85 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1258,6 +1258,10 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) p=buf; sk=s->session->ciphers; + + if (sk_SSL_CIPHER_num(sk) == 0) + return NULL; + for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { int n; @@ -1567,7 +1571,9 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); ret->extra_certs=NULL; - ret->comp_methods=SSL_COMP_get_compression_methods(); + /* No compression for DTLS */ + if (meth->version != DTLS1_VERSION) + ret->comp_methods=SSL_COMP_get_compression_methods(); #ifndef OPENSSL_NO_TLSEXT ret->tlsext_servername_callback = 0; @@ -2428,9 +2434,7 @@ void ssl_clear_cipher_ctx(SSL *s) /* Fix this function so that it takes an optional type parameter */ X509 *SSL_get_certificate(const SSL *s) { - if (s->server) - return(ssl_get_server_send_cert(s)); - else if (s->cert != NULL) + if (s->cert != NULL) return(s->cert->key->x509); else return(NULL); diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c index e7509f030315f..cd52184a99340 100644 --- a/ssl/ssl_stat.c +++ b/ssl/ssl_stat.c @@ -414,6 +414,12 @@ const char *SSL_alert_desc_string(int value) case TLS1_AD_INTERNAL_ERROR: str="IE"; break; case TLS1_AD_USER_CANCELLED: str="US"; break; case TLS1_AD_NO_RENEGOTIATION: str="NR"; break; + case TLS1_AD_UNSUPPORTED_EXTENSION: str="UE"; break; + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: str="CO"; break; + case TLS1_AD_UNRECOGNIZED_NAME: str="UN"; break; + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break; + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break; + case TLS1_AD_UNKNOWN_PSK_IDENTITY: str="UP"; break; default: str="UK"; break; } return(str); @@ -497,6 +503,24 @@ const char *SSL_alert_desc_string_long(int value) case TLS1_AD_NO_RENEGOTIATION: str="no renegotiation"; break; + case TLS1_AD_UNSUPPORTED_EXTENSION: + str="unsupported extension"; + break; + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + str="certificate unobtainable"; + break; + case TLS1_AD_UNRECOGNIZED_NAME: + str="unrecognized name"; + break; + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + str="bad certificate status response"; + break; + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + str="bad certificate hash value"; + break; + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + str="unknown PSK identity"; + break; default: str="unknown"; break; } return(str); diff --git a/ssl/ssltest.c b/ssl/ssltest.c index 310e0677e90a3..26ff634ea3c8b 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -735,7 +735,13 @@ bad: meth=SSLv23_method(); #else #ifdef OPENSSL_NO_SSL2 - meth=SSLv3_method(); + if (tls1) + meth=TLSv1_method(); + else + if (ssl3) + meth=SSLv3_method(); + else + meth=SSLv23_method(); #else meth=SSLv2_method(); #endif diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 323d3847d4ad5..eb4acef8b8aa7 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -774,14 +774,10 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) HMAC_CTX_cleanup(&hmac); #ifdef TLS_DEBUG -printf("sec="); -{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); } printf("seq="); {int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); } -printf("buf="); -{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); } printf("rec="); -{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); } +{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",rec->data[z]); printf("\n"); } #endif if ( SSL_version(ssl) != DTLS1_VERSION && SSL_version(ssl) != DTLS1_BAD_VER) @@ -853,6 +849,12 @@ int tls1_alert_code(int code) case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR); case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED); case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION); + case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION); + case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE); + case SSL_AD_UNRECOGNIZED_NAME: return(TLS1_AD_UNRECOGNIZED_NAME); + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE); + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE); + case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index d56456e14dfdd..09b06a5af7306 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -344,6 +344,89 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha return ret; } +#ifndef OPENSSL_NO_EC +/* ssl_check_for_safari attempts to fingerprint Safari using OS X + * SecureTransport using the TLS extension block in |d|, of length |n|. + * Safari, since 10.6, sends exactly these extensions, in this order: + * SNI, + * elliptic_curves + * ec_point_formats + * + * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8, + * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them. + * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from + * 10.8..10.8.3 (which don't work). + */ +static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) { + unsigned short type, size; + static const unsigned char kSafariExtensionsBlock[] = { + 0x00, 0x0a, /* elliptic_curves extension */ + 0x00, 0x08, /* 8 bytes */ + 0x00, 0x06, /* 6 bytes of curve ids */ + 0x00, 0x17, /* P-256 */ + 0x00, 0x18, /* P-384 */ + 0x00, 0x19, /* P-521 */ + + 0x00, 0x0b, /* ec_point_formats */ + 0x00, 0x02, /* 2 bytes */ + 0x01, /* 1 point format */ + 0x00, /* uncompressed */ + }; + + /* The following is only present in TLS 1.2 */ + static const unsigned char kSafariTLS12ExtensionsBlock[] = { + 0x00, 0x0d, /* signature_algorithms */ + 0x00, 0x0c, /* 12 bytes */ + 0x00, 0x0a, /* 10 bytes */ + 0x05, 0x01, /* SHA-384/RSA */ + 0x04, 0x01, /* SHA-256/RSA */ + 0x02, 0x01, /* SHA-1/RSA */ + 0x04, 0x03, /* SHA-256/ECDSA */ + 0x02, 0x03, /* SHA-1/ECDSA */ + }; + + if (data >= (d+n-2)) + return; + data += 2; + + if (data > (d+n-4)) + return; + n2s(data,type); + n2s(data,size); + + if (type != TLSEXT_TYPE_server_name) + return; + + if (data+size > d+n) + return; + data += size; + + if (TLS1_get_client_version(s) >= TLS1_2_VERSION) + { + const size_t len1 = sizeof(kSafariExtensionsBlock); + const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock); + + if (data + len1 + len2 != d+n) + return; + if (memcmp(data, kSafariExtensionsBlock, len1) != 0) + return; + if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0) + return; + } + else + { + const size_t len = sizeof(kSafariExtensionsBlock); + + if (data + len != d+n) + return; + if (memcmp(data, kSafariExtensionsBlock, len) != 0) + return; + } + + s->s3->is_probably_safari = 1; +} +#endif /* !OPENSSL_NO_EC */ + int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short type; @@ -355,6 +438,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->servername_done = 0; s->tlsext_status_type = -1; +#ifndef OPENSSL_NO_EC + if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) + ssl_check_for_safari(s, data, d, n); +#endif /* !OPENSSL_NO_EC */ + if (data >= (d+n-2)) goto ri_check; diff --git a/ssl/tls1.h b/ssl/tls1.h index afe4807fa9005..47f25afb1d04d 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -80,10 +80,24 @@ extern "C" { #define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0 +#define TLS1_2_VERSION 0x0303 +#define TLS1_2_VERSION_MAJOR 0x03 +#define TLS1_2_VERSION_MINOR 0x03 + +#define TLS1_1_VERSION 0x0302 +#define TLS1_1_VERSION_MAJOR 0x03 +#define TLS1_1_VERSION_MINOR 0x02 + #define TLS1_VERSION 0x0301 #define TLS1_VERSION_MAJOR 0x03 #define TLS1_VERSION_MINOR 0x01 +#define TLS1_get_version(s) \ + ((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0) + +#define TLS1_get_client_version(s) \ + ((s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0) + #define TLS1_AD_DECRYPTION_FAILED 21 #define TLS1_AD_RECORD_OVERFLOW 22 #define TLS1_AD_UNKNOWN_CA 48 /* fatal */ |