Handle a memory allocation failure in ssl3_init_finished_mac()
[openssl.git] / ssl / statem / statem.c
index 5032c3b2676e925349bb9adfaf616d5990d650a5..28483e7944ff6e7cd0bfc1a59bf732d1cfad01a3 100644 (file)
@@ -1,59 +1,10 @@
-/* ssl/statem/statem.c */
 /*
- * Written by Matt Caswell for the OpenSSL project.
- */
-/* ====================================================================
- * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
 #include <openssl/rand.h>
  */
 
 /* Sub state machine return values */
-enum SUB_STATE_RETURN {
+typedef enum  {
     /* Something bad happened or NBIO */
     SUB_STATE_ERROR,
     /* Sub state finished go to the next sub state */
     SUB_STATE_FINISHED,
     /* Sub state finished and handshake was completed */
     SUB_STATE_END_HANDSHAKE
-};
+} SUB_STATE_RETURN;
 
 static int state_machine(SSL *s, int server);
 static void init_read_state_machine(SSL *s);
-static enum SUB_STATE_RETURN read_state_machine(SSL *s);
+static SUB_STATE_RETURN read_state_machine(SSL *s);
 static void init_write_state_machine(SSL *s);
-static enum SUB_STATE_RETURN write_state_machine(SSL *s);
+static SUB_STATE_RETURN write_state_machine(SSL *s);
 
-enum HANDSHAKE_STATE SSL_state(const SSL *ssl)
+OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
 {
     return ssl->statem.hand_state;
 }
 
-void SSL_set_state(SSL *ssl, enum HANDSHAKE_STATE state)
-{
-    /*
-     * This function seems like a really bad idea. Should we remove it
-     * completely?
-     */
-    ssl->statem.hand_state = state;
-}
-
 int SSL_in_init(SSL *s)
 {
     return s->statem.in_init;
@@ -150,17 +92,18 @@ int SSL_in_before(SSL *s)
 /*
  * Clear the state machine state and reset back to MSG_FLOW_UNINITED
  */
-void statem_clear(SSL *s)
+void ossl_statem_clear(SSL *s)
 {
     s->statem.state = MSG_FLOW_UNINITED;
     s->statem.hand_state = TLS_ST_BEFORE;
     s->statem.in_init = 1;
+    s->statem.no_cert_verify = 0;
 }
 
 /*
  * Set the state machine up ready for a renegotiation handshake
  */
-void statem_set_renegotiate(SSL *s)
+void ossl_statem_set_renegotiate(SSL *s)
 {
     s->statem.state = MSG_FLOW_RENEGOTIATE;
     s->statem.in_init = 1;
@@ -170,7 +113,7 @@ void statem_set_renegotiate(SSL *s)
  * Put the state machine into an error state. This is a permanent error for
  * the current connection.
  */
-void statem_set_error(SSL *s)
+void ossl_statem_set_error(SSL *s)
 {
     s->statem.state = MSG_FLOW_ERROR;
 }
@@ -182,7 +125,7 @@ void statem_set_error(SSL *s)
  *   1: Yes
  *   0: No
  */
-int statem_in_error(const SSL *s)
+int ossl_statem_in_error(const SSL *s)
 {
     if (s->statem.state == MSG_FLOW_ERROR)
         return 1;
@@ -190,20 +133,57 @@ int statem_in_error(const SSL *s)
     return 0;
 }
 
-void statem_set_in_init(SSL *s, int init)
+void ossl_statem_set_in_init(SSL *s, int init)
 {
     s->statem.in_init = init;
 }
 
-int statem_connect(SSL *s) {
+int ossl_statem_get_in_handshake(SSL *s)
+{
+    return s->statem.in_handshake;
+}
+
+void ossl_statem_set_in_handshake(SSL *s, int inhand)
+{
+    if (inhand)
+        s->statem.in_handshake++;
+    else
+        s->statem.in_handshake--;
+}
+
+void ossl_statem_set_hello_verify_done(SSL *s)
+{
+    s->statem.state = MSG_FLOW_UNINITED;
+    s->statem.in_init = 1;
+    /*
+     * This will get reset (briefly) back to TLS_ST_BEFORE when we enter
+     * state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
+     * calls to SSL_in_before() will return false. Also calls to
+     * SSL_state_string() and SSL_state_string_long() will return something
+     * sensible.
+     */
+    s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
+}
+
+int ossl_statem_connect(SSL *s) {
     return state_machine(s, 0);
 }
 
-int statem_accept(SSL *s)
+int ossl_statem_accept(SSL *s)
 {
     return state_machine(s, 1);
 }
 
+static void (*get_callback(SSL *s))(const SSL *, int, int)
+{
+    if (s->info_callback != NULL)
+        return s->info_callback;
+    else if (s->ctx->info_callback != NULL)
+        return s->ctx->info_callback;
+
+    return NULL;
+}
+
 /*
  * The main message flow state machine. We start in the MSG_FLOW_UNINITED or
  * MSG_FLOW_RENEGOTIATE state and finish in MSG_FLOW_FINISHED. Valid states and
@@ -232,11 +212,12 @@ int statem_accept(SSL *s)
  *   1: Success
  * <=0: NBIO or error
  */
-static int state_machine(SSL *s, int server) {
+static int state_machine(SSL *s, int server)
+{
     BUF_MEM *buf = NULL;
     unsigned long Time = (unsigned long)time(NULL);
     void (*cb) (const SSL *ssl, int type, int val) = NULL;
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
     int ret = -1;
     int ssret;
 
@@ -249,12 +230,9 @@ static int state_machine(SSL *s, int server) {
     ERR_clear_error();
     clear_sys_error();
 
-    if (s->info_callback != NULL)
-        cb = s->info_callback;
-    else if (s->ctx->info_callback != NULL)
-        cb = s->ctx->info_callback;
+    cb = get_callback(s);
 
-    s->in_handshake++;
+    st->in_handshake++;
     if (!SSL_in_init(s) || SSL_in_before(s)) {
         if (!SSL_clear(s))
             return -1;
@@ -267,7 +245,7 @@ static int state_machine(SSL *s, int server) {
          * identifier other than 0. Will be ignored if no SCTP is used.
          */
         BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
-                 s->in_handshake, NULL);
+                 st->in_handshake, NULL);
     }
 #endif
 
@@ -310,19 +288,15 @@ static int state_machine(SSL *s, int server) {
                 goto end;
             }
         } else {
-            if ((s->version >> 8) != SSL3_VERSION_MAJOR
-                    && s->version != TLS_ANY_VERSION) {
+            if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
                 SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
                 goto end;
             }
         }
 
-        if (!SSL_IS_DTLS(s)) {
-            if (s->version != TLS_ANY_VERSION &&
-                    !ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
-                SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
-                goto end;
-            }
+        if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
+            SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
+            goto end;
         }
 
         if (s->init_buf == NULL) {
@@ -346,19 +320,23 @@ static int state_machine(SSL *s, int server) {
          */
         s->s3->change_cipher_spec = 0;
 
-        if (!server || st->state != MSG_FLOW_RENEGOTIATE) {
-                /*
-                 * Ok, we now need to push on a buffering BIO ...but not with
-                 * SCTP
-                 */
+
+        /*
+         * Ok, we now need to push on a buffering BIO ...but not with
+         * SCTP
+         */
 #ifndef OPENSSL_NO_SCTP
-                if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
+        if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
 #endif
-                    if (!ssl_init_wbio_buffer(s, server ? 1 : 0)) {
-                        goto end;
-                    }
+            if (!ssl_init_wbio_buffer(s)) {
+                goto end;
+            }
 
-            ssl3_init_finished_mac(s);
+        if (!server || st->state != MSG_FLOW_RENEGOTIATE) {
+            if (!ssl3_init_finished_mac(s)) {
+                ossl_statem_set_error(s);
+                goto end;
+            }
         }
 
         if (server) {
@@ -374,7 +352,7 @@ static int state_machine(SSL *s, int server) {
                 SSLerr(SSL_F_STATE_MACHINE,
                        SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
                 ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-                statem_set_error(s);
+                ossl_statem_set_error(s);
                 goto end;
             } else {
                 /*
@@ -425,7 +403,7 @@ static int state_machine(SSL *s, int server) {
             }
         } else {
             /* Error */
-            statem_set_error(s);
+            ossl_statem_set_error(s);
             goto end;
         }
     }
@@ -434,7 +412,7 @@ static int state_machine(SSL *s, int server) {
     ret = 1;
 
  end:
-    s->in_handshake--;
+    st->in_handshake--;
 
 #ifndef OPENSSL_NO_SCTP
     if (SSL_IS_DTLS(s)) {
@@ -443,7 +421,7 @@ static int state_machine(SSL *s, int server) {
          * identifier other than 0. Will be ignored if no SCTP is used.
          */
         BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
-                 s->in_handshake, NULL);
+                 st->in_handshake, NULL);
     }
 #endif
 
@@ -462,7 +440,7 @@ static int state_machine(SSL *s, int server) {
  */
 static void init_read_state_machine(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     st->read_state = READ_STATE_HEADER;
 }
@@ -489,36 +467,33 @@ static void init_read_state_machine(SSL *s)
  * READ_STATE_POST_PROCESS is an optional step that may occur if some post
  * processing activity performed on the message may block.
  *
- * Any of the above states could result in an NBIO event occuring in which case
+ * Any of the above states could result in an NBIO event occurring in which case
  * control returns to the calling application. When this function is recalled we
  * will resume in the same state where we left off.
  */
-static enum SUB_STATE_RETURN read_state_machine(SSL *s) {
-    STATEM *st = &s->statem;
+static SUB_STATE_RETURN read_state_machine(SSL *s) {
+    OSSL_STATEM *st = &s->statem;
     int ret, mt;
-    unsigned long len;
+    unsigned long len = 0;
     int (*transition)(SSL *s, int mt);
     PACKET pkt;
-    enum MSG_PROCESS_RETURN (*process_message)(SSL *s, PACKET *pkt);
-    enum WORK_STATE (*post_process_message)(SSL *s, enum WORK_STATE wst);
+    MSG_PROCESS_RETURN (*process_message)(SSL *s, PACKET *pkt);
+    WORK_STATE (*post_process_message)(SSL *s, WORK_STATE wst);
     unsigned long (*max_message_size)(SSL *s);
     void (*cb) (const SSL *ssl, int type, int val) = NULL;
 
-    if (s->info_callback != NULL)
-        cb = s->info_callback;
-    else if (s->ctx->info_callback != NULL)
-        cb = s->ctx->info_callback;
+    cb = get_callback(s);
 
     if(s->server) {
-        transition = server_read_transition;
-        process_message = server_process_message;
-        max_message_size = server_max_message_size;
-        post_process_message = server_post_process_message;
+        transition = ossl_statem_server_read_transition;
+        process_message = ossl_statem_server_process_message;
+        max_message_size = ossl_statem_server_max_message_size;
+        post_process_message = ossl_statem_server_post_process_message;
     } else {
-        transition = client_read_transition;
-        process_message = client_process_message;
-        max_message_size = client_max_message_size;
-        post_process_message = client_post_process_message;
+        transition = ossl_statem_client_read_transition;
+        process_message = ossl_statem_client_process_message;
+        max_message_size = ossl_statem_client_max_message_size;
+        post_process_message = ossl_statem_client_post_process_message;
     }
 
     if (st->read_state_first_init) {
@@ -529,7 +504,6 @@ static enum SUB_STATE_RETURN read_state_machine(SSL *s) {
     while(1) {
         switch(st->read_state) {
         case READ_STATE_HEADER:
-            s->init_num = 0;
             /* Get the state the peer wants to move to */
             if (SSL_IS_DTLS(s)) {
                 /*
@@ -588,6 +562,10 @@ static enum SUB_STATE_RETURN read_state_machine(SSL *s) {
                 return SUB_STATE_ERROR;
             }
             ret = process_message(s, &pkt);
+
+            /* Discard the packet data */
+            s->init_num = 0;
+
             if (ret == MSG_PROCESS_ERROR) {
                 return SUB_STATE_ERROR;
             }
@@ -629,7 +607,7 @@ static enum SUB_STATE_RETURN read_state_machine(SSL *s) {
             /* Shouldn't happen */
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
             SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
-            statem_set_error(s);
+            ossl_statem_set_error(s);
             return SUB_STATE_ERROR;
         }
     }
@@ -640,7 +618,7 @@ static enum SUB_STATE_RETURN read_state_machine(SSL *s) {
  */
 static int statem_do_write(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     if (st->hand_state == TLS_ST_CW_CHANGE
             || st->hand_state == TLS_ST_SW_CHANGE) {
@@ -658,7 +636,7 @@ static int statem_do_write(SSL *s)
  */
 static void init_write_state_machine(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     st->write_state = WRITE_STATE_TRANSITION;
 }
@@ -683,7 +661,7 @@ static void init_write_state_machine(SSL *s)
  * WRITE_STATE_TRANSITION transitions the state of the handshake state machine
 
  * WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
- * sending of the message. This could result in an NBIO event occuring in
+ * sending of the message. This could result in an NBIO event occurring in
  * which case control returns to the calling application. When this function
  * is recalled we will resume in the same state where we left off.
  *
@@ -694,31 +672,28 @@ static void init_write_state_machine(SSL *s)
  * message has been completed. As for WRITE_STATE_PRE_WORK this could also
  * result in an NBIO event.
  */
-static enum SUB_STATE_RETURN write_state_machine(SSL *s)
+static SUB_STATE_RETURN write_state_machine(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
     int ret;
-    enum WRITE_TRAN (*transition)(SSL *s);
-    enum WORK_STATE (*pre_work)(SSL *s, enum WORK_STATE wst);
-    enum WORK_STATE (*post_work)(SSL *s, enum WORK_STATE wst);
+    WRITE_TRAN (*transition)(SSL *s);
+    WORK_STATE (*pre_work)(SSL *s, WORK_STATE wst);
+    WORK_STATE (*post_work)(SSL *s, WORK_STATE wst);
     int (*construct_message)(SSL *s);
     void (*cb) (const SSL *ssl, int type, int val) = NULL;
 
-    if (s->info_callback != NULL)
-        cb = s->info_callback;
-    else if (s->ctx->info_callback != NULL)
-        cb = s->ctx->info_callback;
+    cb = get_callback(s);
 
     if(s->server) {
-        transition = server_write_transition;
-        pre_work = server_pre_work;
-        post_work = server_post_work;
-        construct_message = server_construct_message;
+        transition = ossl_statem_server_write_transition;
+        pre_work = ossl_statem_server_pre_work;
+        post_work = ossl_statem_server_post_work;
+        construct_message = ossl_statem_server_construct_message;
     } else {
-        transition = client_write_transition;
-        pre_work = client_pre_work;
-        post_work = client_post_work;
-        construct_message = client_construct_message;
+        transition = ossl_statem_client_write_transition;
+        pre_work = ossl_statem_client_pre_work;
+        post_work = ossl_statem_client_post_work;
+        construct_message = ossl_statem_client_construct_message;
     }
 
     while(1) {
@@ -817,9 +792,9 @@ int statem_flush(SSL *s)
  *   1: Yes (application data allowed)
  *   0: No (application data not allowed)
  */
-int statem_app_data_allowed(SSL *s)
+int ossl_statem_app_data_allowed(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE)
         return 0;
@@ -851,7 +826,7 @@ int statem_app_data_allowed(SSL *s)
 /*
  * Set flag used by SCTP to determine whether we are in the read sock state
  */
-void statem_set_sctp_read_sock(SSL *s, int read_sock)
+void ossl_statem_set_sctp_read_sock(SSL *s, int read_sock)
 {
     s->statem.in_sctp_read_sock = read_sock;
 }
@@ -864,7 +839,7 @@ void statem_set_sctp_read_sock(SSL *s, int read_sock)
  *   1: Yes (we are in the read sock state)
  *   0: No (we are not in the read sock state)
  */
-int statem_in_sctp_read_sock(SSL *s)
+int ossl_statem_in_sctp_read_sock(SSL *s)
 {
     return s->statem.in_sctp_read_sock;
 }