DTLS revision.
[oweals/openssl.git] / ssl / s3_srvr.c
index fdf8052aa127c11618aa424795cbf503baa46aa0..5d7ab1325e6085ee4f112772300d6e3cec79f079 100644 (file)
@@ -868,24 +868,15 @@ end:
 
 int ssl3_send_hello_request(SSL *s)
        {
-       unsigned char *p;
 
        if (s->state == SSL3_ST_SW_HELLO_REQ_A)
                {
-               p=(unsigned char *)s->init_buf->data;
-               *(p++)=SSL3_MT_HELLO_REQUEST;
-               *(p++)=0;
-               *(p++)=0;
-               *(p++)=0;
-
+               ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0);
                s->state=SSL3_ST_SW_HELLO_REQ_B;
-               /* number of bytes to write */
-               s->init_num=4;
-               s->init_off=0;
                }
 
        /* SSL3_ST_SW_HELLO_REQ_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 int ssl3_check_client_hello(SSL *s)
@@ -940,9 +931,10 @@ int ssl3_get_client_hello(SSL *s)
        unsigned int cookie_len;
        long n;
        unsigned long id;
-       unsigned char *p,*d,*q;
+       unsigned char *p,*d;
        SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
+       unsigned char *q;
        SSL_COMP *comp=NULL;
 #endif
        STACK_OF(SSL_CIPHER) *ciphers=NULL;
@@ -1178,7 +1170,9 @@ int ssl3_get_client_hello(SSL *s)
                SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
                goto f_err;
                }
+#ifndef OPENSSL_NO_COMP
        q=p;
+#endif
        for (j=0; j<i; j++)
                {
                if (p[j] == 0) break;
@@ -1358,6 +1352,14 @@ int ssl3_get_client_hello(SSL *s)
                        goto f_err;
                        }
                ciphers=NULL;
+               /* Let cert callback update server certificates if required */
+               if (s->cert->cert_cb
+                       && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0)
+                       {
+                       al=SSL_AD_INTERNAL_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR);
+                       goto f_err;
+                       }
                c=ssl3_choose_cipher(s,s->session->ciphers,
                                     SSL_get_ciphers(s));
 
@@ -1424,6 +1426,16 @@ int ssl3_get_client_hello(SSL *s)
         * s->tmp.new_cipher    - the new cipher to use.
         */
 
+       /* Handles TLS extensions that we couldn't check earlier */
+       if (s->version >= SSL3_VERSION)
+               {
+               if (ssl_check_clienthello_tlsext_late(s) <= 0)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+                       goto err;
+                       }
+               }
+
        if (ret < 0) ret=1;
        if (0)
                {
@@ -1457,7 +1469,7 @@ int ssl3_send_server_hello(SSL *s)
                        return -1;
 #endif
                /* Do the message type and length last */
-               d=p= &(buf[4]);
+               d=p= ssl_handshake_start(s);
 
                *(p++)=s->version>>8;
                *(p++)=s->version&0xff;
@@ -1523,42 +1535,25 @@ int ssl3_send_server_hello(SSL *s)
 #endif
                /* do the header */
                l=(p-d);
-               d=buf;
-               *(d++)=SSL3_MT_SERVER_HELLO;
-               l2n3(l,d);
-
+               ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l);
                s->state=SSL3_ST_SW_SRVR_HELLO_B;
-               /* number of bytes to write */
-               s->init_num=p-buf;
-               s->init_off=0;
                }
 
        /* SSL3_ST_SW_SRVR_HELLO_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 int ssl3_send_server_done(SSL *s)
        {
-       unsigned char *p;
 
        if (s->state == SSL3_ST_SW_SRVR_DONE_A)
                {
-               p=(unsigned char *)s->init_buf->data;
-
-               /* do the header */
-               *(p++)=SSL3_MT_SERVER_DONE;
-               *(p++)=0;
-               *(p++)=0;
-               *(p++)=0;
-
-               s->state=SSL3_ST_SW_SRVR_DONE_B;
-               /* number of bytes to write */
-               s->init_num=4;
-               s->init_off=0;
+               ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0);
+               s->state = SSL3_ST_SW_SRVR_DONE_B;
                }
 
        /* SSL3_ST_SW_SRVR_DONE_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 int ssl3_send_server_key_exchange(SSL *s)
@@ -1696,8 +1691,8 @@ int ssl3_send_server_key_exchange(SSL *s)
                        ecdhp=cert->ecdh_tmp;
                        if (s->cert->ecdh_tmp_auto)
                                {
-                               /* Get NID of first shared curve */
-                               int nid = tls1_shared_curve(s, 0);
+                               /* Get NID of appropriate shared curve */
+                               int nid = tls1_shared_curve(s, -2);
                                if (nid != NID_undef)
                                        ecdhp = EC_KEY_new_by_curve_name(nid);
                                }
@@ -1882,13 +1877,12 @@ int ssl3_send_server_key_exchange(SSL *s)
                        kn=0;
                        }
 
-               if (!BUF_MEM_grow_clean(buf,n+4+kn))
+               if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn))
                        {
                        SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
                        goto err;
                        }
-               d=(unsigned char *)s->init_buf->data;
-               p= &(d[4]);
+               d = p = ssl_handshake_start(s);
 
                for (i=0; r[i] != NULL && i<4; i++)
                        {
@@ -1960,7 +1954,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                                                ?s->ctx->md5:s->ctx->sha1, NULL);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-                                       EVP_DigestUpdate(&md_ctx,&(d[4]),n);
+                                       EVP_DigestUpdate(&md_ctx,d,n);
                                        EVP_DigestFinal_ex(&md_ctx,q,
                                                (unsigned int *)&i);
                                        q+=i;
@@ -1999,7 +1993,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                                EVP_SignInit_ex(&md_ctx, md, NULL);
                                EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-                               EVP_SignUpdate(&md_ctx,&(d[4]),n);
+                               EVP_SignUpdate(&md_ctx,d,n);
                                if (!EVP_SignFinal(&md_ctx,&(p[2]),
                                        (unsigned int *)&i,pkey))
                                        {
@@ -2020,18 +2014,12 @@ int ssl3_send_server_key_exchange(SSL *s)
                                }
                        }
 
-               *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
-               l2n3(n,d);
-
-               /* we should now have things packed up, so lets send
-                * it off */
-               s->init_num=n+4;
-               s->init_off=0;
+               ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);
                }
 
        s->state = SSL3_ST_SW_KEY_EXCH_B;
        EVP_MD_CTX_cleanup(&md_ctx);
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
 f_err:
        ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
@@ -2055,7 +2043,7 @@ int ssl3_send_certificate_request(SSL *s)
                {
                buf=s->init_buf;
 
-               d=p=(unsigned char *)&(buf->data[4]);
+               d=p=ssl_handshake_start(s);
 
                /* get the list of acceptable cert types */
                p++;
@@ -2066,9 +2054,11 @@ int ssl3_send_certificate_request(SSL *s)
 
                if (TLS1_get_version(s) >= TLS1_2_VERSION)
                        {
-                       nl = tls12_get_req_sig_algs(s, p + 2);
+                       const unsigned char *psigs;
+                       nl = tls12_get_psigalgs(s, &psigs);
                        s2n(nl, p);
-                       p += nl + 2;
+                       memcpy(p, psigs, nl);
+                       p += nl;
                        n += nl + 2;
                        }
 
@@ -2108,34 +2098,29 @@ int ssl3_send_certificate_request(SSL *s)
                                }
                        }
                /* else no CA names */
-               p=(unsigned char *)&(buf->data[4+off]);
+               p = ssl_handshake_start(s) + off;
                s2n(nl,p);
 
-               d=(unsigned char *)buf->data;
-               *(d++)=SSL3_MT_CERTIFICATE_REQUEST;
-               l2n3(n,d);
-
-               /* we should now have things packed up, so lets send
-                * it off */
+               ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n);
 
-               s->init_num=n+4;
-               s->init_off=0;
 #ifdef NETSCAPE_HANG_BUG
-               p=(unsigned char *)s->init_buf->data + s->init_num;
-
-               /* do the header */
-               *(p++)=SSL3_MT_SERVER_DONE;
-               *(p++)=0;
-               *(p++)=0;
-               *(p++)=0;
-               s->init_num += 4;
+               if (!SSL_IS_DTLS(s))
+                       {
+                       p=(unsigned char *)s->init_buf->data + s->init_num;
+                       /* do the header */
+                       *(p++)=SSL3_MT_SERVER_DONE;
+                       *(p++)=0;
+                       *(p++)=0;
+                       *(p++)=0;
+                       s->init_num += 4;
+                       }
 #endif
 
                s->state = SSL3_ST_SW_CERT_REQ_B;
                }
 
        /* SSL3_ST_SW_CERT_REQ_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
 err:
        return(-1);
        }
@@ -3041,26 +3026,15 @@ int ssl3_get_cert_verify(SSL *s)
                {       
                if (TLS1_get_version(s) >= TLS1_2_VERSION)
                        {
-                       int sigalg = tls12_get_sigid(pkey);
-                       /* Should never happen */
-                       if (sigalg == -1)
+                       int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+                       if (rv == -1)
                                {
-                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
-                               al=SSL_AD_INTERNAL_ERROR;
+                               al = SSL_AD_INTERNAL_ERROR;
                                goto f_err;
                                }
-                       /* Check key type is consistent with signature */
-                       if (sigalg != (int)p[1])
+                       else if (rv == 0)
                                {
-                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
-                               al=SSL_AD_DECODE_ERROR;
-                               goto f_err;
-                               }
-                       md = tls12_get_hash(p[0]);
-                       if (md == NULL)
-                               {
-                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
-                               al=SSL_AD_DECODE_ERROR;
+                               al = SSL_AD_DECODE_ERROR;
                                goto f_err;
                                }
 #ifdef SSL_DEBUG
@@ -3339,7 +3313,7 @@ int ssl3_get_client_certificate(SSL *s)
                if (i <= 0)
                        {
                        al=ssl_verify_alarm_type(s->verify_result);
-                       SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
                        goto f_err;
                        }
                }
@@ -3382,7 +3356,6 @@ err:
 
 int ssl3_send_server_certificate(SSL *s)
        {
-       unsigned long l;
        CERT_PKEY *cpk;
 
        if (s->state == SSL3_ST_SW_CERT_A)
@@ -3399,14 +3372,12 @@ int ssl3_send_server_certificate(SSL *s)
                                }
                        }
 
-               l=ssl3_output_cert_chain(s,cpk);
+               ssl3_output_cert_chain(s,cpk);
                s->state=SSL3_ST_SW_CERT_B;
-               s->init_num=(int)l;
-               s->init_off=0;
                }
 
        /* SSL3_ST_SW_CERT_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 #ifndef OPENSSL_NO_TLSEXT
@@ -3460,22 +3431,17 @@ int ssl3_send_newsession_ticket(SSL *s)
                SSL_SESSION_free(sess);
 
                /* Grow buffer if need be: the length calculation is as
-                * follows 1 (size of message name) + 3 (message length
-                * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
+                * follows handshake_header_length +
+                * 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,
-                       26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
-                       EVP_MAX_MD_SIZE + slen))
+                       SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH +
+                       EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
                        return -1;
-
-               p=(unsigned char *)s->init_buf->data;
-               /* do the header */
-               *(p++)=SSL3_MT_NEWSESSION_TICKET;
-               /* Skip message length for now */
-               p += 3;
+               p = ssl_handshake_start(s);
                EVP_CIPHER_CTX_init(&ctx);
                HMAC_CTX_init(&hctx);
                /* Initialize HMAC and cipher contexts. If callback present
@@ -3530,21 +3496,17 @@ int ssl3_send_newsession_ticket(SSL *s)
                p += hlen;
                /* Now write out lengths: p points to end of data written */
                /* Total length */
-               len = p - (unsigned char *)s->init_buf->data;
-               p=(unsigned char *)s->init_buf->data + 1;
-               l2n3(len - 4, p); /* Message length */
-               p += 4;
-               s2n(len - 10, p);  /* Ticket length */
-
-               /* number of bytes to write */
-               s->init_num= len;
+               len = p - ssl_handshake_start(s);
+               ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len);
+               /* Skip ticket lifetime hint */
+               p = ssl_handshake_start(s) + 4;
+               s2n(len - 6, p);
                s->state=SSL3_ST_SW_SESSION_TICKET_B;
-               s->init_off=0;
                OPENSSL_free(senc);
                }
 
        /* SSL3_ST_SW_SESSION_TICKET_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 int ssl3_send_cert_status(SSL *s)
@@ -3676,6 +3638,8 @@ int tls1_send_server_supplemental_data(SSL *s)
 
                type = *(authz++);
                n2s(authz, len);
+               /* n2s increments authz by 2*/
+               i += 2;
 
                if (memchr(s->s3->tlsext_authz_client_types,
                           type,
@@ -3719,6 +3683,8 @@ int tls1_send_server_supplemental_data(SSL *s)
 
                type = *(authz++);
                n2s(authz, len);
+               /* n2s increments authz by 2 */
+               i += 2;
 
                if (memchr(s->s3->tlsext_authz_client_types,
                           type,