Commit f7e393be authored by Matt Caswell's avatar Matt Caswell
Browse files

Various fixes required to allow SSL_write/SSL_read during early data

parent d7f8783f
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -1650,7 +1650,6 @@ int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes)
            s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
        }
        *readbytes = 0;
        ossl_statem_set_in_init(s, 1);
        return SSL_READ_EARLY_FINISH;

    default:
@@ -1661,7 +1660,8 @@ int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes)

int ssl_end_of_early_data_seen(SSL *s)
{
    if (s->early_data_state == SSL_EARLY_DATA_READING) {
    if (s->early_data_state == SSL_EARLY_DATA_READING
            || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
        s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
        ossl_statem_finish_early_data(s);
        return 1;
@@ -3242,15 +3242,21 @@ int SSL_do_handshake(SSL *s)
        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_ACCEPTING
            && s->early_data_state != SSL_EARLY_DATA_CONNECTING) {
        SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
            || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
        /*
         * We skip this if we were called via SSL_read_early() or
         * SSL_write_early()
         */
        if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
            int edfin;

            edfin = SSL_write_early_finish(s);
            if (edfin <= 0)
                return edfin;
        }
        ossl_statem_set_in_init(s, 1);
    }

    s->method->ssl_renegotiate_check(s, 0);

+18 −6
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ int ossl_statem_skip_early_data(SSL *s)
        if (s->statem.hand_state != TLS_ST_SW_HELLO_RETRY_REQUEST)
            return 0;
    } else {
        if (s->statem.hand_state != TLS_ST_SW_FINISHED)
        if (!s->server || s->statem.hand_state != TLS_ST_EARLY_DATA)
            return 0;
    }

@@ -171,9 +171,14 @@ int ossl_statem_skip_early_data(SSL *s)
void ossl_statem_check_finish_init(SSL *s, int send)
{
    if (!s->server) {
        if ((send && s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END)
        if ((send && s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
                  && s->early_data_state != SSL_EARLY_DATA_WRITING)
                || (!send && s->statem.hand_state == TLS_ST_EARLY_DATA))
            ossl_statem_set_in_init(s, 1);
    } else {
        if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
                && s->statem.hand_state == TLS_ST_EARLY_DATA)
            ossl_statem_set_in_init(s, 1);
    }
}

@@ -339,9 +344,7 @@ static int state_machine(SSL *s, int server)
                goto end;
            }

        if ((SSL_IS_FIRST_HANDSHAKE(s)
                    && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING
                    && s->early_data_state != SSL_EARLY_DATA_FINISHED_READING)
        if ((SSL_in_before(s))
                || s->renegotiate) {
            if (!tls_setup_handshake(s)) {
                ossl_statem_set_error(s);
@@ -746,8 +749,17 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
            case WORK_FINISHED_STOP:
                return SUB_STATE_END_HANDSHAKE;
            }
            if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
                ossl_statem_set_error(s);
                return SUB_STATE_ERROR;
            }
            if (mt == SSL3_MT_DUMMY) {
                /* Skip construction and sending. This isn't a "real" state */
                st->write_state = WRITE_STATE_POST_WORK;
                st->write_state_work = WORK_MORE_A;
                break;
            }
            if (!WPACKET_init(&pkt, s->init_buf)
                    || !get_construct_message_f(s, &pkt, &confunc, &mt)
                    || !ssl_set_handshake_header(s, &pkt, mt)
                    || (confunc != NULL && !confunc(s, &pkt))
                    || !ssl_close_construct_packet(s, &pkt, mt)
+13 −4
Original line number Diff line number Diff line
@@ -1513,8 +1513,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     */
    if (SSL_IS_TLS13(s)
            && (!s->method->ssl3_enc->setup_key_block(s)
                || !s->method->ssl3_enc->change_cipher_state(s,
                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE)
                || !s->method->ssl3_enc->change_cipher_state(s,
                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
        al = SSL_AD_INTERNAL_ERROR;
@@ -3272,11 +3270,22 @@ int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
                                                          : s->cert->key,
                                &al)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
        ssl3_send_alert(s, SSL3_AL_FATAL, al);
        return 0;
        goto err;
    }

    if (SSL_IS_TLS13(s)
            && SSL_IS_FIRST_HANDSHAKE(s)
            && (!s->method->ssl3_enc->change_cipher_state(s,
                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
               SSL_R_CANNOT_CHANGE_CIPHER);
        goto err;
    }

    return 1;
 err:
    ssl3_send_alert(s, SSL3_AL_FATAL, al);
    return 0;
}

#define has_bits(i,m)   (((i)&(m)) == (m))
+19 −1
Original line number Diff line number Diff line
@@ -442,6 +442,23 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
    const char *sender;
    size_t slen;

    /* This is a real handshake so make sure we clean it up at the end */
    if (!s->server)
        s->statem.cleanuphand = 1;

    /*
     * We only change the keys if we didn't already do this when we sent the
     * client certificate
     */
    if (SSL_IS_TLS13(s)
            && !s->server
            && s->s3->tmp.cert_req == 0
            && (!s->method->ssl3_enc->change_cipher_state(s,
                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
        goto err;
    }

    if (s->server) {
        sender = s->method->ssl3_enc->server_finished_label;
        slen = s->method->ssl3_enc->server_finished_label_len;
@@ -656,6 +673,7 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)


    /* This is a real handshake so make sure we clean it up at the end */
    if (s->server)
        s->statem.cleanuphand = 1;

    /* If this occurs, we have missed a message */
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@
#define EXT_TLS1_3_CERTIFICATE              0x0800
#define EXT_TLS1_3_NEW_SESSION_TICKET       0x1000

/* Dummy message type */
#define SSL3_MT_DUMMY   -1

/* Message processing return codes */
typedef enum {
    /* Something bad happened */
Loading