diff options
Diffstat (limited to 'ssl/s3_pkt.c')
-rw-r--r-- | ssl/s3_pkt.c | 3053 |
1 files changed, 1509 insertions, 1544 deletions
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 1cd7ee4d47..780acec505 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 @@ -122,177 +122,174 @@ # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 #endif -#if defined(OPENSSL_SMALL_FOOTPRINT) || \ - !( defined(AES_ASM) && ( \ - defined(__x86_64) || defined(__x86_64__) || \ - defined(_M_AMD64) || defined(_M_X64) || \ - defined(__INTEL__) ) \ - ) +#if defined(OPENSSL_SMALL_FOOTPRINT) || \ + !( defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) || \ + defined(__INTEL__) ) \ + ) # undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 #endif 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,len,left; - long align=0; - unsigned char *pkt; - SSL3_BUFFER *rb; - - if (n <= 0) return n; - - rb = &(s->s3->rbuf); - if (rb->buf == NULL) - if (!ssl3_setup_read_buffer(s)) - return -1; - - left = rb->left; +{ + /* + * 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, len, left; + long align = 0; + unsigned char *pkt; + SSL3_BUFFER *rb; + + if (n <= 0) + return n; + + rb = &(s->s3->rbuf); + if (rb->buf == NULL) + if (!ssl3_setup_read_buffer(s)) + return -1; + + left = rb->left; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 - align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; - align = (-align)&(SSL3_ALIGN_PAYLOAD-1); + align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); #endif - if (!extend) - { - /* start with empty packet ... */ - if (left == 0) - rb->offset = align; - else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) - { - /* check if next packet length is large - * enough to justify payload alignment... */ - pkt = rb->buf + rb->offset; - if (pkt[0] == SSL3_RT_APPLICATION_DATA - && (pkt[3]<<8|pkt[4]) >= 128) - { - /* Note that even if packet is corrupted - * and its length field is insane, we can - * only be led to wrong decision about - * whether memmove will occur or not. - * Header values has no effect on memmove - * arguments and therefore no buffer - * overrun can be triggered. */ - memmove (rb->buf+align,pkt,left); - rb->offset = align; - } - } - s->packet = rb->buf + rb->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_IS_DTLS(s)) - { - if (left == 0 && extend) - return 0; - if (left > 0 && n > left) - n = left; - } - - /* if there is enough in the buffer from a previous read, take some */ - if (left >= n) - { - s->packet_length+=n; - rb->left=left-n; - rb->offset+=n; - return(n); - } - - /* else we need to read more data */ - - len = s->packet_length; - pkt = rb->buf+align; - /* Move any available bytes to front of buffer: - * 'len' bytes already pointed to by 'packet', - * 'left' extra ones at the end */ - if (s->packet != pkt) /* len > 0 */ - { - memmove(pkt, s->packet, len+left); - s->packet = pkt; - rb->offset = len + align; - } - - if (n > (int)(rb->len - rb->offset)) /* does not happen */ - { - SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR); - return -1; - } - - if (!s->read_ahead) - /* ignore max parameter */ - max = n; - else - { - if (max < n) - max = n; - if (max > (int)(rb->len - rb->offset)) - max = rb->len - rb->offset; - } - - while (left < n) - { - /* Now we have len+left bytes at the front of s->s3->rbuf.buf - * and need to read in more until we have len+n (up to - * len+max if possible) */ - - clear_sys_error(); - if (s->rbio != NULL) - { - s->rwstate=SSL_READING; - i=BIO_read(s->rbio,pkt+len+left, max-left); - } - else - { - SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); - i = -1; - } - - if (i <= 0) - { - rb->left = left; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && - !SSL_IS_DTLS(s)) - if (len+left == 0) - ssl3_release_read_buffer(s); - return(i); - } - left+=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_IS_DTLS(s)) - { - if (n > left) - n = left; /* makes the while condition false */ - } - } - - /* done reading, now the book-keeping */ - rb->offset += n; - rb->left = left - 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) { + /* start with empty packet ... */ + if (left == 0) + rb->offset = align; + else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) { + /* + * check if next packet length is large enough to justify payload + * alignment... + */ + pkt = rb->buf + rb->offset; + if (pkt[0] == SSL3_RT_APPLICATION_DATA + && (pkt[3] << 8 | pkt[4]) >= 128) { + /* + * Note that even if packet is corrupted and its length field + * is insane, we can only be led to wrong decision about + * whether memmove will occur or not. Header values has no + * effect on memmove arguments and therefore no buffer + * overrun can be triggered. + */ + memmove(rb->buf + align, pkt, left); + rb->offset = align; + } + } + s->packet = rb->buf + rb->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_IS_DTLS(s)) { + if (left == 0 && extend) + return 0; + if (left > 0 && n > left) + n = left; + } + + /* if there is enough in the buffer from a previous read, take some */ + if (left >= n) { + s->packet_length += n; + rb->left = left - n; + rb->offset += n; + return (n); + } + + /* else we need to read more data */ + + len = s->packet_length; + pkt = rb->buf + align; + /* + * Move any available bytes to front of buffer: 'len' bytes already + * pointed to by 'packet', 'left' extra ones at the end + */ + if (s->packet != pkt) { /* len > 0 */ + memmove(pkt, s->packet, len + left); + s->packet = pkt; + rb->offset = len + align; + } + + if (n > (int)(rb->len - rb->offset)) { /* does not happen */ + SSLerr(SSL_F_SSL3_READ_N, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!s->read_ahead) + /* ignore max parameter */ + max = n; + else { + if (max < n) + max = n; + if (max > (int)(rb->len - rb->offset)) + max = rb->len - rb->offset; + } + + while (left < n) { + /* + * Now we have len+left bytes at the front of s->s3->rbuf.buf and + * need to read in more until we have len+n (up to len+max if + * possible) + */ + + clear_sys_error(); + if (s->rbio != NULL) { + s->rwstate = SSL_READING; + i = BIO_read(s->rbio, pkt + len + left, max - left); + } else { + SSLerr(SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET); + i = -1; + } + + if (i <= 0) { + rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + if (len + left == 0) + ssl3_release_read_buffer(s); + return (i); + } + left += 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_IS_DTLS(s)) { + if (n > left) + n = left; /* makes the while condition false */ + } + } + + /* done reading, now the book-keeping */ + rb->offset += n; + rb->left = left - 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 /*- @@ -301,840 +298,821 @@ 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->init_extra) - { - /* 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; - 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; - n2s(p,rr->length); +{ + 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->init_extra) { + /* + * 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; + 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; + n2s(p, rr->length); #if 0 -fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); + fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); #endif - /* 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) && !s->enc_write_ctx && !s->write_hash) - /* 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 > s->s3->rbuf.len - 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->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; - } - + /* 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) + && !s->enc_write_ctx && !s->write_hash) + /* + * 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 > s->s3->rbuf.len - 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->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) && - (EVP_MD_CTX_md(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_CTX_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; - } - + /* r->length is now the compressed data plus mac */ + if ((sess != NULL) && + (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(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_CTX_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; + } #if 0 -fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length); + fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, + rr->length); #endif - return(1); + return (1); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); -err: - return(ret); - } + 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_; - int tot; - unsigned int n,nw; +{ + const unsigned char *buf = buf_; + int tot; + unsigned int n, nw; #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK - unsigned int max_send_fragment; + unsigned int max_send_fragment; #endif - SSL3_BUFFER *wb=&(s->s3->wbuf); - int i; - - 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); |