diff options
author | Matt Caswell <matt@openssl.org> | 2015-01-22 02:47:42 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2015-01-22 09:52:55 +0000 |
commit | 40720ce3caf44294b5b87a18856b7aef06123314 (patch) | |
tree | 30d57dec407c05fe6ea57275517805e8c79a7dcc /ssl/s3_pkt.c | |
parent | 9d03aabea3ead1fe6a194297ddffd4a87f89b93c (diff) |
Run util/openssl-format-source -v -c .
Reviewed-by: Tim Hudson <tjh@openssl.org>
Diffstat (limited to 'ssl/s3_pkt.c')
-rw-r--r-- | ssl/s3_pkt.c | 2469 |
1 files changed, 1229 insertions, 1240 deletions
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 75cae7f20d..61a863ae00 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -5,21 +5,21 @@ * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +34,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -49,7 +49,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence @@ -63,7 +63,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -118,123 +118,122 @@ #include <openssl/buffer.h> static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len, int create_empty_fragment); + unsigned int len, int create_empty_fragment); static int ssl3_get_record(SSL *s); int ssl3_read_n(SSL *s, int n, int max, int extend) - { - /* If extend == 0, obtain new n-byte packet; if extend == 1, increase - * packet by another n bytes. - * The packet will be in the sub-array of s->s3->rbuf.buf specified - * by s->packet and s->packet_length. - * (If s->read_ahead is set, 'max' bytes may be stored in rbuf - * [plus s->packet_length bytes if extend == 1].) - */ - int i,off,newb; - - if (!extend) - { - /* start with empty packet ... */ - if (s->s3->rbuf.left == 0) - s->s3->rbuf.offset = 0; - s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset; - s->packet_length = 0; - /* ... now we can act as if 'extend' was set */ - } - - /* For DTLS/UDP reads should not span multiple packets - * because the read operation returns the whole packet - * at once (as long as it fits into the buffer). */ - if (SSL_version(s) == DTLS1_VERSION) - { - if (s->s3->rbuf.left == 0 && extend) - return 0; - if ( s->s3->rbuf.left > 0 && n > s->s3->rbuf.left) - n = s->s3->rbuf.left; - } - - /* if there is enough in the buffer from a previous read, take some */ - if (s->s3->rbuf.left >= (int)n) - { - s->packet_length+=n; - s->s3->rbuf.left-=n; - s->s3->rbuf.offset+=n; - return(n); - } - - /* else we need to read more data */ - if (!s->read_ahead) - max=n; - - { - /* avoid buffer overflow */ - int max_max = s->s3->rbuf.len - s->packet_length; - if (max > max_max) - max = max_max; - } - if (n > max) /* does not happen */ - { - SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR); - return -1; - } - - off = s->packet_length; - newb = s->s3->rbuf.left; - /* Move any available bytes to front of buffer: - * 'off' bytes already pointed to by 'packet', - * 'newb' extra ones at the end */ - if (s->packet != s->s3->rbuf.buf) - { - /* off > 0 */ - memmove(s->s3->rbuf.buf, s->packet, off+newb); - s->packet = s->s3->rbuf.buf; - } - - while (newb < n) - { - /* Now we have off+newb bytes at the front of s->s3->rbuf.buf and need - * to read in more until we have off+n (up to off+max if possible) */ - - clear_sys_error(); - if (s->rbio != NULL) - { - s->rwstate=SSL_READING; - i=BIO_read(s->rbio, &(s->s3->rbuf.buf[off+newb]), max-newb); - } - else - { - SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); - i = -1; - } - - if (i <= 0) - { - s->s3->rbuf.left = newb; - return(i); - } - newb+=i; - /* reads should *never* span multiple packets for DTLS because - * the underlying transport protocol is message oriented as opposed - * to byte oriented as in the TLS case. */ - if (SSL_version(s) == DTLS1_VERSION) - { - if (n > newb) - n = newb; /* makes the while condition false */ - } - } - - /* done reading, now the book-keeping */ - s->s3->rbuf.offset = off + n; - s->s3->rbuf.left = newb - n; - s->packet_length += n; - s->rwstate=SSL_NOTHING; - return(n); - } - -/* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that will - * be processed per call to ssl3_get_record. Without this limit an attacker - * could send empty records at a faster rate than we can process and cause - * ssl3_get_record to loop forever. */ +{ + /* + * If extend == 0, obtain new n-byte packet; if extend == 1, increase + * packet by another n bytes. The packet will be in the sub-array of + * s->s3->rbuf.buf specified by s->packet and s->packet_length. (If + * s->read_ahead is set, 'max' bytes may be stored in rbuf [plus + * s->packet_length bytes if extend == 1].) + */ + int i, off, newb; + + if (!extend) { + /* start with empty packet ... */ + if (s->s3->rbuf.left == 0) + s->s3->rbuf.offset = 0; + s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset; + s->packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + /* + * For DTLS/UDP reads should not span multiple packets because the read + * operation returns the whole packet at once (as long as it fits into + * the buffer). + */ + if (SSL_version(s) == DTLS1_VERSION) { + if (s->s3->rbuf.left == 0 && extend) + return 0; + if (s->s3->rbuf.left > 0 && n > s->s3->rbuf.left) + n = s->s3->rbuf.left; + } + + /* if there is enough in the buffer from a previous read, take some */ + if (s->s3->rbuf.left >= (int)n) { + s->packet_length += n; + s->s3->rbuf.left -= n; + s->s3->rbuf.offset += n; + return (n); + } + + /* else we need to read more data */ + if (!s->read_ahead) + max = n; + + { + /* avoid buffer overflow */ + int max_max = s->s3->rbuf.len - s->packet_length; + if (max > max_max) + max = max_max; + } + if (n > max) { /* does not happen */ + SSLerr(SSL_F_SSL3_READ_N, ERR_R_INTERNAL_ERROR); + return -1; + } + + off = s->packet_length; + newb = s->s3->rbuf.left; + /* + * Move any available bytes to front of buffer: 'off' bytes already + * pointed to by 'packet', 'newb' extra ones at the end + */ + if (s->packet != s->s3->rbuf.buf) { + /* off > 0 */ + memmove(s->s3->rbuf.buf, s->packet, off + newb); + s->packet = s->s3->rbuf.buf; + } + + while (newb < n) { + /* + * Now we have off+newb bytes at the front of s->s3->rbuf.buf and + * need to read in more until we have off+n (up to off+max if + * possible) + */ + + clear_sys_error(); + if (s->rbio != NULL) { + s->rwstate = SSL_READING; + i = BIO_read(s->rbio, &(s->s3->rbuf.buf[off + newb]), max - newb); + } else { + SSLerr(SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET); + i = -1; + } + + if (i <= 0) { + s->s3->rbuf.left = newb; + return (i); + } + newb += i; + /* + * reads should *never* span multiple packets for DTLS because the + * underlying transport protocol is message oriented as opposed to + * byte oriented as in the TLS case. + */ + if (SSL_version(s) == DTLS1_VERSION) { + if (n > newb) + n = newb; /* makes the while condition false */ + } + } + + /* done reading, now the book-keeping */ + s->s3->rbuf.offset = off + n; + s->s3->rbuf.left = newb - n; + s->packet_length += n; + s->rwstate = SSL_NOTHING; + return (n); +} + +/* + * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that + * will be processed per call to ssl3_get_record. Without this limit an + * attacker could send empty records at a faster rate than we can process and + * cause ssl3_get_record to loop forever. + */ #define MAX_EMPTY_RECORDS 32 /*- @@ -243,585 +242,585 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) * 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.data, - data * ssl->s3->rrec.length, - number of bytes */ /* used only by ssl3_read_bytes */ static int ssl3_get_record(SSL *s) - { - int ssl_major,ssl_minor,al; - int enc_err,n,i,ret= -1; - SSL3_RECORD *rr; - SSL_SESSION *sess; - unsigned char *p; - unsigned char md[EVP_MAX_MD_SIZE]; - short version; - unsigned mac_size, orig_len; - size_t extra; - unsigned empty_record_count = 0; - - rr= &(s->s3->rrec); - sess=s->session; - - if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) - extra=SSL3_RT_MAX_EXTRA; - else - extra=0; - if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE) - { - /* actually likely an application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER - * set after ssl3_setup_buffers() was done */ - SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR); - return -1; - } - -again: - /* check if we have the header */ - if ( (s->rstate != SSL_ST_READ_BODY) || - (s->packet_length < SSL3_RT_HEADER_LENGTH)) - { - n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); - if (n <= 0) return(n); /* error or non-blocking */ - s->rstate=SSL_ST_READ_BODY; - - p=s->packet; - - /* Pull apart the header into the SSL3_RECORD */ - rr->type= *(p++); - ssl_major= *(p++); - ssl_minor= *(p++); - version=(ssl_major<<8)|ssl_minor; - n2s(p,rr->length); - - /* Lets check version */ - if (!s->first_packet) - { - if (version != s->version) - { - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - if ((s->version & 0xFF00) == (version & 0xFF00)) - /* Send back error using their minor version number :-) */ - s->version = (unsigned short)version; - al=SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - } - - if ((version>>8) != SSL3_VERSION_MAJOR) - { - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - goto err; - } - - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; - } - - /* now s->rstate == SSL_ST_READ_BODY */ - } - - /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ - - if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH) - { - /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ - i=rr->length; - n=ssl3_read_n(s,i,i,1); - if (n <= 0) return(n); /* error or non-blocking io */ - /* now n == rr->length, - * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */ - } - - s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */ - - /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, - * and we have that many bytes in s->packet - */ - rr->input= &(s->packet[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 */ - - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] - * rr->length bytes of encrypted compressed stuff. */ - - /* check is not needed I believe */ - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) - { - 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; - - enc_err = s->method->ssl3_enc->enc(s,0); - /*- - * enc_err is: - * 0: (in non-constant time) if the record is publically invalid. - * 1: if the padding is valid - * -1: if the padding is invalid - */ - if (enc_err == 0) - { - al=SSL_AD_DECRYPTION_FAILED; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - goto f_err; - } - +{ + int ssl_major, ssl_minor, al; + int enc_err, n, i, ret = -1; + SSL3_RECORD *rr; + SSL_SESSION *sess; + unsigned char *p; + unsigned char md[EVP_MAX_MD_SIZE]; + short version; + unsigned mac_size, orig_len; + size_t extra; + unsigned empty_record_count = 0; + + rr = &(s->s3->rrec); + sess = s->session; + + if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) + extra = SSL3_RT_MAX_EXTRA; + else + extra = 0; + if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE) { + /* + * actually likely an application error: + * SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER set after ssl3_setup_buffers() + * was done + */ + SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR); + return -1; + } + + again: + /* check if we have the header */ + if ((s->rstate != SSL_ST_READ_BODY) || + (s->packet_length < SSL3_RT_HEADER_LENGTH)) { + n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); + if (n <= 0) + return (n); /* error or non-blocking */ + s->rstate = SSL_ST_READ_BODY; + + p = s->packet; + + /* Pull apart the header into the SSL3_RECORD */ + rr->type = *(p++); + ssl_major = *(p++); + ssl_minor = *(p++); + version = (ssl_major << 8) | ssl_minor; + n2s(p, rr->length); + + /* Lets check version */ + if (!s->first_packet) { + if (version != s->version) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + if ((s->version & 0xFF00) == (version & 0xFF00)) + /* + * Send back error using their minor version number :-) + */ + s->version = (unsigned short)version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + } + + if ((version >> 8) != SSL3_VERSION_MAJOR) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + goto err; + } + + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } + + /* now s->rstate == SSL_ST_READ_BODY */ + } + + /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + + if (rr->length > s->packet_length - SSL3_RT_HEADER_LENGTH) { + /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + i = rr->length; + n = ssl3_read_n(s, i, i, 1); + if (n <= 0) + return (n); /* error or non-blocking io */ + /* + * now n == rr->length, and s->packet_length == SSL3_RT_HEADER_LENGTH + * + rr->length + */ + } + + s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */ + + /* + * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, + * and we have that many bytes in s->packet + */ + rr->input = &(s->packet[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 + */ + + /* + * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length + * bytes of encrypted compressed stuff. + */ + + /* check is not needed I believe */ + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) { + 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; + + enc_err = s->method->ssl3_enc->enc(s, 0); + /*- + * enc_err is: + * 0: (in non-constant time) if the record is publically invalid. + * 1: if the padding is valid + * -1: if the padding is invalid + */ + if (enc_err == 0) { + al = SSL_AD_DECRYPTION_FAILED; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + goto f_err; + } #ifdef TLS_DEBUG -printf("dec %d\n",rr->length); -{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } -printf("\n"); + printf("dec %d\n", rr->length); + { + unsigned int z; + for (z = 0; z < rr->length; z++) + printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n'); + } + printf("\n"); #endif - /* r->length is now the compressed data plus mac */ - if ((sess != NULL) && - (s->enc_read_ctx != NULL) && - (s->read_hash != NULL)) - { - /* s->read_hash != NULL => mac_size != -1 */ - unsigned char *mac = NULL; - unsigned char mac_tmp[EVP_MAX_MD_SIZE]; - 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 - * amount of time if it's too short to possibly contain a MAC. - */ - if (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 && - 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, orig_len); - rr->length -= mac_size; - } - else - { - /* In this case there's no padding, so |orig_len| - * equals |rec->length| and we checked that there's - * enough bytes for |mac_size| above. */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } - - i=s->method->ssl3_enc->mac(s,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+extra+mac_size) - enc_err = -1; - } - - if (enc_err < 0) - { - /* A separate 'decryption_failed' alert was introduced with TLS 1.0, - * SSL 3.0 only has 'bad_record_mac'. But unless a decryption - * failure is directly visible from the ciphertext anyway, - * we should not reveal which kind of error occured -- this - * might become visible to an attacker (e.g. via a logfile) */ - al=SSL_AD_BAD_RECORD_MAC; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - goto f_err; - } - - /* r->length is now just compressed */ - if (s->expand != NULL) - { - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) - { - 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)) - { - al=SSL_AD_DECOMPRESSION_FAILURE; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); - goto f_err; - } - } - - if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) - { - 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 */ - s->packet_length=0; - - /* 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; - } - goto again; - } - - return(1); - -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); -err: - return(ret); - } + /* r->length is now the compressed data plus mac */ + if ((sess != NULL) && (s->enc_read_ctx != NULL) && (s->read_hash != NULL)) { + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + 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 amount + * of time if it's too short to possibly contain a MAC. + */ + if (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 && + 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, orig_len); + rr->length -= mac_size; + } else { + /* + * In this case there's no padding, so |orig_len| equals + * |rec->length| and we checked that there's enough bytes for + * |mac_size| above. + */ + rr->length -= mac_size; + mac = &rr->data[rr->length]; + } + + i = s->method->ssl3_enc->mac(s, 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 + extra + mac_size) + enc_err = -1; + } + + if (enc_err < 0) { + /* + * A separate 'decryption_failed' alert was introduced with TLS 1.0, + * SSL 3.0 only has 'bad_record_mac'. But unless a decryption + * failure is directly visible from the ciphertext anyway, we should + * not reveal which kind of error occured -- this might become + * visible to an attacker (e.g. via a logfile) + */ + al = SSL_AD_BAD_RECORD_MAC; + SSLerr(SSL_F_SSL3_GET_RECORD, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + goto f_err; + } + + /* r->length is now just compressed */ + if (s->expand != NULL) { + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) { + 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)) { + al = SSL_AD_DECOMPRESSION_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION); + goto f_err; + } + } + + if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) { + 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 */ + s->packet_length = 0; + + /* 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; + } + goto again; + } + + return (1); + + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (ret); +} int ssl3_do_uncompress(SSL *ssl) - { +{ #ifndef OPENSSL_NO_COMP - int i; - SSL3_RECORD *rr; - - rr= &(ssl->s3->rrec); - i=COMP_expand_block(ssl->expand,rr->comp, - SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); - if (i < 0) - return(0); - else - rr->length=i; - rr->data=rr->comp; + int i; + SSL3_RECORD *rr; + + rr = &(ssl->s3->rrec); + i = COMP_expand_block(ssl->expand, rr->comp, + SSL3_RT_MAX_PLAIN_LENGTH, rr->data, + (int)rr->length); + if (i < 0) + return (0); + else + rr->length = i; + rr->data = rr->comp; #endif - return(1); - } + return (1); +} int ssl3_do_compress(SSL *ssl) - { +{ #ifndef OPENSSL_NO_COMP - int i; - SSL3_RECORD *wr; - - wr= &(ssl->s3->wrec); - i=COMP_compress_block(ssl->compress,wr->data, - SSL3_RT_MAX_COMPRESSED_LENGTH, - wr->input,(int)wr->length); - if (i < 0) - return(0); - else - wr->length=i; - - wr->input=wr->data; + int i; + SSL3_RECORD *wr; + + wr = &(ssl->s3->wrec); + i = COMP_compress_block(ssl->compress, wr->data, + SSL3_RT_MAX_COMPRESSED_LENGTH, + wr->input, (int)wr->length); + if (i < 0) + return (0); + else + wr->length = i; + + wr->input = wr->data; #endif - return(1); - } + return (1); +} -/* Call this to write data in records of type 'type' - * It will return <= 0 if not all data has been sent or non-blocking IO. +/* + * Call this to write data in records of type 'type' It will return <= 0 if + * not all data has been sent or non-blocking IO. */ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) - { - const unsigned char *buf=buf_; - 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; - - if (SSL_in_init(s) && !s->in_handshake) - { - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return -1; - } - } - - /* 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 (;;) - { - if (n > SSL3_RT_MAX_PLAIN_LENGTH) - nw=SSL3_RT_MAX_PLAIN_LENGTH; - else - nw=n; - - i=do_ssl3_write(s, type, &(buf[tot]), nw, 0); - if (i <= 0) - { - s->s3->wnum=tot; - return i; - } - - if ((i == (int)n) || - (type == SSL3_RT_APPLICATION_DATA && - (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) - { - /* next chunk of data should get another prepended empty fragment - * in ciphersuites with known-IV weakness: */ - s->s3->empty_fragment_done = 0; - - return tot+i; - } - - n-=i; - tot+=i; - } - } +{ + const unsigned char *buf = buf_; + 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; + + if (SSL_in_init(s) && !s->in_handshake) { + i = s->handshake_func(s); + if (i < 0) + return (i); + if (i == 0) { + SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + /* + * 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 (;;) { + if (n > SSL3_RT_MAX_PLAIN_LENGTH) + nw = SSL3_RT_MAX_PLAIN_LENGTH; + else + nw = n; + + i = do_ssl3_write(s, type, &(buf[tot]), nw, 0); + if (i <= 0) { + s->s3->wnum = tot; + return i; + } + + if ((i == (int)n) || + (type == SSL3_RT_APPLICATION_DATA && + (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { + /* + * next chunk of data should get another prepended empty fragment + * in ciphersuites with known-IV weakness: + */ + s->s3->empty_fragment_done = 0; + + return tot + i; + } + + n -= i; + tot += i; + } +} static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len, int create_empty_fragment) - { - unsigned char *p,*plen; - int i,mac_size,clear=0; - int prefix_len = 0; - SSL3_RECORD *wr; - SSL3_BUFFER *wb; - SSL_SESSION *sess; - - /* first check if there is a |