Use a common state to begin the handshake.
This simplifies the logic around SSL_clear to reset the state for a new
handshake. The state around here is still a little iffy, but this is a
slight improvement.
The SSL_ST_CONNECT and SSL_ST_ACCEPT states are still kept separate to
avoid problems with the info callback reporting SSL_ST_INIT. Glancing
through info callback consumers, although they're all debugging, they
tend to assume that all intermediate states either have only
SSL_ST_CONNECT set or only SSL_ST_ACCEPT set.
(They also all look identical which makes me think it's copy-and-pasted
from OpenSSL command-line tool or something.)
Change-Id: I55503781e52b51b4ca829256c14de6f5942dae51
Reviewed-on: https://boringssl-review.googlesource.com/10760
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 93562e57..9a5cd02 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -196,6 +196,11 @@
state = ssl->state;
switch (ssl->state) {
+ case SSL_ST_INIT:
+ ssl->state = SSL_ST_CONNECT;
+ skip = 1;
+ break;
+
case SSL_ST_CONNECT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 20986ec..c5bd4be 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -197,6 +197,11 @@
state = ssl->state;
switch (ssl->state) {
+ case SSL_ST_INIT:
+ ssl->state = SSL_ST_ACCEPT;
+ skip = 1;
+ break;
+
case SSL_ST_ACCEPT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 4c3b40e..bdc1074 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -393,6 +393,8 @@
ssl->min_version = ctx->min_version;
ssl->max_version = ctx->max_version;
+ ssl->state = SSL_ST_INIT;
+
/* RFC 6347 states that implementations SHOULD use an initial timer value of
* 1 second. */
ssl->initial_timeout_duration_ms = 1000;
@@ -529,13 +531,11 @@
void SSL_set_connect_state(SSL *ssl) {
ssl->server = 0;
- ssl->state = SSL_ST_CONNECT;
ssl->handshake_func = ssl3_connect;
}
void SSL_set_accept_state(SSL *ssl) {
ssl->server = 1;
- ssl->state = SSL_ST_ACCEPT;
ssl->handshake_func = ssl3_accept;
}
@@ -681,7 +681,7 @@
/* Begin a new handshake. */
ssl->s3->total_renegotiations++;
- ssl->state = SSL_ST_CONNECT;
+ ssl->state = SSL_ST_INIT;
return 1;
no_renegotiation:
@@ -2887,25 +2887,13 @@
return 0;
}
- /* SSL_clear may be called before or after the |ssl| is initialized in either
- * accept or connect state. In the latter case, SSL_clear should preserve the
- * half and reset |ssl->state| accordingly. */
- if (ssl->handshake_func != NULL) {
- if (ssl->server) {
- SSL_set_accept_state(ssl);
- } else {
- SSL_set_connect_state(ssl);
- }
- } else {
- assert(ssl->state == 0);
- }
-
/* TODO(davidben): Some state on |ssl| is reset both in |SSL_new| and
* |SSL_clear| because it is per-connection state rather than configuration
* state. Per-connection state should be on |ssl->s3| and |ssl->d1| so it is
* naturally reset at the right points between |SSL_new|, |SSL_clear|, and
* |ssl3_new|. */
+ ssl->state = SSL_ST_INIT;
ssl->rwstate = SSL_NOTHING;
BUF_MEM_free(ssl->init_buf);