X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=7551220e060c4f95f40e1e78794c9487b6f5670e;hb=e0af04056cafff7cbfd2f4426cd0b44700a374a4;hp=9a2be883929b793f59f0cca4e6626f813e8b4409;hpb=f37f20ffd33bf13545cddb16b6292752aa5ab012;p=openssl.git diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 9a2be88392..7551220e06 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -611,7 +611,7 @@ int ssl3_accept(SSL *s) #endif s->init_num = 0; } - else if (s->version >= TLS1_2_VERSION) + else if (TLS1_get_version(s) >= TLS1_2_VERSION) { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; @@ -695,14 +695,11 @@ int ssl3_accept(SSL *s) ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; -#ifndef OPENSSL_NO_TLSEXT - if (s->tlsext_ticket_expected) - s->state=SSL3_ST_SW_SESSION_TICKET_A; - else if (s->hit) - s->state=SSL_ST_OK; -#else 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; @@ -789,9 +786,6 @@ int ssl3_accept(SSL *s) if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { - /* actually not necessarily a 'new' session unless - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ - s->renegotiate=0; s->new_session=0; @@ -883,15 +877,20 @@ int ssl3_check_client_hello(SSL *s) if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) { /* Throw away what we have done so far in the current handshake, - * which will now be aborted. (A full SSL_clear would be too much.) - * I hope that tmp.dh is the only thing that may need to be cleared - * when a handshake is not completed ... */ + * which will now be aborted. (A full SSL_clear would be too much.) */ #ifndef OPENSSL_NO_DH if (s->s3->tmp.dh != NULL) { DH_free(s->s3->tmp.dh); s->s3->tmp.dh = NULL; } +#endif +#ifndef OPENSSL_NO_ECDH + if (s->s3->tmp.ecdh != NULL) + { + EC_KEY_free(s->s3->tmp.ecdh); + s->s3->tmp.ecdh = NULL; + } #endif return 2; } @@ -978,13 +977,16 @@ int ssl3_get_client_hello(SSL *s) j= *(p++); s->hit=0; - /* Versions before 0.9.7 always allow session reuse during renegotiation - * (i.e. when s->new_session is true), option - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7. - * Maybe this optional behaviour should always have been the default, - * but we cannot safely change the default behaviour (or new applications - * might be written that become totally unsecure when compiled with - * an earlier library version) + /* 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))) { @@ -1380,7 +1382,7 @@ int ssl3_get_client_hello(SSL *s) s->s3->tmp.new_cipher=s->session->cipher; } - if (s->version < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER)) + if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER)) { if (!ssl3_digest_cached_records(s)) goto f_err; @@ -1439,20 +1441,20 @@ int ssl3_send_server_hello(SSL *s) memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; - /* now in theory we have 3 options to sending back the - * session id. If it is a re-use, we send back the - * old session-id, if it is a new session, we send - * back the new session-id or we send back a 0 length - * session-id if we want it to be single use. - * Currently I will not implement the '0' length session-id - * 12-Jan-98 - I'll now support the '0' length stuff. - * - * We also have an additional case where stateless session - * resumption is successful: we always send back the old - * session id. In this case s->hit is non zero: this can - * only happen if stateless session resumption is succesful - * if session caching is disabled so existing functionality - * is unaffected. + /* There are several cases for the session ID to send + * back in the server hello: + * - For session reuse from the session cache, + * we send back the old session ID. + * - If stateless session reuse (using a session ticket) + * is successful, we send back the client's "session ID" + * (which doesn't actually identify the session). + * - If it is a new session, we send back the new + * session ID. + * - However, if we want the new session to be single-use, + * we send back a 0-length session ID. + * s->hit is non-zero in either case of session reuse, + * so the following won't overwrite an ID that we're supposed + * to send back. */ if (s->session->not_resumable || (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) @@ -1622,7 +1624,6 @@ int ssl3_send_server_key_exchange(SSL *s) if (s->s3->tmp.dh != NULL) { - DH_free(dh); SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } @@ -1683,7 +1684,6 @@ int ssl3_send_server_key_exchange(SSL *s) if (s->s3->tmp.ecdh != NULL) { - EC_KEY_free(s->s3->tmp.ecdh); SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } @@ -1694,12 +1694,11 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } - if (!EC_KEY_up_ref(ecdhp)) + if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } - ecdh = ecdhp; s->s3->tmp.ecdh=ecdh; if ((EC_KEY_get0_public_key(ecdh) == NULL) || @@ -1915,16 +1914,16 @@ int ssl3_send_server_key_exchange(SSL *s) * and p points to the space at the end. */ #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA - && s->version < TLS1_2_VERSION) + && TLS1_get_version(s) < TLS1_2_VERSION) { q=md_buf; j=0; for (num=2; num > 0; num--) { - EVP_DigestInit_ex(&md_ctx,(num == 2) - ?s->ctx->md5:s->ctx->sha1, NULL); EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + EVP_DigestInit_ex(&md_ctx,(num == 2) + ?s->ctx->md5:s->ctx->sha1, NULL); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(d[4]),n); @@ -1948,7 +1947,7 @@ int ssl3_send_server_key_exchange(SSL *s) { /* For TLS1.2 and later send signature * algorithm */ - if (s->version >= TLS1_2_VERSION) + if (TLS1_get_version(s) >= TLS1_2_VERSION) { if (!tls12_get_sigandhash(p, pkey, md)) { @@ -1975,7 +1974,7 @@ int ssl3_send_server_key_exchange(SSL *s) } s2n(i,p); n+=i+2; - if (s->version >= TLS1_2_VERSION) + if (TLS1_get_version(s) >= TLS1_2_VERSION) n+= 2; } else @@ -2031,7 +2030,7 @@ int ssl3_send_certificate_request(SSL *s) p+=n; n++; - if (s->version >= TLS1_2_VERSION) + if (TLS1_get_version(s) >= TLS1_2_VERSION) { nl = tls12_get_req_sig_algs(s, p + 2); s2n(nl, p); @@ -2611,6 +2610,12 @@ int ssl3_get_client_key_exchange(SSL *s) /* Get encoded point length */ i = *p; p += 1; + if (n != 1 + i) + { + 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) { @@ -2964,7 +2969,7 @@ int ssl3_get_cert_verify(SSL *s) } else { - if (s->version >= TLS1_2_VERSION) + if (TLS1_get_version(s) >= TLS1_2_VERSION) { int sigalg = tls12_get_sigid(pkey); /* Should never happen */ @@ -2984,7 +2989,7 @@ int ssl3_get_cert_verify(SSL *s) md = tls12_get_hash(p[0]); if (md == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST); + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST); al=SSL_AD_DECODE_ERROR; goto f_err; } @@ -3011,7 +3016,7 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); goto f_err; } - if (s->version >= TLS1_2_VERSION) + if (TLS1_get_version(s) >= TLS1_2_VERSION) { long hdatalen = 0; void *hdata; @@ -3333,13 +3338,17 @@ int ssl3_send_server_certificate(SSL *s) /* SSL3_ST_SW_CERT_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } + #ifndef OPENSSL_NO_TLSEXT +/* send a new session ticket (not necessarily for a new session) */ int ssl3_send_newsession_ticket(SSL *s) { if (s->state == SSL3_ST_SW_SESSION_TICKET_A) { unsigned char *p, *senc, *macstart; - int len, slen; + const unsigned char *const_p; + int len, slen_full, slen; + SSL_SESSION *sess; unsigned int hlen; EVP_CIPHER_CTX ctx; HMAC_CTX hctx; @@ -3348,12 +3357,38 @@ int ssl3_send_newsession_ticket(SSL *s) unsigned char key_name[16]; /* get session encoding length */ - slen = i2d_SSL_SESSION(s->session, NULL); + slen_full = i2d_SSL_SESSION(s->session, NULL); /* Some length values are 16 bits, so forget it if session is * too long */ - if (slen > 0xFF00) + if (slen_full > 0xFF00) return -1; + senc = OPENSSL_malloc(slen_full); + if (!senc) + return -1; + p = senc; + i2d_SSL_SESSION(s->session, &p); + + /* create a fresh copy (not shared with other threads) to clean up */ + const_p = senc; + sess = d2i_SSL_SESSION(NULL, &const_p, slen_full); + if (sess == NULL) + { + OPENSSL_free(senc); + return -1; + } + sess->session_id_length = 0; /* ID is irrelevant for the ticket */ + + slen = i2d_SSL_SESSION(sess, NULL); + if (slen > slen_full) /* shouldn't ever happen */ + { + OPENSSL_free(senc); + return -1; + } + p = senc; + i2d_SSL_SESSION(sess, &p); + SSL_SESSION_free(sess); + /* Grow buffer if need be: the length calculation is as * follows 1 (size of message name) + 3 (message length * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) + @@ -3365,11 +3400,6 @@ int ssl3_send_newsession_ticket(SSL *s) 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) return -1; - senc = OPENSSL_malloc(slen); - if (!senc) - return -1; - p = senc; - i2d_SSL_SESSION(s->session, &p); p=(unsigned char *)s->init_buf->data; /* do the header */ @@ -3400,7 +3430,13 @@ int ssl3_send_newsession_ticket(SSL *s) tlsext_tick_md(), NULL); memcpy(key_name, tctx->tlsext_tick_key_name, 16); } - l2n(s->session->tlsext_tick_lifetime_hint, p); + + /* Ticket lifetime hint (advisory only): + * We leave this unspecified for resumed session (for simplicity), + * and guess that tickets for new sessions will live as long + * as their sessions. */ + l2n(s->hit ? 0 : s->session->timeout, p); + /* Skip ticket length for now */ p += 2; /* Output key name */