⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 record.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (diff > WINDOW_SIZE) {         /* Too old, beyond the window's */
    return -1;                      /* left edge. */
  }

  if (conn->mask & ((UINT32)1 << (diff - 1))) { /* Inside window, but */
    return -1;                              /* marked as having been seen. */
  }

  return RET_OK;  /* Passed all tests. */
}

/*
 * Update the read sequence number.
 * Assumes that seqNum has previously been checked and found valid.
 */
static void
wtls_rec_update_seqnum (UINT16 seqnum, wtls_connection_t *conn)
{
  UINT16 diff;

  if (seqnum >= conn->read.seqnum) {
    /* A new larger sequence number, we have to update the window. */
    diff = seqnum - conn->read.seqnum;
    if (diff < WINDOW_SIZE) { /* Move the window */
      conn->mask <<= (diff + 1);
      conn->mask |= 1;
    }
    else {
      conn->mask = 1;
    }
    conn->read.seqnum = seqnum + 1;
  }
  else {
    /* Set one of the bits in the window. */
    diff = conn->read.seqnum - seqnum;
    conn->mask |= ((UINT32)1 << (diff - 1));
  }
}

/*
 * Decrypt, check padding and MAC, and decompress a record.
 */
INT16
wtls_rec_decrypt_record (wtls_connection_state *cstate, wtls_record_t *rec)
{
  INT16  i;
  UINT16 len;
  UINT8  paddinglen;
  BYTE   md[MAX_HASH_MAC_SIZE];

  /* Decrypt: */
  if (cstate->cobj.type == CIPHER_TYPE_BLOCK) {
    BYTE iv1[MAX_IV_SIZE];

    /* Fix the per-record IV */
    for (i = 0; i < cstate->cobj.iv_size; i += 2) {
      iv1[i] = cstate->iv[i] ^ (rec->seqnum >> 8);
      iv1[i + 1] = cstate->iv[i + 1] ^ (rec->seqnum & 0xff);
    }
    len = rec->length;
    if (wtls_crypto_decrypt (&(cstate->cobj), cstate->encryption_key, iv1,
                             rec->fragment, rec->length,
                             rec->fragment) < 0) {
      return -1;
    }

    /* Check padding */
    paddinglen = rec->fragment[len - 1];
    if (len < paddinglen + 1) {
      wtls_err_set (ERR_GENERAL, ERR_BAD_PADDING,
                    1, ALERT_LEVEL_WARNING, ALERT_DESC_DECRYPTION_FAILED);
      return -1;
    }
    rec->length = len - (paddinglen + 1);
    for (i = 0; i < paddinglen; i++) {
      if (rec->fragment[len - i - 2] != paddinglen) {
        wtls_err_set (ERR_GENERAL, ERR_BAD_PADDING,
                      1, ALERT_LEVEL_WARNING, ALERT_DESC_DECRYPTION_FAILED);
        return -1;
      }
    }
  }
  else if (cstate->cobj.bulk_cipher_alg != CIPHER_NULL) {
    /* Currently we have no stream ciphers except the NULL alg. */
  }

  /* Check MAC: */
  if (cstate->cobj.mac_size > 0) {
    if (rec->length < cstate->cobj.mac_size) {
      wtls_err_set (ERR_GENERAL, ERR_BAD_MAC,
                    1, ALERT_LEVEL_WARNING, ALERT_DESC_BAD_RECORD_MAC);
      return -1;
    }
    rec->length -= cstate->cobj.mac_size;
    if (wtls_crypto_MAC (&(cstate->cobj), cstate->mac_secret,
                         rec->fragment, rec->length,
                         rec->seqnum, rec->rec_type, md) < 0) {
      return -1;
    }

    /* Compare with MAC in decrypted record. */
    for (i = 0; i < cstate->cobj.mac_size; i++) {
      if (rec->fragment[rec->length + i] != md[i]) {
        wtls_err_set (ERR_GENERAL, ERR_BAD_MAC,
                      1, ALERT_LEVEL_WARNING, ALERT_DESC_BAD_RECORD_MAC);
        return -1;
      }
    }
  }

  /* Decompress: */
  if (cstate->cobj.compression_alg != COMPRESS_NULL) {
    /* Currently we have no compression algorithms. */
  }

  return RET_OK;
}

/*
 * Get the next incoming record from this connection's list of
 * incoming records, and delete it from that list.
 */
INT16
wtls_rec_next_msg (void *connptr, void **pprec, SDL_Boolean same_SDU)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec;
  UINT16            msg_type;

  rec = wtls_main_peek_incoming_message (conn->cm_proc);
  if ((rec == NULL) ||
      (rec->is_first && (same_SDU == SDL_True))) {
    return RET_QUEUE_EMPTY;
  }
  rec = wtls_main_pop_incoming_message (conn->cm_proc);
  msg_type = rec->rec_type & RECTYPE_CONTENT_TYPE;

  /* STEP 1: does the record have a sequence number? */
  if (!(rec->rec_type & RECTYPE_SEQNUM)) {
    /* Is it allowed to leave out the sequence number? */
    if ((msg_type == CONTENT_TYPE_CCS) ||
        (msg_type == CONTENT_TYPE_HANDSHAKE) ||
        (conn->read.seqnum_mode == SEQNUMMODE_EXPLICIT)) {
      wtls_rec_delete_record (rec);
      return RET_NEXT_MESSAGE;
    }
  }

  /* STEP 2: does the use cipher spec bit agree with our current state? */
  if ((rec->rec_type & RECTYPE_USE_CS) && !conn->read.use_cipher_spec) {
    wtls_rec_delete_record (rec);
    return RET_NEXT_MESSAGE;
  }
  if (!(rec->rec_type & RECTYPE_USE_CS) && conn->read.use_cipher_spec) {
    /* Certain alerts are allowed to be transmitted in the clear. */
    if (msg_type == CONTENT_TYPE_ALERT) {
      UINT8 alertdesc = rec->fragment[1];
      if ((alertdesc == ALERT_DESC_NO_CONNECTION) ||
          (alertdesc == ALERT_DESC_BAD_RECORD_MAC) ||
          (alertdesc == ALERT_DESC_DECRYPTION_FAILED) ||
          (alertdesc == ALERT_DESC_RECORD_OVERFLOW) ||
          (alertdesc == ALERT_DESC_DECOMPRESSION_FAILURE)) {
        goto rec_ok;
      }
    }
    wtls_rec_delete_record (rec);
    return RET_NEXT_MESSAGE;
  }
  rec_ok:
  *pprec = rec;

  /* As a preparation to decryption, check if we need to
   * refresh the keys. */
  if (rec->rec_type & RECTYPE_USE_CS) {
    UINT16 s;

    /* Time for key refresh? */
    s = (~0 << conn->read.key_refresh_rate) & (rec->seqnum);
    if (s != conn->read.last_refresh) {
      conn->read.last_refresh = s;

      return RET_KEY_REFRESH;
    }
  }

  return RET_OK;
}

INT16
wtls_rec_continue_next_msg (void *connptr, void *recptr,
                            SDL_Natural *pmsg_type,
                            void **pbuf, SDL_Natural *pbuflen,
                            SDL_Natural *alert_level,
                            SDL_Natural *alert_desc)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec = (wtls_record_t *)recptr;
  wtls_alert_t      alert;
  UINT16            msg_type = rec->rec_type & RECTYPE_CONTENT_TYPE;

  *pbuf = NULL;
  *pbuflen = 0;

  /* STEP 3: If this record is encrypted, try to decrypt it.
   * If decryption fails, send a warning Alert and get next message. */
  if (rec->rec_type & RECTYPE_USE_CS) {
    if (wtls_rec_decrypt_record (&(conn->read), rec) < 0) {
      SDL_Integer errtype, errcode, sendalert;

      wtls_rec_delete_record (rec);
      wtls_err_get (&errtype, &errcode, &sendalert,
                    (SDL_Integer *)alert_level,
                    (SDL_Integer *)alert_desc);
      if (*alert_level == ALERT_LEVEL_WARNING) {
        return RET_DECRYPTION_FAILED;
      }
      return -1;
    }
  }

  /* STEP 4: If it is an alert, verify the checksum.
   * We accept checksums of any of the last 4 messages we sent. */ 
  if (msg_type == CONTENT_TYPE_ALERT) {
    INT16     i, limit;
    wap_cvt_t cvt_obj;

    wap_cvt_init (&cvt_obj, WAP_CVT_DECODE, rec->fragment, rec->length);
    if (!wtls_cvt_alert (&cvt_obj, &alert)) {
      /* Error in message format, ignore record silently. */
      wtls_err_set (ERR_GENERAL, ERR_DECODING, 1,
                    ALERT_LEVEL_CRITICAL, ALERT_DESC_DECODE_ERROR);
      wtls_rec_delete_record (rec);
      return RET_NEXT_MESSAGE;
    }
    limit = MIN (4, conn->num_cksums);
    for (i = 0; i < limit; i++) {
      if (alert.checksum == conn->write_cksum[i]) {
        /* We found a match. */
        break;
      }
    }
#ifndef TEST_WTLS
    if (i == limit) {
      /* No match, ignore record silently. */
      wtls_rec_delete_record (rec);
      return RET_NEXT_MESSAGE;
    }
#endif
    /* Fatal Alert sent in cleartext should be treated as critical. */
    if ((alert.level == ALERT_LEVEL_FATAL) &&
        (!(rec->rec_type & RECTYPE_USE_CS))) {
      alert.level = ALERT_LEVEL_CRITICAL;
    }
    *alert_level = (SDL_Natural)alert.level;
    *alert_desc = (SDL_Natural)alert.description;
  }

  /* STEP 5: If it is an alert of type "no connection", go to step 6.
   * Otherwise, check the sequence number. */
  if ((msg_type != CONTENT_TYPE_ALERT) ||
      (alert.description != ALERT_DESC_NO_CONNECTION)) {
    if (wtls_rec_check_seqnum (rec->seqnum, conn) < 0) {
      /* Invalid sequence number, ignore silently. */
      wtls_rec_delete_record (rec);
      return RET_NEXT_MESSAGE;
    }
  }
  /* Handshake messages must increment sequence numbers by 1. */
  /* How can we check this?  */
  /* (Consider, e.g., if this is the FIRST handshake message?) */

  /* STEP 6: Increment the sequence number. */
  wtls_rec_update_seqnum (rec->seqnum, conn);

#ifdef LOG_WTLS
  wtls_log_msg (0, "\n--------PROCESSING RECEIVED RECORD--------\n");
  wtls_log_record (rec, LOG_INCOMING);
#endif

  /* STEP 7: Retrieve buffer and delete record. */
  if ((msg_type == CONTENT_TYPE_HANDSHAKE) &&
      (rec->fragment != NULL) &&
      (rec->fragment[0] == HANDSHK_HELLO_REQUEST)) {
    msg_type = CONTENT_TYPE_HELLO_REQUEST;
  }
  *pbuflen = rec->length;
  *pbuf = rec->fragment;
  if ((msg_type == CONTENT_TYPE_CCS) ||
      (msg_type == CONTENT_TYPE_ALERT) ||
      (msg_type == CONTENT_TYPE_HELLO_REQUEST)) {
    DEALLOC (&(rec->fragment));
    *pbuf = NULL;
    *pbuflen = 0;
  }
  rec->fragment = NULL;

  *pmsg_type = msg_type;
  wtls_rec_delete_record (rec);

  if (msg_type == CONTENT_TYPE_ALERT) {
    if (alert.description == ALERT_DESC_TIME_REQUIRED) {
      return RET_TIME_REQUIRED;
    }
    else {
      return RET_ALERT;
    }
  }

  return RET_OK;
}

/*
 * Routines to handle the lists of records.
 */

/*
 * Add a record at the end of a list of records.
 */
void
wtls_rec_list_append (wtls_record_t *rec, wtls_record_t **rec_list)
{
  rec->next = NULL;
  if (*rec_list == NULL) {
    *rec_list = rec;
  }
  else {
    wtls_record_t *p = *rec_list;
    while (p->next != NULL) {
      p = p->next;
    }
    p->next = rec;
  }
}

/*
 * Remove, and return, the first record in a list of records.
 */
wtls_record_t *
wtls_rec_list_pop (wtls_record_t **rec_list)
{
  wtls_record_t *rec = *rec_list;

  if (rec != NULL) {
    *rec_list = rec->next;
    rec->next = NULL;
  }

  return rec;
}

void
wtls_rec_delete_record (wtls_record_t *rec)
{
  if (rec) {
    DEALLOC (&(rec->fragment));
    OSConnectorFree (rec);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -