},
};
+static int ssl_write_early_finish(SSL *s);
+
static int dane_ctx_enable(struct dane_ctx_st *dctx)
{
const EVP_MD **mdevp;
s->mode = ctx->mode;
s->max_cert_list = ctx->max_cert_list;
s->references = 1;
+ s->max_early_data = ctx->max_early_data;
/*
* Earlier library versions used to copy the pointer to the CERT, not
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;
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) {
return -1;
}
+ 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;
struct ssl_async_args args;
return ret;
}
+int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
+{
+ int ret;
+
+ switch (s->early_data_state) {
+ case SSL_EARLY_DATA_NONE:
+ 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 */
+
+ case SSL_EARLY_DATA_CONNECT_RETRY:
+ s->early_data_state = SSL_EARLY_DATA_CONNECTING;
+ ret = SSL_connect(s);
+ if (ret <= 0) {
+ /* NBIO or error */
+ s->early_data_state = SSL_EARLY_DATA_CONNECT_RETRY;
+ return 0;
+ }
+ /* fall through */
+
+ case SSL_EARLY_DATA_WRITE_RETRY:
+ s->early_data_state = SSL_EARLY_DATA_WRITING;
+ ret = SSL_write_ex(s, buf, num, 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_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+}
+
+static int ssl_write_early_finish(SSL *s)
+{
+ int ret;
+
+ if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY) {
+ SSLerr(SSL_F_SSL_WRITE_EARLY_FINISH, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_WRITING;
+ ret = ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_END_OF_EARLY_DATA);
+ if (ret <= 0) {
+ s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+ return 0;
+ }
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ /*
+ * We set the enc_write_ctx back to NULL because we may end up writing
+ * in cleartext again if we get a HelloRetryRequest from the server.
+ */
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+ ossl_statem_set_in_init(s, 1);
+ return 1;
+}
+
int SSL_shutdown(SSL *s)
{
/*
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);
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);
if (SSL_in_init(s) || SSL_in_before(s)) {
sk_SSL_CIPHER_free(scsvs);
return 0;
}
+
+int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data)
+{
+ ctx->max_early_data = max_early_data;
+
+ return 1;
+}
+
+uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx)
+{
+ return ctx->max_early_data;
+}
+
+int SSL_set_max_early_data(SSL *s, uint32_t max_early_data)
+{
+ s->max_early_data = max_early_data;
+
+ return 1;
+}
+
+uint32_t SSL_get_max_early_data(const SSL_CTX *s)
+{
+ return s->max_early_data;
+}