📄 crypto.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.
*/
/*
* Crypto.c
*
* Created by Anders Edenbrandt, Fri Jun 02 07:59:31 2000.
*
* Revision history:
*
*/
#include "wtlsdef.h"
#ifdef LOG_EXTERNAL
#include "aapiclnt.h"
#include "logcodes.h"
#endif
/* Information below is from WTLS spec. Appendix A */
#define NUM_CIPHER_ALGS 12
static const struct {
UINT8 bulk_cipher_alg;
UINT8 is_exportable;
UINT8 type;
UINT8 key_material_length;
UINT8 key_size;
UINT8 iv_size;
UINT8 block_size;
} bulk_cipher_alg_info[NUM_CIPHER_ALGS] = {
{CIPHER_NULL, TRUE, CIPHER_TYPE_STREAM, 0, 0, 0, 0},
{CIPHER_RC5_CBC_40, TRUE, CIPHER_TYPE_BLOCK, 5, 16, 8, 8},
{CIPHER_RC5_CBC_56, TRUE, CIPHER_TYPE_BLOCK, 7, 16, 8, 8},
{CIPHER_RC5_CBC, FALSE, CIPHER_TYPE_BLOCK, 16, 16, 8, 8},
{CIPHER_DES_CBC_40, TRUE, CIPHER_TYPE_BLOCK, 5, 8, 8, 8},
{CIPHER_DES_CBC, FALSE, CIPHER_TYPE_BLOCK, 8, 8, 8, 8},
{CIPHER_3DES_CBC_EDE, FALSE, CIPHER_TYPE_BLOCK, 24, 24, 8, 8},
{CIPHER_IDEA_CBC_40, TRUE, CIPHER_TYPE_BLOCK, 5, 16, 8, 8},
{CIPHER_IDEA_CBC_56, TRUE, CIPHER_TYPE_BLOCK, 7, 16, 8, 8},
{CIPHER_IDEA_CBC, FALSE, CIPHER_TYPE_BLOCK, 16, 16, 8, 8},
{CIPHER_RC5_CBC_64, TRUE, CIPHER_TYPE_BLOCK, 8, 16, 8, 8},
{CIPHER_IDEA_CBC_64, TRUE, CIPHER_TYPE_BLOCK, 8, 16, 8, 8}
};
#define NUM_MAC_ALGS 8
static const struct {
UINT8 mac_alg;
UINT8 mac_key_size;
UINT8 mac_size;
UINT8 full_mac_size;
UINT8 mac_block_size;
} MAC_alg_info[NUM_MAC_ALGS] = {
{MAC_SHA_0, 0, 0, 20, 64},
{MAC_SHA_40, 20, 5, 20, 64},
{MAC_SHA_80, 20, 10, 20, 64},
{MAC_SHA, 20, 20, 20, 64},
{MAC_SHA_XOR_40, 0, 5, 20, 5},
{MAC_MD5_40, 16, 5, 16, 64},
{MAC_MD5_80, 16, 10, 16, 64},
{MAC_MD5, 16, 16, 16, 64}
};
/*
* For a given WTLS MAC algorithm, return the underlying
* secure hash algorithm.
*/
HashAlgorithm
wtls_crypto_MAC_to_hash_alg (wtls_MAC_algorithm alg)
{
switch (alg) {
case MAC_SHA_0:
case MAC_SHA_40:
case MAC_SHA_80:
case MAC_SHA:
case MAC_SHA_XOR_40:
return HASH_SHA;
case MAC_MD5_40:
case MAC_MD5_80:
case MAC_MD5:
return HASH_MD5;
default:
return 0;
}
}
/*
* Initialize a cryptographic object according to the given parameters.
*/
INT16
wtls_crypto_init (wtls_crypto_t *cobj,
BulkCipherAlgorithm bulk_cipher_alg,
wtls_MAC_algorithm mac_alg,
UINT8 compression_alg)
{
/* First, the bulk encryption algorithm. */
if (bulk_cipher_alg >= NUM_CIPHER_ALGS) {
wtls_err_set (ERR_INTERNAL, ERR_PROGRAMMING_ERROR,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
/* Consistency check */
if (bulk_cipher_alg !=
bulk_cipher_alg_info[bulk_cipher_alg].bulk_cipher_alg) {
wtls_err_set (ERR_INTERNAL, ERR_PROGRAMMING_ERROR,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
cobj->bulk_cipher_alg = bulk_cipher_alg;
cobj->is_exportable = bulk_cipher_alg_info[bulk_cipher_alg].is_exportable;
cobj->type = bulk_cipher_alg_info[bulk_cipher_alg].type;
cobj->key_material_length =
bulk_cipher_alg_info[bulk_cipher_alg].key_material_length;
cobj->key_size = bulk_cipher_alg_info[bulk_cipher_alg].key_size;
cobj->iv_size = bulk_cipher_alg_info[bulk_cipher_alg].iv_size;
cobj->block_size = bulk_cipher_alg_info[bulk_cipher_alg].block_size;
/* Next, the cryptographic hash algorithm. */
if (mac_alg >= NUM_MAC_ALGS) {
wtls_err_set (ERR_INTERNAL, ERR_PROGRAMMING_ERROR,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
/* Consistency check */
if (mac_alg != MAC_alg_info[mac_alg].mac_alg) {
wtls_err_set (ERR_INTERNAL, ERR_PROGRAMMING_ERROR,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
cobj->mac_alg = mac_alg;
cobj->mac_key_size = MAC_alg_info[mac_alg].mac_key_size;
cobj->mac_size = MAC_alg_info[mac_alg].mac_size;
cobj->full_mac_size = MAC_alg_info[mac_alg].full_mac_size;
cobj->mac_block_size = MAC_alg_info[mac_alg].mac_block_size;
cobj->hash_handle = NULL;
cobj->hash_alg = wtls_crypto_MAC_to_hash_alg (mac_alg);
/* Finally, the compression algorithm. */
if (compression_alg != COMPRESS_NULL) {
wtls_err_set (ERR_INTERNAL, ERR_PROGRAMMING_ERROR,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
cobj->compression_alg = COMPRESS_NULL;
return RET_OK;
}
/*
* Bulk encryption.
*/
INT16
wtls_crypto_encrypt (wtls_crypto_t *cobj,
BYTE *key, BYTE *iv,
BYTE *buf, UINT16 buflen,
BYTE *outbuf)
{
KeyObject keyobj;
INT16 r;
keyobj.key = key;
keyobj.keyLen = cobj->key_size;
keyobj.iv = iv;
keyobj.ivLen = cobj->iv_size;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_encrypt, "WTLS: calling CRYPTa_encrypt");
#endif
if ((r = CRYPTa_encrypt (cobj->bulk_cipher_alg, keyobj,
buf, buflen, outbuf)) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_ENCRYPT,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_encrypt,
"WTLS: error return from CRYPTa_encrypt: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
/*
* Bulk decryption.
*/
INT16
wtls_crypto_decrypt (wtls_crypto_t *cobj,
BYTE *key, BYTE *iv,
BYTE *buf, UINT16 buflen,
BYTE *outbuf)
{
KeyObject keyobj;
INT16 r;
keyobj.key = key;
keyobj.keyLen = cobj->key_size;
keyobj.iv = iv;
keyobj.ivLen = cobj->iv_size;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_decrypt, "WTLS: calling CRYPTa_decrypt");
#endif
if ((r = CRYPTa_decrypt (cobj->bulk_cipher_alg,
keyobj, buf, buflen,
outbuf)) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_DECRYPT,
1, ALERT_LEVEL_WARNING, ALERT_DESC_DECRYPTION_FAILED);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_decrypt,
"WTLS: error return from CRYPTa_decrypt: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
/*
* Secure hash algorithms.
*/
INT16
wtls_crypto_hash (wtls_crypto_t *cobj, BYTE *buf, UINT16 buflen, BYTE *digest)
{
INT16 r;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hash, "WTLS: calling CRYPTa_hash");
#endif
if ((r = CRYPTa_hash (cobj->hash_alg,
buf, buflen, digest)) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_HASH,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hash,
"WTLS: error return from CRYPTa_hash: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
INT16
wtls_crypto_hash_init (wtls_crypto_t *cobj)
{
INT16 r;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashInit, "WTLS: calling CRYPTa_hashInit");
#endif
if ((r = CRYPTa_hashInit (cobj->hash_alg,
&(cobj->hash_handle))) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_HASH_INIT,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashInit,
"WTLS: error return from CRYPTa_hashInit: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
INT16
wtls_crypto_hash_update (wtls_crypto_t *cobj, BYTE *buf, UINT16 buflen)
{
INT16 r;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashUpdate, "WTLS: calling CRYPTa_hashUpdate");
#endif
if ((r = CRYPTa_hashUpdate (cobj->hash_handle, buf, buflen)) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_HASH_UPDATE,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashUpdate,
"WTLS: error return from CRYPTa_hashUpdate: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
INT16
wtls_crypto_hash_final (wtls_crypto_t *cobj, BYTE *digest)
{
INT16 r;
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashFinal, "WTLS: calling CRYPTa_hashFinal");
#endif
if ((r = CRYPTa_hashFinal (cobj->hash_handle, digest)) != CRV_OK) {
wtls_err_set (ERR_CRYPTLIB, ERR_HASH_FINAL,
1, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
#ifdef LOG_EXTERNAL
CLNTa_log (0, log_wtls_CRYPTa_hashFinal,
"WTLS: error return from CRYPTa_hashFinal: %d\n", r);
#endif
return -1;
}
return RET_OK;
}
#if 0
/*
* The NULL compression algorithm, which does not do any compression.
* The WTLS spec requires that we support the NULL compression algorithm,
* and, in fact does not presently define any alternative method.
*/
INT16
wtls_crypto_compress (wtls_crypto_t *cobj,
BYTE *buf, UINT16 buflen,
BYTE *outbuf, UINT16 *outbuflen)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -