Commit 564547e4 authored by Matt Caswell's avatar Matt Caswell
Browse files

Enable the client to call SSL_read() without stopping the ability to call SSL_write_early()

parent 4004ce5f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -900,7 +900,8 @@ typedef enum {
    TLS_ST_CW_KEY_UPDATE,
    TLS_ST_SR_KEY_UPDATE,
    TLS_ST_CR_KEY_UPDATE,
    TLS_ST_CW_EARLY_DATA
    TLS_ST_CW_EARLY_DATA,
    TLS_ST_CW_PENDING_EARLY_DATA_END
} OSSL_HANDSHAKE_STATE;

/*
+18 −8
Original line number Diff line number Diff line
@@ -1545,13 +1545,16 @@ int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
        return 0;
    }

    if (s->early_data_state != SSL_EARLY_DATA_NONE
            && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING
            && s->early_data_state != SSL_EARLY_DATA_FINISHED_READING
            && s->early_data_state != SSL_EARLY_DATA_READING) {
    if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
                || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) {
        SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    /*
     * If we are a client and haven't received the ServerHello etc then we
     * better do that
     */
    ossl_statem_check_finish_init(s, 0);

    if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
        struct ssl_async_args args;
@@ -1745,13 +1748,20 @@ int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
        return -1;
    }

    if (s->early_data_state != SSL_EARLY_DATA_NONE
            && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING
            && s->early_data_state != SSL_EARLY_DATA_FINISHED_READING
            && s->early_data_state != SSL_EARLY_DATA_WRITING) {
    if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
        /*
         * We're still writing early data. We need to stop that so we can write
         * normal data
         */
        if (!SSL_write_early_finish(s))
            return 0;
    } else if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
                || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) {
        SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    /* If we are a client and haven't sent the Finished we better do that */
    ossl_statem_check_finish_init(s, 1);

    if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
        int ret;
+7 −0
Original line number Diff line number Diff line
@@ -168,6 +168,13 @@ int ossl_statem_skip_early_data(SSL *s)
    return 1;
}

void ossl_statem_check_finish_init(SSL *s, int send)
{
    if ((send && s->statem.hand_state == TLS_ST_CW_PENDING_EARLY_DATA_END)
            || (!send && s->statem.hand_state == TLS_ST_CW_EARLY_DATA))
        ossl_statem_set_in_init(s, 1);
}

void ossl_statem_set_hello_verify_done(SSL *s)
{
    s->statem.state = MSG_FLOW_UNINITED;
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ void ossl_statem_set_in_init(SSL *s, int init);
int ossl_statem_get_in_handshake(SSL *s);
void ossl_statem_set_in_handshake(SSL *s, int inhand);
__owur int ossl_statem_skip_early_data(SSL *s);
void ossl_statem_check_finish_init(SSL *s, int send);
void ossl_statem_set_hello_verify_done(SSL *s);
__owur int ossl_statem_app_data_allowed(SSL *s);
#ifndef OPENSSL_NO_SCTP
+9 −0
Original line number Diff line number Diff line
@@ -435,6 +435,14 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
        return WRITE_TRAN_CONTINUE;

    case TLS_ST_CR_FINISHED:
        if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
            st->hand_state = TLS_ST_CW_PENDING_EARLY_DATA_END;
        else
            st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
                                                        : TLS_ST_CW_FINISHED;
        return WRITE_TRAN_CONTINUE;

    case TLS_ST_CW_PENDING_EARLY_DATA_END:
        st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
                                                    : TLS_ST_CW_FINISHED;
        return WRITE_TRAN_CONTINUE;
@@ -659,6 +667,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
        break;

    case TLS_ST_CW_EARLY_DATA:
    case TLS_ST_CW_PENDING_EARLY_DATA_END:
    case TLS_ST_OK:
        return tls_finish_handshake(s, wst, 1);
    }