Fix source where indent will not be able to cope
[openssl.git] / ssl / s3_clnt.c
index c51f3d0b0f48f9fad52f0eb71a248deeb0c68073..1ddcf26d4971b68aab4f0c5d157d01653e76494d 100644 (file)
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/md5.h>
-#ifdef OPENSSL_FIPS
-#include <openssl/fips.h>
-#endif
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
 #include <openssl/engine.h>
 #endif
 
-static const SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 
+#ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_client_method(int ver)
        {
        if (ver == SSL3_VERSION)
@@ -182,6 +179,7 @@ IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
                        ssl_undefined_function,
                        ssl3_connect,
                        ssl3_get_client_method)
+#endif
 
 int ssl3_connect(SSL *s)
        {
@@ -240,6 +238,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;
@@ -272,6 +277,9 @@ int ssl3_connect(SSL *s)
                        s->state=SSL3_ST_CW_CLNT_HELLO_A;
                        s->ctx->stats.sess_connect++;
                        s->init_num=0;
+                       s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
+                       /* Should have been reset by ssl3_get_finished, too. */
+                       s->s3->change_cipher_spec = 0;
                        break;
 
                case SSL3_ST_CW_CLNT_HELLO_A:
@@ -307,45 +315,15 @@ int ssl3_connect(SSL *s)
                                }
                        else
                                {
-#ifndef OPENSSL_NO_TLSEXT
-                               /* The server hello indicated that
-                                * an audit proof would follow. */
-                               if (s->s3->tlsext_authz_server_promised)
-                                       s->state=SSL3_ST_CR_SUPPLEMENTAL_DATA_A;
-                               else
-#endif
                                        s->state=SSL3_ST_CR_CERT_A;
                                }
                        s->init_num=0;
                        break;
-#ifndef OPENSSL_NO_TLSEXT
-               case SSL3_ST_CR_SUPPLEMENTAL_DATA_A:
-               case SSL3_ST_CR_SUPPLEMENTAL_DATA_B:
-                       ret = tls1_get_server_supplemental_data(s);
-                       if (ret <= 0) goto end;
-                       s->state=SSL3_ST_CR_CERT_A;
-                       s->init_num = 0;
-                       break;
-#endif
                case SSL3_ST_CR_CERT_A:
                case SSL3_ST_CR_CERT_B:
-#ifndef OPENSSL_NO_TLSEXT
-                       ret=ssl3_check_finished(s);
-                       if (ret <= 0) goto end;
-                       if (ret == 2)
-                               {
-                               s->hit = 1;
-                               if (s->tlsext_ticket_expected)
-                                       s->state=SSL3_ST_CR_SESSION_TICKET_A;
-                               else
-                                       s->state=SSL3_ST_CR_FINISHED_A;
-                               s->init_num=0;
-                               break;
-                               }
-#endif
-                       /* Check if it is anon DH/ECDH */
+                       /* Check if it is anon DH/ECDH, SRP auth */
                        /* or PSK */
-                       if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+                       if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) &&
                            !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                                {
                                ret=ssl3_get_server_certificate(s);
@@ -450,12 +428,10 @@ int ssl3_connect(SSL *s)
                        else
                                {
                                s->state=SSL3_ST_CW_CHANGE_A;
-                               s->s3->change_cipher_spec=0;
                                }
                        if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
                                {
                                s->state=SSL3_ST_CW_CHANGE_A;
-                               s->s3->change_cipher_spec=0;
                                }
 
                        s->init_num=0;
@@ -467,7 +443,6 @@ int ssl3_connect(SSL *s)
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_CW_CHANGE_A;
                        s->init_num=0;
-                       s->s3->change_cipher_spec=0;
                        break;
 
                case SSL3_ST_CW_CHANGE_A:
@@ -575,7 +550,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;
@@ -672,7 +647,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;
@@ -684,28 +660,78 @@ int ssl3_client_hello(SSL *s)
                SSL_SESSION *sess = s->session;
                if ((sess == NULL) ||
                        (sess->ssl_version != s->version) ||
-#ifdef OPENSSL_NO_TLSEXT
                        !sess->session_id_length ||
-#else
-                       (!sess->session_id_length && !sess->tlsext_tick) ||
-#endif
                        (sess->not_resumable))
                        {
                        if (!ssl_get_new_session(s,0))
                                goto err;
                        }
+               if (s->method->version == DTLS_ANY_VERSION)
+                       {
+                       /* Determine which DTLS version to use */
+                       int options = s->options;
+                       /* If DTLS 1.2 disabled correct the version number */
+                       if (options & SSL_OP_NO_DTLSv1_2)
+                               {
+                               if (tls1_suiteb(s))
+                                       {
+                                       SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+                                       goto err;
+                                       }
+                               /* Disabling all versions is silly: return an
+                                * error.
+                                */
+                               if (options & SSL_OP_NO_DTLSv1)
+                                       {
+                                       SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_WRONG_SSL_VERSION);
+                                       goto err;
+                                       }
+                               /* Update method so we don't use any DTLS 1.2
+                                * features.
+                                */
+                               s->method = DTLSv1_client_method();
+                               s->version = DTLS1_VERSION;
+                               }
+                       else
+                               {
+                               /* We only support one version: update method */
+                               if (options & SSL_OP_NO_DTLSv1)
+                                       s->method = DTLSv1_2_client_method();
+                               s->version = DTLS1_2_VERSION;
+                               }
+                       s->client_version = s->version;
+                       }
                /* else use the pre-loaded session */
 
                p=s->s3->client_random;
-               Time=(unsigned long)time(NULL);                 /* Time */
-               l2n(Time,p);
-               if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
-                       goto err;
+
+               /* for DTLS if client_random is initialized, reuse it, we are
+                * required to use same upon reply to HelloVerify */
+               if (SSL_IS_DTLS(s))
+                       {
+                       size_t idx;
+                       i = 1;
+                       for (idx=0; idx < sizeof(s->s3->client_random); idx++)
+                               {
+                               if (p[idx])
+                                       {
+                                       i = 0;
+                                       break;
+                                       }
+                               }
+                       }
+               else 
+                       i = 1;
+
+               if (i)
+                       ssl_fill_hello_random(s, 0, p,
+                                             sizeof(s->s3->client_random));
 
                /* Do the message type and length last */
-               d=p= &(buf[4]);
+               d=p= ssl_handshake_start(s);
 
-               /* version indicates the negotiated version: for example from
+               /*-
+                * version indicates the negotiated version: for example from
                 * an SSLv2/v3 compatible client hello). The client_version
                 * field is the maximum version we permit and it is also
                 * used in RSA encrypted premaster secrets. Some servers can
@@ -764,6 +790,19 @@ int ssl3_client_hello(SSL *s)
                        p+=i;
                        }
                
+               /* cookie stuff for DTLS */
+               if (SSL_IS_DTLS(s))
+                       {
+                       if ( s->d1->cookie_len > sizeof(s->d1->cookie))
+                               {
+                               SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+                               goto err;
+                               }
+                       *(p++) = s->d1->cookie_len;
+                       memcpy(p, s->d1->cookie, s->d1->cookie_len);
+                       p += s->d1->cookie_len;
+                       }
+               
                /* Ciphers supported */
                i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
                if (i == 0)
@@ -788,8 +827,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);
@@ -809,26 +847,21 @@ 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;
                        }
 #endif
                
-               l=(p-d);
-               d=buf;
-               *(d++)=SSL3_MT_CLIENT_HELLO;
-               l2n3(l,d);
-
+               l= p-d;
+               ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
                s->state=SSL3_ST_CW_CLNT_HELLO_B;
-               /* number of bytes to write */
-               s->init_num=p-buf;
-               s->init_off=0;
                }
 
        /* SSL3_ST_CW_CLNT_HELLO_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
 err:
        return(-1);
        }
@@ -837,6 +870,7 @@ int ssl3_get_server_hello(SSL *s)
        {
        STACK_OF(SSL_CIPHER) *sk;
        const SSL_CIPHER *c;
+       CERT *ct = s->cert;
        unsigned char *p,*d;
        int i,al=SSL_AD_INTERNAL_ERROR,ok;
        unsigned int j;
@@ -844,18 +878,24 @@ int ssl3_get_server_hello(SSL *s)
 #ifndef OPENSSL_NO_COMP
        SSL_COMP *comp;
 #endif
+       /* Hello verify request and/or server hello version may not
+        * match so set first packet if we're negotiating version.
+        */
+       if (SSL_IS_DTLS(s))
+               s->first_packet = 1;
 
        n=s->method->ssl_get_message(s,
                SSL3_ST_CR_SRVR_HELLO_A,
                SSL3_ST_CR_SRVR_HELLO_B,
                -1,
-               20000, /* ?? */
+               20000,
                &ok);
 
        if (!ok) return((int)n);
 
-       if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+       if (SSL_IS_DTLS(s))
                {
+               s->first_packet = 0;
                if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
                        {
                        if ( s->d1->send_cookie == 0)
@@ -880,6 +920,33 @@ int ssl3_get_server_hello(SSL *s)
                }
 
        d=p=(unsigned char *)s->init_msg;
+       if (s->method->version == DTLS_ANY_VERSION)
+               {
+               /* Work out correct protocol version to use */
+               int hversion = (p[0] << 8)|p[1];
+               int options = s->options;
+               if (hversion == DTLS1_2_VERSION
+                       && !(options & SSL_OP_NO_DTLSv1_2))
+                       s->method = DTLSv1_2_client_method();
+               else if (tls1_suiteb(s))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+                       s->version = hversion;
+                       al = SSL_AD_PROTOCOL_VERSION;
+                       goto f_err;
+                       }
+               else if (hversion == DTLS1_VERSION
+                       && !(options & SSL_OP_NO_DTLSv1))
+                       s->method = DTLSv1_client_method();
+               else
+                       {
+                       SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+                       s->version = hversion;
+                       al = SSL_AD_PROTOCOL_VERSION;
+                       goto f_err;
+                       }
+               s->version = s->method->version;
+               }
 
        if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
                {
@@ -895,6 +962,8 @@ int ssl3_get_server_hello(SSL *s)
        memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
        p+=SSL3_RANDOM_SIZE;
 
+       s->hit = 0;
+
        /* get the session-id */
        j= *(p++);
 
@@ -918,11 +987,12 @@ int ssl3_get_server_hello(SSL *s)
                        {
                        s->session->cipher = pref_cipher ?
                                pref_cipher : ssl_get_cipher_by_char(s, p+j);
+                       s->hit = 1;
                        }
                }
 #endif /* OPENSSL_NO_TLSEXT */
 
-       if (j != 0 && j == s->session->session_id_length
+       if (!s->hit && j != 0 && j == s->session->session_id_length
            && memcmp(p,s->session->session_id,j) == 0)
            {
            if(s->sid_ctx_length != s->session->sid_ctx_length
@@ -935,11 +1005,11 @@ int ssl3_get_server_hello(SSL *s)
                }
            s->hit=1;
            }
-       else    /* a miss or crap from the other end */
+       /* a miss or crap from the other end */
+       if (!s->hit)
                {
                /* If we were trying for session-id reuse, make a new
                 * SSL_SESSION so we don't stuff up other people */
-               s->hit=0;
                if (s->session->session_id_length > 0)
                        {
                        if (!ssl_get_new_session(s,0))
@@ -959,9 +1029,15 @@ int ssl3_get_server_hello(SSL *s)
                SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
                goto f_err;
                }
-       /* TLS v1.2 only ciphersuites require v1.2 or later */
-       if ((c->algorithm_ssl & SSL_TLSV1_2) && 
-               (TLS1_get_version(s) < TLS1_2_VERSION))
+       /* 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.
+        */
+       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);
@@ -998,10 +1074,10 @@ int ssl3_get_server_hello(SSL *s)
                        }
                }
        s->s3->tmp.new_cipher=c;
-       /* Don't digest cached records if TLS v1.2: we may need them for
+       /* Don't digest cached records if no sigalgs: we may need them for
         * client authentication.
         */
-       if (TLS1_get_version(s) < TLS1_2_VERSION && !ssl3_digest_cached_records(s))
+       if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s))
                goto f_err;
        /* lets get the compression algorithm */
        /* COMPRESSION */
@@ -1030,7 +1106,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);
@@ -1172,6 +1248,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;
@@ -1194,9 +1276,9 @@ int ssl3_get_server_certificate(SSL *s)
                    ? 0 : 1;
 
 #ifdef KSSL_DEBUG
-       printf("pkey,x = %p, %p\n", pkey,x);
-       printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
-       printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name,
+       fprintf(stderr,"pkey,x = %p, %p\n", pkey,x);
+       fprintf(stderr,"ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
+       fprintf(stderr,"cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name,
                s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert);
 #endif    /* KSSL_DEBUG */
 
@@ -1221,6 +1303,15 @@ int ssl3_get_server_certificate(SSL *s)
 
        if (need_cert)
                {
+               int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+               if (exp_idx >= 0 && i != exp_idx)
+                       {
+                       x=NULL;
+                       al=SSL_AD_ILLEGAL_PARAMETER;
+                       SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+                               SSL_R_WRONG_CERTIFICATE_TYPE);
+                       goto f_err;
+                       }
                sc->peer_cert_type=i;
                CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
                /* Why would the following ever happen?
@@ -1247,21 +1338,6 @@ int ssl3_get_server_certificate(SSL *s)
        s->session->verify_result = s->verify_result;
 
        x=NULL;
-#ifndef OPENSSL_NO_TLSEXT
-       /* Check the audit proof. */
-       if (s->ctx->tlsext_authz_server_audit_proof_cb)
-               {
-               ret = s->ctx->tlsext_authz_server_audit_proof_cb(s,
-                       s->ctx->tlsext_authz_server_audit_proof_cb_arg);
-               if (ret <= 0)
-                       {
-                       al = SSL_AD_BAD_CERTIFICATE;
-                       SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_INVALID_AUDIT_PROOF);
-                       goto f_err;
-                       }
-               }
-
-#endif
        ret=1;
        if (0)
                {
@@ -1282,8 +1358,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_k,alg_a;
+       int al,j,ok;
+       long i,param_len,n,alg_k,alg_a;
        EVP_PKEY *pkey=NULL;
        const EVP_MD *md = NULL;
 #ifndef OPENSSL_NO_RSA
@@ -1300,6 +1376,8 @@ int ssl3_get_key_exchange(SSL *s)
        int encoded_pt_len = 0;
 #endif
 
+       EVP_MD_CTX_init(&md_ctx);
+
        /* use same message size as in ssl3_get_certificate_request()
         * as ServerKeyExchange message may be skipped */
        n=s->method->ssl_get_message(s,
@@ -1310,14 +1388,26 @@ int ssl3_get_key_exchange(SSL *s)
                &ok);
        if (!ok) return((int)n);
 
+       alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
        if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
                {
+               /*
+                * Can't skip server key exchange if this is an ephemeral
+                * ciphersuite.
+                */
+               if (alg_k & (SSL_kDHE|SSL_kECDHE))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
+                       al = SSL_AD_UNEXPECTED_MESSAGE;
+                       goto f_err;
+                       }
 #ifndef OPENSSL_NO_PSK
                /* In plain PSK ciphersuite, ServerKeyExchange can be
                   omitted if no identity hint is sent. Set
                   session->sess_cert anyway to avoid problems
                   later.*/
-               if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+               if (alg_k & SSL_kPSK)
                        {
                        s->session->sess_cert=ssl_sess_cert_new();
                        if (s->ctx->psk_identity_hint)
@@ -1359,36 +1449,46 @@ 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_k=s->s3->tmp.new_cipher->algorithm_mkey;
+
        alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-       EVP_MD_CTX_init(&md_ctx);
+
+       al=SSL_AD_DECODE_ERROR;
 
 #ifndef OPENSSL_NO_PSK
        if (alg_k & SSL_kPSK)
                {
                char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
 
-               al=SSL_AD_HANDSHAKE_FAILURE;
+               param_len = 2;
+               if (param_len > n)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
                n2s(p,i);
-               param_len=i+2;
+
                /* Store PSK identity hint for later use, hint is used
                 * in ssl3_send_client_key_exchange.  Assume that the
                 * maximum length of a PSK identity hint can be as
                 * long as the maximum length of a PSK identity. */
                if (i > PSK_MAX_IDENTITY_LEN)
                        {
+                       al=SSL_AD_HANDSHAKE_FAILURE;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
                                SSL_R_DATA_LENGTH_TOO_LONG);
                        goto f_err;
                        }
-               if (param_len > n)
+               if (i > n - param_len)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
                                SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                /* If received PSK identity hint contains NULL
                 * characters, the hint is truncated from the first
                 * NULL. p may not be ending with NULL, so create a
@@ -1400,6 +1500,7 @@ int ssl3_get_key_exchange(SSL *s)
                s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
                if (s->ctx->psk_identity_hint == NULL)
                        {
+                       al=SSL_AD_HANDSHAKE_FAILURE;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
                        goto f_err;
                        }          
@@ -1412,14 +1513,22 @@ int ssl3_get_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_SRP
        if (alg_k & SSL_kSRP)
                {
-               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_SRP_N_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(s->srp_ctx.N=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1427,14 +1536,24 @@ 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_SRP_G_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(s->srp_ctx.g=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1442,15 +1561,25 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                p+=i;
 
+
+               if (1 > n - param_len)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
+               param_len += 1;
+
                i = (unsigned int)(p[0]);
                p++;
-               param_len+=i+1;
-               if (param_len > n)
+
+               if (i > n - param_len)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_S_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(s->srp_ctx.s=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1458,14 +1587,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_SRP_B_LENGTH);
                        goto f_err;
                        }
+               param_len += i;
+
                if (!(s->srp_ctx.B=BN_bin2bn(p,i,NULL)))
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
@@ -1474,6 +1612,12 @@ int ssl3_get_key_exchange(SSL *s)
                p+=i;
                n-=param_len;
 
+               if (!srp_verify_server_param(s, &al))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
+                       goto f_err;
+                       }
+
 /* We must check if there is a certificate */
 #ifndef OPENSSL_NO_RSA
                if (alg_a & SSL_aRSA)
@@ -1492,19 +1636,35 @@ int ssl3_get_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_RSA
        if (alg_k & SSL_kRSA)
                {
+               /* Temporary RSA keys only allowed in export ciphersuites */
+               if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher))
+                       {
+                       al=SSL_AD_UNEXPECTED_MESSAGE;
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+                       goto f_err;
+                       }
                if ((rsa=RSA_new()) == NULL)
                        {
                        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);
@@ -1512,14 +1672,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);
@@ -1544,21 +1713,30 @@ 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)
                        {
                        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);
@@ -1566,14 +1744,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);
@@ -1581,14 +1768,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);
@@ -1597,6 +1793,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);
@@ -1622,7 +1826,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;
@@ -1640,12 +1844,26 @@ 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 = tls1_ec_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;
+                       }
+               /* Check curve is one of our preferences, if not server has
+                * sent an invalid curve. ECParameters is 3 bytes.
+                */
+               if (!tls1_check_curve(s, p, 3))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_CURVE);
+                       goto f_err;
+                       }
+
+               if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) 
                        {
                        al=SSL_AD_INTERNAL_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
@@ -1687,15 +1905,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;
@@ -1736,27 +1954,20 @@ int ssl3_get_key_exchange(SSL *s)
        /* if it was signed, check the signature */
        if (pkey != NULL)
                {
-               if (TLS1_get_version(s) >= TLS1_2_VERSION)
+               if (SSL_USE_SIGALGS(s))
                        {
-                       int sigalg = tls12_get_sigid(pkey);
-                       /* Should never happen */
-                       if (sigalg == -1)
-                               {
-                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
-                               goto err;
-                               }
-                       /* Check key type is consistent with signature */
-                       if (sigalg != (int)p[1])
+                       int rv;
+                       if (2 > n)
                                {
-                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
-                               al=SSL_AD_DECODE_ERROR;
+                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                                       SSL_R_LENGTH_TOO_SHORT);
                                goto f_err;
                                }
-                       md = tls12_get_hash(p[0]);
-                       if (md == NULL)
+                       rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+                       if (rv == -1)
+                               goto err;
+                       else if (rv == 0)
                                {
-                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
-                               al=SSL_AD_DECODE_ERROR;
                                goto f_err;
                                }
 #ifdef SSL_DEBUG
@@ -1767,23 +1978,30 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
                        }
                else
                        md = EVP_sha1();
-                       
+
+               if (2 > n)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_LENGTH_TOO_SHORT);
+                       goto f_err;
+                       }
                n2s(p,i);
                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;
                        }
 
 #ifndef OPENSSL_NO_RSA
-               if (pkey->type == EVP_PKEY_RSA && TLS1_get_version(s) < TLS1_2_VERSION)
+               if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
                        {
                        int num;
+                       unsigned int size;
 
                        j=0;
                        q=md_buf;
@@ -1796,9 +2014,9 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
                                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);
@@ -1834,16 +2052,18 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
                }
        else
                {
-               if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
-                       /* aNULL or kPSK do not need public keys */
+               /* aNULL, aSRP or kPSK do not need public keys */
+               if (!(alg_a & (SSL_aNULL|SSL_aSRP)) && !(alg_k & SSL_kPSK))
                        {
-                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+                       /* Might be wrong key type, check it */
+                       if (ssl3_check_cert_and_algorithm(s))
+                               /* Otherwise this shouldn't happen */
+                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
                /* still data left over */
                if (n != 0)
                        {
-                       al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
                        goto f_err;
                        }
@@ -1936,12 +2156,28 @@ int ssl3_get_certificate_request(SSL *s)
 
        /* get the certificate types */
        ctype_num= *(p++);
+       if (s->cert->ctypes)
+               {
+               OPENSSL_free(s->cert->ctypes);
+               s->cert->ctypes = NULL;
+               }
        if (ctype_num > SSL3_CT_NUMBER)
+               {
+               /* If we exceed static buffer copy all to cert structure */
+               s->cert->ctypes = OPENSSL_malloc(ctype_num);
+               if (s->cert->ctypes == NULL)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               memcpy(s->cert->ctypes, p, ctype_num);
+               s->cert->ctype_num = (size_t)ctype_num;
                ctype_num=SSL3_CT_NUMBER;
+               }
        for (i=0; i<ctype_num; i++)
                s->s3->tmp.ctype[i]= p[i];
-       p+=ctype_num;
-       if (TLS1_get_version(s) >= TLS1_2_VERSION)
+       p+=p[-1];
+       if (SSL_USE_SIGALGS(s))
                {
                n2s(p, llen);
                /* Check we have enough room for signature algorithms and
@@ -1953,12 +2189,24 @@ int ssl3_get_certificate_request(SSL *s)
                        SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
                        goto err;
                        }
-               if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
+               /* Clear certificate digests and validity flags */
+               for (i = 0; i < SSL_PKEY_NUM; i++)
+                       {
+                       s->cert->pkeys[i].digest = NULL;
+                       s->cert->pkeys[i].valid_flags = 0;
+                       }
+               if ((llen & 1) || !tls1_save_sigalgs(s, p, llen))
                        {
                        ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
                        SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
                        goto err;
                        }
+               if (!tls1_process_sigalgs(s))
+                       {
+                       ssl3_send_alert(s,SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+                       SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
                p += llen;
                }
 
@@ -2058,24 +2306,13 @@ int ssl3_get_new_session_ticket(SSL *s)
        n=s->method->ssl_get_message(s,
                SSL3_ST_CR_SESSION_TICKET_A,
                SSL3_ST_CR_SESSION_TICKET_B,
-               -1,
+               SSL3_MT_NEWSESSION_TICKET,
                16384,
                &ok);
 
        if (!ok)
                return((int)n);
 
-       if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
-               {
-               s->s3->tmp.reuse_message=1;
-               return(1);
-               }
-       if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
-               {
-               al=SSL_AD_UNEXPECTED_MESSAGE;
-               SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
-               goto f_err;
-               }
        if (n < 6)
                {
                /* need at least ticket_lifetime_hint + ticket length */
@@ -2107,7 +2344,7 @@ int ssl3_get_new_session_ticket(SSL *s)
                }
        memcpy(s->session->tlsext_tick, p, ticklen);
        s->session->tlsext_ticklen = ticklen;
-       /* There are two ways to detect a resumed ticket sesion.
+       /* There are two ways to detect a resumed ticket session.
         * One is to set an appropriate session ID and then the server
         * must return a match in ServerHello. This allows the normal
         * client session ID matching to work and we know much 
@@ -2211,11 +2448,12 @@ int ssl3_get_server_done(SSL *s)
        int ok,ret=0;
        long n;
 
+       /* Second to last param should be very small, like 0 :-) */
        n=s->method->ssl_get_message(s,
                SSL3_ST_CR_SRVR_DONE_A,
                SSL3_ST_CR_SRVR_DONE_B,
                SSL3_MT_SERVER_DONE,
-               30, /* should be very small, like 0 :-) */
+               30,
                &ok);
 
        if (!ok) return((int)n);
@@ -2233,7 +2471,7 @@ int ssl3_get_server_done(SSL *s)
 
 int ssl3_send_client_key_exchange(SSL *s)
        {
-       unsigned char *p,*d;
+       unsigned char *p;
        int n;
        unsigned long alg_k;
 #ifndef OPENSSL_NO_RSA
@@ -2254,8 +2492,7 @@ int ssl3_send_client_key_exchange(SSL *s)
 
        if (s->state == SSL3_ST_CW_KEY_EXCH_A)
                {
-               d=(unsigned char *)s->init_buf->data;
-               p= &(d[4]);
+               p = ssl_handshake_start(s);
 
                alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 
@@ -2267,6 +2504,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
@@ -2339,7 +2583,7 @@ int ssl3_send_client_key_exchange(SSL *s)
                        EVP_CIPHER_CTX_init(&ciph_ctx);
 
 #ifdef KSSL_DEBUG
-                       printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
+                       fprintf(stderr,"ssl3_send_client_key_exchange(%lx & %lx)\n",
                                alg_k, SSL_kKRB5);
 #endif /* KSSL_DEBUG */
 
@@ -2355,9 +2599,9 @@ int ssl3_send_client_key_exchange(SSL *s)
                            goto err;
 #ifdef KSSL_DEBUG
                        {
-                       printf("kssl_cget_tkt rtn %d\n", krb5rc);
+                       fprintf(stderr,"kssl_cget_tkt rtn %d\n", krb5rc);
                        if (krb5rc && kssl_err.text)
-                         printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
+                         fprintf(stderr,"kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
                        }
 #endif /* KSSL_DEBUG */
 
@@ -2370,24 +2614,25 @@ int ssl3_send_client_key_exchange(SSL *s)
                                goto err;
                                }
 
-                       /*  20010406 VRS - Earlier versions used KRB5 AP_REQ
-                       **  in place of RFC 2712 KerberosWrapper, as in:
-                       **
-                       **  Send ticket (copy to *p, set n = length)
-                       **  n = krb5_ap_req.length;
-                       **  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
-                       **  if (krb5_ap_req.data)  
-                       **    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
-                       **
-                       **  Now using real RFC 2712 KerberosWrapper
-                       **  (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
-                       **  Note: 2712 "opaque" types are here replaced
-                       **  with a 2-byte length followed by the value.
-                       **  Example:
-                       **  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
-                       **  Where "xx xx" = length bytes.  Shown here with
-                       **  optional authenticator omitted.
-                       */
+                       /*-
+                        * 20010406 VRS - Earlier versions used KRB5 AP_REQ
+                        * in place of RFC 2712 KerberosWrapper, as in:
+                        *
+                        * Send ticket (copy to *p, set n = length)
+                        * n = krb5_ap_req.length;
+                        * memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
+                        * if (krb5_ap_req.data)  
+                        *   kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
+                        *
+                        * Now using real RFC 2712 KerberosWrapper
+                        * (Thanks to Simon Wilkinson <sxw@sxw.org.uk>)
+                        * Note: 2712 "opaque" types are here replaced
+                        * with a 2-byte length followed by the value.
+                        * Example:
+                        * KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
+                        * Where "xx xx" = length bytes.  Shown here with
+                        * optional authenticator omitted.
+                        */
 
                        /*  KerberosWrapper.Ticket              */
                        s2n(enc_ticket->length,p);
@@ -2418,12 +2663,13 @@ int ssl3_send_client_key_exchange(SSL *s)
                            if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
                                goto err;
 
-                       /*  20010420 VRS.  Tried it this way; failed.
-                       **      EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
-                       **      EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
-                       **                              kssl_ctx->length);
-                       **      EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
-                       */
+                       /*-
+                        * 20010420 VRS.  Tried it this way; failed.
+                        *      EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
+                        *      EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
+                        *                              kssl_ctx->length);
+                        *      EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
+                        */
 
                        memset(iv, 0, sizeof iv);  /* per RFC 1510 */
                        EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
@@ -2455,7 +2701,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;
@@ -2559,13 +2805,20 @@ 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;
                        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?
@@ -2573,7 +2826,8 @@ int ssl3_send_client_key_exchange(SSL *s)
                         */
                        if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) 
                                {
-                               /* XXX: For now, we do not support client
+                               /*-
+                                * XXX: For now, we do not support client
                                 * authentication using ECDH certificates.
                                 * To add such support, one needs to add
                                 * code that checks for appropriate 
@@ -2869,7 +3123,11 @@ int ssl3_send_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_PSK
                else if (alg_k & SSL_kPSK)
                        {
-                       char identity[PSK_MAX_IDENTITY_LEN];
+                       /* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes
+                        * to return a \0-terminated identity. The last byte
+                        * is for us for simulating strnlen. */
+                       char identity[PSK_MAX_IDENTITY_LEN + 2];
+                       size_t identity_len;
                        unsigned char *t = NULL;
                        unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
                        unsigned int pre_ms_len = 0, psk_len = 0;
@@ -2883,8 +3141,9 @@ int ssl3_send_client_key_exchange(SSL *s)
                                goto err;
                                }
 
+                       memset(identity, 0, sizeof(identity));
                        psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
-                               identity, PSK_MAX_IDENTITY_LEN,
+                               identity, sizeof(identity) - 1,
                                psk_or_pre_ms, sizeof(psk_or_pre_ms));
                        if (psk_len > PSK_MAX_PSK_LEN)
                                {
@@ -2898,7 +3157,14 @@ int ssl3_send_client_key_exchange(SSL *s)
                                        SSL_R_PSK_IDENTITY_NOT_FOUND);
                                goto psk_err;
                                }
-
+                       identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
+                       identity_len = strlen(identity);
+                       if (identity_len > PSK_MAX_IDENTITY_LEN)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_INTERNAL_ERROR);
+                               goto psk_err;
+                               }
                        /* create PSK pre_master_secret */
                        pre_ms_len = 2+psk_len+2+psk_len;
                        t = psk_or_pre_ms;
@@ -2932,14 +3198,13 @@ int ssl3_send_client_key_exchange(SSL *s)
                        s->session->master_key_length =
                                s->method->ssl3_enc->generate_master_secret(s,
                                        s->session->master_key,
-                                       psk_or_pre_ms, pre_ms_len); 
-                       n = strlen(identity);
-                       s2n(n, p);
-                       memcpy(p, identity, n);
-                       n+=2;
+                                       psk_or_pre_ms, pre_ms_len);
+                       s2n(identity_len, p);
+                       memcpy(p, identity, identity_len);
+                       n = 2 + identity_len;
                        psk_err = 0;
                psk_err:
-                       OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+                       OPENSSL_cleanse(identity, sizeof(identity));
                        OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
                        if (psk_err != 0)
                                {
@@ -2956,18 +3221,13 @@ int ssl3_send_client_key_exchange(SSL *s)
                            ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
-               
-               *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
-               l2n3(n,d);
 
+               ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
                s->state=SSL3_ST_CW_KEY_EXCH_B;
-               /* number of bytes to write */
-               s->init_num=n+4;
-               s->init_off=0;
                }
 
        /* SSL3_ST_CW_KEY_EXCH_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
 err:
 #ifndef OPENSSL_NO_ECDH
        BN_CTX_free(bn_ctx);
@@ -2981,7 +3241,7 @@ err:
 
 int ssl3_send_client_verify(SSL *s)
        {
-       unsigned char *p,*d;
+       unsigned char *p;
        unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
        EVP_PKEY *pkey;
        EVP_PKEY_CTX *pctx=NULL;
@@ -2994,15 +3254,14 @@ int ssl3_send_client_verify(SSL *s)
 
        if (s->state == SSL3_ST_CW_CERT_VRFY_A)
                {
-               d=(unsigned char *)s->init_buf->data;
-               p= &(d[4]);
+               p= ssl_handshake_start(s);
                pkey=s->cert->key->privatekey;
 /* Create context from key and test if sha1 is allowed as digest */
                pctx = EVP_PKEY_CTX_new(pkey,NULL);
                EVP_PKEY_sign_init(pctx);
                if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
                        {
-                       if (TLS1_get_version(s) < TLS1_2_VERSION)
+                       if (!SSL_USE_SIGALGS(s))
                                s->method->ssl3_enc->cert_verify_mac(s,
                                                NID_sha1,
                                                &(data[MD5_DIGEST_LENGTH]));
@@ -3014,7 +3273,7 @@ int ssl3_send_client_verify(SSL *s)
                /* For TLS v1.2 send signature algorithm and signature
                 * using agreed digest and cached handshake records.
                 */
-               if (TLS1_get_version(s) >= TLS1_2_VERSION)
+               if (SSL_USE_SIGALGS(s))
                        {
                        long hdatalen = 0;
                        void *hdata;
@@ -3121,16 +3380,12 @@ int ssl3_send_client_verify(SSL *s)
                        SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
                        goto err;
                }
-               *(d++)=SSL3_MT_CERTIFICATE_VERIFY;
-               l2n3(n,d);
-
+               ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
                s->state=SSL3_ST_CW_CERT_VRFY_B;
-               s->init_num=(int)n+4;
-               s->init_off=0;
                }
        EVP_MD_CTX_cleanup(&mctx);
        EVP_PKEY_CTX_free(pctx);
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
 err:
        EVP_MD_CTX_cleanup(&mctx);
        EVP_PKEY_CTX_free(pctx);
@@ -3138,13 +3393,24 @@ err:
        }
 
 /* Check a certificate can be used for client authentication. Currently
- * just check cert exists and if static DH client certificates can be used.
+ * check cert exists, if we have a suitable digest for TLS 1.2 if
+ * static DH client certificates can be used and optionally checks
+ * suitability for Suite B.
  */
 static int ssl3_check_client_certificate(SSL *s)
        {
        unsigned long alg_k;
        if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
                return 0;
+       /* If no suitable signature algorithm can't use certificate */
+       if (SSL_USE_SIGALGS(s) && !s->cert->key->digest)
+               return 0;
+       /* If strict mode check suitability of chain before using it.
+        * This also adjusts suite B digest if necessary.
+        */
+       if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
+               !tls1_check_chain(s, NULL, NULL, NULL, -2))
+               return 0;
        alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
        /* See if we can use client certificate for fixed DH */
        if (alg_k & (SSL_kDHr|SSL_kDHd))
@@ -3176,10 +3442,25 @@ int ssl3_send_client_certificate(SSL *s)
        X509 *x509=NULL;
        EVP_PKEY *pkey=NULL;
        int i;
-       unsigned long l;
 
        if (s->state == SSL3_ST_CW_CERT_A)
                {
+               /* Let cert callback update client certificates if required */
+               if (s->cert->cert_cb)
+                       {
+                       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;
                else
@@ -3238,13 +3519,16 @@ int ssl3_send_client_certificate(SSL *s)
        if (s->state == SSL3_ST_CW_CERT_C)
                {
                s->state=SSL3_ST_CW_CERT_D;
-               l=ssl3_output_cert_chain(s,
-                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
-               s->init_num=(int)l;
-               s->init_off=0;
+               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(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 #define has_bits(i,m)  (((i)&(m)) == (m))
@@ -3291,7 +3575,8 @@ int ssl3_check_cert_and_algorithm(SSL *s)
                {
                if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
                                                                s) == 0) 
-                       { /* check failed */
+                       {
+                       /* check failed */
                        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
                        goto f_err;
                        }
@@ -3300,6 +3585,16 @@ int ssl3_check_cert_and_algorithm(SSL *s)
                        return 1;
                        }
                }
+       else if (alg_a & SSL_aECDSA)
+               {
+               SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_ECDSA_SIGNING_CERT);
+               goto f_err;
+               }
+       else if (alg_k & (SSL_kECDHr|SSL_kECDHe))
+               {
+               SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_ECDH_CERT);
+               goto f_err;
+               }
 #endif
        pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
        i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
@@ -3328,20 +3623,20 @@ 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);
                goto f_err;
                }
-       else if ((alg_k & SSL_kDHr) && (TLS1_get_version(s) < TLS1_2_VERSION) &&
+       else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) &&
                !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
                {
                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
                goto f_err;
                }
 #ifndef OPENSSL_NO_DSA
-       else if ((alg_k & SSL_kDHd) && (TLS1_get_version(s) < TLS1_2_VERSION) &&
+       else if ((alg_k & SSL_kDHd) && !SSL_USE_SIGALGS(s) &&
                !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
                {
                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
@@ -3365,7 +3660,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))
@@ -3419,30 +3714,6 @@ int ssl3_send_next_proto(SSL *s)
        return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
        }
 # endif
-
-int ssl3_check_finished(SSL *s)
-       {
-       int ok;
-       long n;
-       /* If we have no ticket it cannot be a resumed session. */
-       if (!s->session->tlsext_tick)
-               return 1;
-       /* 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,
-               -1,
-               s->max_cert_list,
-               &ok);
-       if (!ok) return((int)n);
-       s->s3->tmp.reuse_message = 1;
-       if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
-               || (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
-               return 2;
-
-       return 1;
-       }
 #endif
 
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
@@ -3462,106 +3733,3 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
                i = s->ctx->client_cert_cb(s,px509,ppkey);
        return i;
        }
-
-#ifndef OPENSSL_NO_TLSEXT
-int tls1_get_server_supplemental_data(SSL *s)
-       {
-       int al;
-       int ok;
-       unsigned long supp_data_len, authz_data_len;
-       long n;
-       unsigned short supp_data_type, authz_data_type, proof_len;
-       const unsigned char *p;
-       unsigned char *new_proof;
-
-       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);
-
-       if (!ok) return((int)n);
-
-       p = (unsigned char *)s->init_msg;
-
-       /* The message cannot be empty */
-       if (n < 3)
-               {
-               al = SSL_AD_DECODE_ERROR;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
-               goto f_err;
-               }
-       /* Length of supplemental data */
-       n2l3(p,supp_data_len);
-       n -= 3;
-       /* We must have at least one supplemental data entry
-        * with type (1 byte) and length (2 bytes). */
-       if (supp_data_len != (unsigned long) n || n < 4)
-               {
-               al = SSL_AD_DECODE_ERROR;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
-               goto f_err;
-               }
-       /* Supplemental data type: must be authz_data */
-       n2s(p,supp_data_type);
-       n -= 2;
-       if (supp_data_type != TLSEXT_SUPPLEMENTALDATATYPE_authz_data)
-               {
-               al = SSL_AD_UNEXPECTED_MESSAGE;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE);
-               goto f_err;
-               }
-       /* Authz data length */
-       n2s(p, authz_data_len);
-       n -= 2;
-       if (authz_data_len != (unsigned long) n || n < 1)
-               {
-               al = SSL_AD_DECODE_ERROR;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
-               goto f_err;
-               }
-       /* Authz data type: must be audit_proof */
-       authz_data_type = *(p++);
-       n -= 1;
-       if (authz_data_type != TLSEXT_AUTHZDATAFORMAT_audit_proof)
-               {
-               al=SSL_AD_UNEXPECTED_MESSAGE;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_AUTHZ_DATA_TYPE);
-               goto f_err;
-               }
-       /* We have a proof: read its length */
-       if (n < 2)
-               {
-               al = SSL_AD_DECODE_ERROR;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
-               goto f_err;
-               }
-       n2s(p, proof_len);
-       n -= 2;
-       if (proof_len != (unsigned long) n)
-               {
-               al = SSL_AD_DECODE_ERROR;
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
-               goto f_err;
-               }
-       /* Store the proof */
-       new_proof = OPENSSL_realloc(s->session->audit_proof,
-                                   proof_len);
-       if (new_proof == NULL)
-               {
-               SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,ERR_R_MALLOC_FAILURE);
-               return 0;
-               }
-       s->session->audit_proof_length = proof_len;
-       s->session->audit_proof = new_proof;
-       memcpy(s->session->audit_proof, p, proof_len);
-
-       /* Got the proof, but can't verify it yet. */
-       return 1;
-f_err:
-       ssl3_send_alert(s,SSL3_AL_FATAL,al);
-       return -1;
-       }
-#endif