X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_both.c;h=6c5147421ee445ef61382294e36afcc15fe9a0d9;hp=943cf733f0a78cc69f642e325da2f375c7229bf2;hb=23a635c0ec895f9876d4d7633e7e2923b5bbfc17;hpb=c69f2adf71d888ba1a2090ec0be3319eb024efe3 diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 943cf733f0..6c5147421e 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -156,46 +156,42 @@ int ssl3_do_write(SSL *s, int type) return (0); } -int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) +int tls_construct_finished(SSL *s, const char *sender, int slen) { unsigned char *p; int i; unsigned long l; - if (s->state == a) { - p = ssl_handshake_start(s); + p = ssl_handshake_start(s); - i = s->method->ssl3_enc->final_finish_mac(s, - sender, slen, - s->s3->tmp.finish_md); - if (i <= 0) - return 0; - s->s3->tmp.finish_md_len = i; - memcpy(p, s->s3->tmp.finish_md, i); - l = i; + i = s->method->ssl3_enc->final_finish_mac(s, + sender, slen, + s->s3->tmp.finish_md); + if (i <= 0) + return 0; + s->s3->tmp.finish_md_len = i; + memcpy(p, s->s3->tmp.finish_md, i); + l = i; - /* - * Copy the finished so we can use it for renegotiation checks - */ - if (s->type == SSL_ST_CONNECT) { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i); - s->s3->previous_client_finished_len = i; - } else { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i); - s->s3->previous_server_finished_len = i; - } + /* + * Copy the finished so we can use it for renegotiation checks + */ + if (!s->server) { + OPENSSL_assert(i <= EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i); + s->s3->previous_client_finished_len = i; + } else { + OPENSSL_assert(i <= EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i); + s->s3->previous_server_finished_len = i; + } - if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) { - SSLerr(SSL_F_SSL3_SEND_FINISHED, ERR_R_INTERNAL_ERROR); - return -1; - } - s->state = b; + if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) { + SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR); + return 0; } - /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return ssl_do_write(s); + return 1; } #ifndef OPENSSL_NO_NEXTPROTONEG @@ -213,7 +209,7 @@ static void ssl3_take_mac(SSL *s) */ if (s->s3->tmp.new_cipher == NULL) return; - if (s->state & SSL_ST_CONNECT) { + if (!s->server) { sender = s->method->ssl3_enc->server_finished_label; slen = s->method->ssl3_enc->server_finished_label_len; } else { @@ -228,15 +224,9 @@ static void ssl3_take_mac(SSL *s) } #endif -int ssl3_get_change_cipher_spec(SSL *s, int a, int b) +enum MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, long n) { - int ok, al; - long n; - - n = s->method->ssl_get_message(s, a, b, SSL3_MT_CHANGE_CIPHER_SPEC, 1, &ok); - - if (!ok) - return ((int)n); + int al; /* * 'Change Cipher Spec' is just a single byte, which should already have @@ -248,13 +238,15 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b) || (s->version != DTLS1_BAD_VER && n != DTLS1_CCS_HEADER_LENGTH - 1)) { al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); + SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, + SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } else { if (n != 0) { al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); + SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, + SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } @@ -262,14 +254,14 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b) /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); + SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->s3->change_cipher_spec = 1; if (!ssl3_do_change_cipher_spec(s)) { al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); goto f_err; } @@ -289,36 +281,22 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b) #endif } - return 1; + return MSG_PROCESS_CONTINUE_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - return 0; + statem_set_error(s); + return MSG_PROCESS_ERROR; } - -int ssl3_get_finished(SSL *s, int a, int b) +enum MSG_PROCESS_RETURN tls_process_finished(SSL *s, unsigned long n) { - int al, i, ok; - long n; + int al, i; unsigned char *p; -#ifdef OPENSSL_NO_NEXTPROTONEG - /* - * the mac has already been generated when we received the change cipher - * spec message and is in s->s3->tmp.peer_finish_md - */ -#endif - - /* 64 argument should actually be 36+4 :-) */ - n = s->method->ssl_get_message(s, a, b, SSL3_MT_FINISHED, 64, &ok); - - if (!ok) - return ((int)n); - /* If this occurs, we have missed a message */ if (!s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS); + SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; @@ -326,22 +304,22 @@ int ssl3_get_finished(SSL *s, int a, int b) p = (unsigned char *)s->init_msg; i = s->s3->tmp.peer_finish_md_len; - if (i != n) { + if (i < 0 || (unsigned long)i != n) { al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_BAD_DIGEST_LENGTH); + SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) { al = SSL_AD_DECRYPT_ERROR; - SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_DIGEST_CHECK_FAILED); + SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* * Copy the finished so we can use it for renegotiation checks */ - if (s->type == SSL_ST_ACCEPT) { + if (s->server) { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, i); s->s3->previous_client_finished_len = i; @@ -351,36 +329,23 @@ int ssl3_get_finished(SSL *s, int a, int b) s->s3->previous_server_finished_len = i; } - return (1); + return MSG_PROCESS_CONTINUE_PROCESSING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - return (0); + statem_set_error(s); + return MSG_PROCESS_ERROR; } -/*- - * for these 2 messages, we need to - * ssl->enc_read_ctx re-init - * ssl->rlayer.read_sequence zero - * ssl->s3->read_mac_secret re-init - * ssl->session->read_sym_enc assign - * ssl->session->read_compression assign - * ssl->session->read_hash assign - */ -int ssl3_send_change_cipher_spec(SSL *s, int a, int b) +int tls_construct_change_cipher_spec(SSL *s) { unsigned char *p; - if (s->state == a) { - p = (unsigned char *)s->init_buf->data; - *p = SSL3_MT_CCS; - s->init_num = 1; - s->init_off = 0; - - s->state = b; - } + p = (unsigned char *)s->init_buf->data; + *p = SSL3_MT_CCS; + s->init_num = 1; + s->init_off = 0; - /* SSL3_ST_CW_CHANGE_B */ - return (ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); + return 1; } unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) @@ -403,151 +368,187 @@ unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) return l + SSL_HM_HEADER_LENGTH(s); } -/* - * Obtain handshake message of message type 'mt' (any if mt == -1), maximum - * acceptable body length 'max'. The first four bytes (msg_type and length) - * are read in state 'st1', the body is read in state 'stn'. - */ -long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) +enum WORK_STATE tls_finish_handshake(SSL *s, enum WORK_STATE wst) { - unsigned char *p; - unsigned long l; - long n; - int i, al, recvd_type; + void (*cb) (const SSL *ssl, int type, int val) = NULL; - if (s->s3->tmp.reuse_message) { - s->s3->tmp.reuse_message = 0; - if ((mt >= 0) && (s->s3->tmp.message_type != mt)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); - goto f_err; +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) { + enum WORK_STATE ret; + ret = dtls_wait_for_dry(s); + if (ret != WORK_FINISHED_CONTINUE) + return ret; + } +#endif + + /* clean a few things up */ + ssl3_cleanup_key_block(s); + + if (!SSL_IS_DTLS(s)) { + /* + * We don't do this in DTLS because we may still need the init_buf + * in case there are any unexpected retransmits + */ + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + } + + ssl_free_wbio_buffer(s); + + s->init_num = 0; + + if (!s->server || s->renegotiate == 2) { + /* skipped if we just sent a HelloRequest */ + s->renegotiate = 0; + s->new_session = 0; + + if (s->server) { + s->renegotiate = 0; + s->new_session = 0; + + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + + s->ctx->stats.sess_accept_good++; + s->handshake_func = ssl3_accept; + } else { + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + if (s->hit) + s->ctx->stats.sess_hit++; + + s->handshake_func = ssl3_connect; + s->ctx->stats.sess_connect_good++; + } + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + if (cb != NULL) + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + + if (SSL_IS_DTLS(s)) { + /* done with handshaking */ + s->d1->handshake_read_seq = 0; + s->d1->handshake_write_seq = 0; + s->d1->next_handshake_write_seq = 0; } - *ok = 1; - s->state = stn; - s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; - s->init_num = (int)s->s3->tmp.message_size; - return s->init_num; } + return WORK_FINISHED_STOP; +} + +int tls_get_message_header(SSL *s, int *mt) +{ + /* s->init_num < SSL3_HM_HEADER_LENGTH */ + int skip_message, i, recvd_type, al; + unsigned char *p; + unsigned long l; + p = (unsigned char *)s->init_buf->data; - if (s->state == st1) { - /* s->init_num < SSL3_HM_HEADER_LENGTH */ - int skip_message; - - do { - while (s->init_num < SSL3_HM_HEADER_LENGTH) { - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, - &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0); - if (i <= 0) { - s->rwstate = SSL_READING; - *ok = 0; - return i; - } - if (s->init_num == 0 - && recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC - && (mt < 0 || mt == SSL3_MT_CHANGE_CIPHER_SPEC)) { - if (*p != SSL3_MT_CCS) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, - SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - s->init_num = i - 1; - s->init_msg = p + 1; - s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; - s->s3->tmp.message_size = i - 1; - s->state = stn; - *ok = 1; + do { + while (s->init_num < SSL3_HM_HEADER_LENGTH) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, + &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0); + if (i <= 0) { + s->rwstate = SSL_READING; + return 0; + } + if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + s->init_num = i - 1; + s->s3->tmp.message_size = i; + return 1; + } else if (recvd_type != SSL3_RT_HANDSHAKE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY); + goto f_err; + } + s->init_num += i; + } + + skip_message = 0; + if (!s->server) + if (p[0] == SSL3_MT_HELLO_REQUEST) + /* + * The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them if + * their format is correct. Does not count for 'Finished' + * MAC. + */ + if (p[1] == 0 && p[2] == 0 && p[3] == 0) { + s->init_num = 0; + skip_message = 1; + if (s->msg_callback) - s->msg_callback(0, s->version, - SSL3_RT_CHANGE_CIPHER_SPEC, p, 1, s, + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + p, SSL3_HM_HEADER_LENGTH, s, s->msg_callback_arg); - return i - 1; - } else if (recvd_type != SSL3_RT_HANDSHAKE) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_CCS_RECEIVED_EARLY); - goto f_err; } - s->init_num += i; - } + } while (skip_message); + /* s->init_num == SSL3_HM_HEADER_LENGTH */ - skip_message = 0; - if (!s->server) - if (p[0] == SSL3_MT_HELLO_REQUEST) - /* - * The server may always send 'Hello Request' messages -- - * we are doing a handshake anyway now, so ignore them if - * their format is correct. Does not count for 'Finished' - * MAC. - */ - if (p[1] == 0 && p[2] == 0 && p[3] == 0) { - s->init_num = 0; - skip_message = 1; - - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, - p, SSL3_HM_HEADER_LENGTH, s, - s->msg_callback_arg); - } - } while (skip_message); - /* s->init_num == SSL3_HM_HEADER_LENGTH */ - - if ((mt >= 0) && (*p != mt)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); + *mt = *p; + s->s3->tmp.message_type = *(p++); + + if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Only happens with SSLv3+ in an SSLv2 backward compatible + * ClientHello + */ + /* + * Total message size is the remaining record bytes to read + * plus the SSL3_HM_HEADER_LENGTH bytes that we already read + */ + l = RECORD_LAYER_get_rrec_length(&s->rlayer) + + SSL3_HM_HEADER_LENGTH; + if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) { + SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB); + goto err; + } + s->s3->tmp.message_size = l; + + s->init_msg = s->init_buf->data; + s->init_num = SSL3_HM_HEADER_LENGTH; + } else { + n2l3(p, l); + /* BUF_MEM_grow takes an 'int' parameter */ + if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } + if (l && !BUF_MEM_grow_clean(s->init_buf, + (int)l + SSL3_HM_HEADER_LENGTH)) { + SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB); + goto err; + } + s->s3->tmp.message_size = l; - s->s3->tmp.message_type = *(p++); - - if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { - /* - * Only happens with SSLv3+ in an SSLv2 backward compatible - * ClientHello - */ - /* - * Total message size is the remaining record bytes to read - * plus the SSL3_HM_HEADER_LENGTH bytes that we already read - */ - l = RECORD_LAYER_get_rrec_length(&s->rlayer) - + SSL3_HM_HEADER_LENGTH; - if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) { - SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); - goto err; - } - s->s3->tmp.message_size = l; - s->state = stn; + s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; + s->init_num = 0; + } - s->init_msg = s->init_buf->data; - s->init_num = SSL3_HM_HEADER_LENGTH; - } else { - n2l3(p, l); - if (l > (unsigned long)max) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - /* BUF_MEM_grow takes an 'int' parameter */ - if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if (l && !BUF_MEM_grow_clean(s->init_buf, - (int)l + SSL3_HM_HEADER_LENGTH)) { - SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); - goto err; - } - s->s3->tmp.message_size = l; - s->state = stn; + return 1; + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return 0; +} - s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; - s->init_num = 0; - } +int tls_get_message_body(SSL *s, unsigned long *len) +{ + long n; + unsigned char *p; + int i; + + if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* We've already read everything in */ + *len = (unsigned long)s->init_num; + return 1; } - /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { @@ -555,8 +556,8 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) &p[s->init_num], n, 0); if (i <= 0) { s->rwstate = SSL_READING; - *ok = 0; - return i; + *len = 0; + return 0; } s->init_num += i; n -= i; @@ -586,13 +587,18 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s->msg_callback_arg); } - *ok = 1; - return s->init_num; - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - *ok = 0; - return (-1); + /* + * init_num should never be negative...should probably be declared + * unsigned + */ + if (s->init_num < 0) { + SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + *len = 0; + return 0; + } + *len = (unsigned long)s->init_num; + return 1; } int ssl_cert_type(X509 *x, EVP_PKEY *pkey) @@ -618,9 +624,7 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey) ret = SSL_PKEY_ECC; } #endif - else if (i == NID_id_GostR3410_94 || i == NID_id_GostR3410_94_cc) { - ret = SSL_PKEY_GOST94; - } else if (i == NID_id_GostR3410_2001 || i == NID_id_GostR3410_2001_cc) { + else if (i == NID_id_GostR3410_2001) { ret = SSL_PKEY_GOST01; } else if (x && (i == EVP_PKEY_DH || i == EVP_PKEY_DHX)) { /*