Provide a function to test whether we have unread records pending
[openssl.git] / ssl / ssl_lib.c
index 8e28786447c86feeb0e1dd0c432f54969a33ddc5..581941ecb3099bd6fe4488a8d31b5159682cab48 100644 (file)
@@ -105,6 +105,8 @@ static const struct {
     },
 };
 
+static int ssl_write_early_finish(SSL *s);
+
 static int dane_ctx_enable(struct dane_ctx_st *dctx)
 {
     const EVP_MD **mdevp;
@@ -1015,6 +1017,7 @@ void SSL_free(SSL *s)
 #endif
     OPENSSL_free(s->ext.ocsp.resp);
     OPENSSL_free(s->ext.alpn);
+    OPENSSL_free(s->ext.tls13_cookie);
     OPENSSL_free(s->clienthello);
 
     sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
@@ -1320,7 +1323,7 @@ int SSL_has_pending(const SSL *s)
      * data. That data may not result in any application data, or we may fail
      * to parse the records for some reason.
      */
-    if (SSL_pending(s))
+    if (RECORD_LAYER_processed_read_pending(&s->rlayer))
         return 1;
 
     return RECORD_LAYER_read_pending(&s->rlayer);
@@ -1545,6 +1548,17 @@ int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
         return 0;
     }
 
+    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;
         int ret;
@@ -1594,6 +1608,78 @@ int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
     return ret;
 }
 
+int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes)
+{
+    int ret;
+
+    if (!s->server) {
+        SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return SSL_READ_EARLY_DATA_ERROR;
+    }
+
+    switch (s->early_data_state) {
+    case SSL_EARLY_DATA_NONE:
+        if (!SSL_in_before(s)) {
+            SSLerr(SSL_F_SSL_READ_EARLY_DATA,
+                   ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+            return SSL_READ_EARLY_DATA_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_DATA_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_DATA_SUCCESS
+                               : SSL_READ_EARLY_DATA_ERROR;
+            }
+        } else {
+            s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+        }
+        *readbytes = 0;
+        return SSL_READ_EARLY_DATA_FINISH;
+
+    default:
+        SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return SSL_READ_EARLY_DATA_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_READ_RETRY) {
+        s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+        ossl_statem_finish_early_data(s);
+        return 1;
+    }
+
+    return 0;
+}
+
+int SSL_get_early_data_status(const SSL *s)
+{
+    return s->ext.early_data;
+}
+
 static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
 {
     if (s->handshake_func == NULL) {
@@ -1667,9 +1753,21 @@ 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_WRITE_RETRY
-            || s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY)
+    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
+                || s->early_data_state == SSL_EARLY_DATA_READ_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;
@@ -1720,24 +1818,18 @@ int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
     return ret;
 }
 
-int SSL_write_early(SSL *s, const void *buf, size_t num, size_t *written)
+int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
 {
     int ret;
 
-    if (s->server) {
-        SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-        return 0;
-    }
-
-    /*
-     * TODO(TLS1.3): Somehow we need to check that we're not sending too much
-     * data
-     */
-
     switch (s->early_data_state) {
     case SSL_EARLY_DATA_NONE:
-        if (!SSL_in_before(s)) {
-            SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        if (s->server
+                || !SSL_in_before(s)
+                || s->session == NULL
+                || s->session->ext.max_early_data == 0) {
+            SSLerr(SSL_F_SSL_WRITE_EARLY_DATA,
+                   ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
             return 0;
         }
         /* fall through */
@@ -1758,13 +1850,20 @@ int SSL_write_early(SSL *s, const void *buf, size_t num, size_t *written)
         s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
         return ret;
 
+    case SSL_EARLY_DATA_READ_RETRY:
+        /* We are a server writing to an unauthenticated client */
+        s->early_data_state = SSL_EARLY_DATA_UNAUTH_WRITING;
+        ret = SSL_write_ex(s, buf, num, written);
+        s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
+        return ret;
+
     default:
-        SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
         return 0;
     }
 }
 
-int SSL_write_early_finish(SSL *s)
+static int ssl_write_early_finish(SSL *s)
 {
     int ret;
 
@@ -2697,6 +2796,12 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 
     ret->ext.status_type = TLSEXT_STATUSTYPE_nothing;
 
+    /*
+     * Default max early data is a fully loaded single record. Could be split
+     * across multiple records in practice
+     */
+    ret->max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
+
     return ret;
  err:
     SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
@@ -3147,9 +3252,14 @@ int SSL_do_handshake(SSL *s)
         return -1;
     }
 
-    if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
-            || s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY)
-        return -1;
+    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_check_finish_init(s, -1);
 
     s->method->ssl_renegotiate_check(s, 0);
 
@@ -4744,7 +4854,7 @@ int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data)
     return 1;
 }
 
-uint32_t SSL_CTX_get_max_early_data(SSL_CTX *ctx)
+uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx)
 {
     return ctx->max_early_data;
 }
@@ -4756,7 +4866,7 @@ int SSL_set_max_early_data(SSL *s, uint32_t max_early_data)
     return 1;
 }
 
-uint32_t SSL_get_max_early_data(SSL_CTX *s)
+uint32_t SSL_get_max_early_data(const SSL_CTX *s)
 {
     return s->max_early_data;
 }