int ssl3_get_finished(SSL *ssl) { int al, finished_len, ok; long message_len; uint8_t *p; message_len = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED, ssl_dont_hash_message, &ok); if (!ok) { return message_len; } /* Snapshot the finished hash before incorporating the new message. */ ssl3_take_mac(ssl); if (!ssl3_hash_current_message(ssl)) { goto err; } p = ssl->init_msg; finished_len = ssl->s3->tmp.peer_finish_md_len; if (finished_len != message_len) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } int finished_ret = CRYPTO_memcmp(p, ssl->s3->tmp.peer_finish_md, finished_len); #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) finished_ret = 0; #endif if (finished_ret != 0) { al = SSL_AD_DECRYPT_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* Copy the finished so we can use it for renegotiation checks */ if (ssl->server) { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.peer_finish_md, finished_len); ssl->s3->previous_client_finished_len = finished_len; } else { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.peer_finish_md, finished_len); ssl->s3->previous_server_finished_len = finished_len; } return 1; f_err: ssl3_send_alert(ssl, SSL3_AL_FATAL, al); err: return 0; }
/* 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) { unsigned char *p; unsigned long l; long n; int i,al; 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; } *ok=1; s->init_msg = s->init_buf->data + 4; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } p=(unsigned char *)s->init_buf->data; if (s->state == st1) /* s->init_num < 4 */ { int skip_message; do { while (s->init_num < 4) { i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, &p[s->init_num],4 - s->init_num, 0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } 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_HANDSHAKE, p, 4, s, s->msg_callback_arg); } } while (skip_message); /* s->init_num == 4 */ if ((mt >= 0) && (*p != mt)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && (st1 == SSL3_ST_SR_CERT_A) && (stn == SSL3_ST_SR_CERT_B)) { /* At this point we have got an MS SGC second client * hello (maybe we should always allow the client to * start a new handshake?). We need to restart the mac. * Don't increment {num,total}_renegotiations because * we have not completed the handshake. */ ssl3_init_finished_mac(s); } s->s3->tmp.message_type= *(p++); 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; } if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */ { 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+4)) { 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 + 4; s->init_num = 0; } /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } #ifndef OPENSSL_NO_NEXTPROTONEG /* If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif /* Feed this message into MAC computation. */ ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, 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); }
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; } p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, &p[s->init_num], n, 0); if (i <= 0) { s->rwstate = SSL_READING; *len = 0; return 0; } s->init_num += i; n -= i; } #ifndef OPENSSL_NO_NEXTPROTONEG /* * If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif /* Feed this message into MAC computation. */ if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num)) { SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); *len = 0; return 0; } if (s->msg_callback) s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, (size_t)s->init_num, s, s->msg_callback_arg); } else { if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + SSL3_HM_HEADER_LENGTH)) { SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); *len = 0; return 0; } if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, s->msg_callback_arg); } /* * 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 ssl3_get_finished(SSL *s, int a, int b) { int al, finished_len, ok; long message_len; uint8_t *p; message_len = s->method->ssl_get_message(s, a, b, SSL3_MT_FINISHED, EVP_MAX_MD_SIZE, ssl_dont_hash_message, &ok); if (!ok) { return message_len; } /* Snapshot the finished hash before incorporating the new message. */ ssl3_take_mac(s); if (!ssl3_hash_current_message(s)) { goto err; } /* If this occurs, we have missed a message. * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */ if (!s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; p = s->init_msg; finished_len = s->s3->tmp.peer_finish_md_len; if (finished_len != message_len) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, finished_len) != 0) { al = SSL_AD_DECRYPT_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* Copy the finished so we can use it for renegotiation checks */ if (s->server) { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, finished_len); s->s3->previous_client_finished_len = finished_len; } else { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, finished_len); s->s3->previous_server_finished_len = finished_len; } return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: return 0; }
/* 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) { uint8_t *p; uint32_t l; long n; int i, al; CBS cbs; uint8_t message_type; 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; } *ok = 1; s->state = stn; s->init_msg = s->init_buf->data + 4; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } p = (uint8_t *)s->init_buf->data; if (s->state == st1) /* s->init_num < 4 */ { int skip_message; do { while (s->init_num < 4) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], 4 - s->init_num, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; return i; } s->init_num += i; } skip_message = 0; if (!s->server && 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, 4, s, s->msg_callback_arg); } } } while (skip_message); /* s->init_num == 4 */ if ((mt >= 0) && (*p != mt)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } /* XXX remove call to n2l3 */ CBS_init(&cbs, p, 4); if (!CBS_get_u8(&cbs, &message_type) || !CBS_get_u24(&cbs, &l)) { SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_type = message_type; if (l > (unsigned long)max) { 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, l + 4)) { 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 + 4; s->init_num = 0; } /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], n, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } /* If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); /* Feed this message into MAC computation. */ tls1_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + 4); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, 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); }
/* * 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) { unsigned char *p; unsigned long l; long n; int i, al, recvd_type; 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; } *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; } 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; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, p, 1, 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; } 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); goto f_err; } 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; 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; s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; s->init_num = 0; } } /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, &p[s->init_num], n, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } #ifndef OPENSSL_NO_NEXTPROTONEG /* * If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif /* Feed this message into MAC computation. */ if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num); if (s->msg_callback) s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, (size_t)s->init_num, s, s->msg_callback_arg); } else { ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + SSL3_HM_HEADER_LENGTH); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, 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); }