{
int offset=0;
int dgst_num;
+
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
* should be generalized. But it is next step
*/
if (s->s3->handshake_buffer)
- ssl3_digest_cached_records(s);
+ if (!ssl3_digest_cached_records(s))
+ return -1;
for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)
if (s->s3->handshake_dgst[dgst_num])
{
+ int dgst_size;
+
s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
- offset+=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
+ dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
+ if (dgst_size < 0)
+ {
+ ret = -1;
+ goto end;
+ }
+ offset+=dgst_size;
}
}
break;
break;
}
}
- if (j == 0)
+ if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
{
- if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
+ /* Special case as client bug workaround: the previously used cipher may
+ * not be in the current list, the client instead might be trying to
+ * continue using a cipher that before wasn't chosen due to server
+ * preferences. We'll have to reject the connection if the cipher is not
+ * enabled, though. */
+ c = sk_SSL_CIPHER_value(ciphers, 0);
+ if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
{
- /* Very bad for multi-threading.... */
- s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0);
- }
- else
- {
- /* we need to have the cipher in the cipher
- * list if we are asked to reuse it */
- al=SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
- goto f_err;
+ s->session->cipher = c;
+ j = 1;
}
}
+ if (j == 0)
+ {
+ /* we need to have the cipher in the cipher
+ * list if we are asked to reuse it */
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
+ goto f_err;
+ }
}
/* compression */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
goto f_err;
}
s->s3->tmp.new_cipher=c;
- ssl3_digest_cached_records(s);
}
else
{
else
#endif
s->s3->tmp.new_cipher=s->session->cipher;
- /* Clear cached handshake records */
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
}
+
+ if (!ssl3_digest_cached_records(s))
+ goto f_err;
/* we now have the following setup.
* client_random
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
*(d++)=SSL3_MT_SERVER_HELLO;
l2n3(l,d);
- s->state=SSL3_ST_CW_CLNT_HELLO_B;
+ s->state=SSL3_ST_SW_SRVR_HELLO_B;
/* number of bytes to write */
s->init_num=p-buf;
s->init_off=0;
}
- /* SSL3_ST_CW_CLNT_HELLO_B */
+ /* SSL3_ST_SW_SRVR_HELLO_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
s->init_off=0;
}
- /* SSL3_ST_CW_CLNT_HELLO_B */
+ /* SSL3_ST_SW_SRVR_DONE_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
}
/* TLS and [incidentally] DTLS{0xFEFF} */
- if (s->version > SSL3_VERSION)
+ if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
{
n2s(p,i);
if (n != i+2)
krb5_data enc_pms;
KSSL_CTX *kssl_ctx = s->kssl_ctx;
EVP_CIPHER_CTX ciph_ctx;
- EVP_CIPHER *enc = NULL;
+ const EVP_CIPHER *enc = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH
+ EVP_MAX_BLOCK_LENGTH];
n2s(p,i);
enc_ticket.length = i;
- if (n < enc_ticket.length + 6)
+ if (n < (long)(enc_ticket.length + 6))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
n2s(p,i);
authenticator.length = i;
- if (n < enc_ticket.length + authenticator.length + 6)
+ if (n < (long)(enc_ticket.length + authenticator.length + 6))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
- if (srvr_ecdh != NULL)
- EC_KEY_free(srvr_ecdh);
+ EC_KEY_free(srvr_ecdh);
BN_CTX_free(bn_ctx);
+ EC_KEY_free(s->s3->tmp.ecdh);
+ s->s3->tmp.ecdh = NULL;
/* Compute the master secret */
s->session->master_key_length = s->method->ssl3_enc-> \
else
{
i=ssl_verify_cert_chain(s,sk);
- if (!i)
+ if (i <= 0)
{
al=ssl_verify_alarm_type(s->verify_result);
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);