/* Provenance: openssl/openssl tls_get_more_records (fixed). * repo: openssl/openssl * commit: 2b9e2afc382490592078cdb69d06f54f0fefd4c6 * parent: 7b2625274f5d5ec90aee522ec4e4f3aa08fa5b70 * commit_url: https://github.com/openssl/openssl/commit/2b9e2afc382490592078cdb69d06f54f0fefd4c6 * cve: CVE-2021-3449 * license: OpenSSL License * function: tls_get_more_records * relpath: ssl/record/methods/tls_common.c */ int tls_get_more_records(OSSL_RECORD_LAYER *rl) { int enc_err, rret; int i; size_t more, n; TLS_RL_RECORD *rr, *thisrr; TLS_BUFFER *rbuf; unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; unsigned int version; size_t mac_size = 0; int imac_size; size_t num_recs = 0, max_recs, j; PACKET pkt, sslv2pkt; SSL_MAC_BUF *macbufs = NULL; int ret = OSSL_RECORD_RETURN_FATAL; rr = rl->rrec; rbuf = &rl->rbuf; if (rbuf->buf == NULL) { if (!tls_setup_read_buffer(rl)) { /* RLAYERfatal() already called */ return OSSL_RECORD_RETURN_FATAL; } } max_recs = rl->max_pipelines; if (max_recs == 0) max_recs = 1; do { thisrr = &rr[num_recs]; /* check if we have the header */ if ((rl->rstate != SSL_ST_READ_BODY) || (rl->packet_length < SSL3_RT_HEADER_LENGTH)) { size_t sslv2len; unsigned int type; rret = rl->funcs->read_n(rl, SSL3_RT_HEADER_LENGTH, TLS_BUFFER_get_len(rbuf), 0, num_recs == 0 ? 1 : 0, &n); if (rret < OSSL_RECORD_RETURN_SUCCESS) return rret; /* error or non-blocking */ rl->rstate = SSL_ST_READ_BODY; p = rl->packet; if (!PACKET_buf_init(&pkt, p, rl->packet_length)) { RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return OSSL_RECORD_RETURN_FATAL; } sslv2pkt = pkt; if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len) || !PACKET_get_1(&sslv2pkt, &type)) { RLAYERfatal(rl, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR); return OSSL_RECORD_RETURN_FATAL; } /* * The first record received by the server may be a V2ClientHello. */ if (rl->role == OSSL_RECORD_ROLE_SERVER && rl->is_first_record && (sslv2len & 0x8000) != 0 && (type == SSL2_MT_CLIENT_HELLO)) { /* * SSLv2 style record * * |num_recs| here will actually always be 0 because * |num_recs > 0| only ever occurs when we are processing * multiple app data records - which we know isn't the case here * because it is an SSLv2ClientHello. We keep it using * |num_recs| for the sake of consistency */ thisrr->type = SSL3_RT_HANDSHAKE; thisrr->rec_version = SSL2_VERSION; thisrr->length = sslv2len & 0x7fff; if (thisrr->length > TLS_BUFFER_get_len(rbuf) - SSL2_RT_HEADER_LENGTH) { RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_PACKET_LENGTH_TOO_LONG); return OSSL_RECORD_RETURN_FATAL; } } else { /* SSLv3+ style record */ /* Pull apart the header into the TLS_RL_RECORD */ if (!PACKET_get_1(&pkt, &type) || !PACKET_get_net_2(&pkt, &version) || !PACKET_get_net_2_len(&pkt, &thisrr->length)) { if (rl->msg_callback != NULL) rl->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, rl->cbarg); RLAYERfatal(rl, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR); return OSSL_RECORD_RETURN_FATAL; } thisrr->type = type; thisrr->rec_version = version; /* * When we call validate_record_header() only records actually * received in SSLv2 format should have the record version set * to SSL2_VERSION. This way validate_record_header() can know * what format the record was in based on the version. */ if (thisrr->rec_version == SSL2_VERSION) { RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, SSL_R_WRONG_VERSION_NUMBER); return OSSL_RECORD_RETURN_FATAL; } if (rl->msg_callback != NULL) rl->msg_callback(0, version, SSL3_RT_HEADER, p, 5, rl->cbarg); if (thisrr->length > TLS_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) { RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_PACKET_LENGTH_TOO_LONG); return OSSL_RECORD_RETURN_FATAL; } } if (!rl->funcs->validate_record_header(rl, thisrr)) { /* RLAYERfatal already called */ return OSSL_RECORD_RETURN_FATAL; } /* now rl->rstate == SSL_ST_READ_BODY */ } /* * rl->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 (thisrr->rec_version == SSL2_VERSION) { more = thisrr->length + SSL2_RT_HEADER_LENGTH - SSL3_RT_HEADER_LENGTH; } else { more = thisrr->length; } if (more > 0) { /* now rl->packet_length == SSL3_RT_HEADER_LENGTH */ rret = rl->funcs->read_n(rl, more, more, 1, 0, &n); if (rret < OSSL_RECORD_RETURN_SUCCESS) return rret; /* error or non-blocking io */ } /* set state for later operations */ rl->rstate = SSL_ST_READ_HEADER; /* * At this point, rl->packet_length == SSL3_RT_HEADER_LENGTH * + thisrr->length, or rl->packet_length == SSL2_RT_HEADER_LENGTH * + thisrr->length and we have that many bytes in rl->packet */ if (thisrr->rec_version == SSL2_VERSION) thisrr->input = &(rl->packet[SSL2_RT_HEADER_LENGTH]); else thisrr->input = &(rl->packet[SSL3_RT_HEADER_LENGTH]); /* * ok, we can now read from 'rl->packet' data into 'thisrr'. * thisrr->input points at thisrr->length bytes, which need to be copied * into thisrr->data by either the decryption or by the decompression. * When the data is 'copied' into the thisrr->data buffer, * thisrr->input will be updated to point at the new buffer */ /* * We now have - encrypted [ MAC [ compressed [ plain ] ] ] * thisrr->length bytes of encrypted compressed stuff. */ /* decrypt in place in 'thisrr->input' */ thisrr->data = thisrr->input; thisrr->orig_len = thisrr->length; num_recs++; /* we have pulled in a full packet so zero things */ rl->packet_length = 0; rl->is_first_record = 0; } while (num_recs < max_recs && thisrr->type == SSL3_RT_APPLICATION_DATA && RLAYER_USE_EXPLICIT_IV(rl) && rl->enc_ctx != NULL && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(rl->enc_ctx)) & EVP_CIPH_FLAG_PIPELINE) != 0 && tls_record_app_data_waiting(rl)); if (num_recs == 1 && thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC /* The following can happen in tlsany_meth after HRR */ && rl->version == TLS1_3_VERSION && rl->is_first_handshake) { /* * CCS messages must be exactly 1 byte long, containing the value 0x01 */ if (thisrr->length != 1 || thisrr->data[0] != 0x01) { RLAYERfatal(rl, SSL_AD_ILLEGAL_PARAMETER, SSL_R_INVALID_CCS_MESSAGE); return OSSL_RECORD_RETURN_FATAL; } /* * CCS messages are ignored in TLSv1.3. We treat it like an empty * handshake record */ thisrr->type = SSL3_RT_HANDSHAKE; if (++(rl->empty_record_count) > MAX_EMPTY_RECORDS) { RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_CCS_MESSAGE); return OSSL_RECORD_RETURN_FATAL; } rl->num_recs = 0; rl->curr_rec = 0; rl->num_released = 0; return OSSL_RECORD_RETURN_SUCCESS; } if (rl->md_ctx != NULL) { const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(rl->md_ctx); if (tmpmd != NULL) { imac_size = EVP_MD_get_size(tmpmd); if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) { RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); return OSSL_RECORD_RETURN_FATAL; } mac_size = (size_t)imac_size; } } /* * If in encrypt-then-mac mode calculate mac from encrypted record. All * the details below are public so no timing details can leak. */ if (rl->use_etm && rl->md_ctx != NULL) { unsigned char *mac; for (j = 0; j < num_recs; j++) { thisrr = &rr[j]; if (thisrr->length < mac_size) { RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT); return OSSL_RECORD_RETURN_FATAL; } thisrr->length -= mac_size; mac = thisrr->data + thisrr->length; i = rl->funcs->mac(rl, thisrr, md, 0 /* not send */); if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) { RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); return OSSL_RECORD_RETURN_FATAL; } } /* * We've handled the mac now - there is no MAC inside the encrypted * record */ mac_size = 0; } if (mac_size > 0) { macbufs = OPENSSL_zalloc(sizeof(*macbufs) * num_recs); if (macbufs == NULL) { RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB); return OSSL_RECORD_RETURN_FATAL; } } enc_err = rl->funcs->cipher(rl, rr, num_recs, 0, macbufs, mac_size); /*- * enc_err is: * 0: if the record is publicly invalid, or an internal error, or AEAD * decryption failed, or ETM decryption failed. * 1: Success or MTE decryption failed (MAC will be randomised) */ if (enc_err == 0) { if (rl->alert != SSL_AD_NO_ALERT) { /* RLAYERfatal() already got called */ goto end; } if (num_recs == 1 && rl->skip_early_data != NULL && rl->skip_early_data(rl->cbarg)) { /* * Valid early_data that we cannot decrypt will fail here. We treat * it like an empty record. */ thisrr = &rr[0]; if (!rlayer_early_data_count_ok(rl, thisrr->length, EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) { /* RLAYERfatal() already called */ goto end; } thisrr->length = 0; rl->num_recs = 0; rl->curr_rec = 0; rl->num_released = 0; /* Reset the read sequence */ memset(rl->sequence, 0, sizeof(rl->sequence)); ret = 1; goto end; } RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); goto end; } OSSL_TRACE_BEGIN(TLS) { BIO_printf(trc_out, "dec %lu\n", (unsigned long)rr[0].length); BIO_dump_indent(trc_out, rr[0].data, rr[0].length, 4); } OSSL_TRACE_END(TLS); /* r->length is now the compressed data plus mac */ if (rl->enc_ctx != NULL && !rl->use_etm && EVP_MD_CTX_get0_md(rl->md_ctx) != NULL) { for (j = 0; j < num_recs; j++) { SSL_MAC_BUF *thismb = &macbufs[j]; thisrr = &rr[j]; i = rl->funcs->mac(rl, thisrr, md, 0 /* not send */); if (i == 0 || thismb == NULL || thismb->mac == NULL || CRYPTO_memcmp(md, thismb->mac, (size_t)mac_size) != 0) enc_err = 0; if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) enc_err = 0; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (enc_err == 0 && mac_size > 0 && (md[0] ^ thismb->mac[0]) != 0xFF) { enc_err = 1; } #endif } } if (enc_err == 0) { if (rl->alert != SSL_AD_NO_ALERT) { /* We already called RLAYERfatal() */ goto end; } /* * 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 occurred -- this might become * visible to an attacker (e.g. via a logfile) */ RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); goto end; } for (j = 0; j < num_recs; j++) { thisrr = &rr[j]; if (!rl->funcs->post_process_record(rl, thisrr)) { /* RLAYERfatal already called */ goto end; } /* * Check if the received packet overflows the current * Max Fragment Length setting. * Note: rl->max_frag_len > 0 and KTLS are mutually exclusive. */ if (thisrr->length > rl->max_frag_len) { RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); goto end; } thisrr->off = 0; /*- * So at this point the following is true * thisrr->type is the type of record * thisrr->length == number of bytes in record * thisrr->off == offset to first valid byte * thisrr->data == where to take bytes from, increment after use :-). */ /* just read a 0 length packet */ if (thisrr->length == 0) { if (++(rl->empty_record_count) > MAX_EMPTY_RECORDS) { RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_RECORD_TOO_SMALL); goto end; } } else { rl->empty_record_count = 0; } } if (rl->level == OSSL_RECORD_PROTECTION_LEVEL_EARLY) { thisrr = &rr[0]; if (thisrr->type == SSL3_RT_APPLICATION_DATA && !rlayer_early_data_count_ok(rl, thisrr->length, 0, 0)) { /* RLAYERfatal already called */ goto end; } } rl->num_recs = num_recs; rl->curr_rec = 0; rl->num_released = 0; ret = OSSL_RECORD_RETURN_SUCCESS; end: if (macbufs != NULL) { for (j = 0; j < num_recs; j++) { if (macbufs[j].alloced) OPENSSL_free(macbufs[j].mac); } OPENSSL_free(macbufs); } return ret; }