Additional error checking.
[openssl.git] / ssl / d1_srvr.c
index d79fb1985ef687a41e267aa5198a79417cd0e092..3a0b4d2dde63e180c5b7c9d72208f268ebaca7c9 100644 (file)
@@ -147,10 +147,10 @@ int dtls1_accept(SSL *s)
        BUF_MEM *buf;
        unsigned long Time=(unsigned long)time(NULL);
        void (*cb)(const SSL *ssl,int type,int val)=NULL;
-       long num1;
        unsigned long alg_k;
        int ret= -1;
        int new_state,state,skip=0;
+       int listen;
 
        RAND_add(&Time,sizeof(Time),0);
        ERR_clear_error();
@@ -160,6 +160,8 @@ int dtls1_accept(SSL *s)
                cb=s->info_callback;
        else if (s->ctx->info_callback != NULL)
                cb=s->ctx->info_callback;
+       
+       listen = s->d1->listen;
 
        /* init things to blank */
        s->in_handshake++;
@@ -178,7 +180,7 @@ int dtls1_accept(SSL *s)
                switch (s->state)
                        {
                case SSL_ST_RENEGOTIATE:
-                       s->new_session=1;
+                       s->renegotiate=1;
                        /* s->state=SSL_ST_ACCEPT; */
 
                case SSL_ST_BEFORE:
@@ -266,7 +268,6 @@ int dtls1_accept(SSL *s)
                        ret=ssl3_get_client_hello(s);
                        if (ret <= 0) goto end;
                        dtls1_stop_timer(s);
-                       s->new_session = 2;
 
                        if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
                                s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
@@ -276,10 +277,16 @@ int dtls1_accept(SSL *s)
                        s->init_num=0;
 
                        /* If we're just listening, stop here */
-                       if (s->d1->listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
+                       if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
                                {
                                ret = 2;
                                s->d1->listen = 0;
+                               /* Set expected sequence numbers
+                                * to continue the handshake.
+                                */
+                               s->d1->handshake_read_seq = 2;
+                               s->d1->handshake_write_seq = 1;
+                               s->d1->next_handshake_write_seq = 1;
                                goto end;
                                }
                        
@@ -301,12 +308,23 @@ int dtls1_accept(SSL *s)
                        
                case SSL3_ST_SW_SRVR_HELLO_A:
                case SSL3_ST_SW_SRVR_HELLO_B:
+                       s->renegotiate = 2;
                        dtls1_start_timer(s);
                        ret=dtls1_send_server_hello(s);
                        if (ret <= 0) goto end;
 
+#ifndef OPENSSL_NO_TLSEXT
                        if (s->hit)
-                               s->state=SSL3_ST_SW_CHANGE_A;
+                               {
+                               if (s->tlsext_ticket_expected)
+                                       s->state=SSL3_ST_SW_SESSION_TICKET_A;
+                               else
+                                       s->state=SSL3_ST_SW_CHANGE_A;
+                               }
+#else
+                       if (s->hit)
+                                       s->state=SSL3_ST_SW_CHANGE_A;
+#endif
                        else
                                s->state=SSL3_ST_SW_CERT_A;
                        s->init_num=0;
@@ -321,10 +339,24 @@ int dtls1_accept(SSL *s)
                                dtls1_start_timer(s);
                                ret=dtls1_send_server_certificate(s);
                                if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+                               if (s->tlsext_status_expected)
+                                       s->state=SSL3_ST_SW_CERT_STATUS_A;
+                               else
+                                       s->state=SSL3_ST_SW_KEY_EXCH_A;
+                               }
+                       else
+                               {
+                               skip = 1;
+                               s->state=SSL3_ST_SW_KEY_EXCH_A;
+                               }
+#else
                                }
                        else
                                skip=1;
+
                        s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
                        s->init_num=0;
                        break;
 
@@ -430,16 +462,13 @@ int dtls1_accept(SSL *s)
                        break;
                
                case SSL3_ST_SW_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;
+                               ret= -1;
+                               goto end;
                                }
-
+                       s->rwstate=SSL_NOTHING;
                        s->state=s->s3->tmp.next_state;
                        break;
 
@@ -519,11 +548,34 @@ int dtls1_accept(SSL *s)
                        dtls1_stop_timer(s);
                        if (s->hit)
                                s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_TLSEXT
+                       else if (s->tlsext_ticket_expected)
+                               s->state=SSL3_ST_SW_SESSION_TICKET_A;
+#endif
                        else
                                s->state=SSL3_ST_SW_CHANGE_A;
                        s->init_num=0;
                        break;
 
+#ifndef OPENSSL_NO_TLSEXT
+               case SSL3_ST_SW_SESSION_TICKET_A:
+               case SSL3_ST_SW_SESSION_TICKET_B:
+                       ret=dtls1_send_newsession_ticket(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_SW_CHANGE_A;
+                       s->init_num=0;
+                       break;
+
+               case SSL3_ST_SW_CERT_STATUS_A:
+               case SSL3_ST_SW_CERT_STATUS_B:
+                       ret=ssl3_send_cert_status(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_SW_KEY_EXCH_A;
+                       s->init_num=0;
+                       break;
+
+#endif
+
                case SSL3_ST_SW_CHANGE_A:
                case SSL3_ST_SW_CHANGE_B:
 
@@ -577,11 +629,12 @@ int dtls1_accept(SSL *s)
 
                        s->init_num=0;
 
-                       if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+                       if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
                                {
                                /* actually not necessarily a 'new' session unless
                                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
                                
+                               s->renegotiate=0;
                                s->new_session=0;
                                
                                ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
@@ -693,9 +746,6 @@ int dtls1_send_hello_verify_request(SSL *s)
                /* number of bytes to write */
                s->init_num=p-buf;
                s->init_off=0;
-
-               /* buffer the message to handle re-xmits */
-               dtls1_buffer_message(s, 0);
                }
 
        /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
@@ -749,6 +799,8 @@ int dtls1_send_server_hello(SSL *s)
                p+=sl;
 
                /* put the cipher */
+               if (s->s3->tmp.new_cipher == NULL)
+                       return -1;
                i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
                p+=i;
 
@@ -762,6 +814,14 @@ int dtls1_send_server_hello(SSL *s)
                        *(p++)=s->s3->tmp.new_compression->id;
 #endif
 
+#ifndef OPENSSL_NO_TLSEXT
+               if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                       {
+                       SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+                       return -1;
+                       }
+#endif
+
                /* do the header */
                l=(p-d);
                d=buf;
@@ -1082,7 +1142,7 @@ int dtls1_send_server_key_exchange(SSL *s)
                if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
                        && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                        {
-                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher, NULL))
                                == NULL)
                                {
                                al=SSL_AD_DECODE_ERROR;
@@ -1384,3 +1444,115 @@ int dtls1_send_server_certificate(SSL *s)
        /* SSL3_ST_SW_CERT_B */
        return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
        }
+
+#ifndef OPENSSL_NO_TLSEXT
+int dtls1_send_newsession_ticket(SSL *s)
+       {
+       if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+               {
+               unsigned char *p, *senc, *macstart;
+               int len, slen;
+               unsigned int hlen, msg_len;
+               EVP_CIPHER_CTX ctx;
+               HMAC_CTX hctx;
+               SSL_CTX *tctx = s->initial_ctx;
+               unsigned char iv[EVP_MAX_IV_LENGTH];
+               unsigned char key_name[16];
+
+               /* get session encoding length */
+               slen = i2d_SSL_SESSION(s->session, NULL);
+               /* Some length values are 16 bits, so forget it if session is
+                * too long
+                */
+               if (slen > 0xFF00)
+                       return -1;
+               /* Grow buffer if need be: the length calculation is as
+                * follows 12 (DTLS handshake message header) +
+                * 4 (ticket lifetime hint) + 2 (ticket length) +
+                * 16 (key name) + max_iv_len (iv length) +
+                * session_length + max_enc_block_size (max encrypted session
+                * length) + max_md_size (HMAC).
+                */
+               if (!BUF_MEM_grow(s->init_buf,
+                       DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH +
+                       EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
+                       return -1;
+               senc = OPENSSL_malloc(slen);
+               if (!senc)
+                       return -1;
+               p = senc;
+               i2d_SSL_SESSION(s->session, &p);
+
+               p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]);
+               EVP_CIPHER_CTX_init(&ctx);
+               HMAC_CTX_init(&hctx);
+               /* Initialize HMAC and cipher contexts. If callback present
+                * it does all the work otherwise use generated values
+                * from parent ctx.
+                */
+               if (tctx->tlsext_ticket_key_cb)
+                       {
+                       if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+                                                        &hctx, 1) < 0)
+                               {
+                               OPENSSL_free(senc);
+                               return -1;
+                               }
+                       }
+               else
+                       {
+                       RAND_pseudo_bytes(iv, 16);
+                       EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+                                       tctx->tlsext_tick_aes_key, iv);
+                       HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+                                       tlsext_tick_md(), NULL);
+                       memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+                       }
+               l2n(s->session->tlsext_tick_lifetime_hint, p);
+               /* Skip ticket length for now */
+               p += 2;
+               /* Output key name */
+               macstart = p;
+               memcpy(p, key_name, 16);
+               p += 16;
+               /* output IV */
+               memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+               p += EVP_CIPHER_CTX_iv_length(&ctx);
+               /* Encrypt session data */
+               EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+               p += len;
+               EVP_EncryptFinal(&ctx, p, &len);
+               p += len;
+               EVP_CIPHER_CTX_cleanup(&ctx);
+
+               HMAC_Update(&hctx, macstart, p - macstart);
+               HMAC_Final(&hctx, p, &hlen);
+               HMAC_CTX_cleanup(&hctx);
+
+               p += hlen;
+               /* Now write out lengths: p points to end of data written */
+               /* Total length */
+               len = p - (unsigned char *)(s->init_buf->data);
+               /* Ticket length */
+               p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4;
+               s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p);
+
+               /* number of bytes to write */
+               s->init_num= len;
+               s->state=SSL3_ST_SW_SESSION_TICKET_B;
+               s->init_off=0;
+               OPENSSL_free(senc);
+
+               /* XDTLS:  set message header ? */
+               msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
+               dtls1_set_message_header(s, (void *)s->init_buf->data,
+                       SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len);
+
+               /* buffer the message to handle re-xmits */
+               dtls1_buffer_message(s, 0);
+               }
+
+       /* SSL3_ST_SW_SESSION_TICKET_B */
+       return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+       }
+#endif