X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=74c369604c0af9e87c9b37ce33ab997dc0365e22;hp=04dbb7a735c4290fee1903f2358e38b94a344293;hb=ec30e8566e43d888ab1d7cf01749a979896bb3d9;hpb=55a9a16f1c02837058173c41fa26f36ec3acd22e diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 04dbb7a735..74c369604c 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -151,7 +151,7 @@ #include #include "ssl_locl.h" -#include "../crypto/constant_time_locl.h" +#include "internal/constant_time_locl.h" #include #include #include @@ -164,21 +164,10 @@ #include #include -#ifndef OPENSSL_NO_SSL3_METHOD -static const SSL_METHOD *ssl3_get_server_method(int ver); +static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, + int num, STACK_OF(SSL_CIPHER) **skp, int sslv2format); -static const SSL_METHOD *ssl3_get_server_method(int ver) -{ - if (ver == SSL3_VERSION) - return (SSLv3_server_method()); - else - return (NULL); -} -IMPLEMENT_ssl3_meth_func(SSLv3_server_method, - ssl3_accept, - ssl_undefined_function, ssl3_get_server_method) -#endif #ifndef OPENSSL_NO_SRP static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) { @@ -256,7 +245,7 @@ int ssl3_accept(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); - if ((s->version >> 8) != 3) { + if ((s->version >> 8 != 3) && s->version != TLS_ANY_VERSION) { SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; return -1; @@ -292,7 +281,6 @@ int ssl3_accept(SSL *s) s->init_num = 0; s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY; - s->s3->flags &= ~SSL3_FLAGS_CCS_OK; /* * Should have been reset by ssl3_get_finished, too. */ @@ -398,19 +386,15 @@ int ssl3_accept(SSL *s) ret = ssl3_send_server_hello(s); if (ret <= 0) goto end; -#ifndef OPENSSL_NO_TLSEXT + if (s->hit) { if (s->tlsext_ticket_expected) s->state = SSL3_ST_SW_SESSION_TICKET_A; else s->state = SSL3_ST_SW_CHANGE_A; - } -#else - if (s->hit) - s->state = SSL3_ST_SW_CHANGE_A; -#endif - else + } else { s->state = SSL3_ST_SW_CERT_A; + } s->init_num = 0; break; @@ -418,14 +402,12 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ /* normal PSK or SRP */ - if (! - (s->s3->tmp. - new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) -&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + if (!(s->s3->tmp.new_cipher->algorithm_auth & + (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { ret = ssl3_send_server_certificate(s); if (ret <= 0) goto end; -#ifndef OPENSSL_NO_TLSEXT + if (s->tlsext_status_expected) s->state = SSL3_ST_SW_CERT_STATUS_A; else @@ -434,12 +416,6 @@ int ssl3_accept(SSL *s) skip = 1; s->state = SSL3_ST_SW_KEY_EXCH_A; } -#else - } else - skip = 1; - - s->state = SSL3_ST_SW_KEY_EXCH_A; -#endif s->init_num = 0; break; @@ -467,7 +443,10 @@ int ssl3_accept(SSL *s) * provided */ #ifndef OPENSSL_NO_PSK - || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) + /* Only send SKE if we have identity hint for plain PSK */ + || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->ctx->psk_identity_hint) + /* For other PSK always send SKE */ + || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) #endif #ifndef OPENSSL_NO_SRP /* SRP: send ServerKeyExchange */ @@ -523,16 +502,14 @@ int ssl3_accept(SSL *s) * With normal PSK Certificates and Certificate Requests * are omitted */ - || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) { /* no cert request */ skip = 1; s->s3->tmp.cert_request = 0; s->state = SSL3_ST_SW_SRVR_DONE_A; - if (s->s3->handshake_buffer) { - if (!ssl3_digest_cached_records(s)) { - s->state = SSL_ST_ERR; - return -1; - } + if (!ssl3_digest_cached_records(s, 0)) { + s->state = SSL_ST_ERR; + return -1; } } else { s->s3->tmp.cert_request = 1; @@ -598,14 +575,7 @@ int ssl3_accept(SSL *s) * not sent. Also for GOST ciphersuites when the client uses * its key from the certificate for key exchange. */ -#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) - s->state = SSL3_ST_SR_FINISHED_A; -#else - if (s->s3->next_proto_neg_seen) - s->state = SSL3_ST_SR_NEXT_PROTO_A; - else - s->state = SSL3_ST_SR_FINISHED_A; -#endif + s->state = SSL3_ST_SR_CHANGE_A; s->init_num = 0; } else if (SSL_USE_SIGALGS(s)) { s->state = SSL3_ST_SR_CERT_VRFY_A; @@ -619,14 +589,11 @@ int ssl3_accept(SSL *s) } /* * For sigalgs freeze the handshake buffer. If we support - * extms we've done this already. + * extms we've done this already so this is a no-op */ - if (!(s->s3->flags & SSL_SESS_FLAG_EXTMS)) { - s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; - if (!ssl3_digest_cached_records(s)) { - s->state = SSL_ST_ERR; - return -1; - } + if (!ssl3_digest_cached_records(s, 1)) { + s->state = SSL_ST_ERR; + return -1; } } else { int offset = 0; @@ -641,11 +608,9 @@ int ssl3_accept(SSL *s) * CertificateVerify should be generalized. But it is next * step */ - if (s->s3->handshake_buffer) { - if (!ssl3_digest_cached_records(s)) { - s->state = SSL_ST_ERR; - return -1; - } + if (!ssl3_digest_cached_records(s, 0)) { + s->state = SSL_ST_ERR; + return -1; } for (dgst_num = 0; dgst_num < SSL_MAX_DIGEST; dgst_num++) if (s->s3->handshake_dgst[dgst_num]) { @@ -677,32 +642,13 @@ int ssl3_accept(SSL *s) if (ret <= 0) goto end; -#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) - s->state = SSL3_ST_SR_FINISHED_A; -#else - if (s->s3->next_proto_neg_seen) - s->state = SSL3_ST_SR_NEXT_PROTO_A; - else - s->state = SSL3_ST_SR_FINISHED_A; -#endif + s->state = SSL3_ST_SR_CHANGE_A; s->init_num = 0; break; -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) case SSL3_ST_SR_NEXT_PROTO_A: case SSL3_ST_SR_NEXT_PROTO_B: - /* - * Enable CCS for NPN. Receiving a CCS clears the flag, so make - * sure not to re-enable it to ban duplicates. This *should* be the - * first time we have received one - but we check anyway to be - * cautious. - * s->s3->change_cipher_spec is set when a CCS is - * processed in s3_pkt.c, and remains set until - * the client's Finished message is read. - */ - if (!s->s3->change_cipher_spec) - s->s3->flags |= SSL3_FLAGS_CCS_OK; - ret = ssl3_get_next_proto(s); if (ret <= 0) goto end; @@ -711,34 +657,40 @@ int ssl3_accept(SSL *s) break; #endif + + case SSL3_ST_SR_CHANGE_A: + case SSL3_ST_SR_CHANGE_B: + ret = ssl3_get_change_cipher_spec(s, SSL3_ST_SR_CHANGE_A, + SSL3_ST_SR_CHANGE_B); + if (ret <= 0) + goto end; + +#if defined(OPENSSL_NO_NEXTPROTONEG) + s->state = SSL3_ST_SR_FINISHED_A; +#else + if (s->s3->next_proto_neg_seen) + s->state = SSL3_ST_SR_NEXT_PROTO_A; + else + s->state = SSL3_ST_SR_FINISHED_A; +#endif + s->init_num = 0; + break; + case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: - /* - * Enable CCS for handshakes without NPN. In NPN the CCS flag has - * already been set. Receiving a CCS clears the flag, so make - * sure not to re-enable it to ban duplicates. - * s->s3->change_cipher_spec is set when a CCS is - * processed in s3_pkt.c, and remains set until - * the client's Finished message is read. - */ - if (!s->s3->change_cipher_spec) - s->s3->flags |= SSL3_FLAGS_CCS_OK; ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; if (s->hit) s->state = SSL_ST_OK; -#ifndef OPENSSL_NO_TLSEXT else if (s->tlsext_ticket_expected) s->state = SSL3_ST_SW_SESSION_TICKET_A; -#endif else s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; -#ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret = ssl3_send_newsession_ticket(s); @@ -757,8 +709,6 @@ int ssl3_accept(SSL *s) s->init_num = 0; break; -#endif - case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: @@ -801,14 +751,7 @@ int ssl3_accept(SSL *s) goto end; s->state = SSL3_ST_SW_FLUSH; if (s->hit) { -#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) - s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A; -#else - if (s->s3->next_proto_neg_seen) { - s->s3->tmp.next_state = SSL3_ST_SR_NEXT_PROTO_A; - } else - s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A; -#endif + s->s3->tmp.next_state = SSL3_ST_SR_CHANGE_A; } else s->s3->tmp.next_state = SSL_ST_OK; s->init_num = 0; @@ -894,17 +837,17 @@ int ssl3_send_hello_request(SSL *s) int ssl3_get_client_hello(SSL *s) { - int i, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; - unsigned int cookie_len; + int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; + unsigned int j, complen = 0; long n; unsigned long id; - unsigned char *p, *d; SSL_CIPHER *c; #ifndef OPENSSL_NO_COMP - unsigned char *q; SSL_COMP *comp = NULL; #endif STACK_OF(SSL_CIPHER) *ciphers = NULL; + int protverr = 1; + PACKET pkt, cipher_suite, compression; if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) goto retry_cert; @@ -928,31 +871,129 @@ int ssl3_get_client_hello(SSL *s) if (!ok) return ((int)n); s->first_packet = 0; - d = p = (unsigned char *)s->init_msg; - - /* - * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte - * for session id length - */ - if (n < 2 + SSL3_RANDOM_SIZE + 1) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + if (!PACKET_buf_init(&pkt, s->init_msg, n)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; goto f_err; } - /* - * use version from inside client hello, not from record header (may - * differ: see RFC 2246, Appendix E, second paragraph) - */ - s->client_version = (((int)p[0]) << 8) | (int)p[1]; - p += 2; - - if (SSL_IS_DTLS(s) ? (s->client_version > s->version && - s->method->version != DTLS_ANY_VERSION) - : (s->client_version < s->version)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); - if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && - !s->enc_write_ctx && !s->write_hash) { + /* First lets get s->client_version set correctly */ + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + unsigned int version; + unsigned int mt; + /*- + * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 + * header is sent directly on the wire, not wrapped as a TLS + * record. Our record layer just processes the message length and passes + * the rest right through. Its format is: + * Byte Content + * 0-1 msg_length - decoded by the record layer + * 2 msg_type - s->init_msg points here + * 3-4 version + * 5-6 cipher_spec_length + * 7-8 session_id_length + * 9-10 challenge_length + * ... ... + */ + + if (!PACKET_get_1(&pkt, &mt) + || mt != SSL2_MT_CLIENT_HELLO) { + /* + * Should never happen. We should have tested this in the record + * layer in order to have determined that this is a SSLv2 record + * in the first place + */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!PACKET_get_net_2(&pkt, &version)) { + /* No protocol version supplied! */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + if (version == 0x0002) { + /* This is real SSLv2. We don't support it. */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + goto err; + } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) { + /* SSLv3/TLS */ + s->client_version = version; + } else { + /* No idea what protocol this is */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + } else { + /* + * use version from inside client hello, not from record header (may + * differ: see RFC 2246, Appendix E, second paragraph) + */ + if(!PACKET_get_net_2(&pkt, (unsigned int *)&s->client_version)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + } + + /* Do SSL/TLS version negotiation if applicable */ + if (!SSL_IS_DTLS(s)) { + if (s->version != TLS_ANY_VERSION) { + if (s->client_version >= s->version) { + protverr = 0; + } + } else if (s->client_version >= SSL3_VERSION) { + switch(s->client_version) { + default: + case TLS1_2_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1_2)) { + s->version = TLS1_2_VERSION; + s->method = TLSv1_2_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case TLS1_1_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1_1)) { + s->version = TLS1_1_VERSION; + s->method = TLSv1_1_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case TLS1_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1)) { + s->version = TLS1_VERSION; + s->method = TLSv1_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case SSL3_VERSION: +#ifndef OPENSSL_NO_SSL3 + if(!(s->options & SSL_OP_NO_SSLv3)) { + s->version = SSL3_VERSION; + s->method = SSLv3_server_method(); + protverr = 0; + break; + } +#else + break; +#endif + } + } + } else if (s->client_version <= s->version + || s->method->version == DTLS_ANY_VERSION) { + /* + * For DTLS we just check versions are potentially compatible. Version + * negotiation comes later. + */ + protverr = 0; + } + + if (protverr) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + if ((!s->enc_write_ctx && !s->write_hash)) { /* * similar to ssl3_get_record, send alert using remote version * number @@ -963,267 +1004,325 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } - /* - * If we require cookies and this ClientHello doesn't contain one, just - * return since we do not want to allocate any memory yet. So check - * cookie length... - */ - if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - unsigned int session_length, cookie_length; - - session_length = *(p + SSL3_RANDOM_SIZE); + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Handle an SSLv2 backwards compatible ClientHello + * Note, this is only for SSLv3+ using the backward compatible format. + * Real SSLv2 is not supported, and is rejected above. + */ + unsigned int cipher_len, session_id_len, challenge_len; - if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + if (!PACKET_get_net_2(&pkt, &cipher_len) + || !PACKET_get_net_2(&pkt, &session_id_len) + || !PACKET_get_net_2(&pkt, &challenge_len)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } - cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1); - - if (cookie_length == 0) - return 1; - } - - /* load the client random */ - memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - /* get the session-id */ - j = *(p++); + if (cipher_len == 0) { + /* we need at least one cipher */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } - if (p + j > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } + if (!PACKET_get_sub_packet(&pkt, &cipher_suite, cipher_len)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } - s->hit = 0; - /* - * Versions before 0.9.7 always allow clients to resume sessions in - * renegotiation. 0.9.7 and later allow this by default, but optionally - * ignore resumption requests with flag - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather - * than a change to default behavior so that applications relying on this - * for security won't even compile against older library versions). - * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to - * request renegotiation but not a new session (s->new_session remains - * unset): for servers, this essentially just means that the - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be ignored. - */ - if ((s->new_session - && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { - if (!ssl_get_new_session(s, 1)) + if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite), + cipher_len, &(ciphers), 1) == NULL) { goto err; - } else { - i = ssl_get_prev_session(s, p, j, d + n); + } + /* - * Only resume if the session's version matches the negotiated - * version. - * RFC 5246 does not provide much useful advice on resumption - * with a different protocol version. It doesn't forbid it but - * the sanity of such behaviour would be questionable. - * In practice, clients do not accept a version mismatch and - * will abort the handshake with an error. + * Ignore any session id. We don't allow resumption in a backwards + * compatible ClientHello */ - if (i == 1 && s->version == s->session->ssl_version) { /* previous - * session */ - s->hit = 1; - } else if (i == -1) - goto err; - else { /* i == 0 */ - - if (!ssl_get_new_session(s, 1)) - goto err; + if (!PACKET_forward(&pkt, session_id_len)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); + al = SSL_AD_DECODE_ERROR; + goto f_err; } - } + s->hit = 0; - p += j; + if (!ssl_get_new_session(s, 1)) + goto err; - if (SSL_IS_DTLS(s)) { - /* cookie stuff */ - if (p + 1 > d + n) { + /* Load the client random */ + i = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE : challenge_len; + memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE); + if (!PACKET_peek_copy_bytes(&pkt, + s->s3->client_random + SSL3_RANDOM_SIZE - i, + i) + || !PACKET_forward(&pkt, challenge_len) + || PACKET_remaining(&pkt) != 0) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } - cookie_len = *(p++); - - if (p + cookie_len > d + n) { + } else { + /* If we get here we've got SSLv3+ in an SSLv3+ record */ + PACKET session_id; + unsigned int cookie_len; + /* load the client random and get the session-id */ + if (!PACKET_copy_bytes(&pkt, s->s3->client_random, SSL3_RANDOM_SIZE) + || !PACKET_get_length_prefixed_1(&pkt, &session_id)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } /* - * The ClientHello may contain a cookie even if the - * HelloVerify message has not been sent--make sure that it - * does not cause an overflow. + * If we require cookies and this ClientHello doesn't contain one, just + * return since we do not want to allocate any memory yet. So check + * cookie length... */ - if (cookie_len > sizeof(s->d1->rcvd_cookie)) { - /* too much data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); - goto f_err; + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + + if (!PACKET_peek_1(&pkt, &cookie_len)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + + if (cookie_len == 0) + return 1; } - /* verify the cookie if appropriate option is set. */ - if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && cookie_len > 0) { - memcpy(s->d1->rcvd_cookie, p, cookie_len); + s->hit = 0; + /* + * Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather + * than a change to default behavior so that applications relying on + * this for security won't even compile against older library versions). + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be + * ignored. + */ + if ((s->new_session + && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { + if (!ssl_get_new_session(s, 1)) + goto err; + } else { + /* + * TODO(openssl-team): ssl_get_prev_session passes a non-const + * 'unsigned char*' session id to a user callback. Grab a copy of + * the data? + */ + i = ssl_get_prev_session(s, &pkt, PACKET_data(&session_id), + PACKET_remaining(&session_id)); + /* + * Only resume if the session's version matches the negotiated + * version. + * RFC 5246 does not provide much useful advice on resumption + * with a different protocol version. It doesn't forbid it but + * the sanity of such behaviour would be questionable. + * In practice, clients do not accept a version mismatch and + * will abort the handshake with an error. + */ + if (i == 1 && s->version == s->session->ssl_version) { + /* previous session */ + s->hit = 1; + } else if (i == -1) + goto err; + else { + /* i == 0 */ + if (!ssl_get_new_session(s, 1)) + goto err; + } + } - if (s->ctx->app_verify_cookie_cb != NULL) { - if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, - cookie_len) == 0) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* else cookie verification succeeded */ + if (SSL_IS_DTLS(s)) { + PACKET cookie; + if (!PACKET_get_length_prefixed_1(&pkt, &cookie)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; } - /* default verification */ - else if (memcmp(s->d1->rcvd_cookie, s->d1->cookie, - s->d1->cookie_len) != 0) { - al = SSL_AD_HANDSHAKE_FAILURE; + cookie_len = PACKET_remaining(&cookie); + /* + * The ClientHello may contain a cookie even if the + * HelloVerify message has not been sent--make sure that it + * does not cause an overflow. + */ + if (cookie_len > sizeof(s->d1->rcvd_cookie)) { + /* too much data */ + al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); goto f_err; } - /* Set to -2 so if successful we return 2 */ - ret = -2; - } - p += cookie_len; - if (s->method->version == DTLS_ANY_VERSION) { - /* Select version to use */ - if (s->client_version <= DTLS1_2_VERSION && - !(s->options & SSL_OP_NO_DTLSv1_2)) { - s->version = DTLS1_2_VERSION; - s->method = DTLSv1_2_server_method(); - } else if (tls1_suiteb(s)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } else if (s->client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { - s->version = DTLS1_VERSION; - s->method = DTLSv1_server_method(); - } else { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_WRONG_VERSION_NUMBER); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; + /* verify the cookie if appropriate option is set. */ + if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) + && cookie_len > 0) { + /* Get cookie */ + /* + * TODO(openssl-team): rcvd_cookie appears unused outside this + * function. Remove the field? + */ + if (!PACKET_copy_bytes(&cookie, s->d1->rcvd_cookie, cookie_len)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto f_err; + } + + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, + cookie_len) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* else cookie verification succeeded */ + } + /* default verification */ + else if (memcmp(s->d1->rcvd_cookie, s->d1->cookie, + s->d1->cookie_len) != 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* Set to -2 so if successful we return 2 */ + ret = -2; + } + if (s->method->version == DTLS_ANY_VERSION) { + /* Select version to use */ + if (s->client_version <= DTLS1_2_VERSION && + !(s->options & SSL_OP_NO_DTLSv1_2)) { + s->version = DTLS1_2_VERSION; + s->method = DTLSv1_2_server_method(); + } else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } else if (s->client_version <= DTLS1_VERSION && + !(s->options & SSL_OP_NO_DTLSv1)) { + s->version = DTLS1_VERSION; + s->method = DTLSv1_server_method(); + } else { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_WRONG_VERSION_NUMBER); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version; } - s->session->ssl_version = s->version; } - } - if (p + 2 > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - n2s(p, i); + if (!PACKET_get_length_prefixed_2(&pkt, &cipher_suite)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } - if (i == 0) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); - goto f_err; - } + if (PACKET_remaining(&cipher_suite) == 0) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } - /* i bytes of cipher data + 1 byte for compression length later */ - if ((p + i + 1) > (d + n)) { - /* not enough data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) == NULL) { - goto err; - } - p += i; + if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite), + PACKET_remaining(&cipher_suite), + &(ciphers), 0) == NULL) { + goto err; + } - /* If it is a hit, check that the cipher is in the list */ - if (s->hit) { - j = 0; - id = s->session->cipher->id; + /* If it is a hit, check that the cipher is in the list */ + if (s->hit) { + j = 0; + id = s->session->cipher->id; #ifdef CIPHER_DEBUG - fprintf(stderr, "client sent %d ciphers\n", - sk_SSL_CIPHER_num(ciphers)); + fprintf(stderr, "client sent %d ciphers\n", + sk_SSL_CIPHER_num(ciphers)); #endif - for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { - c = sk_SSL_CIPHER_value(ciphers, i); + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + c = sk_SSL_CIPHER_value(ciphers, i); #ifdef CIPHER_DEBUG - fprintf(stderr, "client [%2d of %2d]:%s\n", - i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); + fprintf(stderr, "client [%2d of %2d]:%s\n", + i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); #endif - if (c->id == id) { - j = 1; - break; + if (c->id == id) { + j = 1; + break; + } } - } - /* - * Disabled because it can be used in a ciphersuite downgrade attack: - * CVE-2010-4180. - */ -#if 0 - if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) - && (sk_SSL_CIPHER_num(ciphers) == 1)) { /* - * Special case as client bug workaround: the previously used - * cipher may not be in the current list, the client instead - * might be trying to continue using a cipher that before wasn't - * chosen due to server preferences. We'll have to reject the - * connection if the cipher is not enabled, though. + * Disabled because it can be used in a ciphersuite downgrade + * attack: + * CVE-2010-4180. */ - c = sk_SSL_CIPHER_value(ciphers, 0); - if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0) { - s->session->cipher = c; - j = 1; +#if 0 + if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) + && (sk_SSL_CIPHER_num(ciphers) == 1)) { + /* + * Special case as client bug workaround: the previously used + * cipher may not be in the current list, the client instead + * might be trying to continue using a cipher that before wasn't + * chosen due to server preferences. We'll have to reject the + * connection if the cipher is not enabled, though. + */ + c = sk_SSL_CIPHER_value(ciphers, 0); + if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0) { + s->session->cipher = c; + j = 1; + } } - } #endif - if (j == 0) { + if (j == 0) { + /* + * we need to have the cipher in the cipher list if we are asked + * to reuse it + */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } + + /* compression */ + if (!PACKET_get_length_prefixed_1(&pkt, &compression)) { + /* not enough data */ + al = SSL_AD_DECODE_ERROR; /* - * we need to have the cipher in the cipher list if we are asked - * to reuse it + * TODO(openssl-team): + * SSL_R_LENGTH_TOO_SHORT and SSL_R_LENGTH_MISMATCH are used + * interchangeably. Pick one. */ - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_REQUIRED_CIPHER_MISSING); + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); goto f_err; } - } - /* compression */ - i = *(p++); - if ((p + i) > (d + n)) { - /* not enough data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } -#ifndef OPENSSL_NO_COMP - q = p; -#endif - for (j = 0; j < i; j++) { - if (p[j] == 0) - break; - } + complen = PACKET_remaining(&compression); + for (j = 0; j < complen; j++) { + if (PACKET_data(&compression)[j] == 0) + break; + } - p += i; - if (j >= i) { - /* no compress */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); - goto f_err; + if (j >= complen) { + /* no compress */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); + goto f_err; + } } -#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions */ if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s, &p, d, n)) { + if (!ssl_parse_clienthello_tlsext(s, &pkt)) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT); goto err; } @@ -1277,11 +1376,10 @@ int ssl3_get_client_hello(SSL *s) s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); } } -#endif /* * Worst case, we will use the NULL compression, but if we have other - * options, we will now look for them. We have i-1 compression + * options, we will now look for them. We have complen-1 compression * algorithms from the client, starting at q. */ s->s3->tmp.new_compression = NULL; @@ -1289,6 +1387,7 @@ int ssl3_get_client_hello(SSL *s) /* This only happens if we have a cache hit */ if (s->session->compress_meth != 0) { int m, comp_id = s->session->compress_meth; + unsigned int k; /* Perform sanity checks on resumed compression algorithm */ /* Can't disable compression */ if (!ssl_allow_compression(s)) { @@ -1310,11 +1409,11 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } /* Look for resumed method in compression list */ - for (m = 0; m < i; m++) { - if (q[m] == comp_id) + for (k = 0; k < complen; k++) { + if (PACKET_data(&compression)[k] == comp_id) break; } - if (m >= i) { + if (k >= complen) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING); @@ -1324,14 +1423,15 @@ int ssl3_get_client_hello(SSL *s) comp = NULL; else if (ssl_allow_compression(s) && s->ctx->comp_methods) { /* See if we have a match */ - int m, nn, o, v, done = 0; + int m, nn, v, done = 0; + unsigned int o; nn = sk_SSL_COMP_num(s->ctx->comp_methods); for (m = 0; m < nn; m++) { comp = sk_SSL_COMP_value(s->ctx->comp_methods, m); v = comp->id; - for (o = 0; o < i; o++) { - if (v == q[o]) { + for (o = 0; o < complen; o++) { + if (v == PACKET_data(&compression)[o]) { done = 1; break; } @@ -1414,7 +1514,7 @@ int ssl3_get_client_hello(SSL *s) } if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) { - if (!ssl3_digest_cached_records(s)) + if (!ssl3_digest_cached_records(s, 0)) goto f_err; } @@ -1461,20 +1561,17 @@ int ssl3_send_server_hello(SSL *s) if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { buf = (unsigned char *)s->init_buf->data; -#ifdef OPENSSL_NO_TLSEXT - p = s->s3->server_random; - if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0) { - s->state = SSL_ST_ERR; - return -1; - } -#endif + /* Do the message type and length last */ d = p = ssl_handshake_start(s); *(p++) = s->version >> 8; *(p++) = s->version & 0xff; - /* Random stuff */ + /* + * Random stuff. Filling of the server_random takes place in + * ssl3_get_client_hello() + */ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); p += SSL3_RANDOM_SIZE; @@ -1522,7 +1619,7 @@ int ssl3_send_server_hello(SSL *s) else *(p++) = s->s3->tmp.new_compression->id; #endif -#ifndef OPENSSL_NO_TLSEXT + if (ssl_prepare_serverhello_tlsext(s) <= 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT); s->state = SSL_ST_ERR; @@ -1536,7 +1633,7 @@ int ssl3_send_server_hello(SSL *s) s->state = SSL_ST_ERR; return -1; } -#endif + /* do the header */ l = (p - d); if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) { @@ -1605,6 +1702,19 @@ int ssl3_send_server_key_exchange(SSL *s) r[0] = r[1] = r[2] = r[3] = NULL; n = 0; +#ifndef OPENSSL_NO_PSK + if (type & SSL_PSK) { + /* + * reserve size for record length and PSK identity hint + */ + n += 2; + if (s->ctx->psk_identity_hint) + n += strlen(s->ctx->psk_identity_hint); + } + /* Plain PSK or RSAPSK nothing to do */ + if (type & (SSL_kPSK | SSL_kRSAPSK)) { + } else +#endif /* !OPENSSL_NO_PSK */ #ifndef OPENSSL_NO_RSA if (type & SSL_kRSA) { rsa = cert->rsa_tmp; @@ -1635,7 +1745,7 @@ int ssl3_send_server_key_exchange(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (type & SSL_kDHE) { + if (type & (SSL_kDHE | SSL_kDHEPSK)) { if (s->cert->dh_tmp_auto) { dhp = ssl_get_auto_dh(s); if (dhp == NULL) { @@ -1700,7 +1810,7 @@ int ssl3_send_server_key_exchange(SSL *s) } else #endif #ifndef OPENSSL_NO_EC - if (type & SSL_kECDHE) { + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { const EC_GROUP *group; ecdhp = cert->ecdh_tmp; @@ -1816,7 +1926,7 @@ int ssl3_send_server_key_exchange(SSL *s) * additional bytes to encode the entire ServerECDHParams * structure. */ - n = 4 + encodedlen; + n += 4 + encodedlen; /* * We'll generate the serverKeyExchange message explicitly so we @@ -1828,14 +1938,6 @@ int ssl3_send_server_key_exchange(SSL *s) r[3] = NULL; } else #endif /* !OPENSSL_NO_EC */ -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { - /* - * reserve size for record length and PSK identity hint - */ - n += 2 + strlen(s->ctx->psk_identity_hint); - } else -#endif /* !OPENSSL_NO_PSK */ #ifndef OPENSSL_NO_SRP if (type & SSL_kSRP) { if ((s->srp_ctx.N == NULL) || @@ -1867,8 +1969,8 @@ int ssl3_send_server_key_exchange(SSL *s) n += 2 + nr[i]; } - if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) { if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md)) == NULL) { al = SSL_AD_DECODE_ERROR; @@ -1886,6 +1988,20 @@ int ssl3_send_server_key_exchange(SSL *s) } d = p = ssl_handshake_start(s); +#ifndef OPENSSL_NO_PSK + if (type & SSL_PSK) { + /* copy PSK identity hint */ + if (s->ctx->psk_identity_hint) { + s2n(strlen(s->ctx->psk_identity_hint), p); + strncpy((char *)p, s->ctx->psk_identity_hint, + strlen(s->ctx->psk_identity_hint)); + p += strlen(s->ctx->psk_identity_hint); + } else { + s2n(0, p); + } + } +#endif + for (i = 0; i < 4 && r[i] != NULL; i++) { #ifndef OPENSSL_NO_SRP if ((i == 2) && (type & SSL_kSRP)) { @@ -1899,7 +2015,7 @@ int ssl3_send_server_key_exchange(SSL *s) } #ifndef OPENSSL_NO_EC - if (type & SSL_kECDHE) { + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { /* * XXX: For now, we only support named (not generic) curves. In * this situation, the serverKeyExchange message has: [1 byte @@ -1921,16 +2037,6 @@ int ssl3_send_server_key_exchange(SSL *s) } #endif -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { - /* copy PSK identity hint */ - s2n(strlen(s->ctx->psk_identity_hint), p); - strncpy((char *)p, s->ctx->psk_identity_hint, - strlen(s->ctx->psk_identity_hint)); - p += strlen(s->ctx->psk_identity_hint); - } -#endif - /* not anonymous */ if (pkey != NULL) { /* @@ -2102,10 +2208,10 @@ int ssl3_send_certificate_request(SSL *s) int ssl3_get_client_key_exchange(SSL *s) { - int i, al, ok; + unsigned int i; + int al, ok; long n; unsigned long alg_k; - unsigned char *p; #ifndef OPENSSL_NO_RSA RSA *rsa = NULL; EVP_PKEY *pkey = NULL; @@ -2114,13 +2220,15 @@ int ssl3_get_client_key_exchange(SSL *s) BIGNUM *pub = NULL; DH *dh_srvr, *dh_clnt = NULL; #endif - #ifndef OPENSSL_NO_EC EC_KEY *srvr_ecdh = NULL; EVP_PKEY *clnt_pub_pkey = NULL; EC_POINT *clnt_ecpoint = NULL; BN_CTX *bn_ctx = NULL; #endif + PACKET pkt; + unsigned char *data; + size_t remain; n = s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, @@ -2129,12 +2237,100 @@ int ssl3_get_client_key_exchange(SSL *s) if (!ok) return ((int)n); - p = (unsigned char *)s->init_msg; + if (!PACKET_buf_init(&pkt, s->init_msg, n)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +#ifndef OPENSSL_NO_PSK + /* For PSK parse and retrieve identity, obtain PSK key */ + if (alg_k & SSL_PSK) { + unsigned char psk[PSK_MAX_PSK_LEN]; + size_t psklen; + + if (!PACKET_get_net_2(&pkt, &i)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if (i > PSK_MAX_IDENTITY_LEN) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } + if (s->psk_server_callback == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_NO_SERVER_CB); + goto f_err; + } + + OPENSSL_free(s->session->psk_identity); + s->session->psk_identity = OPENSSL_malloc(i + 1); + if (s->session->psk_identity == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto f_err; + } + if (!PACKET_copy_bytes(&pkt, (unsigned char *)s->session->psk_identity, + i)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + s->session->psk_identity[i] = '\0'; + + psklen = s->psk_server_callback(s, s->session->psk_identity, + psk, sizeof(psk)); + + if (psklen > PSK_MAX_PSK_LEN) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } else if (psklen == 0) { + /* + * PSK related to the given identity not found + */ + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + al = SSL_AD_UNKNOWN_PSK_IDENTITY; + goto f_err; + } + + OPENSSL_free(s->s3->tmp.psk); + s->s3->tmp.psk = BUF_memdup(psk, psklen); + OPENSSL_cleanse(psk, psklen); + + if (s->s3->tmp.psk == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto f_err; + } + + s->s3->tmp.psklen = psklen; + } + if (alg_k & SSL_kPSK) { + /* Identity extracted earlier: should be nothing left */ + if (PACKET_remaining(&pkt) != 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + /* PSK handled by ssl_generate_master_secret */ + if (!ssl_generate_master_secret(s, NULL, 0, 0)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } + } else +#endif #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) { + if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) { unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; int decrypt_len; unsigned char decrypt_good, version_good; @@ -2168,17 +2364,34 @@ int ssl3_get_client_key_exchange(SSL *s) /* TLS and [incidentally] DTLS{0xFEFF} */ if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER) { - n2s(p, i); - if (n != i + 2) { + if (!PACKET_get_net_2(&pkt, &i)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + remain = PACKET_remaining(&pkt); + if (remain != i) { if (!(s->options & SSL_OP_TLS_D5_BUG)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); goto f_err; - } else - p -= 2; - } else - n = i; + } else { + remain += 2; + if (!PACKET_back(&pkt, 2)) { + /* + * We already read these 2 bytes so this should never + * fail + */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + } + } else { + remain = PACKET_remaining(&pkt); } /* @@ -2188,13 +2401,20 @@ int ssl3_get_client_key_exchange(SSL *s) * actual expected size is larger due to RSA padding, but the * bound is sufficient to be safe. */ - if (n < SSL_MAX_MASTER_KEY_LENGTH) { + + if (remain < SSL_MAX_MASTER_KEY_LENGTH) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); goto f_err; } + if (!PACKET_get_bytes(&pkt, &data, remain)) { + /* We already checked we had enough data so this shouldn't happen */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } /* * We must not leak whether a decryption failure occurs because of * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, @@ -2207,7 +2427,7 @@ int ssl3_get_client_key_exchange(SSL *s) sizeof(rand_premaster_secret)) <= 0) goto err; decrypt_len = - RSA_private_decrypt((int)n, p, p, rsa, RSA_PKCS1_PADDING); + RSA_private_decrypt(remain, data, data, rsa, RSA_PKCS1_PADDING); ERR_clear_error(); /* @@ -2226,9 +2446,9 @@ int ssl3_get_client_key_exchange(SSL *s) * constant time and are treated like any other decryption error. */ version_good = - constant_time_eq_8(p[0], (unsigned)(s->client_version >> 8)); + constant_time_eq_8(data[0], (unsigned)(s->client_version >> 8)); version_good &= - constant_time_eq_8(p[1], (unsigned)(s->client_version & 0xff)); + constant_time_eq_8(data[1], (unsigned)(s->client_version & 0xff)); /* * The premaster secret must contain the same version number as the @@ -2242,9 +2462,9 @@ int ssl3_get_client_key_exchange(SSL *s) if (s->options & SSL_OP_TLS_ROLLBACK_BUG) { unsigned char workaround_good; workaround_good = - constant_time_eq_8(p[0], (unsigned)(s->version >> 8)); + constant_time_eq_8(data[0], (unsigned)(s->version >> 8)); workaround_good &= - constant_time_eq_8(p[1], (unsigned)(s->version & 0xff)); + constant_time_eq_8(data[1], (unsigned)(s->version & 0xff)); version_good |= workaround_good; } @@ -2261,19 +2481,12 @@ int ssl3_get_client_key_exchange(SSL *s) * it is still sufficiently large to read from. */ for (j = 0; j < sizeof(rand_premaster_secret); j++) { - p[j] = constant_time_select_8(decrypt_good, p[j], + data[j] = constant_time_select_8(decrypt_good, data[j], rand_premaster_secret[j]); } - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, - sizeof - (rand_premaster_secret)); - OPENSSL_cleanse(p, sizeof(rand_premaster_secret)); - if (s->session->master_key_length < 0) { + if (!ssl_generate_master_secret(s, data, sizeof(rand_premaster_secret), + 0)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; @@ -2281,13 +2494,19 @@ int ssl3_get_client_key_exchange(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { + if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) { int idx = -1; EVP_PKEY *skey = NULL; - if (n > 1) { - n2s(p, i); - } else { - if (alg_k & SSL_kDHE) { + size_t bookm; + unsigned char shared[(OPENSSL_DH_MAX_MODULUS_BITS + 7) / 8]; + + if (!PACKET_get_bookmark(&pkt, &bookm)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } + if (!PACKET_get_net_2(&pkt, &i)) { + if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); @@ -2295,14 +2514,19 @@ int ssl3_get_client_key_exchange(SSL *s) } i = 0; } - if (n && n != i + 2) { + if (PACKET_remaining(&pkt) != i) { if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); goto err; } else { - p -= 2; - i = (int)n; + if (!PACKET_goto_bookmark(&pkt, bookm)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + i = PACKET_remaining(&pkt); } } if (alg_k & SSL_kDHr) @@ -2342,14 +2566,22 @@ int ssl3_get_client_key_exchange(SSL *s) } EVP_PKEY_free(clkey); pub = dh_clnt->pub_key; - } else - pub = BN_bin2bn(p, i, NULL); + } else { + if (!PACKET_get_bytes(&pkt, &data, i)) { + /* We already checked we have enough data */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + pub = BN_bin2bn(data, i, NULL); + } if (pub == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_BN_LIB); goto err; } - i = DH_compute_key(p, pub, dh_srvr); + i = DH_compute_key(shared, pub, dh_srvr); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); @@ -2364,13 +2596,7 @@ int ssl3_get_client_key_exchange(SSL *s) else BN_clear_free(pub); pub = NULL; - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, i); - OPENSSL_cleanse(p, i); - if (s->session->master_key_length < 0) { + if (!ssl_generate_master_secret(s, shared, i, 0)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; @@ -2381,12 +2607,13 @@ int ssl3_get_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_EC - if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) { + if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) { int ret = 1; int field_size = 0; const EC_KEY *tkey; const EC_GROUP *group; const BIGNUM *priv_key; + unsigned char *shared; /* initialize structures for server's ECDH key pair */ if ((srvr_ecdh = EC_KEY_new()) == NULL) { @@ -2424,7 +2651,7 @@ int ssl3_get_client_key_exchange(SSL *s) if (n == 0L) { /* Client Publickey was in Client Certificate */ - if (alg_k & SSL_kECDHE) { + if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_TMP_ECDH_KEY); @@ -2465,21 +2692,21 @@ int ssl3_get_client_key_exchange(SSL *s) } /* Get encoded point length */ - i = *p; - p += 1; - if (n != 1 + i) { + if (!PACKET_get_1(&pkt, &i)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if (!PACKET_get_bytes(&pkt, &data, i) + || PACKET_remaining(&pkt) != 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } - if (EC_POINT_oct2point(group, clnt_ecpoint, p, i, bn_ctx) == 0) { + if (EC_POINT_oct2point(group, clnt_ecpoint, data, i, bn_ctx) == 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } - /* - * p is pointing to somewhere in the buffer currently, so set it - * to the start - */ - p = (unsigned char *)s->init_buf->data; } /* Compute the shared pre-master secret */ @@ -2488,10 +2715,16 @@ int ssl3_get_client_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - i = ECDH_compute_key(p, (field_size + 7) / 8, clnt_ecpoint, srvr_ecdh, - NULL); + shared = OPENSSL_malloc((field_size + 7) / 8); + if (shared == NULL) { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + i = ECDH_compute_key(shared, (field_size + 7) / 8, clnt_ecpoint, + srvr_ecdh, NULL); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); + OPENSSL_free(shared); goto err; } @@ -2502,15 +2735,7 @@ int ssl3_get_client_key_exchange(SSL *s) EC_KEY_free(s->s3->tmp.ecdh); s->s3->tmp.ecdh = NULL; - /* Compute the master secret */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, i); - - OPENSSL_cleanse(p, i); - if (s->session->master_key_length < 0) { + if (!ssl_generate_master_secret(s, shared, i, 1)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; @@ -2518,110 +2743,15 @@ int ssl3_get_client_key_exchange(SSL *s) return (ret); } else #endif -#ifndef OPENSSL_NO_PSK - if (alg_k & SSL_kPSK) { - unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4]; - unsigned int pre_ms_len = 0, psk_len = 0; - int psk_err = 1; - char tmp_id[PSK_MAX_IDENTITY_LEN + 1]; - - al = SSL_AD_HANDSHAKE_FAILURE; - - n2s(p, i); - if (n != i + 2) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH); - goto psk_err; - } - if (i > PSK_MAX_IDENTITY_LEN) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_DATA_LENGTH_TOO_LONG); - goto psk_err; - } - if (s->psk_server_callback == NULL) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_NO_SERVER_CB); - goto psk_err; - } - - /* - * Create guaranteed NULL-terminated identity string for the callback - */ - memcpy(tmp_id, p, i); - memset(tmp_id + i, 0, PSK_MAX_IDENTITY_LEN + 1 - i); - psk_len = s->psk_server_callback(s, tmp_id, - psk_or_pre_ms, - sizeof(psk_or_pre_ms)); - OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN + 1); - - if (psk_len > PSK_MAX_PSK_LEN) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); - goto psk_err; - } else if (psk_len == 0) { - /* - * PSK related to the given identity not found - */ - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_IDENTITY_NOT_FOUND); - al = SSL_AD_UNKNOWN_PSK_IDENTITY; - 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); - s2n(psk_len, t); - memset(t, 0, psk_len); - t += psk_len; - s2n(psk_len, t); - - OPENSSL_free(s->session->psk_identity); - s->session->psk_identity = BUF_strdup((char *)p); - if (s->session->psk_identity == NULL) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL && - s->session->psk_identity_hint == NULL) { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - 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); - if (s->session->master_key_length < 0) { - al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); - goto psk_err; - } - psk_err = 0; - psk_err: - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_err != 0) - goto f_err; - } else -#endif #ifndef OPENSSL_NO_SRP if (alg_k & SSL_kSRP) { - int param_len; - - n2s(p, i); - param_len = i + 2; - if (param_len > n) { + if (!PACKET_get_net_2(&pkt, &i) + || !PACKET_get_bytes(&pkt, &data, i)) { al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_BAD_SRP_A_LENGTH); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_BAD_SRP_A_LENGTH); goto f_err; } - if ((s->srp_ctx.A = BN_bin2bn(p, i, NULL)) == NULL) { + if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -2639,14 +2769,10 @@ int ssl3_get_client_key_exchange(SSL *s) goto err; } - if ((s->session->master_key_length = - SRP_generate_server_master_secret(s, - s->session->master_key)) < 0) { + if (!srp_generate_server_master_secret(s)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - - p += i; } else #endif /* OPENSSL_NO_SRP */ if (alg_k & SSL_kGOST) { @@ -2661,9 +2787,7 @@ int ssl3_get_client_key_exchange(SSL *s) /* Get our certificate private key */ alg_a = s->s3->tmp.new_cipher->algorithm_auth; - if (alg_a & SSL_aGOST94) - pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey; - else if (alg_a & SSL_aGOST01) + if (alg_a & SSL_aGOST01) pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; pkey_ctx = EVP_PKEY_CTX_new(pk, NULL); @@ -2680,15 +2804,20 @@ int ssl3_get_client_key_exchange(SSL *s) ERR_clear_error(); } /* Decrypt session key */ + if (!PACKET_get_bytes(&pkt, &data, n)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto f_err; + } if (ASN1_get_object - ((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, + ((const unsigned char **)&data, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED || Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); goto gerr; } - start = p; + start = data; inlen = Tlen; if (EVP_PKEY_decrypt (pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) { @@ -2697,12 +2826,8 @@ int ssl3_get_client_key_exchange(SSL *s) goto gerr; } /* Generate master secret */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - premaster_secret, 32); - if (s->session->master_key_length < 0) { + if (!ssl_generate_master_secret(s, premaster_secret, + sizeof(premaster_secret), 0)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; @@ -2736,6 +2861,10 @@ int ssl3_get_client_key_exchange(SSL *s) EC_POINT_free(clnt_ecpoint); EC_KEY_free(srvr_ecdh); BN_CTX_free(bn_ctx); +#endif +#ifndef OPENSSL_NO_PSK + OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen); + s->s3->tmp.psk = NULL; #endif s->state = SSL_ST_ERR; return (-1); @@ -2744,13 +2873,15 @@ int ssl3_get_client_key_exchange(SSL *s) int ssl3_get_cert_verify(SSL *s) { EVP_PKEY *pkey = NULL; - unsigned char *p; + unsigned char *sig, *data; int al, ok, ret = 0; long n; int type = 0, i, j; + unsigned int len; X509 *peer; const EVP_MD *md = NULL; EVP_MD_CTX mctx; + PACKET pkt; EVP_MD_CTX_init(&mctx); /* @@ -2787,18 +2918,27 @@ int ssl3_get_cert_verify(SSL *s) } /* we now have a signature that we need to verify */ - p = (unsigned char *)s->init_msg; + if (!PACKET_buf_init(&pkt, s->init_msg, n)) { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } /* Check for broken implementations of GOST ciphersuites */ /* * If key is GOST and n is exactly 64, it is bare signature without * length field */ - if (n == 64 && (pkey->type == NID_id_GostR3410_94 || - pkey->type == NID_id_GostR3410_2001)) { - i = 64; + if (n == 64 && pkey->type == NID_id_GostR3410_2001) { + len = 64; } else { if (SSL_USE_SIGALGS(s)) { - int rv = tls12_check_peer_sigalg(&md, s, p, pkey); + int rv; + + if (!PACKET_get_bytes(&pkt, &sig, 2)) { + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + rv = tls12_check_peer_sigalg(&md, s, sig, pkey); if (rv == -1) { al = SSL_AD_INTERNAL_ERROR; goto f_err; @@ -2809,23 +2949,24 @@ int ssl3_get_cert_verify(SSL *s) #ifdef SSL_DEBUG fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); #endif - p += 2; - n -= 2; } - n2s(p, i); - n -= 2; - if (i > n) { + if (!PACKET_get_net_2(&pkt, &len)) { SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_LENGTH_MISMATCH); al = SSL_AD_DECODE_ERROR; goto f_err; } } j = EVP_PKEY_size(pkey); - if ((i > j) || (n > j) || (n <= 0)) { + if (((int)len > j) || ((int)PACKET_remaining(&pkt) > j) || (n <= 0)) { SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE); al = SSL_AD_DECODE_ERROR; goto f_err; } + if (!PACKET_get_bytes(&pkt, &data, len)) { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_LENGTH_MISMATCH); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; @@ -2847,7 +2988,7 @@ int ssl3_get_cert_verify(SSL *s) goto f_err; } - if (EVP_VerifyFinal(&mctx, p, i, pkey) <= 0) { + if (EVP_VerifyFinal(&mctx, data, len, pkey) <= 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_BAD_SIGNATURE); goto f_err; @@ -2856,7 +2997,7 @@ int ssl3_get_cert_verify(SSL *s) #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { i = RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md, - MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, p, i, + MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, data, len, pkey->pkey.rsa); if (i < 0) { al = SSL_AD_DECRYPT_ERROR; @@ -2874,7 +3015,7 @@ int ssl3_get_cert_verify(SSL *s) if (pkey->type == EVP_PKEY_DSA) { j = DSA_verify(pkey->save_type, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH, p, i, pkey->pkey.dsa); + SHA_DIGEST_LENGTH, data, len, pkey->pkey.dsa); if (j <= 0) { /* bad signature */ al = SSL_AD_DECRYPT_ERROR; @@ -2887,7 +3028,7 @@ int ssl3_get_cert_verify(SSL *s) if (pkey->type == EVP_PKEY_EC) { j = ECDSA_verify(pkey->save_type, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH, p, i, pkey->pkey.ec); + SHA_DIGEST_LENGTH, data, len, pkey->pkey.ec); if (j <= 0) { /* bad signature */ al = SSL_AD_DECRYPT_ERROR; @@ -2896,17 +3037,16 @@ int ssl3_get_cert_verify(SSL *s) } } else #endif - if (pkey->type == NID_id_GostR3410_94 - || pkey->type == NID_id_GostR3410_2001) { + if (pkey->type == NID_id_GostR3410_2001) { unsigned char signature[64]; int idx; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL); EVP_PKEY_verify_init(pctx); - if (i != 64) { - fprintf(stderr, "GOST signature length is %d", i); + if (len != 64) { + fprintf(stderr, "GOST signature length is %d", len); } for (idx = 0; idx < 64; idx++) { - signature[63 - idx] = p[idx]; + signature[63 - idx] = data[idx]; } j = EVP_PKEY_verify(pctx, signature, 64, s->s3->tmp.cert_verify_md, 32); @@ -2931,7 +3071,6 @@ int ssl3_get_cert_verify(SSL *s) end: BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; - s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE; EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_free(pkey); return (ret); @@ -2941,10 +3080,11 @@ int ssl3_get_client_certificate(SSL *s) { int i, ok, al, ret = -1; X509 *x = NULL; - unsigned long l, nc, llen, n; - const unsigned char *p, *q; - unsigned char *d; + unsigned long l, llen, n; + const unsigned char *certstart; + unsigned char *certbytes; STACK_OF(X509) *sk = NULL; + PACKET pkt, spkt; n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, @@ -2980,35 +3120,42 @@ int ssl3_get_client_certificate(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, SSL_R_WRONG_MESSAGE_TYPE); goto f_err; } - p = d = (unsigned char *)s->init_msg; + + if (!PACKET_buf_init(&pkt, s->init_msg, n)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + goto f_err; + } if ((sk = sk_X509_new_null()) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE); goto done; } - n2l3(p, llen); - if (llen + 3 != n) { + if (!PACKET_get_net_3(&pkt, &llen) + || !PACKET_get_sub_packet(&pkt, &spkt, llen) + || PACKET_remaining(&pkt) != 0) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH); goto f_err; } - for (nc = 0; nc < llen;) { - n2l3(p, l); - if ((l + nc + 3) > llen) { + + while (PACKET_remaining(&spkt) > 0) { + if (!PACKET_get_net_3(&spkt, &l) + || !PACKET_get_bytes(&spkt, &certbytes, l)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } - q = p; - x = d2i_X509(NULL, &p, l); + certstart = certbytes; + x = d2i_X509(NULL, (const unsigned char **)&certbytes, l); if (x == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB); goto done; } - if (p != (q + l)) { + if (certbytes != (certstart + l)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, SSL_R_CERT_LENGTH_MISMATCH); @@ -3019,7 +3166,6 @@ int ssl3_get_client_certificate(SSL *s) goto done; } x = NULL; - nc += l + 3; } if (sk_X509_num(sk) <= 0) { @@ -3039,7 +3185,7 @@ int ssl3_get_client_certificate(SSL *s) goto f_err; } /* No client certificate so digest cached records */ - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s)) { + if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) { al = SSL_AD_INTERNAL_ERROR; goto f_err; } @@ -3071,19 +3217,8 @@ int ssl3_get_client_certificate(SSL *s) s->session->peer = sk_X509_shift(sk); s->session->verify_result = s->verify_result; - /* - * With the current implementation, sess_cert will always be NULL when we - * arrive here. - */ - if (s->session->sess_cert == NULL) { - s->session->sess_cert = ssl_sess_cert_new(); - if (s->session->sess_cert == NULL) { - SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE); - goto done; - } - } - sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); - s->session->sess_cert->cert_chain = sk; + sk_X509_pop_free(s->session->peer_chain, X509_free); + s->session->peer_chain = sk; /* * Inconsistency alert: cert_chain does *not* include the peer's own * certificate, while we do include it in s3_clnt.c @@ -3125,7 +3260,6 @@ int ssl3_send_server_certificate(SSL *s) return ssl_do_write(s); } -#ifndef OPENSSL_NO_TLSEXT /* send a new session ticket (not necessarily for a new session) */ int ssl3_send_newsession_ticket(SSL *s) { @@ -3313,7 +3447,7 @@ int ssl3_send_cert_status(SSL *s) return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); } -# ifndef OPENSSL_NO_NEXTPROTONEG +#ifndef OPENSSL_NO_NEXTPROTONEG /* * ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. * It sets the next_proto member in s if found @@ -3321,9 +3455,9 @@ int ssl3_send_cert_status(SSL *s) int ssl3_get_next_proto(SSL *s) { int ok; - int proto_len, padding_len; + unsigned int proto_len, padding_len; long n; - const unsigned char *p; + PACKET pkt; /* * Clients cannot send a NextProtocol message if we didn't see the @@ -3357,11 +3491,13 @@ int ssl3_get_next_proto(SSL *s) } if (n < 2) { - s->state = SSL_ST_ERR; - return 0; /* The body must be > 1 bytes long */ + goto err; /* The body must be > 1 bytes long */ } - p = (unsigned char *)s->init_msg; + if (!PACKET_buf_init(&pkt, s->init_msg, n)) { + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, ERR_R_INTERNAL_ERROR); + goto err; + } /*- * The payload looks like: @@ -3370,28 +3506,145 @@ int ssl3_get_next_proto(SSL *s) * uint8 padding_len; * uint8 padding[padding_len]; */ - proto_len = p[0]; - if (proto_len + 2 > s->init_num) { - s->state = SSL_ST_ERR; - return 0; - } - padding_len = p[proto_len + 1]; - if (proto_len + padding_len + 2 != s->init_num) { - s->state = SSL_ST_ERR; - return 0; + if (!PACKET_get_1(&pkt, &proto_len)){ + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_LENGTH_MISMATCH); + goto err; } s->next_proto_negotiated = OPENSSL_malloc(proto_len); - if (!s->next_proto_negotiated) { + if (s->next_proto_negotiated == NULL) { SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, ERR_R_MALLOC_FAILURE); - s->state = SSL_ST_ERR; - return 0; + goto err; + } + + if (!PACKET_copy_bytes(&pkt, s->next_proto_negotiated, proto_len) + || !PACKET_get_1(&pkt, &padding_len) + || PACKET_remaining(&pkt) != padding_len) { + OPENSSL_free(s->next_proto_negotiated); + s->next_proto_negotiated = NULL; + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_LENGTH_MISMATCH); + goto err; } - memcpy(s->next_proto_negotiated, p + 1, proto_len); - s->next_proto_negotiated_len = proto_len; return 1; +err: + s->state = SSL_ST_ERR; + return 0; } -# endif +#endif + +#define SSLV2_CIPHER_LEN 3 + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, + int num, + STACK_OF(SSL_CIPHER) **skp, + int sslv2format) +{ + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *sk; + int i, n; + + if (s->s3) + s->s3->send_connection_binding = 0; + + if(sslv2format) { + n = SSLV2_CIPHER_LEN; + } else { + n = ssl_put_cipher_by_char(s, NULL, NULL); + } + if (n == 0 || (num % n) != 0) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, + SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return (NULL); + } + if ((skp == NULL) || (*skp == NULL)) { + sk = sk_SSL_CIPHER_new_null(); /* change perhaps later */ + if(sk == NULL) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + sk = *skp; + sk_SSL_CIPHER_zero(sk); + } + OPENSSL_free(s->s3->tmp.ciphers_raw); + s->s3->tmp.ciphers_raw = BUF_memdup(p, num); + if (s->s3->tmp.ciphers_raw == NULL) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + s->s3->tmp.ciphers_rawlen = (size_t)num; + + for (i = 0; i < num; i += n) { + /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ + if (s->s3 && (n != 3 || !p[0]) && + (p[n - 2] == ((SSL3_CK_SCSV >> 8) & 0xff)) && + (p[n - 1] == (SSL3_CK_SCSV & 0xff))) { + /* SCSV fatal if renegotiating */ + if (s->renegotiate) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, + SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + s->s3->send_connection_binding = 1; + p += n; +#ifdef OPENSSL_RI_DEBUG + fprintf(stderr, "SCSV received by server\n"); #endif + continue; + } + + /* Check for TLS_FALLBACK_SCSV */ + if ((n != 3 || !p[0]) && + (p[n - 2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) && + (p[n - 1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) { + /* + * The SCSV indicates that the client previously tried a higher + * version. Fail if the current version is an unexpected + * downgrade. + */ + if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, + SSL_R_INAPPROPRIATE_FALLBACK); + if (s->s3) + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_INAPPROPRIATE_FALLBACK); + goto err; + } + p += n; + continue; + } + + if(sslv2format) { + /* + * We only support SSLv2 format ciphers in SSLv3+ using a + * SSLv2 backward compatible ClientHello. In this case the first + * byte is always 0 for SSLv3 compatible ciphers. Anything else + * is an SSLv2 cipher and we ignore it + */ + if(p[0] == 0) + c = ssl_get_cipher_by_char(s, &p[1]); + else + c = NULL; + } else { + c = ssl_get_cipher_by_char(s, p); + } + p += n; + if (c != NULL) { + if (!sk_SSL_CIPHER_push(sk, c)) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } + + if (skp != NULL) + *skp = sk; + return (sk); + err: + if ((skp == NULL) || (*skp == NULL)) + sk_SSL_CIPHER_free(sk); + return (NULL); +}