diff options
-rw-r--r-- | ssl/record/rec_layer_d1.c | 4 | ||||
-rw-r--r-- | ssl/record/rec_layer_s3.c | 139 | ||||
-rw-r--r-- | ssl/record/record.h | 5 | ||||
-rw-r--r-- | ssl/record/record_locl.h | 14 | ||||
-rw-r--r-- | ssl/record/ssl3_record.c | 618 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 4 |
6 files changed, 472 insertions, 312 deletions
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index cd033e0..86b6585 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -355,7 +355,7 @@ int dtls1_process_buffered_records(SSL *s) if (!dtls1_process_record(s)) return (0); if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), - SSL3_RECORD_get_seq_num(&s->rlayer.rrec)) < 0) + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) return -1; } } @@ -464,7 +464,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, * s->s3->rrec.off, - offset into 'data' for next read * s->s3->rrec.length, - number of bytes. */ - rr = &s->rlayer.rrec; + rr = s->rlayer.rrec; /* * We are not handshaking and have no data yet, so process data buffered diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 3a232e5..1aceed3 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -135,8 +135,8 @@ void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s) { rl->s = s; - SSL3_RECORD_clear(&rl->rrec); - SSL3_RECORD_clear(&rl->wrec); + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); + SSL3_RECORD_clear(&rl->wrec, 1); } void RECORD_LAYER_clear(RECORD_LAYER *rl) @@ -166,8 +166,8 @@ void RECORD_LAYER_clear(RECORD_LAYER *rl) for(pipes = 0; pipes < rl->numwpipes; pipes++) SSL3_BUFFER_clear(&rl->wbuf[pipes]); rl->numwpipes = 0; - SSL3_RECORD_clear(&rl->rrec); - SSL3_RECORD_clear(&rl->wrec); + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); + SSL3_RECORD_clear(&rl->wrec, 1); RECORD_LAYER_reset_read_sequence(rl); RECORD_LAYER_reset_write_sequence(rl); @@ -182,7 +182,8 @@ void RECORD_LAYER_release(RECORD_LAYER *rl) ssl3_release_read_buffer(rl->s); if (rl->numwpipes > 0) ssl3_release_write_buffer(rl->s); - SSL3_RECORD_release(&rl->rrec); + /* TODO: Check why there is no release of wrec here?? */ + SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES); } int RECORD_LAYER_read_pending(RECORD_LAYER *rl) @@ -224,16 +225,25 @@ void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl) int RECORD_LAYER_setup_comp_buffer(RECORD_LAYER *rl) { - return SSL3_RECORD_setup(&(rl)->rrec); + return SSL3_RECORD_setup((rl)->rrec, SSL_MAX_PIPELINES); } int ssl3_pending(const SSL *s) { + unsigned int i; + int num = 0; + if (s->rlayer.rstate == SSL_ST_READ_BODY) return 0; - return (SSL3_RECORD_get_type(&s->rlayer.rrec) == SSL3_RT_APPLICATION_DATA) - ? SSL3_RECORD_get_length(&s->rlayer.rrec) : 0; + for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) { + if (SSL3_RECORD_get_type(&s->rlayer.rrec[i]) + != SSL3_RT_APPLICATION_DATA) + return 0; + num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]); + } + + return num; } const char *SSL_rstate_string_long(const SSL *s) @@ -278,7 +288,7 @@ const char *SSL_rstate_string(const SSL *s) return (str); } -int ssl3_read_n(SSL *s, int n, int max, int extend) +int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold) { /* * If extend == 0, obtain new n-byte packet; if extend == 1, increase @@ -286,6 +296,8 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) * s->s3->rbuf.buf specified by s->packet and s->packet_length. (If * s->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus * s->packet_length bytes if extend == 1].) + * if clearold == 1, move the packet to the start of the buffer; if + * clearold == 0 then leave any old packets where they were */ int i, len, left; size_t align = 0; @@ -362,7 +374,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) * Move any available bytes to front of buffer: 'len' bytes already * pointed to by 'packet', 'left' extra ones at the end */ - if (s->rlayer.packet != pkt) { /* len > 0 */ + if (s->rlayer.packet != pkt && clearold == 1) { /* len > 0 */ memmove(pkt, s->rlayer.packet, len + left); s->rlayer.packet = pkt; rb->offset = len + align; @@ -1071,11 +1083,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, int len, int peek) { int al, i, j, ret; - unsigned int n; + unsigned int n, curr_rec, num_recs, read_bytes; SSL3_RECORD *rr; + SSL3_BUFFER *rbuf; void (*cb) (const SSL *ssl, int type2, int val) = NULL; - if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) { + rbuf = &s->rlayer.rbuf; + + if (!SSL3_BUFFER_is_initialised(rbuf)) { /* Not initialized yet */ if (!ssl3_setup_read_buffer(s)) return (-1); @@ -1132,20 +1147,40 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, s->rwstate = SSL_NOTHING; /*- - * s->s3->rrec.type - is the type of record - * s->s3->rrec.data, - data - * s->s3->rrec.off, - offset into 'data' for next read - * s->s3->rrec.length, - number of bytes. + * For each record 'i' up to |num_recs] + * rr[i].type - is the type of record + * rr[i].data, - data + * rr[i].off, - offset into 'data' for next read + * rr[i].length, - number of bytes. */ - rr = &s->rlayer.rrec; - - /* get new packet if necessary */ - if ((SSL3_RECORD_get_length(rr) == 0) - || (s->rlayer.rstate == SSL_ST_READ_BODY)) { - ret = ssl3_get_record(s); - if (ret <= 0) - return (ret); - } + rr = s->rlayer.rrec; + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + + do { + /* get new records if necessary */ + if (num_recs == 0) { + ret = ssl3_get_record(s); + if (ret <= 0) + return (ret); + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + if (num_recs == 0) { + /* Shouldn't happen */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + /* Skip over any records we have already used or are zero in length */ + for (curr_rec = 0; + curr_rec < num_recs && SSL3_RECORD_get_length(&rr[curr_rec]) == 0; + curr_rec++); + if (curr_rec == num_recs) { + RECORD_LAYER_set_numrpipes(&s->rlayer, 0); + num_recs = 0; + curr_rec = 0; + } + } while (num_recs == 0); + rr = &rr[curr_rec]; /* we now have a packet which can be read and processed */ @@ -1200,24 +1235,36 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, if (len <= 0) return (len); - if ((unsigned int)len > SSL3_RECORD_get_length(rr)) - n = SSL3_RECORD_get_length(rr); - else - n = (unsigned int)len; - - memcpy(buf, &(rr->data[rr->off]), n); - if (!peek) { - SSL3_RECORD_add_length(rr, -n); - SSL3_RECORD_add_off(rr, n); - if (SSL3_RECORD_get_length(rr) == 0) { - s->rlayer.rstate = SSL_ST_READ_HEADER; - SSL3_RECORD_set_off(rr, 0); - if (s->mode & SSL_MODE_RELEASE_BUFFERS - && SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) - ssl3_release_read_buffer(s); + read_bytes = 0; + do { + if ((unsigned int)len - read_bytes > SSL3_RECORD_get_length(rr)) + n = SSL3_RECORD_get_length(rr); + else + n = (unsigned int)len - read_bytes; + + memcpy(buf, &(rr->data[rr->off]), n); + buf += n; + if (!peek) { + SSL3_RECORD_add_length(rr, -n); + SSL3_RECORD_add_off(rr, n); + if (SSL3_RECORD_get_length(rr) == 0) { + s->rlayer.rstate = SSL_ST_READ_HEADER; + SSL3_RECORD_set_off(rr, 0); + } } - } - return (n); + if (SSL3_RECORD_get_length(rr) == 0 + || (peek && n == SSL3_RECORD_get_length(rr))) { + curr_rec++; + rr++; + } + read_bytes += n; + } while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs + && read_bytes < (unsigned int)len); + if (!peek && curr_rec == num_recs + && (s->mode & SSL_MODE_RELEASE_BUFFERS) + && SSL3_BUFFER_get_left(rbuf) == 0) + ssl3_release_read_buffer(s); + return read_bytes; } /* @@ -1339,7 +1386,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, } if (!(s->mode & SSL_MODE_AUTO_RETRY)) { - if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { + if (SSL3_BUFFER_get_left(rbuf) == 0) { /* no read-ahead left? */ BIO *bio; /* @@ -1477,7 +1524,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, } if (!(s->mode & SSL_MODE_AUTO_RETRY)) { - if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { + if (SSL3_BUFFER_get_left(rbuf) == 0) { /* no read-ahead left? */ BIO *bio; /* @@ -1561,7 +1608,7 @@ void ssl3_record_sequence_update(unsigned char *seq) */ int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl) { - return SSL3_RECORD_is_sslv2_record(&rl->rrec); + return SSL3_RECORD_is_sslv2_record(&rl->rrec[0]); } /* @@ -1569,5 +1616,5 @@ int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl) */ unsigned int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl) { - return SSL3_RECORD_get_length(&rl->rrec); + return SSL3_RECORD_get_length(&rl->rrec[0]); } diff --git a/ssl/record/record.h b/ssl/record/record.h index 6105ded..bf3ffa3 100644 --- a/ssl/record/record.h +++ b/ssl/record/record.h @@ -253,13 +253,16 @@ typedef struct record_layer_st { /* where we are when reading */ int rstate; + /* How many pipelines can be used to read data */ + unsigned int numrpipes; + /* How many pipelines can be used to write data */ unsigned int numwpipes; /* read IO goes into here */ SSL3_BUFFER rbuf; /* write IO goes into here */ SSL3_BUFFER wbuf[SSL_MAX_PIPELINES]; /* each decoded record goes in here */ - SSL3_RECORD rrec; + SSL3_RECORD rrec[SSL_MAX_PIPELINES]; /* goes out from here */ SSL3_RECORD wrec; diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h index f44cda1..8239549 100644 --- a/ssl/record/record_locl.h +++ b/ssl/record/record_locl.h @@ -120,7 +120,7 @@ #define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf) #define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf) -#define RECORD_LAYER_get_rrec(rl) (&(rl)->rrec) +#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec) #define RECORD_LAYER_get_wrec(rl) (&(rl)->wrec) #define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p)) #define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0) @@ -128,9 +128,11 @@ #define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st)) #define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence) #define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence) +#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes) +#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n)) #define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch) -__owur int ssl3_read_n(SSL *s, int n, int max, int extend); +__owur int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold); void RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, const unsigned char *ws); DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, @@ -189,13 +191,13 @@ int ssl3_release_write_buffer(SSL *s); #define SSL3_RECORD_is_sslv2_record(r) \ ((r)->rec_version == SSL2_VERSION) -void SSL3_RECORD_clear(SSL3_RECORD *r); -void SSL3_RECORD_release(SSL3_RECORD *r); -int SSL3_RECORD_setup(SSL3_RECORD *r); +void SSL3_RECORD_clear(SSL3_RECORD *r, unsigned int num_recs); +void SSL3_RECORD_release(SSL3_RECORD *r, unsigned int num_recs); +int SSL3_RECORD_setup(SSL3_RECORD *r, unsigned int num_recs); void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num); int ssl3_get_record(SSL *s); __owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr); -__owur int ssl3_do_uncompress(SSL *ssl); +__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr); void ssl3_cbc_copy_mac(unsigned char *out, const SSL3_RECORD *rec, unsigned md_size); __owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec, diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index ad19621..3312262 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -134,27 +134,44 @@ static const unsigned char ssl3_pad_2[48] = { /* * Clear the contents of an SSL3_RECORD but retain any memory allocated */ -void SSL3_RECORD_clear(SSL3_RECORD *r) +void SSL3_RECORD_clear(SSL3_RECORD *r, unsigned int num_recs) { - unsigned char *comp = r->comp; + unsigned char *comp; + unsigned int i; - memset(r, 0, sizeof(*r)); - r->comp = comp; + for (i = 0; i < num_recs; i++) { + comp = r[i].comp; + + memset(&r[i], 0, sizeof(*r)); + r[i].comp = comp; + } } -void SSL3_RECORD_release(SSL3_RECORD *r) +void SSL3_RECORD_release(SSL3_RECORD *r, unsigned int num_recs) { - OPENSSL_free(r->comp); - r->comp = NULL; + unsigned int i; + + for (i = 0; i < num_recs; i++) { + OPENSSL_free(r[i].comp); + r[i].comp = NULL; + } } -int SSL3_RECORD_setup(SSL3_RECORD *r) +int SSL3_RECORD_setup(SSL3_RECORD *r, unsigned int num_recs) { - if (r->comp == NULL) - r->comp = (unsigned char *) - OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); - if (r->comp == NULL) - return 0; + unsigned int i; + + for (i = 0; i < num_recs; i++) { + if (r[i].comp == NULL) + r[i].comp = (unsigned char *) + OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); + if (r[i].comp == NULL) { + if (i > 0) + SSL3_RECORD_release(r, i); + return 0; + } + } + return 1; } @@ -163,6 +180,46 @@ void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num) memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE); } + +/* + * Peeks ahead into "read_ahead" data to see if we have a whole record waiting + * for us in the buffer. + */ +static int have_whole_app_data_record_waiting(SSL *s) +{ + SSL3_BUFFER *rbuf; + int left, len; + unsigned char *p; + + rbuf = RECORD_LAYER_get_rbuf(&s->rlayer); + + p = SSL3_BUFFER_get_buf(rbuf); + if (p == NULL) + return 0; + + left = SSL3_BUFFER_get_left(rbuf); + + if (left < SSL3_RT_HEADER_LENGTH) + return 0; + + p += SSL3_BUFFER_get_offset(rbuf); + + /* + * We only check the type and record length, we will sanity check version + * etc later + */ + if (*p != SSL3_RT_APPLICATION_DATA) + return 0; + + p += 3; + n2s(p, len); + + if (left < SSL3_RT_HEADER_LENGTH + len) + return 0; + + return 1; +} + /* * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that * will be processed per call to ssl3_get_record. Without this limit an @@ -173,13 +230,16 @@ void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num) #define SSL2_RT_HEADER_LENGTH 2 /*- - * Call this to get a new input record. + * Call this to get new input records. * It will return <= 0 if more data is needed, normally due to an error * or non-blocking IO. - * When it finishes, one packet has been decoded and can be found in - * ssl->s3->rrec.type - is the type of record - * ssl->s3->rrec.data, - data - * ssl->s3->rrec.length, - number of bytes + * When it finishes, |numrpipes| records have been decoded. For each record 'i': + * rr[i].type - is the type of record + * rr[i].data, - data + * rr[i].length, - number of bytes + * Multiple records will only be returned if the record types are all + * SSL3_RT_APPLICATION_DATA. The number of records returned will always be <= + * |max_pipelines| */ /* used only by ssl3_read_bytes */ int ssl3_get_record(SSL *s) @@ -187,177 +247,205 @@ int ssl3_get_record(SSL *s) int ssl_major, ssl_minor, al; int enc_err, n, i, ret = -1; SSL3_RECORD *rr; + SSL3_BUFFER *rbuf; SSL_SESSION *sess; unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; short version; unsigned mac_size; - unsigned empty_record_count = 0; + unsigned empty_record_count = 0, curr_empty = 0; + unsigned int num_recs = 0; + unsigned int max_recs; + unsigned int j; rr = RECORD_LAYER_get_rrec(&s->rlayer); + rbuf = RECORD_LAYER_get_rbuf(&s->rlayer); + max_recs = s->max_pipelines; + if (max_recs == 0) + max_recs = 1; sess = s->session; again: - /* check if we have the header */ - if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) || - (RECORD_LAYER_get_packet_length(&s->rlayer) < SSL3_RT_HEADER_LENGTH)) { - n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, - SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0); - if (n <= 0) - return (n); /* error or non-blocking */ - RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY); + do { + /* check if we have the header */ + if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) || + (RECORD_LAYER_get_packet_length(&s->rlayer) + < SSL3_RT_HEADER_LENGTH)) { + n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, + SSL3_BUFFER_get_len(rbuf), 0, num_recs == 0 ? 1 : 0); + if (n <= 0) + return (n); /* error or non-blocking */ + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY); + + p = RECORD_LAYER_get_packet(&s->rlayer); - p = RECORD_LAYER_get_packet(&s->rlayer); - - /* - * Check whether this is a regular record or an SSLv2 style record. The - * latter is only used in an initial ClientHello for old clients. We - * check s->read_hash and s->enc_read_ctx to ensure this does not apply - * during renegotiation - */ - if (s->first_packet && s->server && !s->read_hash && !s->enc_read_ctx - && (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) { - /* SSLv2 style record */ - rr->type = SSL3_RT_HANDSHAKE; - rr->rec_version = SSL2_VERSION; - - rr->length = ((p[0] & 0x7f) << 8) | p[1]; - - if (rr->length > SSL3_BUFFER_get_len(&s->rlayer.rbuf) - - SSL2_RT_HEADER_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; - } + /* + * Check whether this is a regular record or an SSLv2 style record. + * The latter is only used in an initial ClientHello for old + * clients. We check s->read_hash and s->enc_read_ctx to ensure this + * does not apply during renegotiation + */ + if (s->first_packet && s->server && !s->read_hash + && !s->enc_read_ctx + && (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) { + /* SSLv2 style record */ + rr[num_recs].type = SSL3_RT_HANDSHAKE; + rr[num_recs].rec_version = SSL2_VERSION; + + rr[num_recs].length = ((p[0] & 0x7f) << 8) | p[1]; + + if (rr[num_recs].length > SSL3_BUFFER_get_len(&rbuf[num_recs]) + - SSL2_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } - if (rr->length < MIN_SSL2_RECORD_LEN) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - } else { - /* SSLv3+ style record */ - if (s->msg_callback) - s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, - s->msg_callback_arg); - - /* Pull apart the header into the SSL3_RECORD */ - rr->type = *(p++); - ssl_major = *(p++); - ssl_minor = *(p++); - version = (ssl_major << 8) | ssl_minor; - rr->rec_version = version; - n2s(p, rr->length); - - /* Lets check version */ - if (!s->first_packet && version != s->version) { - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); - if ((s->version & 0xFF00) == (version & 0xFF00) - && !s->enc_write_ctx && !s->write_hash) { - if (rr->type == SSL3_RT_ALERT) { + if (rr[num_recs].length < MIN_SSL2_RECORD_LEN) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + } else { + /* SSLv3+ style record */ + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, + s->msg_callback_arg); + + /* Pull apart the header into the SSL3_RECORD */ + rr[num_recs].type = *(p++); + ssl_major = *(p++); + ssl_minor = *(p++); + version = (ssl_major << 8) | ssl_minor; + rr[num_recs].rec_version = version; + n2s(p, rr[num_recs].length); + + /* Lets check version */ + if (!s->first_packet && version != s->version) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + if ((s->version & 0xFF00) == (version & 0xFF00) + && !s->enc_write_ctx && !s->write_hash) { + if (rr->type == SSL3_RT_ALERT) { + /* + * The record is using an incorrect version number, + * but what we've got appears to be an alert. We + * haven't read the body yet to check whether its a + * fatal or not - but chances are it is. We probably + * shouldn't send a fatal alert back. We'll just + * end. + */ + goto err; + } /* - * The record is using an incorrect version number, but - * what we've got appears to be an alert. We haven't - * read the body yet to check whether its a fatal or - * not - but chances are it is. We probably shouldn't - * send a fatal alert back. We'll just end. + * Send back error using their minor version number :-) */ - goto err; + s->version = (unsigned short)version; } - /* - * Send back error using their minor version number :-) - */ - s->version = (unsigned short)version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; } - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - if ((version >> 8) != SSL3_VERSION_MAJOR) { - if (s->first_packet) { - /* Go back to start of packet, look at the five bytes - * that we have. */ - p = RECORD_LAYER_get_packet(&s->rlayer); - if (strncmp((char *)p, "GET ", 4) == 0 || - strncmp((char *)p, "POST ", 5) == 0 || - strncmp((char *)p, "HEAD ", 5) == 0 || - strncmp((char *)p, "PUT ", 4) == 0) { - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST); - goto err; - } else if (strncmp((char *)p, "CONNE", 5) == 0) { - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTPS_PROXY_REQUEST); - goto err; + if ((version >> 8) != SSL3_VERSION_MAJOR) { + if (s->first_packet) { + /* Go back to start of packet, look at the five bytes + * that we have. */ + p = RECORD_LAYER_get_packet(&s->rlayer); + if (strncmp((char *)p, "GET ", 4) == 0 || + strncmp((char *)p, "POST ", 5) == 0 || + strncmp((char *)p, "HEAD ", 5) == 0 || + strncmp((char *)p, "PUT ", 4) == 0) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST); + goto err; + } else if (strncmp((char *)p, "CONNE", 5) == 0) { + SSLerr(SSL_F_SSL3_GET_RECORD, + SSL_R_HTTPS_PROXY_REQUEST); + goto err; + } } + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + goto err; } - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); - goto err; - } - if (rr->length > - SSL3_BUFFER_get_len(&s->rlayer.rbuf) - - SSL3_RT_HEADER_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; + if (rr[num_recs].length > + SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } } + + /* now s->rlayer.rstate == SSL_ST_READ_BODY */ } - /* now s->rlayer.rstate == SSL_ST_READ_BODY */ - } + /* + * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data. + * Calculate how much more data we need to read for the rest of the + * record + */ + if (rr[num_recs].rec_version == SSL2_VERSION) { + i = rr[num_recs].length + SSL2_RT_HEADER_LENGTH + - SSL3_RT_HEADER_LENGTH; + } else { + i = rr[num_recs].length; + } + if (i > 0) { + /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ - /* - * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data. - * Calculate how much more data we need to read for the rest of the record - */ - if (rr->rec_version == SSL2_VERSION) { - i = rr->length + SSL2_RT_HEADER_LENGTH - SSL3_RT_HEADER_LENGTH; - } else { - i = rr->length; - } - if (i > 0) { - /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + n = ssl3_read_n(s, i, i, 1, 0); + if (n <= 0) + return (n); /* error or non-blocking io */ + } - n = ssl3_read_n(s, i, i, 1); - if (n <= 0) - return (n); /* error or non-blocking io */ - } + /* set state for later operations */ + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); - /* set state for later operations */ - RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); + /* + * At this point, s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length, + * or s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length + * and we have that many bytes in s->packet + */ + if(rr[num_recs].rec_version == SSL2_VERSION) { + rr[num_recs].input = + &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]); + } else { + rr[num_recs].input = + &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]); + } - /* - * At this point, s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length, - * or s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length - * and we have that many bytes in s->packet - */ - if(rr->rec_version == SSL2_VERSION) { - rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]); - } else { - rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]); - } + /* + * ok, we can now read from 's->packet' data into 'rr' rr->input points + * at rr->length bytes, which need to be copied into rr->data by either + * the decryption or by the decompression When the data is 'copied' into + * the rr->data buffer, rr->input will be pointed at the new buffer + */ - /* - * ok, we can now read from 's->packet' data into 'rr' rr->input points - * at rr->length bytes, which need to be copied into rr->data by either - * the decryption or by the decompression When the data is 'copied' into - * the rr->data buffer, rr->input will be pointed at the new buffer - */ + /* + * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length + * bytes of encrypted compressed stuff. + */ - /* - * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length - * bytes of encrypted compressed stuff. - */ + /* check is not needed I believe */ + if (rr[num_recs].length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + goto f_err; + } + + /* decrypt in place in 'rr->input' */ + rr[num_recs].data = rr[num_recs].input; + rr[num_recs].orig_len = rr[num_recs].length; + num_recs++; + + /* we have pulled in a full packet so zero things */ + RECORD_LAYER_reset_packet_length(&s->rlayer); + } while (num_recs < max_recs && rr->type == SSL3_RT_APPLICATION_DATA + && SSL_USE_EXPLICIT_IV(s) + && s->enc_read_ctx != NULL + && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) + & EVP_CIPH_FLAG_PIPELINE) + && have_whole_app_data_record_waiting(s)); - /* check is not needed I believe */ - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - goto f_err; - } - /* decrypt in place in 'rr->input' */ - rr->data = rr->input; - rr->orig_len = rr->length; /* * If in encrypt-then-mac mode calculate mac from encrypted record. All * the details below are public so no timing details can leak. @@ -366,23 +454,25 @@ int ssl3_get_record(SSL *s) unsigned char *mac; mac_size = EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - if (rr->length < mac_size) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - rr->length -= mac_size; - mac = rr->data + rr->length; - i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ ); - if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) { - al = SSL_AD_BAD_RECORD_MAC; - SSLerr(SSL_F_SSL3_GET_RECORD, - SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - goto f_err; + for (j = 0; j < num_recs; j++) { + if (rr[j].length < mac_size) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + rr[j].length -= mac_size; + mac = rr[j].data + rr[j].length; + i = s->method->ssl3_enc->mac(s, &rr[j], md, 0 /* not send */ ); + if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) { + al = SSL_AD_BAD_RECORD_MAC; + SSLerr(SSL_F_SSL3_GET_RECORD, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + goto f_err; + } } } - enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0); + enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0); /*- * enc_err is: * 0: (in non-constant time) if the record is publically invalid. @@ -411,50 +501,53 @@ int ssl3_get_record(SSL *s) /* s->read_hash != NULL => mac_size != -1 */ unsigned char *mac = NULL; unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + mac_size = EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - /* - * 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 amount - * of time if it's too short to possibly contain a MAC. - */ - if (rr->orig_len < mac_size || - /* CBC records must have a padding length byte too. */ - (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && - rr->orig_len < mac_size + 1)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - - if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { - /* - * We update the length so that the TLS header bytes can be - * constructed correctly but we need to extract the MAC in - * constant time from within the record, without leaking the - * contents of the padding bytes. - */ - mac = mac_tmp; - ssl3_cbc_copy_mac(mac_tmp, rr, mac_size); - rr->length -= mac_size; - } else { + for (j=0; j < num_recs; j++) { /* - * In this case there's no padding, so |rec->orig_len| equals - * |rec->length| and we checked that there's enough bytes for - * |mac_size| above. + * 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 amount + * of time if it's too short to possibly contain a MAC. */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } + if (rr[j].orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + rr[j].orig_len < mac_size + 1)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } - i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ ); - if (i < 0 || mac == NULL - || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) - enc_err = -1; - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) - enc_err = -1; + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { + /* + * We update the length so that the TLS header bytes can be + * constructed correctly but we need to extract the MAC in + * constant time from within the record, without leaking the + * contents of the padding bytes. + */ + mac = mac_tmp; + ssl3_cbc_copy_mac(mac_tmp, &rr[j], mac_size); + rr[j].length -= mac_size; + } else { + /* + * In this case there's no padding, so |rec->orig_len| equals + * |rec->length| and we checked that there's enough bytes for + * |mac_size| above. + */ + rr[j].length -= mac_size; + mac = &rr[j].data[rr[j].length]; + } + + i = s->method->ssl3_enc->mac(s, &rr[j], md, 0 /* not send */ ); + if (i < 0 || mac == NULL + || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) + enc_err = -1; + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) + enc_err = -1; + } } if (enc_err < 0) { @@ -471,65 +564,68 @@ int ssl3_get_record(SSL *s) goto f_err; } - /* r->length is now just compressed */ - if (s->expand != NULL) { - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG); - goto f_err; + for (j = 0; j < num_recs; j++) { + /* rr[j].length is now just compressed */ + if (s->expand != NULL) { + if (rr[j].length > SSL3_RT_MAX_COMPRESSED_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG); + goto f_err; + } + if (!ssl3_do_uncompress(s, &rr[j])) { + al = SSL_AD_DECOMPRESSION_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION); + goto f_err; + } } - if (!ssl3_do_uncompress(s)) { - al = SSL_AD_DECOMPRESSION_FAILURE; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION); + + if (rr[j].length > SSL3_RT_MAX_PLAIN_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG); goto f_err; } - } - - if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG); - goto f_err; - } - - rr->off = 0; - /*- - * So at this point the following is true - * ssl->s3->rrec.type is the type of record - * ssl->s3->rrec.length == number of bytes in record - * ssl->s3->rrec.off == offset to first valid byte - * ssl->s3->rrec.data == where to take bytes from, increment - * after use :-). - */ - /* we have pulled in a full packet so zero things */ - RECORD_LAYER_reset_packet_length(&s->rlayer); + rr[j].off = 0; + /*- + * So at this point the following is true + * rr[j].type is the type of record + * rr[j].length == number of bytes in record + * rr[j].off == offset to first valid byte + * rr[j].data == where to take bytes from, increment after use :-). + */ - /* just read a 0 length packet */ - if (rr->length == 0) { - empty_record_count++; - if (empty_record_count > MAX_EMPTY_RECORDS) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL); - goto f_err; + /* just read a 0 length packet */ + if (rr[j].length == 0) { + curr_empty++; + empty_record_count++; + if (empty_record_count > MAX_EMPTY_RECORDS) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL); + goto f_err; + } } + } + if (curr_empty == num_recs) { + /* We have no data - do it all again */ + num_recs = 0; + curr_empty = 0; goto again; } - return (1); + RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs); + return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - return (ret); + return ret; } -int ssl3_do_uncompress(SSL *ssl) +int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr) { #ifndef OPENSSL_NO_COMP int i; - SSL3_RECORD *rr; - rr = RECORD_LAYER_get_rrec(&ssl->rlayer); i = COMP_expand_block(ssl->expand, rr->comp, SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length); @@ -827,11 +923,19 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int numpipes, int send) if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) { - /* TODO: We only support writing for pipelining at the moment */ - ret = tls1_cbc_remove_padding(s, recs, bs, mac_size); + int tmpret; + for (ctr = 0; ctr < numpipes; ctr++) { + tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size); + if (tmpret == -1) + return -1; + ret &= tmpret; + } + } + if (pad && !send) { + for (ctr = 0; ctr < numpipes; ctr++) { + recs[ctr].length -= pad; + } } - if (pad && !send) - recs[0].length -= pad; } return ret; } @@ -1388,7 +1492,7 @@ int dtls1_process_record(SSL *s) SSL_R_COMPRESSED_LENGTH_TOO_LONG); goto f_err; } - if (!ssl3_do_uncompress(s)) { + if (!ssl3_do_uncompress(s, rr)) { al = SSL_AD_DECOMPRESSION_FAILURE; SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION); goto f_err; @@ -1469,7 +1573,7 @@ int dtls1_get_record(SSL *s) if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) || (RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) { n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, - SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0); + SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1); /* read timeout is handled by dtls1_read_bytes */ if (n <= 0) return (n); /* error or non-blocking */ @@ -1535,7 +1639,7 @@ int dtls1_get_record(SSL *s) RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) { /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */ i = rr->length; - n = ssl3_read_n(s, i, i, 1); + n = ssl3_read_n(s, i, i, 1, 1); /* this packet contained a partial record, dump it */ if (n != i) { rr->length = 0; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index f27f6ff..92734ea 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -672,6 +672,8 @@ SSL *SSL_new(SSL_CTX *ctx) s->max_send_fragment = ctx->max_send_fragment; s->split_send_fragment = ctx->split_send_fragment; s->max_pipelines = ctx->max_pipelines; + if (s->max_pipelines > 1) + RECORD_LAYER_set_read_ahead(&s->rlayer, 1); CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); s->ctx = ctx; @@ -1694,6 +1696,8 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) if (larg < 1 || larg > SSL_MAX_PIPELINES) return 0; s->max_pipelines = larg; + if (larg > 1) + RECORD_LAYER_set_read_ahead(&s->rlayer, 1); case SSL_CTRL_GET_RI_SUPPORT: if (s->s3) return s->s3->send_connection_binding; |