📄 connmgr.c
字号:
/*
* 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 + -