Check requested security strength in DRBG. Add function to retrieve the
[openssl.git] / ssl / s3_clnt.c
index af30d1af14630161ef44023b973e1883a990cbbb..fe3301349c238c67567231084e2bc5f3b2a9448e 100644 (file)
  */
 
 #include <stdio.h>
+#include <openssl/crypto.h>
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include <openssl/buffer.h>
@@ -184,7 +185,6 @@ int ssl3_connect(SSL *s)
        {
        BUF_MEM *buf=NULL;
        unsigned long Time=(unsigned long)time(NULL);
-       long num1;
        void (*cb)(const SSL *ssl,int type,int val)=NULL;
        int ret= -1;
        int new_state,state,skip=0;
@@ -208,7 +208,7 @@ int ssl3_connect(SSL *s)
                switch(s->state)
                        {
                case SSL_ST_RENEGOTIATE:
-                       s->new_session=1;
+                       s->renegotiate=1;
                        s->state=SSL_ST_CONNECT;
                        s->ctx->stats.sess_connect_renegotiate++;
                        /* break */
@@ -424,7 +424,15 @@ int ssl3_connect(SSL *s)
                        ret=ssl3_send_change_cipher_spec(s,
                                SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
                        if (ret <= 0) goto end;
+
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
                        s->state=SSL3_ST_CW_FINISHED_A;
+#else
+                       if (s->next_proto_negotiated)
+                               s->state=SSL3_ST_CW_NEXT_PROTO_A;
+                       else
+                               s->state=SSL3_ST_CW_FINISHED_A;
+#endif
                        s->init_num=0;
 
                        s->session->cipher=s->s3->tmp.new_cipher;
@@ -452,6 +460,15 @@ int ssl3_connect(SSL *s)
 
                        break;
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+               case SSL3_ST_CW_NEXT_PROTO_A:
+               case SSL3_ST_CW_NEXT_PROTO_B:
+                       ret=ssl3_send_next_proto(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_CW_FINISHED_A;
+                       break;
+#endif
+
                case SSL3_ST_CW_FINISHED_A:
                case SSL3_ST_CW_FINISHED_B:
                        ret=ssl3_send_finished(s,
@@ -520,16 +537,13 @@ int ssl3_connect(SSL *s)
                        break;
 
                case SSL3_ST_CW_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;
 
@@ -550,6 +564,7 @@ int ssl3_connect(SSL *s)
                        /* else do it later in ssl3_write */
 
                        s->init_num=0;
+                       s->renegotiate=0;
                        s->new_session=0;
 
                        ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
@@ -870,8 +885,11 @@ int ssl3_get_server_hello(SSL *s)
                s->session->cipher_id = s->session->cipher->id;
        if (s->hit && (s->session->cipher_id != c->id))
                {
+/* Workaround is now obsolete */
+#if 0
                if (!(s->options &
                        SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
+#endif
                        {
                        al=SSL_AD_ILLEGAL_PARAMETER;
                        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
@@ -902,7 +920,7 @@ int ssl3_get_server_hello(SSL *s)
                }
 #else
        j= *(p++);
-       if (s->hit && j != (int)s->session->compress_meth)
+       if (s->hit && j != s->session->compress_meth)
                {
                al=SSL_AD_ILLEGAL_PARAMETER;
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
@@ -985,7 +1003,9 @@ int ssl3_get_server_certificate(SSL *s)
 
        if (!ok) return((int)n);
 
-       if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE)
+       if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
+               ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && 
+               (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
                {
                s->s3->tmp.reuse_message=1;
                return(1);
@@ -1510,6 +1530,7 @@ int ssl3_get_key_exchange(SSL *s)
                s->session->sess_cert->peer_ecdh_tmp=ecdh;
                ecdh=NULL;
                BN_CTX_free(bn_ctx);
+               bn_ctx = NULL;
                EC_POINT_free(srvr_ecpoint);
                srvr_ecpoint = NULL;
                }
@@ -2672,9 +2693,7 @@ int ssl3_send_client_verify(SSL *s)
        unsigned u=0;
 #endif
        unsigned long n;
-#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
        int j;
-#endif
 
        if (s->state == SSL3_ST_CW_CERT_VRFY_A)
                {
@@ -2874,13 +2893,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
        DH *dh;
 #endif
 
-       sc=s->session->sess_cert;
-       if (sc == NULL)
-               {
-               SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
-               goto err;
-               }
-
        alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
        alg_a=s->s3->tmp.new_cipher->algorithm_auth;
 
@@ -2888,6 +2900,13 @@ int ssl3_check_cert_and_algorithm(SSL *s)
        if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
                return(1);
 
+       sc=s->session->sess_cert;
+       if (sc == NULL)
+               {
+               SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
+               goto err;
+               }
+
 #ifndef OPENSSL_NO_RSA
        rsa=s->session->sess_cert->peer_rsa_tmp;
 #endif
@@ -3004,6 +3023,32 @@ err:
  */
 
 #ifndef OPENSSL_NO_TLSEXT
+# ifndef OPENSSL_NO_NEXTPROTONEG
+int ssl3_send_next_proto(SSL *s)
+       {
+       unsigned int len, padding_len;
+       unsigned char *d;
+
+       if (s->state == SSL3_ST_CW_NEXT_PROTO_A)
+               {
+               len = s->next_proto_negotiated_len;
+               padding_len = 32 - ((len + 2) % 32);
+               d = (unsigned char *)s->init_buf->data;
+               d[4] = len;
+               memcpy(d + 5, s->next_proto_negotiated, len);
+               d[5 + len] = padding_len;
+               memset(d + 6 + len, 0, padding_len);
+               *(d++)=SSL3_MT_NEXT_PROTO;
+               l2n3(2 + len + padding_len, d);
+               s->state = SSL3_ST_CW_NEXT_PROTO_B;
+               s->init_num = 4 + 2 + len + padding_len;
+               s->init_off = 0;
+               }
+
+       return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+       }
+# endif
+
 int ssl3_check_finished(SSL *s)
        {
        int ok;