int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
{
int ret, early_data_state;
+ size_t writtmp;
switch (s->early_data_state) {
case SSL_EARLY_DATA_NONE:
case SSL_EARLY_DATA_WRITE_RETRY:
s->early_data_state = SSL_EARLY_DATA_WRITING;
- ret = SSL_write_ex(s, buf, num, written);
+ ret = SSL_write_ex(s, buf, num, &writtmp);
+ if (!ret) {
+ s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+ return ret;
+ }
+ s->early_data_state = SSL_EARLY_DATA_WRITE_FLUSH;
+ /* fall through */
+
+ case SSL_EARLY_DATA_WRITE_FLUSH:
+ /* The buffering BIO is still in place so we need to flush it */
+ if (statem_flush(s) != 1)
+ return 0;
+ /*
+ * TODO(TLS1.3): Technically this may not be correct in the event of
+ * SSL_MODE_ENABLE_PARTIAL_WRITE. What should we do about this?
+ */
+ *written = num;
s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
- return ret;
+ return 1;
case SSL_EARLY_DATA_FINISHED_READING:
case SSL_EARLY_DATA_READ_RETRY:
SSL_EARLY_DATA_CONNECTING,
SSL_EARLY_DATA_WRITE_RETRY,
SSL_EARLY_DATA_WRITING,
+ SSL_EARLY_DATA_WRITE_FLUSH,
SSL_EARLY_DATA_UNAUTH_WRITING,
SSL_EARLY_DATA_FINISHED_WRITING,
SSL_EARLY_DATA_ACCEPT_RETRY,
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);
+
+/* Flush the write BIO */
+int statem_flush(SSL *s);
/* Fall through */
case TLS_ST_EARLY_DATA:
+ return tls_finish_handshake(s, wst, 0, 1);
+
case TLS_ST_OK:
/* Calls SSLfatal() as required */
- return tls_finish_handshake(s, wst, 1);
+ return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;
* we call tls13_change_cipher_state() directly.
*/
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
- if (!statem_flush(s))
- return WORK_MORE_A;
if (!tls13_change_cipher_state(s,
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
/* SSLfatal() already called */
break;
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->max_early_data > 0) {
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
/*
* We haven't selected TLSv1.3 yet so we don't call the change
* cipher state function associated with the SSL_METHOD. Instead
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
* freed up as well.
*/
-WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
+WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
{
int discard;
void (*cb) (const SSL *ssl, int type, int val) = NULL;
}
}
- /*
- * If we've not cleared the buffers its because we've got more work to do,
- * so continue.
- */
- if (!clearbufs)
+ if (!stop)
return WORK_FINISHED_CONTINUE;
ossl_statem_set_in_init(s, 0);
MSG_PROCESS_CONTINUE_READING
} MSG_PROCESS_RETURN;
-/* Flush the write BIO */
-int statem_flush(SSL *s);
-
typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
__owur int tls_construct_finished(SSL *s, WPACKET *pkt);
__owur int tls_construct_key_update(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt);
-__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs);
+__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs,
+ int stop);
__owur WORK_STATE dtls_wait_for_dry(SSL *s);
/* some client-only functions */
*
* Calls SSLfatal as required.
*/
- return tls_finish_handshake(s, wst, 0);
+ return tls_finish_handshake(s, wst, 0, 0);
} if (SSL_IS_DTLS(s)) {
/*
* We're into the last flight. We don't retransmit the last flight
case TLS_ST_OK:
/* Calls SSLfatal() as required */
- return tls_finish_handshake(s, wst, 1);
+ return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;