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

📄 connmgr.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (C) Ericsson Mobile Communications AB, 2000.
 * Licensed to AU-System AB.
 * All rights reserved.
 *
 * This software is covered by the license agreement between
 * the end user and AU-System AB, and may be used and copied
 * only in accordance with the terms of the said agreement.
 *
 * Neither Ericsson Mobile Communications AB nor AU-System AB
 * assumes any responsibility or liability for any errors or inaccuracies in
 * this software, or any consequential, incidental or indirect damage arising
 * out of the use of the Generic WAP Client software.
 */
/*
 * connmgr.c
 *
 * Created by Anders Edenbrandt, Wed Jun 02 09:10:51 1999.
 *
 * Revision history:
 *
 *
 * This file contains functions that are used by the SDL process
 * "ConnectionManager". That process implements the handshake protocol
 * in WTLS.
 *
 */
#include "wtlsdef.h"
#include "logcodes.h"

#include "aapicrpt.h"
#include "aapiclnt.h"
#include "capiclnt.h"
#include "tapimmi.h"
#include "aapimmi.h"

/*
 * Forward declarations of local functions.
 */

static INT16
wtls_cm_check_client_key_id_index (wtls_connection_t *conn,
                                   wtls_client_hello *ch,
                                   wtls_server_hello *sh);

static INT16
wtls_cm_check_cipher_suite (wtls_connection_t *conn,
                            wtls_client_hello *ch,
                            wtls_server_hello *sh);

static INT16
wtls_cm_make_cipher_suites (INT8 bearer,
                            BYTE *methods, UINT16 methodslen,
                            BYTE **cs, UINT8 *cslen);

static void
wtls_cm_set_key_refresh_rate (UINT8 bearer, UINT8 *key_refresh_rate);

static void
wtls_cm_mkaddr (AddressType *inaddr, BYTE *outaddr);


/************************************************************
 * External routines, called from SDL.
 ************************************************************/

SDL_Integer
wtls_cm_get_handshake_type (void *bufptr, SDL_Natural buflen)
{
  BYTE *buf = (BYTE *)bufptr;

  if ((buf == NULL) || (buflen < 1)) {
    return HANDSHK_ERROR;
  }

  return (SDL_Integer)buf[0];
}


/*
 * Initialize the Connection Manager process.
 */
void *
wtls_cm_init (SDL_PId cm_proc, SDL_PId rec_proc,
              AddressType src_addr, AddressType dst_addr)
{
  wtls_connection_t *conn = NEWARRAY (wtls_connection_t, 1);
  INT16             i;

  if (conn == NULL) {
    wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
                  1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
    return NULL;
  }

  wtls_main_set_connection_pointer (cm_proc, conn);

  yDef_AddressType (&(conn->client_addr));
  yDef_AddressType (&(conn->server_addr));
  yAssF_AddressType (conn->client_addr, src_addr, XASS);
  yAssF_AddressType (conn->server_addr, dst_addr, XASS);

  conn->cm_proc = cm_proc;
  conn->rec_proc = rec_proc;

  conn->h_state = NULL;
  wtls_connection_state_init (&(conn->read));
  wtls_connection_state_init (&(conn->write));

  conn->read_cksum = 0;
  for (i = 0; i < 4; i++) {
    conn->write_cksum[i] = 0;
  }
  conn->num_cksums = 0;

  conn->mask = 0;
  conn->out_records = NULL;

  return conn;
}

void
wtls_cm_delete_connections_session (void *connptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  if (conn == NULL) {
    return;
  }    

  /* Do not remove the session if we are in the middle of a
   * handshake, and are negotiating a new session. */
  if ((conn->h_state != NULL) /* Doing a handshake */
      && (conn->h_state->msgs & BIT_CLIENT_HELLO) /* We sent client hello */
      && ((conn->h_state->client_hello.session_id.length == 0)/* Not reusing session */
          || ((conn->h_state->msgs & BIT_SERVER_HELLO) &&
              (conn->h_state->server_hello.session_id.length > 0) &&
              ((conn->h_state->client_hello.session_id.length !=
                conn->h_state->server_hello.session_id.length) ||
               (memcmp (conn->h_state->client_hello.session_id.id,
                        conn->h_state->server_hello.session_id.id,
                        conn->h_state->client_hello.session_id.length) != 0)))
          )
      ) {
    return;
  }

  if (conn->read.session_id.length > 0) {
    /* There exists a cached session. */
    CRYPTa_sessionInvalidate (conn->read.master_secret_id);
  }
}

/*
 * Return True if a handshake is in progress and that handshake
 * can be aborted, i.e., if the pending state has not yet been
 * installed neither on the read nor the write side.
 */
SDL_Boolean
wtls_cm_can_abort_handshake (void *connptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  if ((conn != NULL) &&
      (conn->h_state != NULL) &&
      (conn->h_state->abortable == 1)) {
    return SDL_True;
  }
  else {
    return SDL_False;
  }
}

/*
 * Abort an ongoing handshake.
 */
void
wtls_cm_abort_handshake (void *connptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  if (conn != NULL) {
    /* Delete the data that is only used during the handshake. */
    wtls_handshake_state_free (conn->h_state);
    conn->h_state = NULL;
  }

}

/*
 * The handshake protocol has completed; store necessary
 * information, and delete data that is no longer required.
 */
void
wtls_cm_handshake_finished (void *connptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_server_hello *sh = &(conn->h_state->server_hello);
  BYTE              addr[18];
  UINT8             session_options = 0;

  if (conn->h_state->msgs & BIT_SERVER_HELLO_DONE) {
    /* It was a full handshake, hence we got a new
     * master secret. Remove links to it, in case it is a
     * slot that has been reused. */
    CRYPTa_peerDeleteLinks (conn->write.master_secret_id);
  }

  /* Cache the session. */
  if (sh->session_id.length > 0) {
    session_options |= SESSION_OPTIONS_RESUMABLE;
  }
  if (conn->h_state->msgs & BIT_SERVER_CERTIFICATE) {
    session_options |= SESSION_OPTIONS_SERVER_AUTH;
  }
  if (conn->h_state->msgs & BIT_CLIENT_CERTIFICATE_VERIFY) {
    session_options |= SESSION_OPTIONS_CLIENT_AUTH;
  }
  CRYPTa_sessionUpdate (conn->write.master_secret_id,
                        session_options,
                        sh->session_id.id,
                        (UINT8)sh->session_id.length,
                        conn->write.cobj.mac_alg,
                        conn->write.cobj.bulk_cipher_alg,
                        conn->write.cobj.compression_alg,
                        "\x00\x00\x00\x00",
                        CLNTa_currentTime ());

  wtls_cm_mkaddr (&(conn->server_addr), addr);
  CRYPTa_peerLinkToSession (addr, (UINT8)(addr[1] + 2),
                            (UINT16)conn->server_addr.PortNumber,
                            conn->write.master_secret_id);
  CRYPTa_sessionActive (conn->write.master_secret_id, 1);

  CRYPTa_connectionEstablished (conn->server_addr.ViewID,
                                conn->server_addr.ChannelID,
                                conn->write.master_secret_id);

  /* Delete the data that is only used during the handshake. */
  wtls_handshake_state_free (conn->h_state);
  conn->h_state = NULL;
}

/*
 * Perform necessary initializations to get a handshake started.
 */
SDL_Integer
wtls_cm_handshake_init (void *connptr, SDL_Boolean established)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  UINT32            gmt_unix_time;
  INT16             r;
  BYTE              addr[18];

  conn->h_state = wtls_handshake_state_new ();
  if (conn->h_state == NULL) {
    return -1;
  }

  wtls_cm_set_key_refresh_rate (conn->server_addr.Bearer,
                                &(conn->h_state->pending.key_refresh_rate));

  gmt_unix_time = CLNTa_currentTime ();
  if (cfg_wae_ua_current_time_is_gmt) {
    conn->h_state->pending.client_hello_random[0] =
      (BYTE)((gmt_unix_time >> 24) & 0xff);
  }
  else {
    conn->h_state->pending.client_hello_random[0] = 0;
  }
  conn->h_state->pending.client_hello_random[1] =
    (BYTE)((gmt_unix_time >> 16) & 0xff);
  conn->h_state->pending.client_hello_random[2] =
    (BYTE)((gmt_unix_time >> 8) & 0xff);
  conn->h_state->pending.client_hello_random[3] =
    (BYTE)(gmt_unix_time & 0xff);
#ifdef LOG_EXTERNAL
  CLNTa_log (0, log_wtls_CRYPTa_generateRandom,
             "WTLS: calling CRYPTa_generateRandom");
#endif
  if ((r = CRYPTa_generateRandom (&(conn->h_state->pending.client_hello_random[4]), 12)) != CRV_OK) {
    wtls_err_set (ERR_CRYPTLIB, ERR_GENERATE_RANDOM, 1,
                  ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
    CLNTa_log (0, log_wtls_CRYPTa_generateRandom,
               "WTLS: error return from CRYPTa_generateRandom: %d\n", r);
#endif
    return -1;
  }

  if (established == SDL_True) {
    conn->h_state->pending.master_secret_id = conn->read.master_secret_id;
    CRYPTa_sessionFetch ((UINT16)conn->cm_proc,
                         conn->read.master_secret_id);
  }
  else {
    wtls_cm_mkaddr (&(conn->server_addr), addr);
    CRYPTa_peerLookup ((UINT16)conn->cm_proc, addr, (UINT8)(addr[1] + 2),
                       (UINT16)conn->server_addr.PortNumber);
  }

  return RET_OK;
}

INT16
wtls_cm_session_fetch1 (void *connptr, SDL_Integer result,
                        SDL_Octet session_options,
                        void *session_id, SDL_Octet session_length,
                        SDL_Octet mac_alg, SDL_Octet cipher_alg,
                        SDL_Octet compression_alg, void *private_key_id,
                        SDL_Natural creation_time)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  BYTE              addr[18];
  INT16             r = RET_OK;

  /* To get rid of warnings: */
  creation_time = creation_time;

  if (private_key_id != NULL)
    OSConnectorFree (private_key_id);

  if ((result == CRV_OK) &&
      (session_options & SESSION_OPTIONS_RESUMABLE)) {
    memcpy (conn->h_state->pending.session_id.id, session_id,
            session_length);
    conn->h_state->pending.session_id.length = session_length;
    conn->h_state->pending.mac_alg = mac_alg;
    conn->h_state->pending.bulk_cipher_alg = cipher_alg;
    conn->h_state->pending.compression_alg = compression_alg;

    r = RET_USING_CURRENT_SESSION;
  }
  else {
    wtls_cm_mkaddr (&(conn->server_addr), addr);
    CRYPTa_peerLookup ((UINT16)conn->cm_proc, addr, (UINT8)(addr[1] + 2),
                       (UINT16)conn->server_addr.PortNumber);
  }
  if (session_id != NULL)
    OSConnectorFree (session_id);

  return r;
}

INT16
wtls_cm_session_fetch2 (void *connptr, SDL_Integer result,
                        SDL_Octet master_secret_id)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  if (result == CRV_OK) {
    conn->h_state->pending.master_secret_id = master_secret_id;
    CRYPTa_sessionFetch ((UINT16)conn->cm_proc, master_secret_id);
    return RET_OK;
  }
  else if (result != CRV_OK) {
    return RET_NO_PEER;
  }
  else {
    return -1;
  }
}

INT16
wtls_cm_session_fetch3 (void *connptr, SDL_Integer result,
                        SDL_Octet session_options,
                        void *session_id, SDL_Octet session_length,
                        SDL_Octet mac_alg, SDL_Octet cipher_alg,
                        SDL_Octet compression_alg, void *private_key_id,
                        SDL_Natural creation_time)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  /* To get rid of warnings: */
  creation_time = creation_time;

  if (private_key_id != NULL)
    OSConnectorFree (private_key_id);

  if ((result == CRV_OK) &&
      (session_options & SESSION_OPTIONS_RESUMABLE)) {
    memcpy (conn->h_state->pending.session_id.id, session_id,
            session_length);
    conn->h_state->pending.session_id.length = session_length;
    conn->h_state->pending.mac_alg = mac_alg;
    conn->h_state->pending.bulk_cipher_alg = cipher_alg;
    conn->h_state->pending.compression_alg = compression_alg;
  }
  else {
    conn->h_state->pending.session_id.length = 0;
  }
  if (session_id != NULL)
    OSConnectorFree (session_id);

  return RET_OK;
}

static void

⌨️ 快捷键说明

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