diff options
Diffstat (limited to 'main/openssl/ssl/s3_clnt.c')
-rw-r--r-- | main/openssl/ssl/s3_clnt.c | 563 |
1 files changed, 497 insertions, 66 deletions
diff --git a/main/openssl/ssl/s3_clnt.c b/main/openssl/ssl/s3_clnt.c index 42bcd629..efbd666b 100644 --- a/main/openssl/ssl/s3_clnt.c +++ b/main/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; @@ -370,6 +400,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 +477,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 +518,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 @@ -611,6 +664,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 +721,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 +752,52 @@ 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 */ + /* Do the message type and length last. + * Note: the code to add the padding extension in t1_lib.c + * depends on the size of this prefix. */ 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 +827,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; @@ -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 @@ -1359,6 +1471,86 @@ int ssl3_get_key_exchange(SSL *s) } 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) { @@ -1606,6 +1798,38 @@ 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) + { + 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 +1843,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 +1851,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 +1880,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,30 +1893,6 @@ 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 { @@ -1740,7 +1939,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 +1959,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 +2003,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 +2036,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 +2142,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 +2153,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; } @@ -2630,6 +2858,39 @@ int ssl3_send_client_key_exchange(SSL *s) 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) { @@ -2749,12 +3010,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 +3027,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 +3036,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 +3174,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); } @@ -2981,7 +3302,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 +3398,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 +3422,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; |