X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=11ffabb460c335791c00483defad9326c4479717;hp=e339dbc431365277f1091ec5f4daf35fb7a502df;hb=d18b716d259d6d3b68ff7f49d154b9158b98df65;hpb=3fc59c84061373c285eb90c4b8fae075a28daaf3 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index e339dbc431..11ffabb460 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -156,6 +156,9 @@ #include #include #include +#ifdef OPENSSL_FIPS +#include +#endif #ifndef OPENSSL_NO_DH #include #endif @@ -166,9 +169,6 @@ 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_TLSEXT -static int ssl3_check_finished(SSL *s); -#endif static const SSL_METHOD *ssl3_get_client_method(int ver) { @@ -187,10 +187,9 @@ int ssl3_connect(SSL *s) { BUF_MEM *buf=NULL; unsigned long Time=(unsigned long)time(NULL); - long num1; void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; - int new_state,state,skip=0;; + int new_state,state,skip=0; RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); @@ -204,6 +203,18 @@ int ssl3_connect(SSL *s) 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; @@ -211,7 +222,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 */ @@ -284,12 +295,38 @@ 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; + { +#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 @@ -362,6 +399,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 @@ -404,6 +452,11 @@ int ssl3_connect(SSL *s) 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; break; @@ -422,7 +475,15 @@ int ssl3_connect(SSL *s) ret=ssl3_send_change_cipher_spec(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->s3->next_proto_neg_seen) + s->state=SSL3_ST_CW_NEXT_PROTO_A; + else + s->state=SSL3_ST_CW_FINISHED_A; +#endif s->init_num=0; s->session->cipher=s->s3->tmp.new_cipher; @@ -450,6 +511,15 @@ int ssl3_connect(SSL *s) break; +#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); + if (ret <= 0) goto end; + s->state=SSL3_ST_CW_FINISHED_A; + break; +#endif + case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: ret=ssl3_send_finished(s, @@ -518,16 +588,13 @@ int ssl3_connect(SSL *s) break; case SSL3_ST_CW_FLUSH: - /* number of bytes to be flushed */ - num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); - if (num1 > 0) + s->rwstate=SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { - s->rwstate=SSL_WRITING; - num1=BIO_flush(s->wbio); - if (num1 <= 0) { ret= -1; goto end; } - s->rwstate=SSL_NOTHING; + ret= -1; + goto end; } - + s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; @@ -548,6 +615,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); @@ -613,9 +681,15 @@ int ssl3_client_hello(SSL *s) buf=(unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { - if ((s->session == NULL) || - (s->session->ssl_version != s->version) || - (s->session->not_resumable)) + 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; @@ -631,9 +705,43 @@ int ssl3_client_hello(SSL *s) /* 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); @@ -663,6 +771,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; @@ -719,9 +836,10 @@ err: int ssl3_get_server_hello(SSL *s) { STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; + const SSL_CIPHER *c; + CERT *ct = s->cert; unsigned char *p,*d; - int i,al,ok; + int i,al=SSL_AD_INTERNAL_ERROR,ok; unsigned int j; long n; #ifndef OPENSSL_NO_COMP @@ -737,7 +855,7 @@ int ssl3_get_server_hello(SSL *s) if (!ok) return((int)n); - if ( SSL_version(s) == DTLS1_VERSION) + if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { @@ -788,6 +906,23 @@ int ssl3_get_server_hello(SSL *s) goto f_err; } +#ifndef OPENSSL_NO_TLSEXT + /* check if we want to resume the session based on external pre-shared secret */ + if (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, + NULL, &pref_cipher, + s->tls_session_secret_cb_arg)) + { + s->session->cipher = pref_cipher ? + pref_cipher : ssl_get_cipher_by_char(s, p+j); + } + } +#endif /* OPENSSL_NO_TLSEXT */ + if (j != 0 && j == s->session->session_id_length && memcmp(p,s->session->session_id,j) == 0) { @@ -810,7 +945,6 @@ int ssl3_get_server_hello(SSL *s) { if (!ssl_get_new_session(s,0)) { - al=SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -826,6 +960,17 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } + /* If it is a disabled cipher we didn't send it in client hello, + * so return an error. + */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || + c->algorithm_auth & ct->mask_a) + { + 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); @@ -845,8 +990,11 @@ int ssl3_get_server_hello(SSL *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); @@ -854,8 +1002,11 @@ int ssl3_get_server_hello(SSL *s) } } s->s3->tmp.new_cipher=c; - 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 @@ -865,10 +1016,30 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); goto f_err; } + /* If compression is disabled we'd better not try to resume a session + * using compression. + */ + if (s->session->compress_meth != 0) + { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION); + goto f_err; + } #else j= *(p++); - if ((j == 0) || (s->options & SSL_OP_NO_COMPRESSION)) + if (s->hit && j != s->session->compress_meth) + { + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED); + goto f_err; + } + if (j == 0) comp=NULL; + else if (s->options & SSL_OP_NO_COMPRESSION) + { + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED); + goto f_err; + } else comp=ssl3_comp_find(s->ctx->comp_methods,j); @@ -886,19 +1057,10 @@ int ssl3_get_server_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions*/ - if (s->version > SSL3_VERSION) + if (!ssl_parse_serverhello_tlsext(s,&p,d,n)) { - if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al)) - { - /* 'al' set by ssl_parse_serverhello_tlsext */ - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT); - goto f_err; - } - if (ssl_check_serverhello_tlsext(s) <= 0) - { - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT); - goto err; - } + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT); + goto err; } #endif @@ -907,7 +1069,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); @@ -938,7 +1100,9 @@ int ssl3_get_server_certificate(SSL *s) if (!ok) return((int)n); - if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) + if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) || + ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && + (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE))) { s->s3->tmp.reuse_message=1; return(1); @@ -1000,7 +1164,7 @@ int ssl3_get_server_certificate(SSL *s) } i=ssl_verify_cert_chain(s,sk); - if ((s->verify_mode != SSL_VERIFY_NONE) && (!i) + if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0) #ifndef OPENSSL_NO_KRB5 && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) @@ -1087,8 +1251,22 @@ int ssl3_get_server_certificate(SSL *s) s->session->verify_result = s->verify_result; x=NULL; - ret=1; +#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) { f_err: @@ -1111,6 +1289,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 @@ -1234,6 +1413,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) { @@ -1388,9 +1647,17 @@ int ssl3_get_key_exchange(SSL *s) * and the ECParameters in this case is just three bytes. */ param_len=3; - if ((param_len > n) || - (*p != NAMED_CURVE_TYPE) || - ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) + /* Check curve is one of our prefrences, if not server has + * sent an invalid curve. + */ + if (!tls1_check_curve(s, p, param_len)) + { + al=SSL_AD_DECODE_ERROR; + 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); @@ -1463,6 +1730,7 @@ int ssl3_get_key_exchange(SSL *s) 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; } @@ -1480,6 +1748,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); @@ -1493,7 +1793,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; @@ -1501,6 +1801,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); @@ -1528,33 +1830,12 @@ 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_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)) - { - /* 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); - if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey)) + if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0) { /* bad signature */ al=SSL_AD_DECRYPT_ERROR; @@ -1562,12 +1843,6 @@ int ssl3_get_key_exchange(SSL *s) goto f_err; } } - else -#endif - { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); - goto err; - } } else { @@ -1614,7 +1889,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; @@ -1634,6 +1909,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); } @@ -1665,11 +1948,42 @@ 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); + memcpy(s->cert->ctypes, p, ctype_num); + s->cert->ctype_num = (size_t)ctype_num; ctype_num=SSL3_CT_NUMBER; + } for (i=0; is3->tmp.ctype[i]= p[i]; - p+=ctype_num; + p+=p[-1]; + 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); @@ -1682,7 +1996,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); @@ -1788,17 +2102,18 @@ 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; } + p=d=(unsigned char *)s->init_msg; n2l(p, s->session->tlsext_tick_lifetime_hint); n2s(p, ticklen); /* 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; } @@ -1815,7 +2130,28 @@ 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. + * 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 + * earlier that the ticket has been accepted. + * + * The other way is to set zero length session ID when the + * ticket is presented and rely on the handshake to determine + * session resumption. + * + * We choose the former approach because this fits in with + * assumptions elsewhere in OpenSSL. The session ID is set + * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the + * ticket. + */ + EVP_Digest(p, ticklen, + s->session->session_id, &s->session->session_id_length, +#ifndef OPENSSL_NO_SHA256 + EVP_sha256(), NULL); +#else + EVP_sha1(), NULL); +#endif ret=1; return(ret); f_err: @@ -2016,7 +2352,7 @@ int ssl3_send_client_key_exchange(SSL *s) krb5_data *enc_ticket; krb5_data authenticator, *authp = NULL; EVP_CIPHER_CTX ciph_ctx; - EVP_CIPHER *enc = NULL; + const EVP_CIPHER *enc = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH @@ -2119,7 +2455,7 @@ int ssl3_send_client_key_exchange(SSL *s) sizeof tmp_buf); EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); outl += padl; - if (outl > sizeof epms) + if (outl > (int)sizeof epms) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; @@ -2145,44 +2481,79 @@ int ssl3_send_client_key_exchange(SSL *s) 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; + dh_clnt = NULL; + 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; } @@ -2193,11 +2564,16 @@ int ssl3_send_client_key_exchange(SSL *s) /* 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); @@ -2398,7 +2774,7 @@ int ssl3_send_client_key_exchange(SSL *s) size_t msglen; unsigned int md_len; int keytype; - unsigned char premaster_secret[32],shared_ukm[32]; + unsigned char premaster_secret[32],shared_ukm[32], tmp[256]; EVP_MD_CTX *ukm_hash; EVP_PKEY *pub_key; @@ -2424,16 +2800,13 @@ int ssl3_send_client_key_exchange(SSL *s) /* Generate session key */ RAND_bytes(premaster_secret,32); /* If we have client certificate, use its secret as peer key */ - if (s->cert->key->privatekey) { - if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) { + if (s->s3->tmp.cert_req && s->cert->key->privatekey) { + if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) { /* If there was an error - just ignore it. Ephemeral key * would be used */ ERR_clear_error(); - } else { - /* Set flag "client cert key is used for key - * exchange"*/ - } + } } /* Compute shared IV and store it in algorithm-specific * context data */ @@ -2452,15 +2825,30 @@ int ssl3_send_client_key_exchange(SSL *s) /* Make GOST keytransport blob message */ /*Encapsulate it into sequence */ *(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; - *(p++)=0x81; - msglen=256; - if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) { + msglen=255; + if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_LIBRARY_BUG); goto err; - } - *(p++)= msglen & 0xff; - n=msglen+3; + } + if (msglen >= 0x80) + { + *(p++)=0x81; + *(p++)= msglen & 0xff; + n=msglen+3; + } + else + { + *(p++)= msglen & 0xff; + n=msglen+2; + } + memcpy(p, tmp, msglen); + /* Check if pubkey from client certificate was used */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) + { + /* Set flag "skip certificate verify" */ + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + } EVP_PKEY_CTX_free(pkey_ctx); s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, @@ -2468,6 +2856,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) { @@ -2587,13 +3008,12 @@ 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; -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) int j; -#endif + + EVP_MD_CTX_init(&mctx); if (s->state == SSL3_ST_CW_CERT_VRFY_A) { @@ -2605,7 +3025,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])); } @@ -2613,6 +3034,41 @@ 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 = 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) { @@ -2672,7 +3128,7 @@ int ssl3_send_client_verify(SSL *s) s->method->ssl3_enc->cert_verify_mac(s, NID_id_GostR3411_94, data); - if (!EVP_PKEY_sign(pctx,signbuf,&sigsize,data,32)) { + if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); goto err; @@ -2695,13 +3151,49 @@ 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); } +/* 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; @@ -2711,12 +3203,17 @@ int ssl3_send_client_certificate(SSL *s) 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 + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb + && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } + 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 */ @@ -2748,6 +3245,8 @@ int ssl3_send_client_certificate(SSL *s) 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) @@ -2770,7 +3269,7 @@ int ssl3_send_client_certificate(SSL *s) { s->state=SSL3_ST_CW_CERT_D; l=ssl3_output_cert_chain(s, - (s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509); + (s->s3->tmp.cert_req == 2)?NULL:s->cert->key); s->init_num=(int)l; s->init_off=0; } @@ -2793,6 +3292,13 @@ int ssl3_check_cert_and_algorithm(SSL *s) DH *dh; #endif + alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + alg_a=s->s3->tmp.new_cipher->algorithm_auth; + + /* we don't have a certificate */ + if ((alg_a & (SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK)) + return(1); + sc=s->session->sess_cert; if (sc == NULL) { @@ -2800,13 +3306,6 @@ int ssl3_check_cert_and_algorithm(SSL *s) goto err; } - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - 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)) - return(1); - #ifndef OPENSSL_NO_RSA rsa=s->session->sess_cert->peer_rsa_tmp; #endif @@ -2821,7 +3320,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; @@ -2859,19 +3358,21 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #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; @@ -2923,15 +3424,38 @@ err: */ #ifndef OPENSSL_NO_TLSEXT -static int ssl3_check_finished(SSL *s) +# ifndef OPENSSL_NO_NEXTPROTONEG +int ssl3_send_next_proto(SSL *s) + { + unsigned int len, padding_len; + unsigned char *d; + + if (s->state == SSL3_ST_CW_NEXT_PROTO_A) + { + len = s->next_proto_negotiated_len; + padding_len = 32 - ((len + 2) % 32); + d = (unsigned char *)s->init_buf->data; + d[4] = len; + memcpy(d + 5, s->next_proto_negotiated, len); + d[5 + len] = padding_len; + memset(d + 6 + len, 0, padding_len); + *(d++)=SSL3_MT_NEXT_PROTO; + l2n3(2 + len + padding_len, d); + s->state = SSL3_ST_CW_NEXT_PROTO_B; + s->init_num = 4 + 2 + len + padding_len; + s->init_off = 0; + } + + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } +# endif + +int ssl3_check_finished(SSL *s) { int ok; long n; - /* If we have no ticket or session ID is non-zero length (a match of - * a non-zero session length would never reach here) it cannot be a - * resumed session. - */ - if (!s->session->tlsext_tick || s->session->session_id_length) + /* 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 */ @@ -2968,3 +3492,106 @@ 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