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

Provide an SSL_read_early() function for reading early data

parent 6cb42265
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -1611,6 +1611,12 @@ __owur int SSL_accept(SSL *ssl);
__owur int SSL_connect(SSL *ssl);
__owur int SSL_read(SSL *ssl, void *buf, int num);
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);

# define SSL_READ_EARLY_ERROR   0
# define SSL_READ_EARLY_SUCCESS 1
# define SSL_READ_EARLY_FINISH  2

__owur int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes);
__owur int SSL_peek(SSL *ssl, void *buf, int num);
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
__owur int SSL_write(SSL *ssl, const void *buf, int num);
@@ -2255,6 +2261,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_SSL_PEEK_EX                                432
# define SSL_F_SSL_PEEK_INTERNAL                          522
# define SSL_F_SSL_READ                                   223
# define SSL_F_SSL_READ_EARLY                             529
# define SSL_F_SSL_READ_EX                                434
# define SSL_F_SSL_READ_INTERNAL                          523
# define SSL_F_SSL_RENEGOTIATE                            516
@@ -2330,7 +2337,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY                489
# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN                    466
# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE             355
# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA              521
# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA              530
# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS           467
# define SSL_F_TLS_CONSTRUCT_CTOS_EMS                     468
# define SSL_F_TLS_CONSTRUCT_CTOS_ETM                     469
@@ -2669,6 +2676,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS       239
# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES           242
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES          243
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA               178
# define SSL_R_UNEXPECTED_MESSAGE                         244
# define SSL_R_UNEXPECTED_RECORD                          245
# define SSL_R_UNINITIALIZED                              276
+8 −0
Original line number Diff line number Diff line
@@ -1437,6 +1437,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                al = SSL_AD_HANDSHAKE_FAILURE;
                SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_NO_RENEGOTIATION);
                goto f_err;
            } else if (alert_descr == SSL_AD_END_OF_EARLY_DATA) {
                if (!ssl_end_of_early_data_seen(s)) {
                    al = SSL_AD_UNEXPECTED_MESSAGE;
                    SSLerr(SSL_F_SSL3_READ_BYTES,
                           SSL_R_UNEXPECTED_END_OF_EARLY_DATA);
                    goto f_err;
                }
                return 0;
            }
        } else if (alert_level == SSL3_AL_FATAL) {
            char tmp[16];
+14 −3
Original line number Diff line number Diff line
@@ -419,15 +419,15 @@ int ssl3_get_record(SSL *s)

    /*-
     * enc_err is:
     *    0: (in non-constant time) if the record is publically invalid.
     *    0: (in non-constant time) if the record is publicly invalid.
     *    1: if the padding is valid
     *    -1: if the padding is invalid
     */
    if (enc_err == 0) {
        if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
            /*
             * We assume this is unreadable early_data - we treat it like an
             * empty record
             * Valid early_data that we cannot decrypt might fail here as
             * publicly invalid. We treat it like an empty record.
             */
            thisrr = &rr[0];
            thisrr->length = 0;
@@ -507,6 +507,17 @@ int ssl3_get_record(SSL *s)
    }

    if (enc_err < 0) {
        if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
            /*
             * We assume this is unreadable early_data - we treat it like an
             * empty record
             */
            thisrr = &rr[0];
            thisrr->length = 0;
            thisrr->read = 1;
            RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
            return 1;
        }
        /*
         * A separate 'decryption_failed' alert was introduced with TLS 1.0,
         * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
+3 −0
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
    {ERR_FUNC(SSL_F_SSL_PEEK_EX), "SSL_peek_ex"},
    {ERR_FUNC(SSL_F_SSL_PEEK_INTERNAL), "ssl_peek_internal"},
    {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
    {ERR_FUNC(SSL_F_SSL_READ_EARLY), "SSL_read_early"},
    {ERR_FUNC(SSL_F_SSL_READ_EX), "SSL_read_ex"},
    {ERR_FUNC(SSL_F_SSL_READ_INTERNAL), "ssl_read_internal"},
    {ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"},
@@ -793,6 +794,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     "unable to load ssl3 md5 routines"},
    {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
     "unable to load ssl3 sha1 routines"},
    {ERR_REASON(SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
     "unexpected end of early data"},
    {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
    {ERR_REASON(SSL_R_UNEXPECTED_RECORD), "unexpected record"},
    {ERR_REASON(SSL_R_UNINITIALIZED), "uninitialized"},
+69 −0
Original line number Diff line number Diff line
@@ -1594,6 +1594,75 @@ int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
    return ret;
}

int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes)
{
    int ret;

    if (!s->server) {
        SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return SSL_READ_EARLY_ERROR;
    }

    /*
     * TODO(TLS1.3): Somehow we need to check that we're not receiving too much
     * data
     */

    switch (s->early_data_state) {
    case SSL_EARLY_DATA_NONE:
        if (!SSL_in_before(s)) {
            SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
            return SSL_READ_EARLY_ERROR;
        }
        /* fall through */

    case SSL_EARLY_DATA_ACCEPT_RETRY:
        s->early_data_state = SSL_EARLY_DATA_ACCEPTING;
        ret = SSL_accept(s);
        if (ret <= 0) {
            /* NBIO or error */
            s->early_data_state = SSL_EARLY_DATA_ACCEPT_RETRY;
            return SSL_READ_EARLY_ERROR;
        }
        /* fall through */

    case SSL_EARLY_DATA_READ_RETRY:
        if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
            s->early_data_state = SSL_EARLY_DATA_READING;
            ret = SSL_read_ex(s, buf, num, readbytes);
            /*
             * Record layer will call ssl_end_of_early_data_seen() if we see
             * that alert - which updates the early_data_state to
             * SSL_EARLY_DATA_FINISHED_READING
             */
            if (ret > 0 || (ret <= 0 && s->early_data_state
                                        != SSL_EARLY_DATA_FINISHED_READING)) {
                s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
                return ret > 0 ? SSL_READ_EARLY_SUCCESS : SSL_READ_EARLY_ERROR;
            }
        } else {
            s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
        }
        *readbytes = 0;
        ossl_statem_set_in_init(s, 1);
        return SSL_READ_EARLY_FINISH;

    default:
        SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return SSL_READ_EARLY_ERROR;
    }
}

int ssl_end_of_early_data_seen(SSL *s)
{
    if (s->early_data_state == SSL_EARLY_DATA_READING) {
        s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
        return 1;
    }

    return 0;
}

static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
    if (s->handshake_func == NULL) {
Loading