Support retries in certificate callback
[openssl.git] / ssl / s3_clnt.c
index 13006b7e05da717c187c3d9b5cabca9fb09bb3aa..68d3131b1e3c426937273572b0b4886e9b599d83 100644 (file)
@@ -688,7 +688,7 @@ int ssl3_client_hello(SSL *s)
        unsigned char *buf;
        unsigned char *p,*d;
        int i;
-       unsigned long Time,l;
+       unsigned long l;
 #ifndef OPENSSL_NO_COMP
        int j;
        SSL_COMP *comp;
@@ -768,12 +768,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);
@@ -928,7 +924,7 @@ int ssl3_get_server_hello(SSL *s)
        /* Hello verify request and/or server hello version may not
         * match so set first packet if we're negotiating version.
         */
-       if (s->method->version == DTLS_ANY_VERSION)
+       if (SSL_IS_DTLS(s))
                s->first_packet = 1;
 
        n=s->method->ssl_get_message(s,
@@ -1073,6 +1069,11 @@ int ssl3_get_server_hello(SSL *s)
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
                goto f_err;
                }
+       /* Set version disabled mask now we know version */
+       if (!SSL_USE_TLS1_2_CIPHERS(s))
+               ct->mask_ssl = SSL_TLSV1_2;
+       else
+               ct->mask_ssl = 0;
        /* If it is a disabled cipher we didn't send it in client hello,
         * so return an error.
         */
@@ -1655,7 +1656,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)
                        {
@@ -1733,7 +1734,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;
@@ -2580,7 +2581,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;
@@ -2684,7 +2685,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;
@@ -3306,11 +3307,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;
@@ -3468,7 +3478,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);
@@ -3505,7 +3515,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))
@@ -3564,9 +3574,11 @@ int ssl3_check_finished(SSL *s)
        {
        int ok;
        long n;
-/*     Read the message to see if it is supplemental data, regardless if there is a session ticket
-       this function is called when we really expect a Certificate
-       message, so permit appropriate message length */
+
+       /* Read the message to see if it is supplemental data,
+        * regardless if there is a session ticket this function is
+        * called when we really expect a Certificate message, so
+        * permit appropriate message length */
        n=s->method->ssl_get_message(s,
                SSL3_ST_CR_CERT_A,
                SSL3_ST_CR_CERT_B,
@@ -3577,9 +3589,7 @@ int ssl3_check_finished(SSL *s)
        s->s3->tmp.reuse_message = 1;
 
        if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA)
-               {
                return 3;
-               }
        /* If we have no ticket it cannot be a resumed session. */
        if (!s->session->tlsext_tick)
                return 1;
@@ -3645,7 +3655,7 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                                SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
                                return 0;
                                }
-                       //if first entry, write handshake message type
+                       /* if first entry, write handshake message type */
                        if (length == 0)
                                {
                                if (!BUF_MEM_grow_clean(s->init_buf, 4))
@@ -3655,9 +3665,12 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                                        }
                                p = (unsigned char *)s->init_buf->data;
                                *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
-                               //update message length when all callbacks complete
+                               /* update message length when all
+                                * callbacks complete */
                                size_loc = p;
-                               //skip over handshake length field (3 bytes) and supp_data length field (3 bytes)
+                               /* skip over handshake length field (3
+                                * bytes) and supp_data length field
+                                * (3 bytes) */
                                p += 3 + 3;
                                length += 1 +3 +3;
                                }
@@ -3674,9 +3687,9 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                        }
                if (length > 0)
                        {
-                       //write handshake length
+                       /* write handshake length */
                        l2n3(length - 4, size_loc);
-                       //supp_data length
+                       /* supp_data length */
                        l2n3(length - 7, size_loc);
                        s->state = SSL3_ST_CW_SUPPLEMENTAL_DATA_B;
                        s->init_num = length;
@@ -3685,7 +3698,7 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                        }
                }
 
-       //no supp data message sent
+       /* no supp data message sent */
        *skip = 1;
        s->init_num = 0;
        s->init_off = 0;
@@ -3724,11 +3737,11 @@ int tls1_get_server_supplemental_data(SSL *s)
                goto f_err;
                }
        n2l3(p, supp_data_len);
-       while (p<d+supp_data_len)
+       while (p < d+supp_data_len)
                {
                n2s(p, supp_data_entry_type);
                n2s(p, supp_data_entry_len);
-               //if there is a callback for this supp data type, send it
+               /* 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)
@@ -3741,7 +3754,7 @@ int tls1_get_server_supplemental_data(SSL *s)
                                        }
                                }
                        }
-               p+=supp_data_entry_len;
+               p += supp_data_entry_len;
                }
        return 1;
 f_err: