X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=a686718b3619ebe8e90f84334d1a921ce772d51e;hp=4b1931a71fe1e0f016bf6087e4c4fb564819db11;hb=ffe181c3662ebf92b5108b2cb48fad3066bd6749;hpb=b0c0f200712ea51b6442fa0d496a6e0088017890 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 4b1931a71f..a686718b36 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -132,8 +132,11 @@ #include #include #include +#include #include +#ifndef OPENSSL_NO_DH #include +#endif #include #ifndef OPENSSL_NO_KRB5 #include @@ -141,7 +144,6 @@ #include static SSL_METHOD *ssl3_get_server_method(int ver); - #ifndef OPENSSL_NO_ECDH static int nid2curve_id(int nid); #endif @@ -154,33 +156,15 @@ static SSL_METHOD *ssl3_get_server_method(int ver) return(NULL); } -SSL_METHOD *SSLv3_server_method(void) - { - static int init=1; - static SSL_METHOD SSLv3_server_data; - - if (init) - { - CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD); - - if (init) - { - memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(), - sizeof(SSL_METHOD)); - SSLv3_server_data.ssl_accept=ssl3_accept; - SSLv3_server_data.get_ssl_method=ssl3_get_server_method; - init=0; - } - - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD); - } - return(&SSLv3_server_data); - } +IMPLEMENT_ssl3_meth_func(SSLv3_server_method, + ssl3_accept, + ssl_undefined_function, + ssl3_get_server_method) int ssl3_accept(SSL *s) { BUF_MEM *buf; - unsigned long l,Time=time(NULL); + unsigned long l,Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; long num1; int ret= -1; @@ -316,15 +300,30 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: - /* Check if it is anon DH or anon ECDH */ - if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) + /* Check if it is anon DH or anon ECDH or KRB5 */ + if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL) + && !(s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)) { 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 + s->state=SSL3_ST_SW_KEY_EXCH_A; + } + else + { + 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; @@ -509,11 +508,34 @@ int ssl3_accept(SSL *s) 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); + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_CHANGE_A; + s->init_num=0; + break; + + case SSL3_ST_SW_CERT_STATUS_A: + case SSL3_ST_SW_CERT_STATUS_B: + ret=ssl3_send_cert_status(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_KEY_EXCH_A; + s->init_num=0; + break; + +#endif + case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: @@ -682,7 +704,9 @@ int ssl3_get_client_hello(SSL *s) unsigned long id; unsigned char *p,*d,*q; SSL_CIPHER *c; +#ifndef OPENSSL_NO_COMP SSL_COMP *comp=NULL; +#endif STACK_OF(SSL_CIPHER) *ciphers=NULL; /* We do this so that we will respond with our native type. @@ -693,9 +717,9 @@ int ssl3_get_client_hello(SSL *s) */ if (s->state == SSL3_ST_SR_CLNT_HELLO_A) { - s->first_packet=1; s->state=SSL3_ST_SR_CLNT_HELLO_B; } + s->first_packet=1; n=s->method->ssl_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, SSL3_ST_SR_CLNT_HELLO_C, @@ -704,6 +728,7 @@ int ssl3_get_client_hello(SSL *s) &ok); if (!ok) return((int)n); + s->first_packet=0; d=p=(unsigned char *)s->init_msg; /* use version from inside client hello, not from record header @@ -711,7 +736,8 @@ int ssl3_get_client_hello(SSL *s) s->client_version=(((int)p[0])<<8)|(int)p[1]; p+=2; - if (s->client_version < s->version) + if ((s->version == DTLS1_VERSION && s->client_version > s->version) || + (s->version != DTLS1_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) @@ -739,14 +765,14 @@ int ssl3_get_client_hello(SSL *s) * might be written that become totally unsecure when compiled with * an earlier library version) */ - if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) + if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { if (!ssl_get_new_session(s,1)) goto err; } else { - i=ssl_get_prev_session(s,p,j); + i=ssl_get_prev_session(s, p, j, d + n); if (i == 1) { /* previous session */ s->hit=1; @@ -762,7 +788,7 @@ int ssl3_get_client_hello(SSL *s) p+=j; - if (SSL_version(s) == DTLS1_VERSION) + if (s->version == DTLS1_VERSION) { /* cookie stuff */ cookie_len = *(p++); @@ -909,10 +935,27 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } +#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions*/ + if (s->version > SSL3_VERSION) + { + if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al)) + { + /* 'al' set by ssl_parse_clienthello_tlsext */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT); + goto f_err; + } + } + if (ssl_check_clienthello_tlsext(s) <= 0) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } +#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 * algorithms from the client, starting at q. */ s->s3->tmp.new_compression=NULL; +#ifndef OPENSSL_NO_COMP if (s->ctx->comp_methods != NULL) { /* See if we have a match */ int m,nn,o,v,done=0; @@ -937,6 +980,7 @@ int ssl3_get_client_hello(SSL *s) else comp=NULL; } +#endif /* TLS does not mind if there is extra stuff */ #if 0 /* SSL 3.0 does not mind either, so we should disable this test @@ -960,7 +1004,11 @@ int ssl3_get_client_hello(SSL *s) if (!s->hit) { +#ifdef OPENSSL_NO_COMP + s->session->compress_meth=0; +#else s->session->compress_meth=(comp == NULL)?0:comp->id; +#endif if (s->session->ciphers != NULL) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers=ciphers; @@ -1046,7 +1094,7 @@ int ssl3_send_server_hello(SSL *s) { buf=(unsigned char *)s->init_buf->data; p=s->s3->server_random; - Time=time(NULL); /* Time */ + Time=(unsigned long)time(NULL); /* Time */ l2n(Time,p); if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) return -1; @@ -1086,11 +1134,21 @@ int ssl3_send_server_hello(SSL *s) p+=i; /* put the compression method */ +#ifdef OPENSSL_NO_COMP + *(p++)=0; +#else if (s->s3->tmp.new_compression == NULL) *(p++)=0; else *(p++)=s->s3->tmp.new_compression->id; - +#endif +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); + return -1; + } +#endif /* do the header */ l=(p-d); d=buf; @@ -1370,11 +1428,11 @@ int ssl3_send_server_key_exchange(SSL *s) /* XXX: For now, we only support named (not * generic) curves in ECDH ephemeral key exchanges. - * In this situation, we need three additional bytes + * In this situation, we need four additional bytes * to encode the entire ServerECDHParams * structure. */ - n = 3 + encodedlen; + n = 4 + encodedlen; /* We'll generate the serverKeyExchange message * explicitly so we can set these to NULLs @@ -1382,6 +1440,7 @@ int ssl3_send_server_key_exchange(SSL *s) r[0]=NULL; r[1]=NULL; r[2]=NULL; + r[3]=NULL; } else #endif /* !OPENSSL_NO_ECDH */ @@ -1432,12 +1491,14 @@ int ssl3_send_server_key_exchange(SSL *s) { /* XXX: For now, we only support named (not generic) curves. * In this situation, the serverKeyExchange message has: - * [1 byte CurveType], [1 byte CurveName] + * [1 byte CurveType], [2 byte CurveName] * [1 byte length of encoded point], followed by * the actual encoded point itself */ *p = NAMED_CURVE_TYPE; p += 1; + *p = 0; + p += 1; *p = curve_id; p += 1; *p = encodedlen; @@ -1641,21 +1702,6 @@ err: return(-1); } - -static const int KDF1_SHA1_len = 20; -static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) - { -#ifndef OPENSSL_NO_SHA - if (*outlen < SHA_DIGEST_LENGTH) - return NULL; - else - *outlen = SHA_DIGEST_LENGTH; - return SHA1(in, inlen, out); -#else - return NULL; -#endif - } - int ssl3_get_client_key_exchange(SSL *s) { int i,al,ok; @@ -1725,8 +1771,9 @@ int ssl3_get_client_key_exchange(SSL *s) rsa=pkey->pkey.rsa; } - /* TLS */ - if (s->version > SSL3_VERSION) + /* TLS and [incidentally] DTLS, including pre-0.9.8f */ + if (s->version > SSL3_VERSION && + s->client_version != DTLS1_BAD_VER) { n2s(p,i); if (n != i+2) @@ -1886,7 +1933,7 @@ int ssl3_get_client_key_exchange(SSL *s) n2s(p,i); enc_ticket.length = i; - if (n < enc_ticket.length + 6) + if (n < (int)enc_ticket.length + 6) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); @@ -1899,7 +1946,7 @@ int ssl3_get_client_key_exchange(SSL *s) n2s(p,i); authenticator.length = i; - if (n < enc_ticket.length + authenticator.length + 6) + if (n < (int)(enc_ticket.length + authenticator.length) + 6) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); @@ -2011,6 +2058,24 @@ int ssl3_get_client_key_exchange(SSL *s) SSL_R_DATA_LENGTH_TOO_LONG); goto err; } + if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff)))) + { + /* The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send random bytes instead of + * the protocol version. + * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. + * (Perhaps we should have a separate BUG value for the Kerberos cipher) + */ + if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_AD_DECODE_ERROR); + goto err; + } + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); s->session->master_key_length= @@ -2019,7 +2084,7 @@ int ssl3_get_client_key_exchange(SSL *s) if (kssl_ctx->client_princ) { - int len = strlen(kssl_ctx->client_princ); + size_t len = strlen(kssl_ctx->client_princ); if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) { s->session->krb5_client_princ_len = len; @@ -2058,7 +2123,7 @@ int ssl3_get_client_key_exchange(SSL *s) if (l & SSL_kECDH) { /* use the certificate */ - tkey = s->cert->key->privatekey->pkey.ec; + tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec; } else { @@ -2118,8 +2183,13 @@ int ssl3_get_client_key_exchange(SSL *s) goto f_err; } - EC_POINT_copy(clnt_ecpoint, - EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)); + if (EC_POINT_copy(clnt_ecpoint, + EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_EC_LIB); + goto err; + } ret = 2; /* Skip certificate verify processing */ } else @@ -2158,14 +2228,7 @@ int ssl3_get_client_key_exchange(SSL *s) ERR_R_ECDH_LIB); goto err; } - /* If field size is not more than 24 octets, then use SHA-1 hash of result; - * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt; - * this is new with this version of the Internet Draft). - */ - if (field_size <= 24 * 8) - i = ECDH_compute_key(p, KDF1_SHA1_len, clnt_ecpoint, srvr_ecdh, KDF1_SHA1); - else - i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL); + i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, @@ -2613,3 +2676,125 @@ static int nid2curve_id(int nid) } } #endif +#ifndef OPENSSL_NO_TLSEXT +int ssl3_send_newsession_ticket(SSL *s) + { + if (s->state == SSL3_ST_SW_SESSION_TICKET_A) + { + unsigned char *p, *senc, *macstart; + int len, slen; + unsigned int hlen; + EVP_CIPHER_CTX ctx; + HMAC_CTX hctx; + + /* get session encoding length */ + slen = i2d_SSL_SESSION(s->session, NULL); + /* Some length values are 16 bits, so forget it if session is + * too long + */ + if (slen > 0xFF00) + return -1; + /* 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) + + * 16 (key name) + max_iv_len (iv length) + + * session_length + max_enc_block_size (max encrypted session + * length) + max_md_size (HMAC). + */ + if (!BUF_MEM_grow(s->init_buf, + 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 */ + *(p++)=SSL3_MT_NEWSESSION_TICKET; + /* Skip message length for now */ + p += 3; + l2n(s->session->tlsext_tick_lifetime_hint, p); + /* Skip ticket length for now */ + p += 2; + /* Output key name */ + macstart = p; + memcpy(p, s->ctx->tlsext_tick_key_name, 16); + p += 16; + /* Generate and output IV */ + RAND_pseudo_bytes(p, 16); + EVP_CIPHER_CTX_init(&ctx); + /* Encrypt session data */ + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + s->ctx->tlsext_tick_aes_key, p); + p += 16; + EVP_EncryptUpdate(&ctx, p, &len, senc, slen); + p += len; + EVP_EncryptFinal(&ctx, p, &len); + p += len; + EVP_CIPHER_CTX_cleanup(&ctx); + + HMAC_CTX_init(&hctx); + HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16, + tlsext_tick_md(), NULL); + HMAC_Update(&hctx, macstart, p - macstart); + HMAC_Final(&hctx, p, &hlen); + HMAC_CTX_cleanup(&hctx); + + p += hlen; + /* Now write out lengths: p points to end of data written */ + /* Total length */ + len = p - (unsigned char *)s->init_buf->data; + p=(unsigned char *)s->init_buf->data + 1; + l2n3(len - 4, p); /* Message length */ + p += 4; + s2n(len - 10, p); /* Ticket length */ + + /* number of bytes to write */ + s->init_num= len; + s->state=SSL3_ST_SW_SESSION_TICKET_B; + s->init_off=0; + OPENSSL_free(senc); + } + + /* SSL3_ST_SW_SESSION_TICKET_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +int ssl3_send_cert_status(SSL *s) + { + if (s->state == SSL3_ST_SW_CERT_STATUS_A) + { + unsigned char *p; + /* Grow buffer if need be: the length calculation is as + * follows 1 (message type) + 3 (message length) + + * 1 (ocsp response type) + 3 (ocsp response length) + * + (ocsp response) + */ + if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) + return -1; + + p=(unsigned char *)s->init_buf->data; + + /* do the header */ + *(p++)=SSL3_MT_CERTIFICATE_STATUS; + /* message length */ + l2n3(s->tlsext_ocsp_resplen + 4, p); + /* status type */ + *(p++)= s->tlsext_status_type; + /* length of OCSP response */ + l2n3(s->tlsext_ocsp_resplen, p); + /* actual response */ + memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen); + /* number of bytes to write */ + s->init_num = 8 + s->tlsext_ocsp_resplen; + s->state=SSL3_ST_SW_CERT_STATUS_B; + s->init_off = 0; + } + + /* SSL3_ST_SW_CERT_STATUS_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } +#endif