예제 #1
0
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;
}
예제 #2
0
/* Obtain handshake message of message type |msg_type| (any if |msg_type| ==
 * -1). */
long ssl3_get_message(SSL *ssl, int msg_type,
                      enum ssl_hash_message_t hash_message, int *ok) {
  *ok = 0;

  if (ssl->s3->tmp.reuse_message) {
    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
     * ssl_dont_hash_message would have to have been applied to the previous
     * call. */
    assert(hash_message == ssl_hash_message);
    assert(ssl->s3->tmp.message_complete);
    ssl->s3->tmp.reuse_message = 0;
    if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
      return -1;
    }
    *ok = 1;
    assert(ssl->init_buf->length >= 4);
    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
    ssl->init_num = (int)ssl->init_buf->length - 4;
    return ssl->init_num;
  }

again:
  if (ssl->s3->tmp.message_complete) {
    ssl->s3->tmp.message_complete = 0;
    ssl->init_buf->length = 0;
  }

  /* Read the message header, if we haven't yet. */
  int ret = extend_handshake_buffer(ssl, 4);
  if (ret <= 0) {
    return ret;
  }

  /* Parse out the length. Cap it so the peer cannot force us to buffer up to
   * 2^24 bytes. */
  const uint8_t *p = (uint8_t *)ssl->init_buf->data;
  size_t msg_len = (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | p[3];
  if (msg_len > ssl_max_handshake_message_len(ssl)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
    return -1;
  }

  /* Read the message body, if we haven't yet. */
  ret = extend_handshake_buffer(ssl, 4 + msg_len);
  if (ret <= 0) {
    return ret;
  }

  /* We have now received a complete message. */
  ssl->s3->tmp.message_complete = 1;
  ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
                      ssl->init_buf->data, ssl->init_buf->length);

  static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
  if (!ssl->server && ssl->init_buf->length == sizeof(kHelloRequest) &&
      memcmp(kHelloRequest, ssl->init_buf->data, sizeof(kHelloRequest)) == 0) {
    /* 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. */
    goto again;
  }

  uint8_t actual_type = ((const uint8_t *)ssl->init_buf->data)[0];
  if (msg_type >= 0 && actual_type != msg_type) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
    return -1;
  }
  ssl->s3->tmp.message_type = actual_type;

  ssl->init_msg = (uint8_t*)ssl->init_buf->data + 4;
  ssl->init_num = ssl->init_buf->length - 4;

  /* Feed this message into MAC computation. */
  if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
    return -1;
  }

  *ok = 1;
  return ssl->init_num;
}
예제 #3
0
/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1),
 * maximum acceptable body length |max|. The first four bytes (msg_type and
 * length) are read in state |header_state|, the body is read in state
 * |body_state|. */
long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
                      long max, enum ssl_hash_message_t hash_message, int *ok) {
  uint8_t *p;
  unsigned long l;
  long n;
  int al;

  if (ssl->s3->tmp.reuse_message) {
    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
     * ssl_dont_hash_message would have to have been applied to the previous
     * call. */
    assert(hash_message == ssl_hash_message);
    ssl->s3->tmp.reuse_message = 0;
    if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
      al = SSL_AD_UNEXPECTED_MESSAGE;
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
      goto f_err;
    }
    *ok = 1;
    ssl->state = body_state;
    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
    ssl->init_num = (int)ssl->s3->tmp.message_size;
    return ssl->init_num;
  }

  p = (uint8_t *)ssl->init_buf->data;

  if (ssl->state == header_state) {
    assert(ssl->init_num < 4);

    for (;;) {
      while (ssl->init_num < 4) {
        int bytes_read = ssl3_read_bytes(
            ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], 4 - ssl->init_num, 0);
        if (bytes_read <= 0) {
          *ok = 0;
          return bytes_read;
        }
        ssl->init_num += bytes_read;
      }

      static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
      if (ssl->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) {
        break;
      }

      /* 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. */
      ssl->init_num = 0;

      if (ssl->msg_callback) {
        ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, p, 4, ssl,
                        ssl->msg_callback_arg);
      }
    }

    /* ssl->init_num == 4 */

    if (msg_type >= 0 && *p != msg_type) {
      al = SSL_AD_UNEXPECTED_MESSAGE;
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
      goto f_err;
    }
    ssl->s3->tmp.message_type = *(p++);

    n2l3(p, l);
    if (l > (unsigned long)max) {
      al = SSL_AD_ILLEGAL_PARAMETER;
      OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
      goto f_err;
    }

    if (l && !BUF_MEM_grow_clean(ssl->init_buf, l + 4)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
      goto err;
    }
    ssl->s3->tmp.message_size = l;
    ssl->state = body_state;

    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
    ssl->init_num = 0;
  }

  /* next state (body_state) */
  p = ssl->init_msg;
  n = ssl->s3->tmp.message_size - ssl->init_num;
  while (n > 0) {
    int bytes_read =
        ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], n, 0);
    if (bytes_read <= 0) {
      ssl->rwstate = SSL_READING;
      *ok = 0;
      return bytes_read;
    }
    ssl->init_num += bytes_read;
    n -= bytes_read;
  }

  /* Feed this message into MAC computation. */
  if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
    goto err;
  }
  if (ssl->msg_callback) {
    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
                    (size_t)ssl->init_num + 4, ssl, ssl->msg_callback_arg);
  }
  *ok = 1;
  return ssl->init_num;

f_err:
  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);

err:
  *ok = 0;
  return -1;
}
예제 #4
0
파일: s3_both.c 프로젝트: a397871706/plug
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;
}