Keep old method in case of an unsupported protocol
[openssl.git] / ssl / s3_clnt.c
index 2c9fb87f528d1b939106bb9290b70ba7fa38245c..48289375669391c7777095d400199f061b8a0e97 100644 (file)
@@ -262,7 +262,16 @@ int ssl3_connect(SSL *s)
                        ret=ssl3_get_server_hello(s);
                        if (ret <= 0) goto end;
                        if (s->hit)
+                               {
                                s->state=SSL3_ST_CR_FINISHED_A;
+#ifndef OPENSSL_NO_TLSEXT
+                               if (s->tlsext_ticket_expected)
+                                       {
+                                       /* receive renewed session ticket */
+                                       s->state=SSL3_ST_CR_SESSION_TICKET_A;
+                                       }
+#endif
+                               }
                        else
                                s->state=SSL3_ST_CR_CERT_A;
                        s->init_num=0;
@@ -433,6 +442,7 @@ int ssl3_connect(SSL *s)
                                s->method->ssl3_enc->client_finished_label,
                                s->method->ssl3_enc->client_finished_label_len);
                        if (ret <= 0) goto end;
+                       s->s3->flags |= SSL3_FLAGS_CCS_OK;
                        s->state=SSL3_ST_CW_FLUSH;
 
                        /* clear flags */
@@ -482,6 +492,7 @@ int ssl3_connect(SSL *s)
                case SSL3_ST_CR_FINISHED_A:
                case SSL3_ST_CR_FINISHED_B:
 
+                       s->s3->flags |= SSL3_FLAGS_CCS_OK;
                        ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
                                SSL3_ST_CR_FINISHED_B);
                        if (ret <= 0) goto end;
@@ -768,6 +779,7 @@ int ssl3_get_server_hello(SSL *s)
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
                goto f_err;
                }
+           s->s3->flags |= SSL3_FLAGS_CCS_OK;
            s->hit=1;
            }
        else    /* a miss or crap from the other end */
@@ -884,7 +896,9 @@ int ssl3_get_server_hello(SSL *s)
        return(1);
 f_err:
        ssl3_send_alert(s,SSL3_AL_FATAL,al);
+#ifndef OPENSSL_NO_TLSEXT
 err:
+#endif
        return(-1);
        }
 
@@ -1081,8 +1095,8 @@ int ssl3_get_key_exchange(SSL *s)
 #endif
        EVP_MD_CTX md_ctx;
        unsigned char *param,*p;
-       int al,i,j,param_len,ok;
-       long n,alg;
+       int al,j,ok;
+       long i,param_len,n,alg;
        EVP_PKEY *pkey=NULL;
 #ifndef OPENSSL_NO_RSA
        RSA *rsa=NULL;
@@ -1146,10 +1160,12 @@ int ssl3_get_key_exchange(SSL *s)
                s->session->sess_cert=ssl_sess_cert_new();
                }
 
+       /* Total length of the parameters including the length prefix */
        param_len=0;
        alg=s->s3->tmp.new_cipher->algorithms;
        EVP_MD_CTX_init(&md_ctx);
 
+       al=SSL_AD_DECODE_ERROR;
 #ifndef OPENSSL_NO_RSA
        if (alg & SSL_kRSA)
                {
@@ -1158,14 +1174,23 @@ int ssl3_get_key_exchange(SSL *s)
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
                        goto err;
                        }
-               n2s(p,i);
-               param_len=i+2;
+
+               param_len = 2;
                if (param_len > n)
                        {
-                       al=SSL_AD_DECODE_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               n2s(p,i);
+
+               if (i > n - param_len)
+                       {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1173,14 +1198,23 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                p+=i;
 
+               if (2 > n - param_len)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               param_len += 2;
+
                n2s(p,i);
-               param_len+=i+2;
-               if (param_len > n)
+
+               if (i > n - param_len)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1212,14 +1246,23 @@ int ssl3_get_key_exchange(SSL *s)
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
                        goto err;
                        }
-               n2s(p,i);
-               param_len=i+2;
+
+               param_len = 2;
                if (param_len > n)
                        {
-                       al=SSL_AD_DECODE_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               n2s(p,i);
+
+               if (i > n - param_len)
+                       {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(dh->p=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1227,14 +1270,23 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                p+=i;
 
+               if (2 > n - param_len)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               param_len += 2;
+
                n2s(p,i);
-               param_len+=i+2;
-               if (param_len > n)
+
+               if (i > n - param_len)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(dh->g=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1242,14 +1294,23 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                p+=i;
 
+               if (2 > n - param_len)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               param_len += 2;
+
                n2s(p,i);
-               param_len+=i+2;
-               if (param_len > n)
+
+               if (i > n - param_len)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1301,12 +1362,19 @@ int ssl3_get_key_exchange(SSL *s)
                 */
 
                /* XXX: For now we only support named (not generic) curves
-                * and the ECParameters in this case is just three bytes.
+                * and the ECParameters in this case is just three bytes. We
+                * also need one byte for the length of the encoded point
                 */
-               param_len=3;
-               if ((param_len > n) ||
-                   (*p != NAMED_CURVE_TYPE) || 
-                   ((curve_nid = curve_id2nid(*(p + 2))) == 0)) 
+               param_len=4;
+               if (param_len > n)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+
+               if ((*p != NAMED_CURVE_TYPE) || 
+                   ((curve_nid = curve_id2nid(*(p + 2))) == 0))
                        {
                        al=SSL_AD_INTERNAL_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
@@ -1348,15 +1416,15 @@ int ssl3_get_key_exchange(SSL *s)
 
                encoded_pt_len = *p;  /* length of encoded point */
                p+=1;
-               param_len += (1 + encoded_pt_len);
-               if ((param_len > n) ||
+
+               if ((encoded_pt_len > n - param_len) ||
                    (EC_POINT_oct2point(group, srvr_ecpoint, 
                        p, encoded_pt_len, bn_ctx) == 0))
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
                        goto f_err;
                        }
+               param_len += encoded_pt_len;
 
                n-=param_len;
                p+=encoded_pt_len;
@@ -1407,10 +1475,10 @@ int ssl3_get_key_exchange(SSL *s)
                n-=2;
                j=EVP_PKEY_size(pkey);
 
+               /* Check signature length. If n is 0 then signature is empty */
                if ((i != n) || (n > j) || (n <= 0))
                        {
                        /* wrong packet length */
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
                        goto f_err;
                        }
@@ -1419,6 +1487,7 @@ int ssl3_get_key_exchange(SSL *s)
                if (pkey->type == EVP_PKEY_RSA)
                        {
                        int num;
+                       unsigned int size;
 
                        j=0;
                        q=md_buf;
@@ -1431,9 +1500,9 @@ int ssl3_get_key_exchange(SSL *s)
                                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,param,param_len);
-                               EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i);
-                               q+=i;
-                               j+=i;
+                               EVP_DigestFinal_ex(&md_ctx,q,&size);
+                               q+=size;
+                               j+=size;
                                }
                        i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
                                                                pkey->pkey.rsa);
@@ -1504,7 +1573,6 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                if (n != 0)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
                        goto f_err;
                        }
@@ -1902,6 +1970,13 @@ int ssl3_send_client_key_exchange(SSL *s)
                        RSA *rsa;
                        unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 
+                       if (s->session->sess_cert == NULL)
+                               {
+                               /* We should always have a server certificate with SSL_kRSA. */
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+                               goto err;
+                               }
+
                        if (s->session->sess_cert->peer_rsa_tmp != NULL)
                                rsa=s->session->sess_cert->peer_rsa_tmp;
                        else
@@ -2161,6 +2236,13 @@ int ssl3_send_client_key_exchange(SSL *s)
                        int ecdh_clnt_cert = 0;
                        int field_size = 0;
 
+                       if (s->session->sess_cert == NULL) 
+                               {
+                               ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+                               goto err;
+                               }
+
                        /* Did we send out the client's
                         * ECDH share for use in premaster
                         * computation as part of client certificate?