int s2n_read_full_record()

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;
}