📄 connmgr.c
字号:
return -1;
}
conn->h_state->msgs |= BIT_SERVER_FINISHED;
wtls_cm_push_buffer (conn, buf, (UINT16)buflen);
/* PRF (master_secret, finished_label, H(handshake_messages))[0..11]; */
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_PRF, "WTLS: calling CRYPTa_PRF");
#endif
CRYPTa_PRF ((UINT16)conn->cm_proc,
cobj->hash_alg,
conn->read.master_secret_id, NULL, 0,
"server finished",
md, cobj->full_mac_size, 12);
return RET_OK;
}
/*
* Check a server Finished message that we received.
* This is defined in WTLS spec section 10.5.9.
*/
SDL_Integer
wtls_cm_check_server_finished (void *connptr, SDL_Integer result,
void *bufptr, SDL_Natural buflen)
{
wtls_connection_t *conn = (wtls_connection_t *)connptr;
BYTE *buf = (BYTE *)bufptr;
wtls_finished *sf = &(conn->h_state->server_finished);
INT16 i;
SDL_Integer retval = RET_OK;
if (result != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_SERVER_FINISHED,
1, ALERT_LEVEL_FATAL, ALERT_DESC_DECRYPT_ERROR);
return -1;
}
if (buflen < 12) {
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_SERVER_FINISHED,
1, ALERT_LEVEL_FATAL, ALERT_DESC_DECRYPT_ERROR);
DEALLOC (&buf);
return -1;
}
/* Is it the same value as in the Finished message? */
#ifndef TEST_WTLS
for (i = 0; i < 12; i++) {
if (buf[i] != sf->verify_data[i]) {
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_SERVER_FINISHED,
1, ALERT_LEVEL_FATAL, ALERT_DESC_DECRYPT_ERROR);
retval = -1;
break;
}
}
#endif
DEALLOC (&buf);
return retval;
}
SDL_Integer
wtls_cm_process_data_msg (void *connptr,
void *bufptr, SDL_Natural buflen,
TDUnitdataIndType *data_ind)
{
wtls_connection_t *conn = (wtls_connection_t *)connptr;
yAssF_AddressType (data_ind->DestinationAddress, conn->client_addr, XASS);
yAssF_AddressType (data_ind->SourceAddress, conn->server_addr, XASS);
data_ind->UserData = pdubuf_newFromData ((UINT16)buflen, (BYTE *)bufptr);
return RET_OK;
}
/*
* Check incoming messages.
* If we see a data message, then we have confirmation and go to
* state OPEN. If we see an alert, then check what type of alert.
*/
SDL_Integer
wtls_cm_opening_msg_ind (void *connptr, SDL_Natural msg_type,
void *bufptr, SDL_Natural buflen,
TDUnitdataIndType *data_ind)
{
wtls_connection_t *conn = (wtls_connection_t *)connptr;
BYTE *buf = (BYTE *)bufptr;
wap_cvt_t cvt_obj;
wtls_alert_t alert;
switch (msg_type) {
case CONTENT_TYPE_ALERT:
wap_cvt_init (&cvt_obj, WAP_CVT_DECODE_STATIC, buf, (UINT16)buflen);
if (!wtls_cvt_alert (&cvt_obj, &alert)) {
wtls_err_set (ERR_GENERAL, ERR_DECODING, 1,
ALERT_LEVEL_CRITICAL, ALERT_DESC_DECODE_ERROR);
return -1;
}
if (alert.level == ALERT_LEVEL_WARNING) {
if (alert.description == ALERT_DESC_DUPLICATE_FINISHED_RECEIVED) {
return RET_DUPLICATE_FINISHED;
}
}
wtls_err_set (ERR_RECEIVED_ALERT, ERR_RECEIVED_ALERT,
0, alert.level, alert.description);
return -1;
case CONTENT_TYPE_DATA:
yAssF_AddressType (data_ind->DestinationAddress, conn->client_addr, XASS);
yAssF_AddressType (data_ind->SourceAddress, conn->server_addr, XASS);
data_ind->UserData = pdubuf_newFromData ((UINT16)buflen, buf);
return RET_OK;
case CONTENT_TYPE_HANDSHAKE:
if (wtls_cm_get_handshake_type (buf, buflen) == HANDSHK_HELLO_REQUEST) {
DEALLOC (&buf);
return RET_HELLO_REQUEST;
}
DEALLOC (&buf);
default:
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_UNEXPECTED_MESSAGE,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_UNEXPECTED_MESSAGE);
return -1;
}
}
SDL_Integer
wtls_cm_get_next_outbound_message (void *connptr,
void **precptr)
{
wtls_connection_t *conn = (wtls_connection_t *)connptr;
*precptr = wtls_main_pop_outbound_message (conn->cm_proc);
if (*precptr == NULL) {
return RET_QUEUE_EMPTY;
}
return RET_OK;
}
void
wtls_cm_terminate (void *connptr, SDL_Boolean established)
{
wtls_connection_t *conn = (wtls_connection_t *)connptr;
if (established == SDL_True) {
CRYPTa_connectionTerminated (conn->server_addr.ViewID,
conn->server_addr.ChannelID);
CRYPTa_sessionActive (conn->write.master_secret_id, 0);
}
wtls_connection_free (conn);
}
/************************************************************
* Local functions
************************************************************/
static INT16
wtls_cm_check_client_key_id_index (wtls_connection_t *conn,
wtls_client_hello *ch,
wtls_server_hello *sh)
{
INT16 i;
wtls_key_exchange_id *key_exchange_id = &(conn->h_state->key_exch);
wap_cvt_t cvt_obj;
wap_cvt_init (&cvt_obj, WAP_CVT_DECODE_STATIC, ch->client_key_ids,
ch->client_key_id_len);
if (sh->client_key_id == 0) {
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_KEY_EXCHANGE_IDX,
1, ALERT_LEVEL_FATAL, ALERT_DESC_ILLEGAL_PARAMETER);
return -1;
}
for (i = sh->client_key_id; i > 0; i--) {
if (!wtls_cvt_key_exchange_id (&cvt_obj, key_exchange_id)) {
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_KEY_EXCHANGE_DECODE,
1, ALERT_LEVEL_FATAL, ALERT_DESC_ILLEGAL_PARAMETER);
return -1;
}
}
return RET_OK;
}
static INT16
wtls_cm_check_cipher_suite (wtls_connection_t *conn,
wtls_client_hello *ch,
wtls_server_hello *sh)
{
INT16 i;
for (i = 0; i < ch->cipher_suites_len; i += 2) {
if ((ch->cipher_suites[i] == sh->cipher_suite.bulk_cipher_alg)
&& (ch->cipher_suites[i + 1] == sh->cipher_suite.mac_alg))
break;
}
if (i >= ch->cipher_suites_len) {
wtls_err_set (ERR_HANDSHAKE_FAILURE, ERR_CIPHER_SUITE,
1, ALERT_LEVEL_FATAL, ALERT_DESC_ILLEGAL_PARAMETER);
return -1;
}
conn->h_state->pending.bulk_cipher_alg = sh->cipher_suite.bulk_cipher_alg;
conn->h_state->pending.mac_alg = sh->cipher_suite.mac_alg;
return RET_OK;
}
#define NUM_MAC_METHODS 3
static INT16
wtls_cm_make_cipher_suites (INT8 bearer,
BYTE *methods, UINT16 methodslen,
BYTE **cs, UINT8 *cslen)
{
BYTE *p;
UINT8 SHA_methods[NUM_MAC_METHODS];
UINT8 MD5_methods[NUM_MAC_METHODS];
INT16 i, j;
BYTE *cipher_suites;
/*
* Our current policy: for each encryption algorithm make cipher
* suites with MAC-algorithms in an order that depends on
* the bearer. The faster the bearer, the longer the MAC.
*/
cipher_suites = NEWARRAY (BYTE, methodslen * NUM_MAC_METHODS);
if (cipher_suites == NULL) {
return -1;
}
switch (bearer) {
case BEARER_ANY_UDP:
case BEARER_GSM_CSD:
case BEARER_GSM_GPRS:
case BEARER_BT:
SHA_methods[0] = WTLS_MAC(SHA, UDP, 1);
SHA_methods[1] = WTLS_MAC(SHA, UDP, 2);
SHA_methods[2] = WTLS_MAC(SHA, UDP, 3);
MD5_methods[0] = WTLS_MAC(MD5, UDP, 1);
MD5_methods[1] = WTLS_MAC(MD5, UDP, 2);
MD5_methods[2] = WTLS_MAC(MD5, UDP, 3);
break;
case BEARER_GSM_USSD:
SHA_methods[0] = WTLS_MAC(SHA, USSD, 1);
SHA_methods[1] = WTLS_MAC(SHA, USSD, 2);
SHA_methods[2] = WTLS_MAC(SHA, USSD, 3);
MD5_methods[0] = WTLS_MAC(MD5, USSD, 1);
MD5_methods[1] = WTLS_MAC(MD5, USSD, 2);
MD5_methods[2] = WTLS_MAC(MD5, USSD, 3);
break;
case BEARER_GSM_SMS:
default:
SHA_methods[0] = WTLS_MAC(SHA, SMS, 1);
SHA_methods[1] = WTLS_MAC(SHA, SMS, 2);
SHA_methods[2] = WTLS_MAC(SHA, SMS, 3);
MD5_methods[0] = WTLS_MAC(MD5, SMS, 1);
MD5_methods[1] = WTLS_MAC(MD5, SMS, 2);
MD5_methods[2] = WTLS_MAC(MD5, SMS, 3);
break;
}
p = cipher_suites;
for (i = 0; i < methodslen; i += 2) {
if (methods[i + 1] == HASH_SHA) {
for (j = 0; j < NUM_MAC_METHODS; j++) {
p[j * 2] = methods[i];
p[j * 2 + 1] = SHA_methods[j];
}
p += (NUM_MAC_METHODS * 2);
}
else if (methods[i + 1] == HASH_MD5) {
for (j = 0; j < NUM_MAC_METHODS; j++) {
p[j * 2] = methods[i];
p[j * 2 + 1] = MD5_methods[j];
}
p += (NUM_MAC_METHODS * 2);
}
}
*cs = cipher_suites;
*cslen = MIN ((p - cipher_suites), 254);;
return RET_OK;
}
/*
* Fetch values for connection parameters.
*
* When starting a new connection, certain parameters have to
* be given values. These values may depend on what type
* of bearer the connection uses. The different parameters are:
*
* Max number of retransmissions:
* The maximum number of times we are willing to resend a handshake
* message without getting an answer.
*
* Retry interval:
* The maximum time to wait for an answer to a handshake message,
* before sending it again. Time unit is 1/10 second.
*
* Timeout interval:
* A connection is closed down if no messages are exchanged during
* a time interval of this size. Time unit is 1/10 second.
*/
void
wtls_cm_get_connection_parameters (SDL_Octet bearer,
SDL_Integer *maxRetransmissions,
SDL_Integer *retryInterval)
{
switch (bearer) {
case BEARER_ANY_UDP:
case BEARER_GSM_CSD:
case BEARER_GSM_GPRS:
case BEARER_BT:
*maxRetransmissions = WTLS_MAX_RETRANSMISSIONS_UDP;
*retryInterval = WTLS_RETRANSMISSION_INTERVAL_UDP;
break;
case BEARER_GSM_USSD:
*maxRetransmissions = WTLS_MAX_RETRANSMISSIONS_USSD;
*retryInterval = WTLS_RETRANSMISSION_INTERVAL_USSD;
break;
case BEARER_GSM_SMS:
*maxRetransmissions = WTLS_MAX_RETRANSMISSIONS_SMS;
*retryInterval = WTLS_RETRANSMISSION_INTERVAL_SMS;
break;
}
}
/*
* Key refresh rate:
* How often do we want to refresh the encryption keys?
* A value n here means that we refresh the keys every 2^n messages.
* For example, if n = 3, we refresh after 8, 16, 24, etc. messages.
* The slower the bearer, the more often we do key refresh; the goal
* being to have the same time interval between key refreshes for
* all bearers.
*/
void
wtls_cm_set_key_refresh_rate (UINT8 bearer, UINT8 *key_refresh_rate)
{
switch (bearer) {
case BEARER_ANY_UDP:
case BEARER_GSM_CSD:
case BEARER_GSM_GPRS:
case BEARER_BT:
*key_refresh_rate = WTLS_KEY_REFRESH_RATE_UDP;
break;
case BEARER_GSM_USSD:
*key_refresh_rate = WTLS_KEY_REFRESH_RATE_USSD;
break;
case BEARER_GSM_SMS:
*key_refresh_rate = WTLS_KEY_REFRESH_RATE_SMS;
break;
}
}
static void
wtls_cm_mkaddr (AddressType *inaddr, BYTE *outaddr)
{
switch (inaddr->Bearer) {
case BEARER_ANY_UDP:
case BEARER_GSM_CSD:
case BEARER_GSM_GPRS:
case BEARER_BT:
outaddr[0] = BEARER_ANY_UDP;
break;
case BEARER_GSM_USSD:
outaddr[0] = BEARER_GSM_USSD;
break;
case BEARER_GSM_SMS:
outaddr[0] = BEARER_GSM_SMS;
break;
default:
outaddr[0] = BEARER_ANY_UDP;
break;
}
outaddr[1] = inaddr->Address.length;
memcpy (outaddr + 2, inaddr->Address.data, inaddr->Address.length);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -