X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=46f9909830ca3a0c3d583fe3ccd7792d5ccebdbc;hb=4d69f9e69d2f5069ab37da68f4b93a6f337fb13e;hp=2713129f15b8c1a32655d6d4e5b80d88e837058e;hpb=0f113f3ee4d629ef9a4a30911b22b224772085e5;p=openssl.git diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 2713129f15..46f9909830 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -150,7 +150,6 @@ #include #include "ssl_locl.h" -#include "kssl_lcl.h" #include #include #include @@ -164,21 +163,17 @@ # include #endif +static int ssl_set_version(SSL *s); 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 int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + unsigned char *p, + int (*put_cb) (const SSL_CIPHER *, + unsigned char *)); -#ifndef OPENSSL_NO_SSL3_METHOD -static const SSL_METHOD *ssl3_get_client_method(int ver) -{ - if (ver == SSL3_VERSION) - return (SSLv3_client_method()); - else - return (NULL); -} -IMPLEMENT_ssl3_meth_func(SSLv3_client_method, - ssl_undefined_function, - ssl3_connect, ssl3_get_client_method) -#endif int ssl3_connect(SSL *s) { BUF_MEM *buf = NULL; @@ -197,8 +192,10 @@ int ssl3_connect(SSL *s) cb = s->ctx->info_callback; s->in_handshake++; - if (!SSL_in_init(s) || SSL_in_before(s)) - SSL_clear(s); + if (!SSL_in_init(s) || SSL_in_before(s)) { + if (!SSL_clear(s)) + return -1; + } #ifndef OPENSSL_NO_HEARTBEATS /* @@ -230,13 +227,16 @@ int ssl3_connect(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); - if ((s->version & 0xff00) != 0x0300) { + if ((s->version >> 8) != SSL3_VERSION_MAJOR + && s->version != TLS_ANY_VERSION) { SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; ret = -1; goto end; } - if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + if (s->version != TLS_ANY_VERSION && + !ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW); return -1; } @@ -247,10 +247,12 @@ int ssl3_connect(SSL *s) if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; + s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; @@ -265,6 +267,7 @@ int ssl3_connect(SSL *s) /* setup buffing BIO */ if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -319,6 +322,18 @@ int ssl3_connect(SSL *s) break; case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: +#ifndef OPENSSL_NO_TLSEXT + /* Noop (ret = 0) for everything but EAP-FAST. */ + ret = ssl3_check_finished(s); + if (ret < 0) + goto end; + if (ret == 1) { + s->hit = 1; + s->state = SSL3_ST_CR_FINISHED_A; + s->init_num = 0; + break; + } +#endif /* Check if it is anon DH/ECDH, SRP auth */ /* or PSK */ if (! @@ -360,6 +375,7 @@ int ssl3_connect(SSL *s) */ if (!ssl3_check_cert_and_algorithm(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } break; @@ -383,6 +399,7 @@ int ssl3_connect(SSL *s) 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); + s->state = SSL_ST_ERR; goto end; } } @@ -474,6 +491,7 @@ int ssl3_connect(SSL *s) #endif if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -481,6 +499,7 @@ int ssl3_connect(SSL *s) SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -555,7 +574,8 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - s->s3->flags |= SSL3_FLAGS_CCS_OK; + if (!s->s3->change_cipher_spec) + 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) @@ -581,11 +601,8 @@ int ssl3_connect(SSL *s) case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); - - if (s->init_buf != NULL) { - BUF_MEM_free(s->init_buf); - s->init_buf = NULL; - } + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; /* * If we are not 'joining' the last two packets, remove the @@ -614,6 +631,7 @@ int ssl3_connect(SSL *s) goto end; /* break; */ + case SSL_ST_ERR: default: SSLerr(SSL_F_SSL3_CONNECT, SSL_R_UNKNOWN_STATE); ret = -1; @@ -639,13 +657,111 @@ int ssl3_connect(SSL *s) } end: s->in_handshake--; - if (buf != NULL) - BUF_MEM_free(buf); + BUF_MEM_free(buf); if (cb != NULL) cb(s, SSL_CB_CONNECT_EXIT, ret); return (ret); } +/* + * Work out what version we should be using for the initial ClientHello if + * the version is currently set to (D)TLS_ANY_VERSION. + * Returns 1 on success + * Returns 0 on error + */ +static int ssl_set_version(SSL *s) +{ + unsigned long mask, options = s->options; + + if (s->method->version == TLS_ANY_VERSION) { + /* + * SSL_OP_NO_X disables all protocols above X *if* there are + * some protocols below X enabled. This is required in order + * to maintain "version capability" vector contiguous. So + * that if application wants to disable TLS1.0 in favour of + * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the + * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3. + */ + mask = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1 +#if !defined(OPENSSL_NO_SSL3) + | SSL_OP_NO_SSLv3 +#endif + ; +#if !defined(OPENSSL_NO_TLS1_2_CLIENT) + if (options & SSL_OP_NO_TLSv1_2) { + if ((options & mask) != mask) { + s->version = TLS1_1_VERSION; + } else { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + } else { + s->version = TLS1_2_VERSION; + } +#else + if ((options & mask) == mask) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + s->version = TLS1_1_VERSION; +#endif + + mask &= ~SSL_OP_NO_TLSv1_1; + if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask) + s->version = TLS1_VERSION; + mask &= ~SSL_OP_NO_TLSv1; +#if !defined(OPENSSL_NO_SSL3) + if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask) + s->version = SSL3_VERSION; +#endif + + if (s->version != TLS1_2_VERSION && tls1_suiteb(s)) { + SSLerr(SSL_F_SSL_SET_VERSION, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + return 0; + } + + if (s->version == SSL3_VERSION && FIPS_mode()) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + return 0; + } + + } else if (s->method->version == DTLS_ANY_VERSION) { + /* Determine which DTLS version to use */ + /* If DTLS 1.2 disabled correct the version number */ + if (options & SSL_OP_NO_DTLSv1_2) { + if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL_SET_VERSION, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + return 0; + } + /* + * Disabling all versions is silly: return an error. + */ + if (options & SSL_OP_NO_DTLSv1) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_WRONG_SSL_VERSION); + return 0; + } + /* + * 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; + + return 1; +} + int ssl3_client_hello(SSL *s) { unsigned char *buf; @@ -661,44 +777,25 @@ int ssl3_client_hello(SSL *s) buf = (unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { SSL_SESSION *sess = s->session; - if ((sess == NULL) || - (sess->ssl_version != s->version) || - !sess->session_id_length || (sess->not_resumable)) { + + /* Work out what SSL/TLS/DTLS version to use */ + if (ssl_set_version(s) == 0) + goto err; + + if ((sess == NULL) || (sess->ssl_version != s->version) || +#ifdef OPENSSL_NO_TLSEXT + !sess->session_id_length || +#else + /* + * In the case of EAP-FAST, we can have a pre-shared + * "ticket" without a session ID. + */ + (!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; @@ -719,50 +816,45 @@ int ssl3_client_hello(SSL *s) } else i = 1; - if (i) - ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)); + if (i && ssl_fill_hello_random(s, 0, p, + sizeof(s->s3->client_random)) <= 0) + goto err; /* 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 + /*- + * 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. + */ *(p++) = s->client_version >> 8; *(p++) = s->client_version & 0xff; -#endif /* Random stuff */ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); @@ -846,13 +938,18 @@ int ssl3_client_hello(SSL *s) #endif l = p - d; - ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); + if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } s->state = SSL3_ST_CW_CLNT_HELLO_B; } /* SSL3_ST_CW_CLNT_HELLO_B */ return ssl_do_write(s); err: + s->state = SSL_ST_ERR; return (-1); } @@ -860,7 +957,6 @@ 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 = SSL_AD_INTERNAL_ERROR, ok; unsigned int j; @@ -904,7 +1000,45 @@ int ssl3_get_server_hello(SSL *s) } d = p = (unsigned char *)s->init_msg; - if (s->method->version == DTLS_ANY_VERSION) { + + if (s->method->version == TLS_ANY_VERSION) { + int sversion = (p[0] << 8) | p[1]; + +#if TLS_MAX_VERSION != TLS1_2_VERSION +#error Code needs updating for new TLS version +#endif +#ifndef OPENSSL_NO_SSL3 + if ((sversion == SSL3_VERSION) && !(s->options & SSL_OP_NO_SSLv3)) { + if (FIPS_mode()) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->method = SSLv3_client_method(); + } else +#endif + if ((sversion == TLS1_VERSION) && !(s->options & SSL_OP_NO_TLSv1)) { + s->method = TLSv1_client_method(); + } else if ((sversion == TLS1_1_VERSION) && + !(s->options & SSL_OP_NO_TLSv1_1)) { + s->method = TLSv1_1_client_method(); + } else if ((sversion == TLS1_2_VERSION) && + !(s->options & SSL_OP_NO_TLSv1_2)) { + s->method = TLSv1_2_client_method(); + } else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version = s->method->version; + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_VERSION_TOO_LOW); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + } else 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; @@ -925,9 +1059,7 @@ int ssl3_get_server_hello(SSL *s) goto f_err; } s->version = s->method->version; - } - - if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { + } else if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); s->version = (s->version & 0xff00) | p[1]; al = SSL_AD_PROTOCOL_VERSION; @@ -952,10 +1084,19 @@ int ssl3_get_server_hello(SSL *s) } #ifndef OPENSSL_NO_TLSEXT /* - * check if we want to resume the session based on external pre-shared - * secret + * Check if we can resume the session based on external pre-shared secret. + * EAP-FAST (RFC 4851) supports two types of session resumption. + * Resumption based on server-side state works with session IDs. + * Resumption based on pre-shared Protected Access Credentials (PACs) + * works by overriding the SessionTicket extension at the application + * layer, and does not send a session ID. (We do not know whether EAP-FAST + * servers would honour the session ID.) Therefore, the session ID alone + * is not a reliable indicator of session resumption, so we first check if + * we can resume, and later peek at the next handshake message to see if the + * server wants to resume. */ - if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) { + if (s->version >= TLS1_VERSION && s->tls_session_secret_cb && + s->session->tlsext_tick) { 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, @@ -964,12 +1105,15 @@ int ssl3_get_server_hello(SSL *s) s->tls_session_secret_cb_arg)) { s->session->cipher = pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s, p + j); - s->hit = 1; + } else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; } } #endif /* OPENSSL_NO_TLSEXT */ - if (!s->hit && j != 0 && j == s->session->session_id_length + if (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 || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { @@ -980,12 +1124,13 @@ int ssl3_get_server_hello(SSL *s) goto f_err; } s->hit = 1; - } - /* a miss or crap from the other end */ - if (!s->hit) { + } else { /* - * If we were trying for session-id reuse, make a new SSL_SESSION so - * we don't stuff up other people + * If we were trying for session-id reuse but the server + * didn't echo the ID, make a new SSL_SESSION. + * In the case of EAP-FAST and PAC, we do not send a session ID, + * so the PAC-based session secret is always preserved. It'll be + * overwritten if the server refuses resumption. */ if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s, 0)) { @@ -1005,9 +1150,9 @@ int ssl3_get_server_hello(SSL *s) } /* Set version disabled mask now we know version */ if (!SSL_USE_TLS1_2_CIPHERS(s)) - ct->mask_ssl = SSL_TLSV1_2; + s->s3->tmp.mask_ssl = SSL_TLSV1_2; else - ct->mask_ssl = 0; + s->s3->tmp.mask_ssl = 0; /* * If it is a disabled cipher we didn't send it in client hello, so * return an error. @@ -1036,16 +1181,10 @@ int ssl3_get_server_hello(SSL *s) if (s->session->cipher) 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); - goto f_err; - } + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + goto f_err; } s->s3->tmp.new_cipher = c; /* @@ -1117,12 +1256,13 @@ int ssl3_get_server_hello(SSL *s) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: + s->state = SSL_ST_ERR; return (-1); } int ssl3_get_server_certificate(SSL *s) { - int al, i, ok, ret = -1; + int al, i, ok, ret = -1, exp_idx; unsigned long n, nc, llen, l; X509 *x = NULL; const unsigned char *q, *p; @@ -1130,8 +1270,6 @@ int ssl3_get_server_certificate(SSL *s) STACK_OF(X509) *sk = NULL; SESS_CERT *sc; EVP_PKEY *pkey = NULL; - int need_cert = 1; /* VRS: 0=> will allow null cert if auth == - * KRB5 */ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_A, @@ -1141,9 +1279,7 @@ int ssl3_get_server_certificate(SSL *s) if (!ok) return ((int)n); - 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))) { + if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { s->s3->tmp.reuse_message = 1; return (1); } @@ -1198,12 +1334,7 @@ int ssl3_get_server_certificate(SSL *s) } i = ssl_verify_cert_chain(s, sk); - 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)) -#endif /* OPENSSL_NO_KRB5 */ - ) { + if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) { al = ssl_verify_alarm_type(s->verify_result); SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_CERTIFICATE_VERIFY_FAILED); @@ -1220,8 +1351,7 @@ int ssl3_get_server_certificate(SSL *s) if (sc == NULL) goto err; - if (s->session->sess_cert) - ssl_sess_cert_free(s->session->sess_cert); + ssl_sess_cert_free(s->session->sess_cert); s->session->sess_cert = sc; sc->cert_chain = sk; @@ -1237,21 +1367,7 @@ int ssl3_get_server_certificate(SSL *s) pkey = X509_get_pubkey(x); - /* VRS: allow null cert if auth == KRB5 */ - need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && - (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) - ? 0 : 1; - -#ifdef KSSL_DEBUG - 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 */ - - if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) { + if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { x = NULL; al = SSL3_AL_FATAL; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, @@ -1260,7 +1376,7 @@ int ssl3_get_server_certificate(SSL *s) } i = ssl_cert_type(x, pkey); - if (need_cert && i < 0) { + if (i < 0) { x = NULL; al = SSL3_AL_FATAL; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, @@ -1268,47 +1384,38 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } - 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? We just created sc a couple - * of lines ago. - */ - if (sc->peer_pkeys[i].x509 != NULL) - X509_free(sc->peer_pkeys[i].x509); - sc->peer_pkeys[i].x509 = x; - sc->peer_key = &(sc->peer_pkeys[i]); - - if (s->session->peer != NULL) - X509_free(s->session->peer); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - s->session->peer = x; - } else { - sc->peer_cert_type = i; - sc->peer_key = NULL; - - if (s->session->peer != NULL) - X509_free(s->session->peer); - s->session->peer = NULL; + 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? We just created sc a couple + * of lines ago. + */ + X509_free(sc->peer_pkeys[i].x509); + sc->peer_pkeys[i].x509 = x; + sc->peer_key = &(sc->peer_pkeys[i]); + + X509_free(s->session->peer); + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + s->session->peer = x; s->session->verify_result = s->verify_result; x = NULL; ret = 1; - if (0) { + goto done; + f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - } + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: + s->state = SSL_ST_ERR; + done: EVP_PKEY_free(pkey); X509_free(x); sk_X509_pop_free(sk, X509_free); @@ -1332,7 +1439,7 @@ int ssl3_get_key_exchange(SSL *s) #ifndef OPENSSL_NO_DH DH *dh = NULL; #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC EC_KEY *ecdh = NULL; BN_CTX *bn_ctx = NULL; EC_POINT *srvr_ecpoint = NULL; @@ -1373,8 +1480,7 @@ int ssl3_get_key_exchange(SSL *s) */ if (alg_k & SSL_kPSK) { s->session->sess_cert = ssl_sess_cert_new(); - if (s->ctx->psk_identity_hint) - OPENSSL_free(s->ctx->psk_identity_hint); + OPENSSL_free(s->ctx->psk_identity_hint); s->ctx->psk_identity_hint = NULL; } #endif @@ -1385,22 +1491,16 @@ int ssl3_get_key_exchange(SSL *s) param = p = (unsigned char *)s->init_msg; if (s->session->sess_cert != NULL) { #ifndef OPENSSL_NO_RSA - if (s->session->sess_cert->peer_rsa_tmp != NULL) { - RSA_free(s->session->sess_cert->peer_rsa_tmp); - s->session->sess_cert->peer_rsa_tmp = NULL; - } + RSA_free(s->session->sess_cert->peer_rsa_tmp); + s->session->sess_cert->peer_rsa_tmp = NULL; #endif #ifndef OPENSSL_NO_DH - if (s->session->sess_cert->peer_dh_tmp) { - DH_free(s->session->sess_cert->peer_dh_tmp); - s->session->sess_cert->peer_dh_tmp = NULL; - } + DH_free(s->session->sess_cert->peer_dh_tmp); + s->session->sess_cert->peer_dh_tmp = NULL; #endif -#ifndef OPENSSL_NO_ECDH - if (s->session->sess_cert->peer_ecdh_tmp) { - EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); - s->session->sess_cert->peer_ecdh_tmp = NULL; - } +#ifndef OPENSSL_NO_EC + EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); + s->session->sess_cert->peer_ecdh_tmp = NULL; #endif } else { s->session->sess_cert = ssl_sess_cert_new(); @@ -1449,8 +1549,7 @@ int ssl3_get_key_exchange(SSL *s) */ memcpy(tmp_id_hint, p, i); memset(tmp_id_hint + i, 0, PSK_MAX_IDENTITY_LEN + 1 - i); - if (s->ctx->psk_identity_hint != NULL) - OPENSSL_free(s->ctx->psk_identity_hint); + OPENSSL_free(s->ctx->psk_identity_hint); s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); if (s->ctx->psk_identity_hint == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; @@ -1477,7 +1576,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.N = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.N = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1497,7 +1596,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.g = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.g = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1518,7 +1617,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.s = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.s = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1538,7 +1637,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.B = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.B = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1594,7 +1693,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(rsa->n = BN_bin2bn(p, i, rsa->n))) { + if ((rsa->n = BN_bin2bn(p, i, rsa->n)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1614,7 +1713,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(rsa->e = BN_bin2bn(p, i, rsa->e))) { + if ((rsa->e = BN_bin2bn(p, i, rsa->e)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1656,7 +1755,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->p = BN_bin2bn(p, i, NULL))) { + if ((dh->p = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1676,7 +1775,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->g = BN_bin2bn(p, i, NULL))) { + if ((dh->g = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1696,7 +1795,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->pub_key = BN_bin2bn(p, i, NULL))) { + if ((dh->pub_key = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1727,15 +1826,10 @@ int ssl3_get_key_exchange(SSL *s) s->session->sess_cert->peer_dh_tmp = dh; dh = NULL; - } else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); - goto f_err; } #endif /* !OPENSSL_NO_DH */ -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC else if (alg_k & SSL_kECDHE) { EC_GROUP *ngroup; const EC_GROUP *group; @@ -1833,7 +1927,7 @@ int ssl3_get_key_exchange(SSL *s) X509_get_pubkey(s->session-> sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); # endif -# ifndef OPENSSL_NO_ECDSA +# ifndef OPENSSL_NO_EC else if (alg_a & SSL_aECDSA) pkey = X509_get_pubkey(s->session-> @@ -1852,7 +1946,7 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } -#endif /* !OPENSSL_NO_ECDH */ +#endif /* !OPENSSL_NO_EC */ /* p points to the next byte, there are 'n' bytes left */ @@ -1965,20 +2059,18 @@ int ssl3_get_key_exchange(SSL *s) err: EVP_PKEY_free(pkey); #ifndef OPENSSL_NO_RSA - if (rsa != NULL) - RSA_free(rsa); + RSA_free(rsa); #endif #ifndef OPENSSL_NO_DH - if (dh != NULL) - DH_free(dh); + DH_free(dh); #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC BN_CTX_free(bn_ctx); EC_POINT_free(srvr_ecpoint); - if (ecdh != NULL) - EC_KEY_free(ecdh); + EC_KEY_free(ecdh); #endif EVP_MD_CTX_cleanup(&md_ctx); + s->state = SSL_ST_ERR; return (-1); } @@ -2040,10 +2132,8 @@ 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; - } + 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); @@ -2072,8 +2162,8 @@ int ssl3_get_certificate_request(SSL *s) } /* 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; + s->s3->tmp.md[i] = NULL; + s->s3->tmp.valid_flags[i] = 0; } if ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -2091,14 +2181,6 @@ int ssl3_get_certificate_request(SSL *s) /* get the CA RDNs */ n2s(p, llen); -#if 0 - { - FILE *out; - out = fopen("/tmp/vsign.der", "w"); - fwrite(p, 1, llen, out); - fclose(out); - } -#endif if ((unsigned long)(p - d + llen) != n) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -2109,8 +2191,6 @@ int ssl3_get_certificate_request(SSL *s) for (nc = 0; nc < llen;) { n2s(p, l); if ((l + nc + 2) > llen) { - if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) - goto cont; /* netscape bugs */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG); goto err; @@ -2119,14 +2199,9 @@ int ssl3_get_certificate_request(SSL *s) q = p; if ((xn = d2i_X509_NAME(NULL, &q, l)) == NULL) { - /* If netscape tolerance is on, ignore errors */ - if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG) - goto cont; - else { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB); - goto err; - } + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB); + goto err; } if (q != (p + l)) { @@ -2144,23 +2219,19 @@ int ssl3_get_certificate_request(SSL *s) nc += l + 2; } - if (0) { - cont: - ERR_clear_error(); - } - /* we should setup a certificate to return.... */ s->s3->tmp.cert_req = 1; s->s3->tmp.ctype_num = ctype_num; - if (s->s3->tmp.ca_names != NULL) - sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); s->s3->tmp.ca_names = ca_sk; ca_sk = NULL; ret = 1; + goto done; err: - if (ca_sk != NULL) - sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); + s->state = SSL_ST_ERR; + done: + sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); return (ret); } @@ -2201,10 +2272,8 @@ int ssl3_get_new_session_ticket(SSL *s) SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH); goto f_err; } - if (s->session->tlsext_tick) { - OPENSSL_free(s->session->tlsext_tick); - s->session->tlsext_ticklen = 0; - } + OPENSSL_free(s->session->tlsext_tick); + s->session->tlsext_ticklen = 0; s->session->tlsext_tick = OPENSSL_malloc(ticklen); if (!s->session->tlsext_tick) { SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE); @@ -2225,16 +2294,13 @@ int ssl3_get_new_session_ticket(SSL *s) */ 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: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: + s->state = SSL_ST_ERR; return (-1); } @@ -2269,8 +2335,7 @@ int ssl3_get_cert_status(SSL *s) SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH); goto f_err; } - if (s->tlsext_ocsp_resp) - OPENSSL_free(s->tlsext_ocsp_resp); + OPENSSL_free(s->tlsext_ocsp_resp); s->tlsext_ocsp_resp = BUF_memdup(p, resplen); if (!s->tlsext_ocsp_resp) { al = SSL_AD_INTERNAL_ERROR; @@ -2295,6 +2360,7 @@ int ssl3_get_cert_status(SSL *s) return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->state = SSL_ST_ERR; return (-1); } #endif @@ -2316,6 +2382,7 @@ int ssl3_get_server_done(SSL *s) /* should contain no data */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_SERVER_DONE, SSL_R_LENGTH_MISMATCH); + s->state = SSL_ST_ERR; return -1; } ret = 1; @@ -2331,10 +2398,7 @@ int ssl3_send_client_key_exchange(SSL *s) unsigned char *q; EVP_PKEY *pkey = NULL; #endif -#ifndef OPENSSL_NO_KRB5 - KSSL_ERR kssl_err; -#endif /* OPENSSL_NO_KRB5 */ -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC EC_KEY *clnt_ecdh = NULL; const EC_POINT *srvr_ecpoint = NULL; EVP_PKEY *srvr_pub_pkey = NULL; @@ -2342,6 +2406,8 @@ int ssl3_send_client_key_exchange(SSL *s) int encoded_pt_len = 0; BN_CTX *bn_ctx = NULL; #endif + unsigned char *pms = NULL; + size_t pmslen = 0; if (s->state == SSL3_ST_CW_KEY_EXCH_A) { p = ssl_handshake_start(s); @@ -2354,7 +2420,10 @@ int ssl3_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_RSA else if (alg_k & SSL_kRSA) { RSA *rsa; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; if (s->session->sess_cert == NULL) { /* @@ -2382,19 +2451,16 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_PKEY_free(pkey); } - tmp_buf[0] = s->client_version >> 8; - tmp_buf[1] = s->client_version & 0xff; - if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0) + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + if (RAND_bytes(pms + 2, pmslen - 2) <= 0) goto err; - s->session->master_key_length = sizeof tmp_buf; - q = p; /* Fix buf for TLS and beyond */ if (s->version > SSL3_VERSION) p += 2; - n = RSA_public_encrypt(sizeof tmp_buf, - tmp_buf, p, rsa, RSA_PKCS1_PADDING); + n = RSA_public_encrypt(pmslen, pms, p, rsa, RSA_PKCS1_PADDING); # ifdef PKCS1_CHECK if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; @@ -2412,144 +2478,6 @@ int ssl3_send_client_key_exchange(SSL *s) s2n(n, q); n += 2; } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); - } -#endif -#ifndef OPENSSL_NO_KRB5 - else if (alg_k & SSL_kKRB5) { - krb5_error_code krb5rc; - KSSL_CTX *kssl_ctx = s->kssl_ctx; - /* krb5_data krb5_ap_req; */ - krb5_data *enc_ticket; - krb5_data authenticator, *authp = NULL; - EVP_CIPHER_CTX ciph_ctx; - 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 + EVP_MAX_IV_LENGTH]; - int padl, outl = sizeof(epms); - - EVP_CIPHER_CTX_init(&ciph_ctx); - -# ifdef KSSL_DEBUG - fprintf(stderr, "ssl3_send_client_key_exchange(%lx & %lx)\n", - alg_k, SSL_kKRB5); -# endif /* KSSL_DEBUG */ - - authp = NULL; -# ifdef KRB5SENDAUTH - if (KRB5SENDAUTH) - authp = &authenticator; -# endif /* KRB5SENDAUTH */ - - krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, &kssl_err); - enc = kssl_map_enc(kssl_ctx->enctype); - if (enc == NULL) - goto err; -# ifdef KSSL_DEBUG - { - fprintf(stderr, "kssl_cget_tkt rtn %d\n", krb5rc); - if (krb5rc && kssl_err.text) - fprintf(stderr, "kssl_cget_tkt kssl_err=%s\n", - kssl_err.text); - } -# endif /* KSSL_DEBUG */ - - if (krb5rc) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason); - 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. - */ - - /* KerberosWrapper.Ticket */ - s2n(enc_ticket->length, p); - memcpy(p, enc_ticket->data, enc_ticket->length); - p += enc_ticket->length; - n = enc_ticket->length + 2; - - /* KerberosWrapper.Authenticator */ - if (authp && authp->length) { - s2n(authp->length, p); - memcpy(p, authp->data, authp->length); - p += authp->length; - n += authp->length + 2; - - free(authp->data); - authp->data = NULL; - authp->length = 0; - } else { - s2n(0, p); /* null authenticator length */ - n += 2; - } - - tmp_buf[0] = s->client_version >> 8; - tmp_buf[1] = s->client_version & 0xff; - 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); - */ - - memset(iv, 0, sizeof iv); /* per RFC 1510 */ - EVP_EncryptInit_ex(&ciph_ctx, enc, NULL, kssl_ctx->key, iv); - EVP_EncryptUpdate(&ciph_ctx, epms, &outl, tmp_buf, - sizeof tmp_buf); - EVP_EncryptFinal_ex(&ciph_ctx, &(epms[outl]), &padl); - outl += padl; - if (outl > (int)sizeof epms) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); - - /* KerberosWrapper.EncryptedPreMasterSecret */ - s2n(outl, p); - memcpy(p, epms, outl); - p += outl; - n += outl + 2; - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); - OPENSSL_cleanse(epms, outl); } #endif #ifndef OPENSSL_NO_DH @@ -2607,12 +2535,17 @@ int ssl3_send_client_key_exchange(SSL *s) } } + pmslen = DH_size(dh_clnt); + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + /* * 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); + n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt); if (scert->peer_dh_tmp == NULL) DH_free(dh_srvr); @@ -2621,15 +2554,7 @@ int ssl3_send_client_key_exchange(SSL *s) DH_free(dh_clnt); goto err; } - - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - /* clean up */ - memset(p, 0, n); + pmslen = n; if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) n = 0; @@ -2647,7 +2572,7 @@ int ssl3_send_client_key_exchange(SSL *s) } #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; @@ -2667,26 +2592,26 @@ int ssl3_send_client_key_exchange(SSL *s) * ecdh_clnt_cert to 1. */ if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) { - /*- - * 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 - * conditions and sets ecdh_clnt_cert to 1. - * For example, the cert have an ECC - * key on the same curve as the server's - * and the key should be authorized for - * key agreement. - * - * One also needs to add code in ssl3_connect - * to skip sending the certificate verify - * message. - * - * if ((s->cert->key->privatekey != NULL) && - * (s->cert->key->privatekey->type == - * EVP_PKEY_EC) && ...) - * ecdh_clnt_cert = 1; - */ + /*- + * 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 + * conditions and sets ecdh_clnt_cert to 1. + * For example, the cert have an ECC + * key on the same curve as the server's + * and the key should be authorized for + * key agreement. + * + * One also needs to add code in ssl3_connect + * to skip sending the certificate verify + * message. + * + * if ((s->cert->key->privatekey != NULL) && + * (s->cert->key->privatekey->type == + * EVP_PKEY_EC) && ...) + * ecdh_clnt_cert = 1; + */ } if (s->session->sess_cert->peer_ecdh_tmp != NULL) { @@ -2762,22 +2687,16 @@ int ssl3_send_client_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - n = ECDH_compute_key(p, (field_size + 7) / 8, srvr_ecpoint, - clnt_ecdh, NULL); - if (n <= 0) { + pmslen = (field_size + 7) / 8; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL); + if (n <= 0 || pmslen != (size_t)n) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - - memset(p, 0, n); /* clean up */ - if (ecdh_clnt_cert) { /* Send empty client key exch message */ n = 0; @@ -2811,20 +2730,18 @@ int ssl3_send_client_key_exchange(SSL *s) /* Encoded point will be copied here */ p += 1; /* copy the point */ - memcpy((unsigned char *)p, encodedPoint, n); + memcpy(p, encodedPoint, n); /* increment n to account for length field */ n += 1; } /* Free allocated memory */ BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) - OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); + OPENSSL_free(encodedPoint); + EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); } -#endif /* !OPENSSL_NO_ECDH */ +#endif /* !OPENSSL_NO_EC */ else if (alg_k & SSL_kGOST) { /* GOST key exchange message creation */ EVP_PKEY_CTX *pkey_ctx; @@ -2832,10 +2749,15 @@ 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], tmp[256]; + unsigned char shared_ukm[32], tmp[256]; EVP_MD_CTX *ukm_hash; EVP_PKEY *pub_key; + pmslen = 32; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + /* * Get server sertificate PKEY and create ctx from it */ @@ -2865,7 +2787,12 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_PKEY_encrypt_init(pkey_ctx); /* Generate session key */ - RAND_bytes(premaster_secret, 32); + if (RAND_bytes(pms, pmslen) <= 0) { + EVP_PKEY_CTX_free(pkey_ctx); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + }; /* * If we have client certificate, use its secret as peer key */ @@ -2905,8 +2832,7 @@ int ssl3_send_client_key_exchange(SSL *s) */ *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; msglen = 255; - if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, 32) - < 0) { + if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) < 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_LIBRARY_BUG); goto err; @@ -2927,12 +2853,6 @@ int ssl3_send_client_key_exchange(SSL *s) 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, - s-> - session->master_key, - premaster_secret, - 32); EVP_PKEY_free(pub_key); } @@ -2949,23 +2869,13 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_INTERNAL_ERROR); goto err; } - if (s->session->srp_username != NULL) - OPENSSL_free(s->session->srp_username); + 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 @@ -2978,8 +2888,7 @@ int ssl3_send_client_key_exchange(SSL *s) 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; + unsigned int psk_len = 0; int psk_err = 1; n = 0; @@ -2990,10 +2899,15 @@ int ssl3_send_client_key_exchange(SSL *s) } memset(identity, 0, sizeof(identity)); + /* Allocate maximum size buffer */ + pmslen = PSK_MAX_PSK_LEN * 2 + 4; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, identity, sizeof(identity) - 1, - psk_or_pre_ms, - sizeof(psk_or_pre_ms)); + pms, pmslen); if (psk_len > PSK_MAX_PSK_LEN) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); @@ -3003,6 +2917,8 @@ int ssl3_send_client_key_exchange(SSL *s) SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } + /* Change pmslen to real length */ + pmslen = 2 + psk_len + 2 + psk_len; identity[PSK_MAX_IDENTITY_LEN + 1] = '\0'; identity_len = strlen(identity); if (identity_len > PSK_MAX_IDENTITY_LEN) { @@ -3011,16 +2927,14 @@ int ssl3_send_client_key_exchange(SSL *s) goto psk_err; } /* create PSK pre_master_secret */ - pre_ms_len = 2 + psk_len + 2 + psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms + psk_len + 4, psk_or_pre_ms, psk_len); + t = pms; + memmove(pms + psk_len + 4, pms, psk_len); s2n(psk_len, t); memset(t, 0, psk_len); t += psk_len; s2n(psk_len, t); - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); + OPENSSL_free(s->session->psk_identity_hint); s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); if (s->ctx->psk_identity_hint != NULL @@ -3030,8 +2944,7 @@ int ssl3_send_client_key_exchange(SSL *s) goto psk_err; } - if (s->session->psk_identity != NULL) - OPENSSL_free(s->session->psk_identity); + OPENSSL_free(s->session->psk_identity); s->session->psk_identity = BUF_strdup(identity); if (s->session->psk_identity == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, @@ -3039,19 +2952,12 @@ int ssl3_send_client_key_exchange(SSL *s) goto psk_err; } - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - psk_or_pre_ms, - pre_ms_len); s2n(identity_len, p); memcpy(p, identity, identity_len); n = 2 + identity_len; psk_err = 0; psk_err: OPENSSL_cleanse(identity, sizeof(identity)); - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_err != 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; @@ -3064,21 +2970,78 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); + if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + s->state = SSL3_ST_CW_KEY_EXCH_B; } /* SSL3_ST_CW_KEY_EXCH_B */ - return ssl_do_write(s); + n = ssl_do_write(s); +#ifndef OPENSSL_NO_SRP + /* Check for SRP */ + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) { + /* + * If everything written generate master key: no need to save PMS as + * SRP_generate_client_master_secret generates it internally. + */ + if (n > 0) { + 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; + } + } + } else +#endif + /* If we haven't written everything save PMS */ + if (n <= 0) { + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + } else { + /* If we don't have a PMS restore */ + if (pms == NULL) { + pms = s->s3->tmp.pms; + pmslen = s->s3->tmp.pmslen; + } + if (pms == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s-> + session->master_key, + pms, pmslen); + OPENSSL_clear_free(pms, pmslen); + s->s3->tmp.pms = NULL; + if (s->session->master_key_length < 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + } + return n; + memerr: + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); err: -#ifndef OPENSSL_NO_ECDH + OPENSSL_clear_free(pms, pmslen); + s->s3->tmp.pms = NULL; +#ifndef OPENSSL_NO_EC BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) - OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); + OPENSSL_free(encodedPoint); + EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); #endif + s->state = SSL_ST_ERR; return (-1); } @@ -3117,7 +3080,7 @@ int ssl3_send_client_verify(SSL *s) if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; - const EVP_MD *md = s->cert->key->digest; + const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys]; 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); @@ -3136,7 +3099,15 @@ int ssl3_send_client_verify(SSL *s) } s2n(u, p); n = u + 4; - if (!ssl3_digest_cached_records(s)) + /* + * For extended master secret we've already digested cached + * records. + */ + if (s->session->flags & SSL_SESS_FLAG_EXTMS) { + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE; + } else if (!ssl3_digest_cached_records(s)) goto err; } else #ifndef OPENSSL_NO_RSA @@ -3165,7 +3136,7 @@ int ssl3_send_client_verify(SSL *s) n = j + 2; } else #endif -#ifndef OPENSSL_NO_ECDSA +#ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { if (!ECDSA_sign(pkey->save_type, &(data[MD5_DIGEST_LENGTH]), @@ -3198,7 +3169,10 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } - ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); + if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } s->state = SSL3_ST_CW_CERT_VRFY_B; } EVP_MD_CTX_cleanup(&mctx); @@ -3207,6 +3181,7 @@ int ssl3_send_client_verify(SSL *s) err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); + s->state = SSL_ST_ERR; return (-1); } @@ -3221,7 +3196,7 @@ static int ssl3_check_client_certificate(SSL *s) 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) + if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys]) return 0; /* * If strict mode check suitability of chain before using it. This also @@ -3270,6 +3245,7 @@ int ssl3_send_client_certificate(SSL *s) } if (i == 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return 0; } s->rwstate = SSL_NOTHING; @@ -3303,10 +3279,8 @@ int ssl3_send_client_certificate(SSL *s) SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); } - if (x509 != NULL) - X509_free(x509); - if (pkey != NULL) - EVP_PKEY_free(pkey); + X509_free(x509); + EVP_PKEY_free(pkey); if (i && !ssl3_check_client_certificate(s)) i = 0; if (i == 0) { @@ -3316,6 +3290,11 @@ int ssl3_send_client_certificate(SSL *s) return (1); } else { s->s3->tmp.cert_req = 2; + if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; + return 0; + } } } @@ -3330,6 +3309,7 @@ int ssl3_send_client_certificate(SSL *s) 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); + s->state = SSL_ST_ERR; return 0; } } @@ -3356,7 +3336,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_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) + if ((alg_a & SSL_aNULL) || (alg_k & SSL_kPSK)) return (1); sc = s->session->sess_cert; @@ -3374,7 +3354,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) /* This is the passed certificate */ idx = sc->peer_cert_type; -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC if (idx == SSL_PKEY_ECC) { if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) { /* check failed */ @@ -3474,13 +3454,56 @@ int ssl3_check_cert_and_algorithm(SSL *s) return (0); } +#ifndef 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. + * Normally, we can tell if the server is resuming the session from + * the session ID. EAP-FAST (RFC 4851), however, relies on the next server + * message after the ServerHello to determine if the server is resuming. + * Therefore, we allow EAP-FAST to peek ahead. + * ssl3_check_finished returns 1 if we are resuming from an external + * pre-shared secret, we have a "ticket" and the next server handshake message + * is Finished; and 0 otherwise. It returns -1 upon an error. */ +static int ssl3_check_finished(SSL *s) +{ + int ok = 0; + + if (s->version < TLS1_VERSION || !s->tls_session_secret_cb || + !s->session->tlsext_tick) + return 0; + + /* Need to permit this temporarily, in case the next message is Finished. */ + s->s3->flags |= SSL3_FLAGS_CCS_OK; + /* + * This function is called when we might get a Certificate message instead, + * so permit appropriate message length. + * We ignore the return value as we're only interested in the message type + * and not its length. + */ + s->method->ssl_get_message(s, + SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, + -1, s->max_cert_list, &ok); + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + + if (!ok) + return -1; + + s->s3->tmp.reuse_message = 1; + + if (s->s3->tmp.message_type == SSL3_MT_FINISHED) + return 1; + + /* If we're not done, then the CCS arrived early and we should bail. */ + if (s->s3->change_cipher_spec) { + SSLerr(SSL_F_SSL3_CHECK_FINISHED, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + return 0; +} -#ifndef OPENSSL_NO_TLSEXT # ifndef OPENSSL_NO_NEXTPROTONEG int ssl3_send_next_proto(SSL *s) { @@ -3523,3 +3546,65 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) i = s->ctx->client_cert_cb(s, px509, ppkey); return i; } + +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + unsigned char *p, + int (*put_cb) (const SSL_CIPHER *, + unsigned char *)) +{ + int i, j = 0; + SSL_CIPHER *c; + unsigned char *q; + int empty_reneg_info_scsv = !s->renegotiate; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); + + if (sk == NULL) + return (0); + q = p; + if (put_cb == NULL) + put_cb = s->method->put_cipher_by_char; + + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + continue; +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (c->id == SSL3_CK_SCSV) { + if (!empty_reneg_info_scsv) + continue; + else + empty_reneg_info_scsv = 0; + } +#endif + j = put_cb(c, p); + p += j; + } + /* + * If p == q, no ciphers; caller indicates an error. Otherwise, add + * applicable SCSVs. + */ + if (p != q) { + if (empty_reneg_info_scsv) { + static SSL_CIPHER scsv = { + 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv, p); + p += j; +#ifdef OPENSSL_RI_DEBUG + fprintf(stderr, + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n"); +#endif + } + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) { + static SSL_CIPHER scsv = { + 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv, p); + p += j; + } + } + + return (p - q); +}