reject zero length point format list or supported curves extensions
[openssl.git] / ssl / d1_clnt.c
index c4f820070f1725b8244a54f89b70853c2fe511ac..4af8ffda4d57f75a2e7e1ccfec5aea2a8e534d4c 100644 (file)
@@ -148,10 +148,13 @@ int dtls1_connect(SSL *s)
        {
        BUF_MEM *buf=NULL;
        unsigned long Time=(unsigned long)time(NULL);
-       long num1;
        void (*cb)(const SSL *ssl,int type,int val)=NULL;
        int ret= -1;
-       int new_state,state,skip=0;;
+       int new_state,state,skip=0;
+#ifndef OPENSSL_NO_SCTP
+       unsigned char sctpauthkey[64];
+       char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+#endif
 
        RAND_add(&Time,sizeof(Time),0);
        ERR_clear_error();
@@ -165,6 +168,27 @@ int dtls1_connect(SSL *s)
        s->in_handshake++;
        if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
 
+#ifndef OPENSSL_NO_SCTP
+       /* Notify SCTP BIO socket to enter handshake
+        * mode and prevent stream 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);
+#endif
+
+#ifndef OPENSSL_NO_HEARTBEATS
+       /* If we're awaiting a HeartbeatResponse, pretend we
+        * already got and don't await it anymore, because
+        * Heartbeats don't make sense during handshakes anyway.
+        */
+       if (s->tlsext_hb_pending)
+               {
+               dtls1_stop_timer(s);
+               s->tlsext_hb_pending = 0;
+               s->tlsext_hb_seq++;
+               }
+#endif
+
        for (;;)
                {
                state=s->state;
@@ -172,7 +196,7 @@ int dtls1_connect(SSL *s)
                switch(s->state)
                        {
                case SSL_ST_RENEGOTIATE:
-                       s->new_session=1;
+                       s->renegotiate=1;
                        s->state=SSL_ST_CONNECT;
                        s->ctx->stats.sess_connect_renegotiate++;
                        /* break */
@@ -227,6 +251,42 @@ int dtls1_connect(SSL *s)
                        s->hit = 0;
                        break;
 
+#ifndef OPENSSL_NO_SCTP
+               case DTLS1_SCTP_ST_CR_READ_SOCK:
+
+                       if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
+                       {
+                               s->s3->in_read_app_data=2;
+                               s->rwstate=SSL_READING;
+                               BIO_clear_retry_flags(SSL_get_rbio(s));
+                               BIO_set_retry_read(SSL_get_rbio(s));
+                               ret = -1;
+                               goto end;
+                       }
+
+                       s->state=s->s3->tmp.next_state;
+                       break;
+
+               case DTLS1_SCTP_ST_CW_WRITE_SOCK:
+                       /* read app data until dry event */
+
+                       ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+                       if (ret < 0) goto end;
+
+                       if (ret == 0)
+                       {
+                               s->s3->in_read_app_data=2;
+                               s->rwstate=SSL_READING;
+                               BIO_clear_retry_flags(SSL_get_rbio(s));
+                               BIO_set_retry_read(SSL_get_rbio(s));
+                               ret = -1;
+                               goto end;
+                       }
+
+                       s->state=s->d1->next_state;
+                       break;
+#endif
+
                case SSL3_ST_CW_CLNT_HELLO_A:
                case SSL3_ST_CW_CLNT_HELLO_B:
 
@@ -249,9 +309,17 @@ int dtls1_connect(SSL *s)
 
                        s->init_num=0;
 
-                       /* turn on buffering for the next lot of output */
-                       if (s->bbio != s->wbio)
-                               s->wbio=BIO_push(s->bbio,s->wbio);
+#ifndef OPENSSL_NO_SCTP
+                       /* Disable buffering for SCTP */
+                       if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
+                               {
+#endif
+                               /* turn on buffering for the next lot of output */
+                               if (s->bbio != s->wbio)
+                                       s->wbio=BIO_push(s->bbio,s->wbio);
+#ifndef OPENSSL_NO_SCTP
+                               }
+#endif
 
                        break;
 
@@ -261,9 +329,25 @@ int dtls1_connect(SSL *s)
                        if (ret <= 0) goto end;
                        else
                                {
-                               dtls1_stop_timer(s);
                                if (s->hit)
+                                       {
+#ifndef OPENSSL_NO_SCTP
+                                       /* Add new shared key for SCTP-Auth,
+                                        * will be ignored if no SCTP used.
+                                        */
+                                       snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+                                                DTLS1_SCTP_AUTH_LABEL);
+
+                                       SSL_export_keying_material(s, sctpauthkey,
+                                                                  sizeof(sctpauthkey), labelbuffer,
+                                                                  sizeof(labelbuffer), NULL, 0, 0);
+
+                                       BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+                                                        sizeof(sctpauthkey), sctpauthkey);
+#endif
+
                                        s->state=SSL3_ST_CR_FINISHED_A;
+                                       }
                                else
                                        s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
                                }
@@ -286,16 +370,44 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CR_CERT_A:
                case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+                       ret=ssl3_check_finished(s);
+                       if (ret <= 0) goto end;
+                       if (ret == 2)
+                               {
+                               s->hit = 1;
+                               if (s->tlsext_ticket_expected)
+                                       s->state=SSL3_ST_CR_SESSION_TICKET_A;
+                               else
+                                       s->state=SSL3_ST_CR_FINISHED_A;
+                               s->init_num=0;
+                               break;
+                               }
+#endif
                        /* Check if it is anon DH or PSK */
                        if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
                            !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                                {
                                ret=ssl3_get_server_certificate(s);
                                if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+                               if (s->tlsext_status_expected)
+                                       s->state=SSL3_ST_CR_CERT_STATUS_A;
+                               else
+                                       s->state=SSL3_ST_CR_KEY_EXCH_A;
+                               }
+                       else
+                               {
+                               skip = 1;
+                               s->state=SSL3_ST_CR_KEY_EXCH_A;
+                               }
+#else
                                }
                        else
                                skip=1;
+
                        s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
                        s->init_num=0;
                        break;
 
@@ -327,12 +439,20 @@ int dtls1_connect(SSL *s)
                case SSL3_ST_CR_SRVR_DONE_B:
                        ret=ssl3_get_server_done(s);
                        if (ret <= 0) goto end;
+                       dtls1_stop_timer(s);
                        if (s->s3->tmp.cert_req)
-                               s->state=SSL3_ST_CW_CERT_A;
+                               s->s3->tmp.next_state=SSL3_ST_CW_CERT_A;
                        else
-                               s->state=SSL3_ST_CW_KEY_EXCH_A;
+                               s->s3->tmp.next_state=SSL3_ST_CW_KEY_EXCH_A;
                        s->init_num=0;
 
+#ifndef OPENSSL_NO_SCTP                        
+                       if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+                           state == SSL_ST_RENEGOTIATE)
+                               s->state=DTLS1_SCTP_ST_CR_READ_SOCK;
+                       else
+#endif                 
+                       s->state=s->s3->tmp.next_state;
                        break;
 
                case SSL3_ST_CW_CERT_A:
@@ -351,6 +471,22 @@ int dtls1_connect(SSL *s)
                        dtls1_start_timer(s);
                        ret=dtls1_send_client_key_exchange(s);
                        if (ret <= 0) goto end;
+
+#ifndef OPENSSL_NO_SCTP
+                       /* Add new shared key for SCTP-Auth,
+                        * will be ignored if no SCTP used.
+                        */
+                       snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+                                DTLS1_SCTP_AUTH_LABEL);
+
+                       SSL_export_keying_material(s, sctpauthkey,
+                                                  sizeof(sctpauthkey), labelbuffer,
+                                                  sizeof(labelbuffer), NULL, 0, 0);
+
+                       BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+                                        sizeof(sctpauthkey), sctpauthkey);
+#endif
+
                        /* EAY EAY EAY need to check for DH fix cert
                         * sent back */
                        /* For TLS, cert_req is set to 2, so a cert chain
@@ -361,7 +497,15 @@ int dtls1_connect(SSL *s)
                                }
                        else
                                {
-                               s->state=SSL3_ST_CW_CHANGE_A;
+#ifndef OPENSSL_NO_SCTP
+                               if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+                                       {
+                                       s->d1->next_state=SSL3_ST_CW_CHANGE_A;
+                                       s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+                                       }
+                               else
+#endif
+                                       s->state=SSL3_ST_CW_CHANGE_A;
                                s->s3->change_cipher_spec=0;
                                }
 
@@ -373,17 +517,34 @@ int dtls1_connect(SSL *s)
                        dtls1_start_timer(s);
                        ret=dtls1_send_client_verify(s);
                        if (ret <= 0) goto end;
-                       s->state=SSL3_ST_CW_CHANGE_A;
+#ifndef OPENSSL_NO_SCTP
+                       if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+                       {
+                               s->d1->next_state=SSL3_ST_CW_CHANGE_A;
+                               s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+                       }
+                       else
+#endif
+                               s->state=SSL3_ST_CW_CHANGE_A;
                        s->init_num=0;
                        s->s3->change_cipher_spec=0;
                        break;
 
                case SSL3_ST_CW_CHANGE_A:
                case SSL3_ST_CW_CHANGE_B:
-                       dtls1_start_timer(s);
+                       if (!s->hit)
+                               dtls1_start_timer(s);
                        ret=dtls1_send_change_cipher_spec(s,
                                SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
                        if (ret <= 0) goto end;
+
+#ifndef OPENSSL_NO_SCTP
+                       /* Change to new shared key of SCTP-Auth,
+                        * will be ignored if no SCTP used.
+                        */
+                       BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+#endif
+
                        s->state=SSL3_ST_CW_FINISHED_A;
                        s->init_num=0;
 
@@ -415,7 +576,8 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CW_FINISHED_A:
                case SSL3_ST_CW_FINISHED_B:
-                       dtls1_start_timer(s);
+                       if (!s->hit)
+                               dtls1_start_timer(s);
                        ret=dtls1_send_finished(s,
                                SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
                                s->method->ssl3_enc->client_finished_label,
@@ -428,20 +590,59 @@ int dtls1_connect(SSL *s)
                        if (s->hit)
                                {
                                s->s3->tmp.next_state=SSL_ST_OK;
+#ifndef OPENSSL_NO_SCTP
+                               if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+                                       {
+                                               s->d1->next_state = s->s3->tmp.next_state;
+                                               s->s3->tmp.next_state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+                                       }
+#endif
                                if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
                                        {
                                        s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_SCTP
+                                       if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+                                               {
+                                                       s->d1->next_state = SSL_ST_OK;
+                                                       s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+                                               }
+#endif
                                        s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
                                        s->s3->delay_buf_pop_ret=0;
                                        }
                                }
                        else
                                {
+#ifndef OPENSSL_NO_TLSEXT
+                               /* Allow NewSessionTicket if ticket expected */
+                               if (s->tlsext_ticket_expected)
+                                       s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+                               else
+#endif
+                               
                                s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
                                }
                        s->init_num=0;
                        break;
 
+#ifndef OPENSSL_NO_TLSEXT
+               case SSL3_ST_CR_SESSION_TICKET_A:
+               case SSL3_ST_CR_SESSION_TICKET_B:
+                       ret=ssl3_get_new_session_ticket(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_CR_FINISHED_A;
+                       s->init_num=0;
+               break;
+
+               case SSL3_ST_CR_CERT_STATUS_A:
+               case SSL3_ST_CR_CERT_STATUS_B:
+                       ret=ssl3_get_cert_status(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_CR_KEY_EXCH_A;
+                       s->init_num=0;
+               break;
+#endif
+
                case SSL3_ST_CR_FINISHED_A:
                case SSL3_ST_CR_FINISHED_B:
                        s->d1->change_cipher_spec_ok = 1;
@@ -454,20 +655,34 @@ int dtls1_connect(SSL *s)
                                s->state=SSL3_ST_CW_CHANGE_A;
                        else
                                s->state=SSL_ST_OK;
+
+#ifndef OPENSSL_NO_SCTP
+                       if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+                               state == SSL_ST_RENEGOTIATE)
+                               {
+                               s->d1->next_state=s->state;
+                               s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+                               }
+#endif
+
                        s->init_num=0;
                        break;
 
                case SSL3_ST_CW_FLUSH:
-                       /* number of bytes to be flushed */
-                       num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
-                       if (num1 > 0)
+                       s->rwstate=SSL_WRITING;
+                       if (BIO_flush(s->wbio) <= 0)
                                {
-                               s->rwstate=SSL_WRITING;
-                               num1=BIO_flush(s->wbio);
-                               if (num1 <= 0) { ret= -1; goto end; }
-                               s->rwstate=SSL_NOTHING;
+                               /* If the write error was fatal, stop trying */
+                               if (!BIO_should_retry(s->wbio))
+                                       {
+                                       s->rwstate=SSL_NOTHING;
+                                       s->state=s->s3->tmp.next_state;
+                                       }
+                               
+                               ret= -1;
+                               goto end;
                                }
-
+                       s->rwstate=SSL_NOTHING;
                        s->state=s->s3->tmp.next_state;
                        break;
 
@@ -490,6 +705,7 @@ int dtls1_connect(SSL *s)
                        /* else do it later in ssl3_write */
 
                        s->init_num=0;
+                       s->renegotiate=0;
                        s->new_session=0;
 
                        ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
@@ -536,6 +752,15 @@ int dtls1_connect(SSL *s)
                }
 end:
        s->in_handshake--;
+       
+#ifndef OPENSSL_NO_SCTP
+       /* Notify SCTP BIO socket to leave handshake
+        * mode and allow stream 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);
+#endif
+
        if (buf != NULL)
                BUF_MEM_free(buf);
        if (cb != NULL)
@@ -554,8 +779,14 @@ int dtls1_client_hello(SSL *s)
        buf=(unsigned char *)s->init_buf->data;
        if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
                {
+               SSL_SESSION *sess = s->session;
                if ((s->session == NULL) ||
                        (s->session->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+                       !sess->session_id_length ||
+#else
+                       (!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
                        (s->session->not_resumable))
                        {
                        if (!ssl_get_new_session(s,0))
@@ -637,9 +868,9 @@ int dtls1_client_hello(SSL *s)
                *(p++)=0; /* Add the NULL method */
 
 #ifndef OPENSSL_NO_TLSEXT
-               if ((p = ssl_add_clienthello_dtlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+               if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
                        {
-                       SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+                       SSLerr(SSL_F_DTLS1_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
 #endif         
@@ -1463,7 +1694,7 @@ int dtls1_send_client_certificate(SSL *s)
                {
                s->state=SSL3_ST_CW_CERT_D;
                l=dtls1_output_cert_chain(s,
-                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
+                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
                s->init_num=(int)l;
                s->init_off=0;