X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=2313fbc1e749c94003330c6d12812b0f7997b5a2;hp=aa5604c1dd285c5d8ae14d3b7c1a31fead98b3c9;hb=b15f8769644b00ef7283521593360b7b2135cb63;hpb=ee2ffc279417f15fef3b1073c7dc81a908991516 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index aa5604c1dd..2313fbc1e7 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -164,9 +164,9 @@ #include #endif -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_SSL3_METHOD static const SSL_METHOD *ssl3_get_client_method(int ver) { if (ver == SSL3_VERSION) @@ -179,6 +179,7 @@ IMPLEMENT_ssl3_meth_func(SSLv3_client_method, ssl_undefined_function, ssl3_connect, ssl3_get_client_method) +#endif int ssl3_connect(SSL *s) { @@ -200,6 +201,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; @@ -207,7 +220,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 */ @@ -225,6 +238,13 @@ int ssl3_connect(SSL *s) ret = -1; goto end; } + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, + s->version, NULL)) + { + SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW); + return -1; + } /* s->version=SSL3_VERSION; */ s->type=SSL_ST_CONNECT; @@ -257,6 +277,9 @@ int ssl3_connect(SSL *s) s->state=SSL3_ST_CW_CLNT_HELLO_A; s->ctx->stats.sess_connect++; s->init_num=0; + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + /* Should have been reset by ssl3_get_finished, too. */ + s->s3->change_cipher_spec = 0; break; case SSL3_ST_CW_CLNT_HELLO_A: @@ -280,31 +303,27 @@ 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->state=SSL3_ST_CR_CERT_A; + } s->init_num=0; break; - case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: -#ifndef OPENSSL_NO_TLSEXT - ret=ssl3_check_finished(s); - if (ret <= 0) goto end; - if (ret == 2) - { - s->hit = 1; - if (s->tlsext_ticket_expected) - s->state=SSL3_ST_CR_SESSION_TICKET_A; - else - s->state=SSL3_ST_CR_FINISHED_A; - s->init_num=0; - break; - } -#endif - /* Check if it is anon DH/ECDH */ + /* Check if it is anon DH/ECDH, SRP auth */ /* or PSK */ - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret=ssl3_get_server_certificate(s); @@ -358,6 +377,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 @@ -398,12 +428,10 @@ int ssl3_connect(SSL *s) else { 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; @@ -415,7 +443,6 @@ int ssl3_connect(SSL *s) if (ret <= 0) goto end; s->state=SSL3_ST_CW_CHANGE_A; s->init_num=0; - s->s3->change_cipher_spec=0; break; case SSL3_ST_CW_CHANGE_A: @@ -424,10 +451,10 @@ 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_NPN) +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_CW_FINISHED_A; #else - if (s->next_proto_negotiated) + if (s->s3->next_proto_neg_seen) s->state=SSL3_ST_CW_NEXT_PROTO_A; else s->state=SSL3_ST_CW_FINISHED_A; @@ -459,7 +486,7 @@ int ssl3_connect(SSL *s) break; -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NPN) +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) case SSL3_ST_CW_NEXT_PROTO_A: case SSL3_ST_CW_NEXT_PROTO_B: ret=ssl3_send_next_proto(s); @@ -523,7 +550,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; @@ -563,6 +590,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); @@ -619,7 +647,8 @@ int ssl3_client_hello(SSL *s) unsigned char *buf; unsigned char *p,*d; int i; - unsigned long Time,l; + unsigned long l; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; @@ -631,30 +660,114 @@ int ssl3_client_hello(SSL *s) 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; } + if (s->method->version == DTLS_ANY_VERSION) + { + /* Determine which DTLS version to use */ + int options = s->options; + /* If DTLS 1.2 disabled correct the version number */ + if (options & SSL_OP_NO_DTLSv1_2) + { + if (tls1_suiteb(s)) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + goto err; + } + /* Disabling all versions is silly: return an + * error. + */ + if (options & SSL_OP_NO_DTLSv1) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_WRONG_SSL_VERSION); + goto err; + } + /* Update method so we don't use any DTLS 1.2 + * features. + */ + s->method = DTLSv1_client_method(); + s->version = DTLS1_VERSION; + } + else + { + /* We only support one version: update method */ + if (options & SSL_OP_NO_DTLSv1) + s->method = DTLSv1_2_client_method(); + s->version = DTLS1_2_VERSION; + } + s->client_version = s->version; + } /* 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) - goto err; - /* Do the message type and length last */ - d=p= &(buf[4]); + /* for DTLS if client_random is initialized, reuse it, we are + * required to use same upon reply to HelloVerify */ + if (SSL_IS_DTLS(s)) + { + size_t idx; + i = 1; + for (idx=0; idx < sizeof(s->s3->client_random); idx++) + { + if (p[idx]) + { + i = 0; + break; + } + } + } + else + i = 1; + if (i) + ssl_fill_hello_random(s, 0, p, + sizeof(s->s3->client_random)); + + /* Do the message type and length last */ + d=p= ssl_handshake_start(s); + + /*- + * 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); @@ -677,6 +790,19 @@ int ssl3_client_hello(SSL *s) p+=i; } + /* cookie stuff for DTLS */ + if (SSL_IS_DTLS(s)) + { + if ( s->d1->cookie_len > sizeof(s->d1->cookie)) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + *(p++) = s->d1->cookie_len; + memcpy(p, s->d1->cookie, s->d1->cookie_len); + p += s->d1->cookie_len; + } + /* Ciphers supported */ i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0); if (i == 0) @@ -684,6 +810,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; @@ -692,8 +827,7 @@ int ssl3_client_hello(SSL *s) *(p++)=1; #else - if ((s->options & SSL_OP_NO_COMPRESSION) - || !s->ctx->comp_methods) + if (!ssl_allow_compression(s) || !s->ctx->comp_methods) j=0; else j=sk_SSL_COMP_num(s->ctx->comp_methods); @@ -713,26 +847,21 @@ int ssl3_client_hello(SSL *s) SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); goto err; } - if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL) { + ssl3_send_alert(s,SSL3_AL_FATAL,al); SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); goto err; } #endif - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; - l2n3(l,d); - + l= p-d; + ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); s->state=SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; } /* SSL3_ST_CW_CLNT_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: return(-1); } @@ -741,13 +870,19 @@ int ssl3_get_server_hello(SSL *s) { STACK_OF(SSL_CIPHER) *sk; 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 SSL_COMP *comp; #endif + /* Hello verify request and/or server hello version may not + * match so set first packet if we're negotiating version. + */ + if (SSL_IS_DTLS(s)) + s->first_packet = 1; n=s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, @@ -758,8 +893,9 @@ int ssl3_get_server_hello(SSL *s) if (!ok) return((int)n); - if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + if (SSL_IS_DTLS(s)) { + s->first_packet = 0; if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { if ( s->d1->send_cookie == 0) @@ -784,6 +920,33 @@ int ssl3_get_server_hello(SSL *s) } d=p=(unsigned char *)s->init_msg; + if (s->method->version == DTLS_ANY_VERSION) + { + /* Work out correct protocol version to use */ + int hversion = (p[0] << 8)|p[1]; + int options = s->options; + if (hversion == DTLS1_2_VERSION + && !(options & SSL_OP_NO_DTLSv1_2)) + s->method = DTLSv1_2_client_method(); + else if (tls1_suiteb(s)) + { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + else if (hversion == DTLS1_VERSION + && !(options & SSL_OP_NO_DTLSv1)) + s->method = DTLSv1_client_method(); + else + { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->version = s->method->version; + } if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff))) { @@ -799,6 +962,8 @@ int ssl3_get_server_hello(SSL *s) memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; + s->hit = 0; + /* get the session-id */ j= *(p++); @@ -822,11 +987,12 @@ int ssl3_get_server_hello(SSL *s) { s->session->cipher = pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s, p+j); + s->hit = 1; } } #endif /* OPENSSL_NO_TLSEXT */ - if (j != 0 && j == s->session->session_id_length + if (!s->hit && j != 0 && j == s->session->session_id_length && memcmp(p,s->session->session_id,j) == 0) { if(s->sid_ctx_length != s->session->sid_ctx_length @@ -839,16 +1005,15 @@ int ssl3_get_server_hello(SSL *s) } s->hit=1; } - else /* a miss or crap from the other end */ + /* a miss or crap from the other end */ + if (!s->hit) { /* If we were trying for session-id reuse, make a new * SSL_SESSION so we don't stuff up other people */ - s->hit=0; if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s,0)) { - al=SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -864,6 +1029,20 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } + /* Set version disabled mask now we know version */ + if (!SSL_USE_TLS1_2_CIPHERS(s)) + ct->mask_ssl = SSL_TLSV1_2; + else + ct->mask_ssl = 0; + /* If it is a disabled cipher we didn't send it in client hello, + * so return an error. + */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) + { + 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); @@ -883,8 +1062,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); @@ -892,9 +1074,11 @@ 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 no sigalgs: we may need them for + * client authentication. + */ + if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s)) goto f_err; - /* lets get the compression algorithm */ /* COMPRESSION */ #ifdef OPENSSL_NO_COMP @@ -909,7 +1093,6 @@ int ssl3_get_server_hello(SSL *s) */ if (s->session->compress_meth != 0) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -923,7 +1106,7 @@ int ssl3_get_server_hello(SSL *s) } if (j == 0) comp=NULL; - else if (s->options & SSL_OP_NO_COMPRESSION) + else if (!ssl_allow_compression(s)) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED); @@ -946,19 +1129,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 @@ -967,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); @@ -1074,6 +1248,12 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } ERR_clear_error(); /* but we keep s->verify_result */ + if (i > 1) + { + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, i); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } sc=ssl_sess_cert_new(); if (sc == NULL) goto err; @@ -1096,9 +1276,9 @@ int ssl3_get_server_certificate(SSL *s) ? 0 : 1; #ifdef KSSL_DEBUG - printf("pkey,x = %p, %p\n", pkey,x); - printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey)); - printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name, + fprintf(stderr,"pkey,x = %p, %p\n", pkey,x); + fprintf(stderr,"ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey)); + fprintf(stderr,"cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name, s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert); #endif /* KSSL_DEBUG */ @@ -1123,6 +1303,15 @@ int ssl3_get_server_certificate(SSL *s) if (need_cert) { + int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (exp_idx >= 0 && i != exp_idx) + { + x=NULL; + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto f_err; + } sc->peer_cert_type=i; CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); /* Why would the following ever happen? @@ -1150,7 +1339,6 @@ int ssl3_get_server_certificate(SSL *s) x=NULL; ret=1; - if (0) { f_err: @@ -1170,9 +1358,10 @@ int ssl3_get_key_exchange(SSL *s) #endif EVP_MD_CTX md_ctx; unsigned char *param,*p; - int al,i,j,param_len,ok; - long n,alg_k,alg_a; + int al,j,ok; + long i,param_len,n,alg_k,alg_a; EVP_PKEY *pkey=NULL; + const EVP_MD *md = NULL; #ifndef OPENSSL_NO_RSA RSA *rsa=NULL; #endif @@ -1187,6 +1376,8 @@ int ssl3_get_key_exchange(SSL *s) int encoded_pt_len = 0; #endif + EVP_MD_CTX_init(&md_ctx); + /* use same message size as in ssl3_get_certificate_request() * as ServerKeyExchange message may be skipped */ n=s->method->ssl_get_message(s, @@ -1197,14 +1388,26 @@ int ssl3_get_key_exchange(SSL *s) &ok); if (!ok) return((int)n); + alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { + /* + * Can't skip server key exchange if this is an ephemeral + * ciphersuite. + */ + if (alg_k & (SSL_kDHE|SSL_kECDHE)) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto f_err; + } #ifndef OPENSSL_NO_PSK /* In plain PSK ciphersuite, ServerKeyExchange can be 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 (alg_k & SSL_kPSK) { s->session->sess_cert=ssl_sess_cert_new(); if (s->ctx->psk_identity_hint) @@ -1246,36 +1449,46 @@ int ssl3_get_key_exchange(SSL *s) s->session->sess_cert=ssl_sess_cert_new(); } + /* Total length of the parameters including the length prefix */ param_len=0; - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + alg_a=s->s3->tmp.new_cipher->algorithm_auth; - EVP_MD_CTX_init(&md_ctx); + + al=SSL_AD_DECODE_ERROR; #ifndef OPENSSL_NO_PSK if (alg_k & SSL_kPSK) { char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1]; - al=SSL_AD_HANDSHAKE_FAILURE; + param_len = 2; + if (param_len > n) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } 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) { + al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto f_err; } - if (param_len > n) + if (i > n - param_len) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); goto f_err; } + param_len += i; + /* 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 @@ -1287,6 +1500,7 @@ int ssl3_get_key_exchange(SSL *s) s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); if (s->ctx->psk_identity_hint == NULL) { + al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto f_err; } @@ -1296,6 +1510,129 @@ int ssl3_get_key_exchange(SSL *s) } else #endif /* !OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_SRP + if (alg_k & SSL_kSRP) + { + param_len = 2; + if (param_len > n) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + n2s(p,i); + + if (i > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_N_LENGTH); + goto f_err; + } + param_len += i; + + 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; + + + if (2 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 2; + + n2s(p,i); + + if (i > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_G_LENGTH); + goto f_err; + } + param_len += i; + + 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; + + + if (1 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 1; + + i = (unsigned int)(p[0]); + p++; + + if (i > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_S_LENGTH); + goto f_err; + } + param_len += i; + + 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; + + if (2 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 2; + + n2s(p,i); + + if (i > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_B_LENGTH); + goto f_err; + } + param_len += i; + + 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; + + if (!srp_verify_server_param(s, &al)) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS); + goto f_err; + } + +/* 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) { @@ -1304,14 +1641,23 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } - n2s(p,i); - param_len=i+2; + + param_len = 2; if (param_len > n) { - al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + n2s(p,i); + + if (i > n - param_len) + { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH); goto f_err; } + param_len += i; + if (!(rsa->n=BN_bin2bn(p,i,rsa->n))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); @@ -1319,14 +1665,23 @@ int ssl3_get_key_exchange(SSL *s) } p+=i; + if (2 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 2; + n2s(p,i); - param_len+=i+2; - if (param_len > n) + + if (i > n - param_len) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH); goto f_err; } + param_len += i; + if (!(rsa->e=BN_bin2bn(p,i,rsa->e))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); @@ -1351,21 +1706,30 @@ int ssl3_get_key_exchange(SSL *s) ; #endif #ifndef OPENSSL_NO_DH - else if (alg_k & SSL_kEDH) + else if (alg_k & SSL_kDHE) { if ((dh=DH_new()) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } - n2s(p,i); - param_len=i+2; + + param_len = 2; if (param_len > n) { - al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + n2s(p,i); + + if (i > n - param_len) + { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH); goto f_err; } + param_len += i; + if (!(dh->p=BN_bin2bn(p,i,NULL))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); @@ -1373,14 +1737,23 @@ int ssl3_get_key_exchange(SSL *s) } p+=i; + if (2 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 2; + n2s(p,i); - param_len+=i+2; - if (param_len > n) + + if (i > n - param_len) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH); goto f_err; } + param_len += i; + if (!(dh->g=BN_bin2bn(p,i,NULL))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); @@ -1388,14 +1761,23 @@ int ssl3_get_key_exchange(SSL *s) } p+=i; + if (2 > n - param_len) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + param_len += 2; + n2s(p,i); - param_len+=i+2; - if (param_len > n) + + if (i > n - param_len) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH); goto f_err; } + param_len += i; + if (!(dh->pub_key=BN_bin2bn(p,i,NULL))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); @@ -1404,6 +1786,14 @@ int ssl3_get_key_exchange(SSL *s) p+=i; n-=param_len; + if (!ssl_security(s, SSL_SECOP_TMP_DH, + DH_security_bits(dh), 0, dh)) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL); + goto f_err; + } + #ifndef OPENSSL_NO_RSA if (alg_a & SSL_aRSA) pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); @@ -1429,7 +1819,7 @@ int ssl3_get_key_exchange(SSL *s) #endif /* !OPENSSL_NO_DH */ #ifndef OPENSSL_NO_ECDH - else if (alg_k & SSL_kEECDH) + else if (alg_k & SSL_kECDHE) { EC_GROUP *ngroup; const EC_GROUP *group; @@ -1447,12 +1837,26 @@ int ssl3_get_key_exchange(SSL *s) */ /* XXX: For now we only support named (not generic) curves - * and the ECParameters in this case is just three bytes. + * and the ECParameters in this case is just three bytes. We + * also need one byte for the length of the encoded point + */ + param_len=4; + if (param_len > n) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + /* Check curve is one of our preferences, if not server has + * sent an invalid curve. ECParameters is 3 bytes. */ - param_len=3; - if ((param_len > n) || - (*p != NAMED_CURVE_TYPE) || - ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) + if (!tls1_check_curve(s, p, 3)) + { + 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); @@ -1494,15 +1898,15 @@ int ssl3_get_key_exchange(SSL *s) encoded_pt_len = *p; /* length of encoded point */ p+=1; - param_len += (1 + encoded_pt_len); - if ((param_len > n) || + + if ((encoded_pt_len > n - param_len) || (EC_POINT_oct2point(group, srvr_ecpoint, p, encoded_pt_len, bn_ctx) == 0)) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT); goto f_err; } + param_len += encoded_pt_len; n-=param_len; p+=encoded_pt_len; @@ -1525,6 +1929,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; } @@ -1542,35 +1947,69 @@ int ssl3_get_key_exchange(SSL *s) /* if it was signed, check the signature */ if (pkey != NULL) { + if (SSL_USE_SIGALGS(s)) + { + int rv; + if (2 > n) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + rv = tls12_check_peer_sigalg(&md, s, p, pkey); + if (rv == -1) + goto err; + else if (rv == 0) + { + 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(); + + if (2 > n) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } n2s(p,i); n-=2; j=EVP_PKEY_size(pkey); + /* Check signature length. If n is 0 then signature is empty */ if ((i != n) || (n > j) || (n <= 0)) { /* wrong packet length */ - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH); goto f_err; } #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { int num; + unsigned int size; j=0; 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); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,param,param_len); - EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i); - q+=i; - j+=i; + EVP_DigestFinal_ex(&md_ctx,q,&size); + q+=size; + j+=size; } i=RSA_verify(NID_md5_sha1, md_buf, j, p, n, pkey->pkey.rsa); @@ -1590,29 +2029,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_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); - EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_VerifyUpdate(&md_ctx,param,param_len); - if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0) - { - /* bad signature */ - al=SSL_AD_DECRYPT_ERROR; - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); - goto f_err; - } - } - else -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) { - /* let's do ECDSA */ - EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL); + EVP_VerifyInit_ex(&md_ctx, md, NULL); EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_VerifyUpdate(&md_ctx,param,param_len); @@ -1624,25 +2042,21 @@ 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 { - if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK)) - /* aNULL or kPSK do not need public keys */ + /* aNULL, aSRP or kPSK do not need public keys */ + if (!(alg_a & (SSL_aNULL|SSL_aSRP)) && !(alg_k & SSL_kPSK)) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); + /* Might be wrong key type, check it */ + if (ssl3_check_cert_and_algorithm(s)) + /* Otherwise this shouldn't happen */ + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } /* still data left over */ if (n != 0) { - al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE); goto f_err; } @@ -1676,7 +2090,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; @@ -1696,6 +2110,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); } @@ -1727,11 +2149,59 @@ 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); + if (s->cert->ctypes == NULL) + { + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); + goto err; + } + 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 (SSL_USE_SIGALGS(s)) + { + 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; + } + /* Clear certificate digests and validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) + { + s->cert->pkeys[i].digest = NULL; + s->cert->pkeys[i].valid_flags = 0; + } + if ((llen & 1) || !tls1_save_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; + } + if (!tls1_process_sigalgs(s)) + { + ssl3_send_alert(s,SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); + goto err; + } + p += llen; + } /* get the CA RDNs */ n2s(p,llen); @@ -1744,7 +2214,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); @@ -1829,28 +2299,17 @@ int ssl3_get_new_session_ticket(SSL *s) n=s->method->ssl_get_message(s, SSL3_ST_CR_SESSION_TICKET_A, SSL3_ST_CR_SESSION_TICKET_B, - -1, + SSL3_MT_NEWSESSION_TICKET, 16384, &ok); if (!ok) return((int)n); - if (s->s3->tmp.message_type == SSL3_MT_FINISHED) - { - s->s3->tmp.reuse_message=1; - return(1); - } - if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE); - goto f_err; - } 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; } @@ -1861,7 +2320,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; } @@ -1878,7 +2337,7 @@ 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. + /* There are two ways to detect a resumed ticket session. * 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 @@ -2004,7 +2463,7 @@ int ssl3_get_server_done(SSL *s) int ssl3_send_client_key_exchange(SSL *s) { - unsigned char *p,*d; + unsigned char *p; int n; unsigned long alg_k; #ifndef OPENSSL_NO_RSA @@ -2025,8 +2484,7 @@ int ssl3_send_client_key_exchange(SSL *s) if (s->state == SSL3_ST_CW_KEY_EXCH_A) { - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + p = ssl_handshake_start(s); alg_k=s->s3->tmp.new_cipher->algorithm_mkey; @@ -2038,6 +2496,13 @@ int ssl3_send_client_key_exchange(SSL *s) RSA *rsa; unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + if (s->session->sess_cert == NULL) + { + /* We should always have a server certificate with SSL_kRSA. */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); + goto err; + } + if (s->session->sess_cert->peer_rsa_tmp != NULL) rsa=s->session->sess_cert->peer_rsa_tmp; else @@ -2110,7 +2575,7 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_CIPHER_CTX_init(&ciph_ctx); #ifdef KSSL_DEBUG - printf("ssl3_send_client_key_exchange(%lx & %lx)\n", + fprintf(stderr,"ssl3_send_client_key_exchange(%lx & %lx)\n", alg_k, SSL_kKRB5); #endif /* KSSL_DEBUG */ @@ -2126,9 +2591,9 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; #ifdef KSSL_DEBUG { - printf("kssl_cget_tkt rtn %d\n", krb5rc); + fprintf(stderr,"kssl_cget_tkt rtn %d\n", krb5rc); if (krb5rc && kssl_err.text) - printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); + fprintf(stderr,"kssl_cget_tkt kssl_err=%s\n", kssl_err.text); } #endif /* KSSL_DEBUG */ @@ -2141,24 +2606,25 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - /* 20010406 VRS - Earlier versions used KRB5 AP_REQ - ** in place of RFC 2712 KerberosWrapper, as in: - ** - ** Send ticket (copy to *p, set n = length) - ** n = krb5_ap_req.length; - ** memcpy(p, krb5_ap_req.data, krb5_ap_req.length); - ** if (krb5_ap_req.data) - ** kssl_krb5_free_data_contents(NULL,&krb5_ap_req); - ** - ** Now using real RFC 2712 KerberosWrapper - ** (Thanks to Simon Wilkinson ) - ** Note: 2712 "opaque" types are here replaced - ** with a 2-byte length followed by the value. - ** Example: - ** KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms - ** Where "xx xx" = length bytes. Shown here with - ** optional authenticator omitted. - */ + /*- + * 20010406 VRS - Earlier versions used KRB5 AP_REQ + * in place of RFC 2712 KerberosWrapper, as in: + * + * Send ticket (copy to *p, set n = length) + * n = krb5_ap_req.length; + * memcpy(p, krb5_ap_req.data, krb5_ap_req.length); + * if (krb5_ap_req.data) + * kssl_krb5_free_data_contents(NULL,&krb5_ap_req); + * + * Now using real RFC 2712 KerberosWrapper + * (Thanks to Simon Wilkinson ) + * Note: 2712 "opaque" types are here replaced + * with a 2-byte length followed by the value. + * Example: + * KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms + * Where "xx xx" = length bytes. Shown here with + * optional authenticator omitted. + */ /* KerberosWrapper.Ticket */ s2n(enc_ticket->length,p); @@ -2189,12 +2655,13 @@ int ssl3_send_client_key_exchange(SSL *s) if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0) goto err; - /* 20010420 VRS. Tried it this way; failed. - ** EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); - ** EVP_CIPHER_CTX_set_key_length(&ciph_ctx, - ** kssl_ctx->length); - ** EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); - */ + /*- + * 20010420 VRS. Tried it this way; failed. + * EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); + * EVP_CIPHER_CTX_set_key_length(&ciph_ctx, + * kssl_ctx->length); + * EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); + */ memset(iv, 0, sizeof iv); /* per RFC 1510 */ EVP_EncryptInit_ex(&ciph_ctx,enc, NULL, @@ -2226,47 +2693,82 @@ int ssl3_send_client_key_exchange(SSL *s) } #endif #ifndef OPENSSL_NO_DH - else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + else if (alg_k & (SSL_kDHE|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; } @@ -2277,11 +2779,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); @@ -2290,13 +2797,20 @@ int ssl3_send_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_ECDH - else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) + else if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; int ecdh_clnt_cert = 0; int field_size = 0; + if (s->session->sess_cert == 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; + } + /* Did we send out the client's * ECDH share for use in premaster * computation as part of client certificate? @@ -2304,7 +2818,8 @@ int ssl3_send_client_key_exchange(SSL *s) */ if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) { - /* XXX: For now, we do not support client + /*- + * XXX: For now, we do not support client * authentication using ECDH certificates. * To add such support, one needs to add * code that checks for appropriate @@ -2564,10 +3079,47 @@ 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) { - char identity[PSK_MAX_IDENTITY_LEN]; + /* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes + * to return a \0-terminated identity. The last byte + * is for us for simulating strnlen. */ + char identity[PSK_MAX_IDENTITY_LEN + 2]; + size_t 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; @@ -2581,8 +3133,9 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } + memset(identity, 0, sizeof(identity)); psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, - identity, PSK_MAX_IDENTITY_LEN, + identity, sizeof(identity) - 1, psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_len > PSK_MAX_PSK_LEN) { @@ -2596,7 +3149,14 @@ int ssl3_send_client_key_exchange(SSL *s) SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } - + identity[PSK_MAX_IDENTITY_LEN + 1] = '\0'; + identity_len = strlen(identity); + if (identity_len > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto psk_err; + } /* create PSK pre_master_secret */ pre_ms_len = 2+psk_len+2+psk_len; t = psk_or_pre_ms; @@ -2630,14 +3190,13 @@ int ssl3_send_client_key_exchange(SSL *s) 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_or_pre_ms, pre_ms_len); + s2n(identity_len, p); + memcpy(p, identity, identity_len); + n = 2 + identity_len; psk_err = 0; psk_err: - OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); + OPENSSL_cleanse(identity, sizeof(identity)); OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_err != 0) { @@ -2654,18 +3213,13 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_INTERNAL_ERROR); goto err; } - - *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n,d); + ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); s->state=SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num=n+4; - s->init_off=0; } /* SSL3_ST_CW_KEY_EXCH_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: #ifndef OPENSSL_NO_ECDH BN_CTX_free(bn_ctx); @@ -2679,27 +3233,28 @@ err: int ssl3_send_client_verify(SSL *s) { - unsigned char *p,*d; + unsigned char *p; 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; - p= &(d[4]); + p= ssl_handshake_start(s); pkey=s->cert->key->privatekey; /* Create context from key and test if sha1 is allowed as digest */ pctx = EVP_PKEY_CTX_new(pkey,NULL); 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 (!SSL_USE_SIGALGS(s)) + s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(data[MD5_DIGEST_LENGTH])); } @@ -2707,6 +3262,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 (SSL_USE_SIGALGS(s)) + { + 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) { @@ -2782,35 +3372,91 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); goto err; } - *(d++)=SSL3_MT_CERTIFICATE_VERIFY; - l2n3(n,d); - + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); s->state=SSL3_ST_CW_CERT_VRFY_B; - 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)); + return ssl_do_write(s); err: + EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); return(-1); } +/* Check a certificate can be used for client authentication. Currently + * check cert exists, if we have a suitable digest for TLS 1.2 if + * static DH client certificates can be used and optionally checks + * suitability for Suite B. + */ +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; + /* If no suitable signature algorithm can't use certificate */ + if (SSL_USE_SIGALGS(s) && !s->cert->key->digest) + return 0; + /* If strict mode check suitability of chain before using it. + * This also adjusts suite B digest if necessary. + */ + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT && + !tls1_check_chain(s, NULL, NULL, NULL, -2)) + 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; EVP_PKEY *pkey=NULL; int i; - unsigned long l; 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) + { + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return -1; + } + if (i == 0) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } + s->rwstate=SSL_NOTHING; + } + 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 */ @@ -2842,6 +3488,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) @@ -2863,13 +3511,16 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_C) { 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->init_num=(int)l; - s->init_off=0; + if (!ssl3_output_cert_chain(s, + (s->s3->tmp.cert_req == 2)?NULL:s->cert->key)) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } } /* SSL3_ST_CW_CERT_D */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #define has_bits(i,m) (((i)&(m)) == (m)) @@ -2891,7 +3542,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_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK)) return(1); sc=s->session->sess_cert; @@ -2915,7 +3566,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; @@ -2925,6 +3576,16 @@ int ssl3_check_cert_and_algorithm(SSL *s) return 1; } } + else if (alg_a & SSL_aECDSA) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_ECDSA_SIGNING_CERT); + goto f_err; + } + else if (alg_k & (SSL_kECDHr|SSL_kECDHe)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_ECDH_CERT); + goto f_err; + } #endif pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); @@ -2953,19 +3614,21 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_DH - if ((alg_k & SSL_kEDH) && + if ((alg_k & SSL_kDHE) && !(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) && !SSL_USE_SIGALGS(s) && + !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) && !SSL_USE_SIGALGS(s) && + !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; @@ -2988,7 +3651,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) { if (dh == NULL || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) @@ -3017,7 +3680,7 @@ err: */ #ifndef OPENSSL_NO_TLSEXT -# ifndef OPENSSL_NO_NPN +# ifndef OPENSSL_NO_NEXTPROTONEG int ssl3_send_next_proto(SSL *s) { unsigned int len, padding_len; @@ -3042,30 +3705,6 @@ int ssl3_send_next_proto(SSL *s) return ssl3_do_write(s, SSL3_RT_HANDSHAKE); } # endif - -int ssl3_check_finished(SSL *s) - { - int ok; - long n; - /* 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 */ - n=s->method->ssl_get_message(s, - SSL3_ST_CR_CERT_A, - SSL3_ST_CR_CERT_B, - -1, - s->max_cert_list, - &ok); - if (!ok) return((int)n); - s->s3->tmp.reuse_message = 1; - if ((s->s3->tmp.message_type == SSL3_MT_FINISHED) - || (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET)) - return 2; - - return 1; - } #endif int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)