in tls/s2n_recv.c [91:157]
int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int *isSSLv2)
{
*isSSLv2 = 0;
if (conn->ktls_recv_enabled) {
return s2n_ktls_read_full_record(conn, record_type);
}
/* If the record has already been decrypted, then leave it alone */
if (conn->in_status == PLAINTEXT) {
/* Only application data packets count as plaintext */
*record_type = TLS_APPLICATION_DATA;
return S2N_SUCCESS;
}
/* Read the record until we at least have a header */
POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
uint32_t header_available = s2n_stuffer_data_available(&conn->header_in);
if (header_available < S2N_TLS_RECORD_HEADER_LENGTH) {
uint32_t header_remaining = S2N_TLS_RECORD_HEADER_LENGTH - header_available;
s2n_result ret = s2n_recv_buffer_in(conn, header_remaining);
uint32_t header_read = MIN(header_remaining, s2n_stuffer_data_available(&conn->buffer_in));
POSIX_GUARD(s2n_stuffer_copy(&conn->buffer_in, &conn->header_in, header_read));
POSIX_GUARD_RESULT(ret);
}
uint16_t fragment_length = 0;
/* If the first bit is set then this is an SSLv2 record */
if (conn->header_in.blob.data[0] & S2N_TLS_SSLV2_HEADER_FLAG) {
*isSSLv2 = 1;
WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_sslv2_record_header_parse(conn, record_type, &conn->client_protocol_version, &fragment_length)));
} else {
WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_record_header_parse(conn, record_type, &fragment_length)));
}
/* Read enough to have the whole record */
uint32_t fragment_available = s2n_stuffer_data_available(&conn->in);
if (fragment_available < fragment_length || fragment_length == 0) {
POSIX_GUARD(s2n_stuffer_rewind_read(&conn->buffer_in, fragment_available));
s2n_result ret = s2n_recv_buffer_in(conn, fragment_length);
uint32_t fragment_read = MIN(fragment_length, s2n_stuffer_data_available(&conn->buffer_in));
POSIX_GUARD_RESULT(s2n_recv_in_init(conn, fragment_read, fragment_length));
POSIX_GUARD_RESULT(ret);
}
if (*isSSLv2) {
return 0;
}
/* Decrypt and parse the record */
if (s2n_early_data_is_trial_decryption_allowed(conn, *record_type)) {
POSIX_ENSURE(s2n_record_parse(conn) >= S2N_SUCCESS, S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
} else {
WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_record_parse(conn)));
}
/* In TLS 1.3, encrypted handshake records would appear to be of record type
* TLS_APPLICATION_DATA. The actual record content type is found after the encrypted
* is decrypted.
*/
if (conn->actual_protocol_version == S2N_TLS13 && *record_type == TLS_APPLICATION_DATA) {
POSIX_GUARD(s2n_tls13_parse_record_type(&conn->in, record_type));
}
return 0;
}