*/
#include <stdio.h>
+#include <openssl/crypto.h>
#include "ssl_locl.h"
#include "kssl_lcl.h"
#include <openssl/buffer.h>
#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
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+#ifndef OPENSSL_NO_HEARTBEATS
+ /* If we're awaiting a HeartbeatResponse, pretend we
+ * already got and don't await it anymore, because
+ * Heartbeats don't make sense during handshakes anyway.
+ */
+ if (s->tlsext_hb_pending)
+ {
+ s->tlsext_hb_pending = 0;
+ s->tlsext_hb_seq++;
+ }
+#endif
+
for (;;)
{
state=s->state;
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 */
if (ret <= 0) goto end;
if (s->hit)
+ {
s->state=SSL3_ST_CR_FINISHED_A;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_ticket_expected)
+ {
+ /* receive renewed session ticket */
+ s->state=SSL3_ST_CR_SESSION_TICKET_A;
+ }
+#endif
+ }
else
s->state=SSL3_ST_CR_CERT_A;
s->init_num=0;
case SSL3_ST_CR_SRVR_DONE_B:
ret=ssl3_get_server_done(s);
if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_SRP
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP)
+ {
+ if ((ret = SRP_Calc_A_param(s))<=0)
+ {
+ SSLerr(SSL_F_SSL3_CONNECT,SSL_R_SRP_A_CALC);
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
+ goto end;
+ }
+ }
+#endif
if (s->s3->tmp.cert_req)
s->state=SSL3_ST_CW_CERT_A;
else
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NPN)
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
s->state=SSL3_ST_CW_FINISHED_A;
#else
- if (s->next_proto_negotiated)
+ if (s->s3->next_proto_neg_seen)
s->state=SSL3_ST_CW_NEXT_PROTO_A;
else
s->state=SSL3_ST_CW_FINISHED_A;
break;
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NPN)
+#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);
/* 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);
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))
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
p+=ssl_put_cipher_by_char(s,NULL,NULL);
sk=ssl_get_ciphers_by_id(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);
}
}
s->s3->tmp.new_cipher=c;
- if (!ssl3_digest_cached_records(s))
+ /* Don't digest cached records if TLS v1.2: we may need them for
+ * client authentication.
+ */
+ if (TLS1_get_version(s) < TLS1_2_VERSION && !ssl3_digest_cached_records(s))
goto f_err;
-
/* lets get the compression algorithm */
/* COMPRESSION */
#ifdef OPENSSL_NO_COMP
/* wrong packet length */
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
- goto err;
+ goto f_err;
}
return(1);
int al,i,j,param_len,ok;
long n,alg_k,alg_a;
EVP_PKEY *pkey=NULL;
+ const EVP_MD *md = NULL;
#ifndef OPENSSL_NO_RSA
RSA *rsa=NULL;
#endif
}
else
#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (alg_k & SSL_kSRP)
+ {
+ n2s(p,i);
+ param_len=i+2;
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_N_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.N=BN_bin2bn(p,i,NULL)))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+ goto err;
+ }
+ p+=i;
+
+ n2s(p,i);
+ param_len+=i+2;
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_G_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.g=BN_bin2bn(p,i,NULL)))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+ goto err;
+ }
+ p+=i;
+
+ i = (unsigned int)(p[0]);
+ p++;
+ param_len+=i+1;
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_S_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.s=BN_bin2bn(p,i,NULL)))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+ goto err;
+ }
+ p+=i;
+
+ n2s(p,i);
+ param_len+=i+2;
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_B_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.B=BN_bin2bn(p,i,NULL)))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
+ goto err;
+ }
+ p+=i;
+ n-=param_len;
+
+/* We must check if there is a certificate */
+#ifndef OPENSSL_NO_RSA
+ if (alg_a & SSL_aRSA)
+ pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#else
+ if (0)
+ ;
+#endif
+#ifndef OPENSSL_NO_DSA
+ else if (alg_a & SSL_aDSS)
+ pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
+#endif
+ }
+ else
+#endif /* !OPENSSL_NO_SRP */
#ifndef OPENSSL_NO_RSA
if (alg_k & SSL_kRSA)
{
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;
}
/* if it was signed, check the signature */
if (pkey != NULL)
{
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ 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])
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
+ al=SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ md = tls12_get_hash(p[0]);
+ if (md == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
+ al=SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+ p += 2;
+ n -= 2;
+ }
+ else
+ md = EVP_sha1();
+
n2s(p,i);
n-=2;
j=EVP_PKEY_size(pkey);
}
#ifndef OPENSSL_NO_RSA
- if (pkey->type == EVP_PKEY_RSA)
+ if (pkey->type == EVP_PKEY_RSA && TLS1_get_version(s) < TLS1_2_VERSION)
{
int num;
q=md_buf;
for (num=2; num > 0; num--)
{
+ EVP_MD_CTX_set_flags(&md_ctx,
+ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
EVP_DigestInit_ex(&md_ctx,(num == 2)
?s->ctx->md5:s->ctx->sha1, NULL);
EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
}
else
#endif
-#ifndef OPENSSL_NO_DSA
- if (pkey->type == EVP_PKEY_DSA)
- {
- /* lets do DSS */
- EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
- EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx,param,param_len);
- if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
- {
- /* bad signature */
- al=SSL_AD_DECRYPT_ERROR;
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
- goto f_err;
- }
- }
- else
-#endif
-#ifndef OPENSSL_NO_ECDSA
- if (pkey->type == EVP_PKEY_EC)
{
- /* let's do ECDSA */
- EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+ EVP_VerifyInit_ex(&md_ctx, md, NULL);
EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
EVP_VerifyUpdate(&md_ctx,param,param_len);
goto f_err;
}
}
- else
-#endif
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
- goto err;
- }
}
else
{
{
int ok,ret=0;
unsigned long n,nc,l;
- unsigned int llen,ctype_num,i;
+ unsigned int llen, ctype_num,i;
X509_NAME *xn=NULL;
const unsigned char *p,*q;
unsigned char *d;
if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
{
s->s3->tmp.reuse_message=1;
+ /* If we get here we don't need any cached handshake records
+ * as we wont be doing client auth.
+ */
+ if (s->s3->handshake_buffer)
+ {
+ if (!ssl3_digest_cached_records(s))
+ goto err;
+ }
return(1);
}
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)
+ {
+ n2s(p, llen);
+ /* Check we have enough room for signature algorithms and
+ * following length value.
+ */
+ if ((unsigned long)(p - d + llen + 2) > n)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+ if ((llen & 1) || !tls1_process_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;
+ }
+ p += llen;
+ }
/* get the CA RDNs */
n2s(p,llen);
}
#endif
- if ((llen+ctype_num+2+1) != n)
+ if ((unsigned long)(p - d + llen) != n)
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
if (n < 6)
{
/* need at least ticket_lifetime_hint + ticket length */
- al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
/* ticket_lifetime_hint + ticket_length + ticket */
if (ticklen + 6 != n)
{
- al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
{
DH *dh_srvr,*dh_clnt;
+ SESS_CERT *scert = s->session->sess_cert;
- if (s->session->sess_cert == NULL)
+ if (scert == 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;
}
- if (s->session->sess_cert->peer_dh_tmp != NULL)
- dh_srvr=s->session->sess_cert->peer_dh_tmp;
+ if (scert->peer_dh_tmp != NULL)
+ dh_srvr=scert->peer_dh_tmp;
else
{
/* we get them from the cert */
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
- goto err;
+ int idx = scert->peer_cert_type;
+ EVP_PKEY *spkey = NULL;
+ dh_srvr = NULL;
+ if (idx >= 0)
+ spkey = X509_get_pubkey(
+ scert->peer_pkeys[idx].x509);
+ if (spkey)
+ {
+ dh_srvr = EVP_PKEY_get1_DH(spkey);
+ EVP_PKEY_free(spkey);
+ }
+ if (dh_srvr == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
}
-
- /* generate a new random key */
- if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
+ if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
- goto err;
+ /* Use client certificate key */
+ EVP_PKEY *clkey = s->cert->key->privatekey;
+ if (clkey)
+ dh_clnt = EVP_PKEY_get1_DH(clkey);
+ if (dh_clnt == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
}
- if (!DH_generate_key(dh_clnt))
+ else
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
- goto err;
+ /* generate a new random key */
+ if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ goto err;
+ }
+ if (!DH_generate_key(dh_clnt))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ DH_free(dh_clnt);
+ goto err;
+ }
}
/* use the 'p' output buffer for the DH key, but
* make sure to clear it out afterwards */
n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
+ if (scert->peer_dh_tmp == NULL)
+ DH_free(dh_srvr);
if (n <= 0)
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ DH_free(dh_clnt);
goto err;
}
/* clean up */
memset(p,0,n);
- /* send off the data */
- n=BN_num_bytes(dh_clnt->pub_key);
- s2n(n,p);
- BN_bn2bin(dh_clnt->pub_key,p);
- n+=2;
+ if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
+ n = 0;
+ else
+ {
+ /* send off the data */
+ n=BN_num_bytes(dh_clnt->pub_key);
+ s2n(n,p);
+ BN_bn2bin(dh_clnt->pub_key,p);
+ n+=2;
+ }
DH_free(dh_clnt);
EVP_PKEY_free(pub_key);
}
+#ifndef OPENSSL_NO_SRP
+ else if (alg_k & SSL_kSRP)
+ {
+ if (s->srp_ctx.A != NULL)
+ {
+ /* send off the data */
+ n=BN_num_bytes(s->srp_ctx.A);
+ s2n(n,p);
+ BN_bn2bin(s->srp_ctx.A,p);
+ n+=2;
+ }
+ else
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (s->session->srp_username != NULL)
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((s->session->master_key_length = SRP_generate_client_master_secret(s,s->session->master_key))<0)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
#ifndef OPENSSL_NO_PSK
else if (alg_k & SSL_kPSK)
{
unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx=NULL;
-#ifndef OPENSSL_NO_RSA
+ EVP_MD_CTX mctx;
unsigned u=0;
-#endif
unsigned long n;
int j;
+ EVP_MD_CTX_init(&mctx);
+
if (s->state == SSL3_ST_CW_CERT_VRFY_A)
{
d=(unsigned char *)s->init_buf->data;
EVP_PKEY_sign_init(pctx);
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
{
- s->method->ssl3_enc->cert_verify_mac(s,
+ if (TLS1_get_version(s) < TLS1_2_VERSION)
+ s->method->ssl3_enc->cert_verify_mac(s,
NID_sha1,
&(data[MD5_DIGEST_LENGTH]));
}
{
ERR_clear_error();
}
+ /* For TLS v1.2 send signature algorithm and signature
+ * using agreed digest and cached handshake records.
+ */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ long hdatalen = 0;
+ void *hdata;
+ const EVP_MD *md = s->cert->key->digest;
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
+ &hdata);
+ if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ p += 2;
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
+ EVP_MD_name(md));
+#endif
+ if (!EVP_SignInit_ex(&mctx, md, NULL)
+ || !EVP_SignUpdate(&mctx, hdata, hdatalen)
+ || !EVP_SignFinal(&mctx, p + 2, &u, pkey))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ s2n(u,p);
+ n = u + 4;
+ if (!ssl3_digest_cached_records(s))
+ goto err;
+ }
+ else
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
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));
err:
+ EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
return(-1);
}
+/* Check a certificate can be used for client authentication. Currently
+ * just check cert exists and if static DH client certificates can be used.
+ */
+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;
+ 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))
+ {
+ SESS_CERT *scert = s->session->sess_cert;
+ int i = scert->peer_cert_type;
+ EVP_PKEY *clkey = NULL, *spkey = NULL;
+ clkey = s->cert->key->privatekey;
+ /* If client key not DH assume it can be used */
+ if (EVP_PKEY_id(clkey) != EVP_PKEY_DH)
+ return 1;
+ if (i >= 0)
+ spkey = X509_get_pubkey(scert->peer_pkeys[i].x509);
+ if (spkey)
+ {
+ /* Compare server and client parameters */
+ i = EVP_PKEY_cmp_parameters(clkey, spkey);
+ EVP_PKEY_free(spkey);
+ if (i != 1)
+ return 0;
+ }
+ s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
+ }
+ return 1;
+ }
+
int ssl3_send_client_certificate(SSL *s)
{
X509 *x509=NULL;
if (s->state == SSL3_ST_CW_CERT_A)
{
- if ((s->cert == NULL) ||
- (s->cert->key->x509 == NULL) ||
- (s->cert->key->privatekey == NULL))
- s->state=SSL3_ST_CW_CERT_B;
- else
+ if (ssl3_check_client_certificate(s))
s->state=SSL3_ST_CW_CERT_C;
+ else
+ s->state=SSL3_ST_CW_CERT_B;
}
/* We need to get a client cert */
if (x509 != NULL) X509_free(x509);
if (pkey != NULL) EVP_PKEY_free(pkey);
+ if (i && !ssl3_check_client_certificate(s))
+ i = 0;
if (i == 0)
{
if (s->version == SSL3_VERSION)
alg_a=s->s3->tmp.new_cipher->algorithm_auth;
/* we don't have a certificate */
- if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
+ if ((alg_a & (SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
return(1);
sc=s->session->sess_cert;
if (idx == SSL_PKEY_ECC)
{
if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
- s->s3->tmp.new_cipher) == 0)
+ s) == 0)
{ /* check failed */
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
goto f_err;
}
#endif
#ifndef OPENSSL_NO_DH
- if ((alg_k & SSL_kEDH) &&
+ if ((alg_k & SSL_kEDH) &&
!(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) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
+ else if ((alg_k & SSL_kDHr) && (TLS1_get_version(s) < TLS1_2_VERSION) &&
+ !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) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
+ else if ((alg_k & SSL_kDHd) && (TLS1_get_version(s) < TLS1_2_VERSION) &&
+ !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
{
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
goto f_err;
*/
#ifndef OPENSSL_NO_TLSEXT
-# ifndef OPENSSL_NO_NPN
+# ifndef OPENSSL_NO_NEXTPROTONEG
int ssl3_send_next_proto(SSL *s)
{
unsigned int len, padding_len;