summaryrefslogtreecommitdiff
path: root/app/openssl/ssl/s3_clnt.c
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2014-06-13 12:21:38 +0200
committerParménides GV <parmegv@sdf.org>2014-06-13 12:21:38 +0200
commitd09435a9d2adb0d0cafa0b1f9f6cfe326346cbc6 (patch)
tree946278cd836aa6af639675f4eb5ec7378d783dd8 /app/openssl/ssl/s3_clnt.c
parent5d47fde84a03acb1201f8650c55dc0cd981df679 (diff)
parent3a71bc9e4aa4296f460e2e3c55de74c9852477ad (diff)
Merge branch 'develop' into release-0.5.2
Diffstat (limited to 'app/openssl/ssl/s3_clnt.c')
-rw-r--r--app/openssl/ssl/s3_clnt.c877
1 files changed, 681 insertions, 196 deletions
diff --git a/app/openssl/ssl/s3_clnt.c b/app/openssl/ssl/s3_clnt.c
index 42bcd629..5e15b75c 100644
--- a/app/openssl/ssl/s3_clnt.c
+++ b/app/openssl/ssl/s3_clnt.c
@@ -156,6 +156,9 @@
#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
@@ -199,19 +202,37 @@ int ssl3_connect(SSL *s)
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
-#if 0 /* Send app data in separate packet, otherwise, some particular site
- * (only one site so far) closes the socket.
- * Note: there is a very small chance that two TCP packets
- * could be arriving at server combined into a single TCP packet,
- * then trigger that site to break. We haven't encounter that though.
+
+#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
+
+// BEGIN android-added
+#if 0
+/* Send app data in separate packet, otherwise, some particular site
+ * (only one site so far) closes the socket. http://b/2511073
+ * Note: there is a very small chance that two TCP packets
+ * could be arriving at server combined into a single TCP packet,
+ * then trigger that site to break. We haven't encounter that though.
+ */
+// END android-added
if (SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH)
{
/* Send app data along with CCS/Finished */
s->s3->flags |= SSL3_FLAGS_DELAY_CLIENT_FINISHED;
}
-#endif
+// BEGIN android-added
+#endif
+// END android-added
for (;;)
{
state=s->state;
@@ -219,7 +240,7 @@ int ssl3_connect(SSL *s)
switch(s->state)
{
case SSL_ST_RENEGOTIATE:
- s->new_session=1;
+ s->renegotiate=1;
s->state=SSL_ST_CONNECT;
s->ctx->stats.sess_connect_renegotiate++;
/* break */
@@ -292,7 +313,16 @@ int ssl3_connect(SSL *s)
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;
@@ -315,9 +345,10 @@ int ssl3_connect(SSL *s)
}
#endif
/* Check if it is anon DH/ECDH */
- /* or PSK */
+ /* or non-RSA PSK */
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
- !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+ !((s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) &&
+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)))
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
@@ -370,6 +401,17 @@ int ssl3_connect(SSL *s)
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
@@ -436,15 +478,15 @@ int ssl3_connect(SSL *s)
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
s->state=SSL3_ST_CW_FINISHED_A;
-#else
- if (s->next_proto_negotiated)
+#if !defined(OPENSSL_NO_TLSEXT)
+ if (s->s3->tlsext_channel_id_valid)
+ s->state=SSL3_ST_CW_CHANNEL_ID_A;
+# if !defined(OPENSSL_NO_NEXTPROTONEG)
+ if (s->s3->next_proto_neg_seen)
s->state=SSL3_ST_CW_NEXT_PROTO_A;
- else
- s->state=SSL3_ST_CW_FINISHED_A;
+# endif
#endif
-
s->init_num=0;
s->session->cipher=s->s3->tmp.new_cipher;
@@ -477,6 +519,18 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CW_NEXT_PROTO_B:
ret=ssl3_send_next_proto(s);
if (ret <= 0) goto end;
+ if (s->s3->tlsext_channel_id_valid)
+ s->state=SSL3_ST_CW_CHANNEL_ID_A;
+ else
+ s->state=SSL3_ST_CW_FINISHED_A;
+ break;
+#endif
+
+#if !defined(OPENSSL_NO_TLSEXT)
+ case SSL3_ST_CW_CHANNEL_ID_A:
+ case SSL3_ST_CW_CHANNEL_ID_B:
+ ret=ssl3_send_channel_id(s);
+ if (ret <= 0) goto end;
s->state=SSL3_ST_CW_FINISHED_A;
break;
#endif
@@ -553,7 +607,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;
@@ -611,6 +665,7 @@ int ssl3_connect(SSL *s)
/* else do it later in ssl3_write */
s->init_num=0;
+ s->renegotiate=0;
s->new_session=0;
ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
@@ -667,7 +722,7 @@ int ssl3_client_hello(SSL *s)
unsigned char *buf;
unsigned char *p,*d;
int i;
- unsigned long Time,l;
+ unsigned long l;
#ifndef OPENSSL_NO_COMP
int j;
SSL_COMP *comp;
@@ -698,17 +753,50 @@ int ssl3_client_hello(SSL *s)
/* 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)
+
+ if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
goto err;
/* Do the message type and length last */
d=p= &(buf[4]);
+ /* 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
+ * choke if we initially report a higher version then
+ * renegotiate to a lower one in the premaster secret. This
+ * didn't happen with TLS 1.0 as most servers supported it
+ * but it can with TLS 1.1 or later if the server only supports
+ * 1.0.
+ *
+ * Possible scenario with previous logic:
+ * 1. Client hello indicates TLS 1.2
+ * 2. Server hello says TLS 1.0
+ * 3. RSA encrypted premaster secret uses 1.2.
+ * 4. Handhaked proceeds using TLS 1.0.
+ * 5. Server sends hello request to renegotiate.
+ * 6. Client hello indicates TLS v1.0 as we now
+ * know that is maximum server supports.
+ * 7. Server chokes on RSA encrypted premaster secret
+ * containing version 1.0.
+ *
+ * For interoperability it should be OK to always use the
+ * maximum version we support in client hello and then rely
+ * on the checking of version to ensure the servers isn't
+ * being inconsistent: for example initially negotiating with
+ * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+ * client_version in client hello and not resetting it to
+ * the negotiated version.
+ */
+#if 0
*(p++)=s->version>>8;
*(p++)=s->version&0xff;
s->client_version=s->version;
+#else
+ *(p++)=s->client_version>>8;
+ *(p++)=s->client_version&0xff;
+#endif
/* Random stuff */
memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
@@ -738,6 +826,15 @@ int ssl3_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
goto err;
}
+#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
+ /* Some servers hang if client hello > 256 bytes
+ * as hack workaround chop number of supported ciphers
+ * to keep it well below this if we use TLS v1.2
+ */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION
+ && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
+ i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
+#endif
s2n(i,p);
p+=i;
@@ -891,6 +988,7 @@ int ssl3_get_server_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto f_err;
}
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
s->hit=1;
}
else /* a miss or crap from the other end */
@@ -924,6 +1022,14 @@ 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))
+ {
+ 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);
@@ -955,9 +1061,14 @@ int ssl3_get_server_hello(SSL *s)
}
}
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))
+ {
+ al = SSL_AD_INTERNAL_ERROR;
goto f_err;
-
+ }
/* lets get the compression algorithm */
/* COMPRESSION */
#ifdef OPENSSL_NO_COMP
@@ -1030,7 +1141,7 @@ int ssl3_get_server_hello(SSL *s)
/* 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);
@@ -1236,6 +1347,7 @@ int ssl3_get_key_exchange(SSL *s)
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
@@ -1267,12 +1379,14 @@ int ssl3_get_key_exchange(SSL *s)
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 (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)
{
s->session->sess_cert=ssl_sess_cert_new();
- if (s->ctx->psk_identity_hint)
- OPENSSL_free(s->ctx->psk_identity_hint);
- s->ctx->psk_identity_hint = NULL;
+ if (s->session->psk_identity_hint)
+ {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ }
}
#endif
s->s3->tmp.reuse_message=1;
@@ -1315,52 +1429,137 @@ int ssl3_get_key_exchange(SSL *s)
EVP_MD_CTX_init(&md_ctx);
#ifndef OPENSSL_NO_PSK
- if (alg_k & SSL_kPSK)
+ if (alg_a & SSL_aPSK)
{
char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
al=SSL_AD_HANDSHAKE_FAILURE;
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)
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
- SSL_R_DATA_LENGTH_TOO_LONG);
+ if (s->session->psk_identity_hint)
+ {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ }
+ if (i != 0)
+ {
+ /* 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)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
+ goto f_err;
+ }
+ /* 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
+ * NULL-terminated string. */
+ memcpy(tmp_id_hint, p, i);
+ memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+ s->session->psk_identity_hint = BUF_strdup(tmp_id_hint);
+ if (s->session->psk_identity_hint == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ }
+ p+=i;
+ n-=param_len;
+ }
+#endif /* !OPENSSL_NO_PSK */
+
+ if (0) {}
+#ifndef OPENSSL_NO_SRP
+ else 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_PSK_IDENTITY_HINT_LENGTH);
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_G_LENGTH);
goto f_err;
}
- /* 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
- * NULL-terminated string. */
- memcpy(tmp_id_hint, p, i);
- memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
- if (s->ctx->psk_identity_hint != NULL)
- OPENSSL_free(s->ctx->psk_identity_hint);
- s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
- if (s->ctx->psk_identity_hint == NULL)
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ 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_PSK */
+#endif /* !OPENSSL_NO_SRP */
#ifndef OPENSSL_NO_RSA
- if (alg_k & SSL_kRSA)
+ else if (alg_k & SSL_kRSA)
{
if ((rsa=RSA_new()) == NULL)
{
@@ -1409,9 +1608,6 @@ int ssl3_get_key_exchange(SSL *s)
s->session->sess_cert->peer_rsa_tmp=rsa;
rsa=NULL;
}
-#else /* OPENSSL_NO_RSA */
- if (0)
- ;
#endif
#ifndef OPENSSL_NO_DH
else if (alg_k & SSL_kEDH)
@@ -1592,20 +1788,52 @@ int ssl3_get_key_exchange(SSL *s)
EC_POINT_free(srvr_ecpoint);
srvr_ecpoint = NULL;
}
- else if (alg_k)
+#endif /* !OPENSSL_NO_ECDH */
+
+ else if (!(alg_k & SSL_kPSK))
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
-#endif /* !OPENSSL_NO_ECDH */
-
/* p points to the next byte, there are 'n' bytes left */
/* 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);
@@ -1619,7 +1847,7 @@ int ssl3_get_key_exchange(SSL *s)
}
#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;
@@ -1627,6 +1855,8 @@ int ssl3_get_key_exchange(SSL *s)
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);
@@ -1654,11 +1884,8 @@ int ssl3_get_key_exchange(SSL *s)
}
else
#endif
-#ifndef OPENSSL_NO_DSA
- if (pkey->type == EVP_PKEY_DSA)
{
- /* lets do DSS */
- EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), 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);
@@ -1670,35 +1897,12 @@ int ssl3_get_key_exchange(SSL *s)
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_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
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
- goto err;
- }
}
else
{
- if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
- /* aNULL or kPSK do not need public keys */
+ if (!(alg_a & SSL_aNULL) &&
+ /* Among PSK ciphers only RSA_PSK needs a public key */
+ !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
@@ -1740,7 +1944,7 @@ int ssl3_get_certificate_request(SSL *s)
{
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;
@@ -1760,6 +1964,14 @@ int ssl3_get_certificate_request(SSL *s)
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);
}
@@ -1796,6 +2008,27 @@ int ssl3_get_certificate_request(SSL *s)
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)
+ {
+ 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;
+ }
+ tls1_process_sigalgs(s, p, llen);
+ p += llen;
+ }
/* get the CA RDNs */
n2s(p,llen);
@@ -1808,7 +2041,7 @@ fclose(out);
}
#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);
@@ -1914,7 +2147,7 @@ int ssl3_get_new_session_ticket(SSL *s)
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;
}
@@ -1925,7 +2158,7 @@ int ssl3_get_new_session_ticket(SSL *s)
/* 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;
}
@@ -2071,6 +2304,7 @@ int ssl3_send_client_key_exchange(SSL *s)
unsigned char *p,*d;
int n;
unsigned long alg_k;
+ unsigned long alg_a;
#ifndef OPENSSL_NO_RSA
unsigned char *q;
EVP_PKEY *pkey=NULL;
@@ -2085,7 +2319,11 @@ int ssl3_send_client_key_exchange(SSL *s)
unsigned char *encodedPoint = NULL;
int encoded_pt_len = 0;
BN_CTX * bn_ctx = NULL;
-#endif
+#ifndef OPENSSL_NO_PSK
+ unsigned int psk_len = 0;
+ unsigned char psk[PSK_MAX_PSK_LEN];
+#endif /* OPENSSL_NO_PSK */
+#endif /* OPENSSL_NO_ECDH */
if (s->state == SSL3_ST_CW_KEY_EXCH_A)
{
@@ -2093,7 +2331,89 @@ int ssl3_send_client_key_exchange(SSL *s)
p= &(d[4]);
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
+#ifndef OPENSSL_NO_PSK
+ if (alg_a & SSL_aPSK)
+ {
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identity_len;
+ unsigned char *t = NULL;
+ unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
+ unsigned int pre_ms_len = 0;
+ int psk_err = 1;
+
+ n = 0;
+ if (s->psk_client_callback == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
+
+ memset(identity, 0, sizeof(identity));
+ psk_len = s->psk_client_callback(s, s->session->psk_identity_hint,
+ identity, sizeof(identity), psk, sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ }
+ else if (psk_len == 0)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ goto psk_err;
+ }
+ identity_len = strnlen(identity, sizeof(identity));
+ if (identity_len > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ }
+
+ if (!(alg_k & SSL_kEECDH))
+ {
+ /* Create the shared secret now if we're not using ECDHE-PSK.*/
+ pre_ms_len = 2+psk_len+2+psk_len;
+ t = pre_ms;
+ s2n(psk_len, t);
+ memset(t, 0, psk_len);
+ t+=psk_len;
+ s2n(psk_len, t);
+ memcpy(t, psk, psk_len);
+
+ s->session->master_key_length =
+ s->method->ssl3_enc->generate_master_secret(s,
+ s->session->master_key,
+ pre_ms, pre_ms_len);
+ s2n(identity_len, p);
+ memcpy(p, identity, identity_len);
+ n = 2 + identity_len;
+ }
+
+ if (s->session->psk_identity != NULL)
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = BUF_strdup(identity);
+ if (s->session->psk_identity == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto psk_err;
+ }
+ psk_err = 0;
+ psk_err:
+ OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+ OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
+ if (psk_err != 0)
+ {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ }
+#endif
/* Fool emacs indentation */
if (0) {}
#ifndef OPENSSL_NO_RSA
@@ -2354,14 +2674,19 @@ int ssl3_send_client_key_exchange(SSL *s)
/* perhaps clean things up a bit EAY EAY EAY EAY*/
}
#endif
-
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_ECDH
else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
{
const EC_GROUP *srvr_group = NULL;
EC_KEY *tkey;
int ecdh_clnt_cert = 0;
int field_size = 0;
+#ifndef OPENSSL_NO_PSK
+ unsigned char *pre_ms;
+ unsigned char *t;
+ unsigned int pre_ms_len;
+ unsigned int i;
+#endif
/* Did we send out the client's
* ECDH share for use in premaster
@@ -2482,15 +2807,41 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
- /* generate master key from the result */
- s->session->master_key_length = s->method->ssl3_enc \
- -> generate_master_secret(s,
- s->session->master_key,
- p, n);
-
+#ifndef OPENSSL_NO_PSK
+ /* ECDHE PSK ciphersuites from RFC 5489 */
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
+ {
+ pre_ms_len = 2+psk_len+2+n;
+ pre_ms = OPENSSL_malloc(pre_ms_len);
+ if (pre_ms == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pre_ms, 0, pre_ms_len);
+ t = pre_ms;
+ s2n(psk_len, t);
+ memcpy(t, psk, psk_len);
+ t += psk_len;
+ s2n(n, t);
+ memcpy(t, p, n);
+ s->session->master_key_length = s->method->ssl3_enc \
+ -> generate_master_secret(s,
+ s->session->master_key, pre_ms, pre_ms_len);
+ OPENSSL_cleanse(pre_ms, pre_ms_len);
+ OPENSSL_free(pre_ms);
+ }
+#endif /* OPENSSL_NO_PSK */
+ if (!(alg_a & SSL_aPSK))
+ {
+ /* generate master key from the result */
+ s->session->master_key_length = s->method->ssl3_enc \
+ -> generate_master_secret(s,
+ s->session->master_key, p, n);
+ }
memset(p, 0, n); /* clean up */
-
- if (ecdh_clnt_cert)
+ if (ecdh_clnt_cert)
{
/* Send empty client key exch message */
n = 0;
@@ -2518,29 +2869,42 @@ int ssl3_send_client_key_exchange(SSL *s)
}
/* Encode the public key */
- n = EC_POINT_point2oct(srvr_group,
- EC_KEY_get0_public_key(clnt_ecdh),
- POINT_CONVERSION_UNCOMPRESSED,
+ encoded_pt_len = EC_POINT_point2oct(srvr_group,
+ EC_KEY_get0_public_key(clnt_ecdh),
+ POINT_CONVERSION_UNCOMPRESSED,
encodedPoint, encoded_pt_len, bn_ctx);
+
+ n = 0;
+#ifndef OPENSSL_NO_PSK
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
+ {
+ i = strlen(s->session->psk_identity);
+ s2n(i, p);
+ memcpy(p, s->session->psk_identity, i);
+ p += i;
+ n = i + 2;
+ }
+#endif
- *p = n; /* length of encoded point */
+ *p = encoded_pt_len; /* length of encoded point */
/* Encoded point will be copied here */
- p += 1;
+ p += 1;
+ n += 1;
/* copy the point */
- memcpy((unsigned char *)p, encodedPoint, n);
+ memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
/* increment n to account for length field */
- n += 1;
+ n += encoded_pt_len;
}
/* Free allocated memory */
BN_CTX_free(bn_ctx);
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
- if (clnt_ecdh != NULL)
+ if (clnt_ecdh != NULL)
EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
}
#endif /* !OPENSSL_NO_ECDH */
- else if (alg_k & SSL_kGOST)
+ else if (alg_k & SSL_kGOST)
{
/* GOST key exchange message creation */
EVP_PKEY_CTX *pkey_ctx;
@@ -2630,89 +2994,40 @@ int ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_free(pub_key);
}
-#ifndef OPENSSL_NO_PSK
- else if (alg_k & SSL_kPSK)
+#ifndef OPENSSL_NO_SRP
+ else if (alg_k & SSL_kSRP)
{
- char identity[PSK_MAX_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;
- int psk_err = 1;
-
- n = 0;
- if (s->psk_client_callback == NULL)
+ if (s->srp_ctx.A != NULL)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
- identity, PSK_MAX_IDENTITY_LEN,
- psk_or_pre_ms, sizeof(psk_or_pre_ms));
- if (psk_len > PSK_MAX_PSK_LEN)
- {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto psk_err;
- }
- else if (psk_len == 0)
- {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
- goto psk_err;
+ /* send off the data */
+ n=BN_num_bytes(s->srp_ctx.A);
+ s2n(n,p);
+ BN_bn2bin(s->srp_ctx.A,p);
+ n+=2;
}
-
- /* create PSK pre_master_secret */
- pre_ms_len = 2+psk_len+2+psk_len;
- t = psk_or_pre_ms;
- memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
- s2n(psk_len, t);
- memset(t, 0, psk_len);
- t+=psk_len;
- s2n(psk_len, t);
-
- if (s->session->psk_identity_hint != NULL)
- OPENSSL_free(s->session->psk_identity_hint);
- s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
- if (s->ctx->psk_identity_hint != NULL &&
- s->session->psk_identity_hint == NULL)
+ else
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
- goto psk_err;
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
}
-
- if (s->session->psk_identity != NULL)
- OPENSSL_free(s->session->psk_identity);
- s->session->psk_identity = BUF_strdup(identity);
- if (s->session->psk_identity == NULL)
+ 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 psk_err;
+ goto err;
}
- 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_err = 0;
- psk_err:
- OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
- OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
- if (psk_err != 0)
+ if ((s->session->master_key_length = SRP_generate_client_master_secret(s,s->session->master_key))<0)
{
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
}
}
#endif
- else
+ else if (!(alg_k & SSL_kPSK))
{
ssl3_send_alert(s, SSL3_AL_FATAL,
SSL_AD_HANDSHAKE_FAILURE);
@@ -2749,12 +3064,13 @@ int ssl3_send_client_verify(SSL *s)
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;
@@ -2765,7 +3081,8 @@ int ssl3_send_client_verify(SSL *s)
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]));
}
@@ -2773,6 +3090,62 @@ int ssl3_send_client_verify(SSL *s)
{
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;
+ switch (ssl_cert_type(NULL, pkey))
+ {
+ case SSL_PKEY_RSA_ENC:
+ md = s->s3->digest_rsa;
+ break;
+ case SSL_PKEY_DSA_SIGN:
+ md = s->s3->digest_dsa;
+ break;
+ case SSL_PKEY_ECC:
+ md = s->s3->digest_ecdsa;
+ break;
+ default:
+ md = NULL;
+ }
+ if (!md)
+ /* Unlike with the SignatureAlgorithm extension (sent by clients),
+ * there are no default algorithms for the CertificateRequest message
+ * (sent by servers). However, now that we've sent a certificate
+ * for which we don't really know what hash to use for signing, the
+ * best we can do is try a default algorithm. */
+ md = EVP_sha1();
+ 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)
{
@@ -2855,9 +3228,11 @@ int ssl3_send_client_verify(SSL *s)
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);
}
@@ -2957,7 +3332,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
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_aDH|SSL_aNULL|SSL_aKRB5)) || ((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
return(1);
sc=s->session->sess_cert;
@@ -2981,7 +3356,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
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;
@@ -3077,13 +3452,8 @@ err:
return(0);
}
-/* Check to see if handshake is full or resumed. Usually this is just a
- * case of checking to see if a cache hit has occurred. In the case of
- * session tickets we have to check the next message to be sure.
- */
-
-#ifndef OPENSSL_NO_TLSEXT
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#if !defined(OPENSSL_NO_TLSEXT)
+# if !defined(OPENSSL_NO_NEXTPROTONEG)
int ssl3_send_next_proto(SSL *s)
{
unsigned int len, padding_len;
@@ -3106,9 +3476,124 @@ int ssl3_send_next_proto(SSL *s)
}
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+}
+# endif /* !OPENSSL_NO_NEXTPROTONEG */
+
+int ssl3_send_channel_id(SSL *s)
+ {
+ unsigned char *d;
+ int ret = -1, public_key_len;
+ EVP_MD_CTX md_ctx;
+ size_t sig_len;
+ ECDSA_SIG *sig = NULL;
+ unsigned char *public_key = NULL, *derp, *der_sig = NULL;
+
+ if (s->state != SSL3_ST_CW_CHANNEL_ID_A)
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+
+ d = (unsigned char *)s->init_buf->data;
+ *(d++)=SSL3_MT_ENCRYPTED_EXTENSIONS;
+ l2n3(2 + 2 + TLSEXT_CHANNEL_ID_SIZE, d);
+ s2n(TLSEXT_TYPE_channel_id, d);
+ s2n(TLSEXT_CHANNEL_ID_SIZE, d);
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL);
+ if (public_key_len <= 0)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY);
+ goto err;
+ }
+ // i2d_PublicKey will produce an ANSI X9.62 public key which, for a
+ // P-256 key, is 0x04 (meaning uncompressed) followed by the x and y
+ // field elements as 32-byte, big-endian numbers.
+ if (public_key_len != 65)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_CHANNEL_ID_NOT_P256);
+ goto err;
+ }
+ public_key = OPENSSL_malloc(public_key_len);
+ if (!public_key)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ derp = public_key;
+ i2d_PublicKey(s->tlsext_channel_id_private, &derp);
+
+ if (EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL,
+ s->tlsext_channel_id_private) != 1)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_EVP_DIGESTSIGNINIT_FAILED);
+ goto err;
+ }
+
+ if (!tls1_channel_id_hash(&md_ctx, s))
+ goto err;
+
+ if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ der_sig = OPENSSL_malloc(sig_len);
+ if (!der_sig)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(&md_ctx, der_sig, &sig_len))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ derp = der_sig;
+ sig = d2i_ECDSA_SIG(NULL, (const unsigned char**)&derp, sig_len);
+ if (sig == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CHANNEL_ID,SSL_R_D2I_ECDSA_SIG);
+ goto err;
+ }
+
+ // The first byte of public_key will be 0x4, denoting an uncompressed key.
+ memcpy(d, public_key + 1, 64);
+ d += 64;
+ memset(d, 0, 2 * 32);
+ BN_bn2bin(sig->r, d + 32 - BN_num_bytes(sig->r));
+ d += 32;
+ BN_bn2bin(sig->s, d + 32 - BN_num_bytes(sig->s));
+ d += 32;
+
+ s->state = SSL3_ST_CW_CHANNEL_ID_B;
+ s->init_num = 4 + 2 + 2 + TLSEXT_CHANNEL_ID_SIZE;
+ s->init_off = 0;
+
+ ret = ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+
+err:
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (public_key)
+ OPENSSL_free(public_key);
+ if (der_sig)
+ OPENSSL_free(der_sig);
+ if (sig)
+ ECDSA_SIG_free(sig);
+
+ return ret;
}
-# endif
+#endif /* !OPENSSL_NO_TLSEXT */
+/* Check to see if handshake is full or resumed. Usually this is just a
+ * case of checking to see if a cache hit has occurred. In the case of
+ * session tickets we have to check the next message to be sure.
+ */
+
+#ifndef OPENSSL_NO_TLSEXT
int ssl3_check_finished(SSL *s)
{
int ok;