Clarify CMS_decrypt behaviour.
[openssl.git] / ssl / s3_clnt.c
index ce7b36aa14083c0a866a6a2a198b4897eb208d32..9a0b1bda8e18178d065747281a4b6bc71187f374 100644 (file)
@@ -240,6 +240,13 @@ int ssl3_connect(SSL *s)
                                ret = -1;
                                goto end;
                                }
+
+                       if (!ssl_security(s, SSL_SECOP_VERSION, 0,
+                                                       s->version, NULL))
+                               {
+                               SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW);
+                               return -1;
+                               }
                                
                        /* s->version=SSL3_VERSION; */
                        s->type=SSL_ST_CONNECT;
@@ -688,7 +695,8 @@ int ssl3_client_hello(SSL *s)
        unsigned char *buf;
        unsigned char *p,*d;
        int i;
-       unsigned long Time,l;
+       unsigned long l;
+       int al = 0;
 #ifndef OPENSSL_NO_COMP
        int j;
        SSL_COMP *comp;
@@ -768,12 +776,8 @@ int ssl3_client_hello(SSL *s)
                        i = 1;
 
                if (i)
-                       {
-                       Time=(unsigned long)time(NULL); /* Time */
-                       l2n(Time,p);
-                       RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
-                                       
-                       }
+                       ssl_fill_hello_random(s, 0, p,
+                                             sizeof(s->s3->client_random));
 
                /* Do the message type and length last */
                d=p= ssl_handshake_start(s);
@@ -874,8 +878,7 @@ int ssl3_client_hello(SSL *s)
                *(p++)=1;
 #else
 
-               if ((s->options & SSL_OP_NO_COMPRESSION)
-                                       || !s->ctx->comp_methods)
+               if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
                        j=0;
                else
                        j=sk_SSL_COMP_num(s->ctx->comp_methods);
@@ -895,8 +898,9 @@ int ssl3_client_hello(SSL *s)
                        SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
                        goto err;
                        }
-               if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+               if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL)
                        {
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al);
                        SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
@@ -1081,9 +1085,7 @@ int ssl3_get_server_hello(SSL *s)
        /* If it is a disabled cipher we didn't send it in client hello,
         * so return an error.
         */
-       if (c->algorithm_ssl & ct->mask_ssl ||
-               c->algorithm_mkey & ct->mask_k ||
-               c->algorithm_auth & ct->mask_a)
+       if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK))
                {
                al=SSL_AD_ILLEGAL_PARAMETER;
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
@@ -1152,7 +1154,7 @@ int ssl3_get_server_hello(SSL *s)
                }
        if (j == 0)
                comp=NULL;
-       else if (s->options & SSL_OP_NO_COMPRESSION)
+       else if (!ssl_allow_compression(s))
                {
                al=SSL_AD_ILLEGAL_PARAMETER;
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
@@ -1294,6 +1296,12 @@ int ssl3_get_server_certificate(SSL *s)
                goto f_err; 
                }
        ERR_clear_error(); /* but we keep s->verify_result */
+       if (i > 1)
+               {
+               SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, i);
+               al = SSL_AD_HANDSHAKE_FAILURE;
+               goto f_err;
+               }
 
        sc=ssl_sess_cert_new();
        if (sc == NULL) goto err;
@@ -1660,7 +1668,7 @@ int ssl3_get_key_exchange(SSL *s)
                ;
 #endif
 #ifndef OPENSSL_NO_DH
-       else if (alg_k & SSL_kEDH)
+       else if (alg_k & SSL_kDHE)
                {
                if ((dh=DH_new()) == NULL)
                        {
@@ -1713,6 +1721,14 @@ int ssl3_get_key_exchange(SSL *s)
                p+=i;
                n-=param_len;
 
+               if (!ssl_security(s, SSL_SECOP_TMP_DH,
+                                               DH_security_bits(dh), 0, dh))
+                       {
+                       al=SSL_AD_HANDSHAKE_FAILURE;
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL);
+                       goto f_err;
+                       }
+
 #ifndef OPENSSL_NO_RSA
                if (alg_a & SSL_aRSA)
                        pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
@@ -1738,7 +1754,7 @@ int ssl3_get_key_exchange(SSL *s)
 #endif /* !OPENSSL_NO_DH */
 
 #ifndef OPENSSL_NO_ECDH
-       else if (alg_k & SSL_kEECDH)
+       else if (alg_k & SSL_kECDHE)
                {
                EC_GROUP *ngroup;
                const EC_GROUP *group;
@@ -2585,7 +2601,7 @@ int ssl3_send_client_key_exchange(SSL *s)
                        }
 #endif
 #ifndef OPENSSL_NO_DH
-               else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+               else if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd))
                        {
                        DH *dh_srvr,*dh_clnt;
                        SESS_CERT *scert = s->session->sess_cert;
@@ -2689,7 +2705,7 @@ int ssl3_send_client_key_exchange(SSL *s)
 #endif
 
 #ifndef OPENSSL_NO_ECDH 
-               else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+               else if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe))
                        {
                        const EC_GROUP *srvr_group = NULL;
                        EC_KEY *tkey;
@@ -3311,11 +3327,20 @@ int ssl3_send_client_certificate(SSL *s)
        if (s->state == SSL3_ST_CW_CERT_A)
                {
                /* Let cert callback update client certificates if required */
-               if (s->cert->cert_cb
-                       && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0)
+               if (s->cert->cert_cb)
                        {
-                       ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
-                       return 0;
+                       i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+                       if (i < 0)
+                               {
+                               s->rwstate=SSL_X509_LOOKUP;
+                               return -1;
+                               }
+                       if (i == 0)
+                               {
+                               ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
+                               return 0;
+                               }
+                       s->rwstate=SSL_NOTHING;
                        }
                if (ssl3_check_client_certificate(s))
                        s->state=SSL3_ST_CW_CERT_C;
@@ -3375,8 +3400,13 @@ int ssl3_send_client_certificate(SSL *s)
        if (s->state == SSL3_ST_CW_CERT_C)
                {
                s->state=SSL3_ST_CW_CERT_D;
-               ssl3_output_cert_chain(s,
-                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
+               if (!ssl3_output_cert_chain(s,
+                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key))
+                       {
+                       SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+                       ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
+                       return 0;
+                       }
                }
        /* SSL3_ST_CW_CERT_D */
        return ssl_do_write(s);
@@ -3473,7 +3503,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
                }
 #endif
 #ifndef OPENSSL_NO_DH
-       if ((alg_k & SSL_kEDH) && 
+       if ((alg_k & SSL_kDHE) && 
                !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
                {
                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
@@ -3510,7 +3540,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
                else
 #endif
 #ifndef OPENSSL_NO_DH
-                       if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+                       if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd))
                            {
                            if (dh == NULL
                                || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
@@ -3617,6 +3647,7 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 #ifndef OPENSSL_NO_TLSEXT
 int tls1_send_client_supplemental_data(SSL *s, int *skip)
        {
+       int al = 0;
        if (s->ctx->cli_supp_data_records_count)
                {
                unsigned char *p = NULL;
@@ -3636,20 +3667,20 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                        if (!record->fn2)
                                continue;
                        cb_retval = record->fn2(s, record->supp_data_type,
-                               &out, &outlen,
-                               record->arg);
+                                               &out, &outlen, &al,
+                                               record->arg);
                        if (cb_retval == -1)
                                continue; /* skip this supp data entry */
                        if (cb_retval == 0)
                                {
                                SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
-                               return 0;
+                               goto f_err;
                                }
                        if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
                                {
                                SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
                                return 0;
-                               }
+                               }
                        /* if first entry, write handshake message type */
                        if (length == 0)
                                {
@@ -3698,6 +3729,10 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
        s->init_num = 0;
        s->init_off = 0;
        return 1;
+
+       f_err:
+       ssl3_send_alert(s,SSL3_AL_FATAL,al);
+       return 0;
        }
 
 int tls1_get_server_supplemental_data(SSL *s)
@@ -3707,18 +3742,18 @@ int tls1_get_server_supplemental_data(SSL *s)
        long n;
        const unsigned char *p, *d;
        unsigned short supp_data_entry_type = 0;
-       unsigned long supp_data_entry_len = 0;
+       unsigned short supp_data_entry_len = 0;
        unsigned long supp_data_len = 0;
        size_t i;
        int cb_retval = 0;
 
        n=s->method->ssl_get_message(s,
-               SSL3_ST_CR_SUPPLEMENTAL_DATA_A,
-               SSL3_ST_CR_SUPPLEMENTAL_DATA_B,
-               SSL3_MT_SUPPLEMENTAL_DATA,
-               /* use default limit */
-               TLSEXT_MAXLEN_supplemental_data,
-               &ok);
+                                    SSL3_ST_CR_SUPPLEMENTAL_DATA_A,
+                                    SSL3_ST_CR_SUPPLEMENTAL_DATA_B,
+                                    SSL3_MT_SUPPLEMENTAL_DATA,
+                                    /* use default limit */
+                                    TLSEXT_MAXLEN_supplemental_data,
+                                    &ok);
 
        if (!ok) return((int)n);
 
@@ -3739,9 +3774,12 @@ int tls1_get_server_supplemental_data(SSL *s)
                /* if there is a callback for this supp data type, send it */
                for (i=0; i < s->ctx->cli_supp_data_records_count; i++)
                        {
-                       if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->cli_supp_data_records[i].fn1)
+                       if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type &&
+                           s->ctx->cli_supp_data_records[i].fn1)
                                {
-                               cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->cli_supp_data_records[i].arg);
+                               cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p,
+                                                                                supp_data_entry_len, &al,
+                                                                                s->ctx->cli_supp_data_records[i].arg);
                                if (cb_retval == 0)
                                        {
                                        SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);