Files
m241Neelima/components/ip_net2-6.9/ipeap/src/ipeap_sim_util.c
T
2026-07-30 11:19:44 +05:30

768 lines
22 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_util.c,v $ $Revision: 1.21 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_util.c,v $
* $Author: hchowdhu $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_sim.h"
#include "ipeap_sim_util.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifndef AES_BLOCK_SIZE
#define AES_BLOCK_SIZE 16
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_sha1_transform
*===========================================================================
* Description: Make a sha-1 transform
* Parameters: state - the current state
* data - data buffer to transform
* Returns:
*/
IP_STATIC void
ipeap_sim_sha1_transform(Ip_u8* state, Ip_u8 data[64]);
/*
*===========================================================================
* ipeap_sim_get_cipher
*===========================================================================
* Description: Get cipher context from cipher name and key length
* Parameters: name - the cipher name
* key_len - key lengths in bytes
* Returns: Cipher context or IP_NULL
*/
#ifndef IPMCRYPTO
IP_STATIC const EVP_CIPHER *
ipeap_sim_get_cipher(const char *name, Ip_u32 key_len);
#endif /* !IPMCRYPTO */
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_sha1_transform
*===========================================================================
*/
IP_STATIC void
ipeap_sim_sha1_transform(Ip_u8* state, Ip_u8 data[64])
{
SHA_CTX ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
ipcom_memcpy(&ctx.h0, state, 4);
ipcom_memcpy(&ctx.h1, state+4, 4);
ipcom_memcpy(&ctx.h2, state+8, 4);
ipcom_memcpy(&ctx.h3, state+12, 4);
ipcom_memcpy(&ctx.h4, state+16, 4);
SHA1_Transform(&ctx, data);
ipcom_memcpy(state, &ctx.h0, 4);
ipcom_memcpy(state+4, &ctx.h1, 4);
ipcom_memcpy(state+8, &ctx.h2, 4);
ipcom_memcpy(state+12, &ctx.h3, 4);
ipcom_memcpy(state+16, &ctx.h4, 4);
return;
}
/*
*===========================================================================
* ipeap_sim_get_cipher
*===========================================================================
*/
#ifndef IPMCRYPTO
IP_STATIC const EVP_CIPHER *
ipeap_sim_get_cipher(const char *name, Ip_u32 key_len)
{
const EVP_CIPHER *cipher = IP_NULL;
char alg_name[32] = {0};
ipcom_snprintf(alg_name, sizeof(alg_name), "%s%d", name, key_len*8);
cipher = EVP_get_cipherbyname(alg_name);
if (cipher == IP_NULL)
IPCOM_LOG1(ERR, "ipeap_sim_get_cipher: %s not found", name);
return cipher;
}
#endif /* !IPMCRYPTO */
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ip_alloc_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_alloc_value(Ip_value* value, Ip_u32 len)
{
value->p = ipcom_calloc(1, len);
if (IP_NULL == value->p)
return IPCOM_ERR_FAILED;
value->n = len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ip_free_value
*===========================================================================
*/
IP_GLOBAL void
ip_free_value(Ip_value* value)
{
if (IP_NULL != value->p)
ipcom_free(value->p);
value->p = IP_NULL;
value->n = 0;
return;
}
/*
*===========================================================================
* ip_set_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_set_value(Ip_value* value, Ip_u8* ptr, Ip_u32 len)
{
Ip_err err = IPCOM_SUCCESS;
ip_free_value(value);
if (IPCOM_SUCCESS != (err = ip_alloc_value(value, len)))
return err;
ipcom_memcpy(value->p, ptr, len);
value->n = len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ip_append_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_append_value(Ip_value* value, Ip_u8* ptr, Ip_u32 len)
{
value->p = ipcom_realloc(value->p, value->n + len);
if (IP_NULL == value->p)
return IPCOM_ERR_FAILED;
ipcom_memcpy(value->p + value->n, ptr, len);
value->n += len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_alloc_pkt
*===========================================================================
*/
IP_GLOBAL Ipeap_pkt*
ipeap_alloc_pkt(Ip_u32 size)
{
Ipeap_pkt* pkt = IP_NULL;
pkt = (Ipeap_pkt*)ipcom_calloc(1, size+sizeof(*pkt));
if (IP_NULL != pkt)
{
pkt->start = 0;
pkt->end = 0;
pkt->max_len = (int)size;
pkt->data = (Ip_u8*)pkt + sizeof(*pkt);
}
return pkt;
}
/*
*===========================================================================
* ipeap_free_pkt
*===========================================================================
*/
IP_GLOBAL void
ipeap_free_pkt(Ipeap_pkt* pkt)
{
if (IP_NULL != pkt)
ipcom_free(pkt);
return;
}
/*
*===========================================================================
* ipeap_set_pkt_data
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_set_pkt_data(Ipeap_pkt* pkt, Ip_u8* data, Ip_u32 len)
{
if ((IP_NULL == pkt) ||
((pkt->start + (int)len) > pkt->max_len))
return IPCOM_ERR_FAILED;
ipcom_memcpy(pkt->data+pkt->start, data, len);
pkt->end = pkt->start + (int)len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_get_pkt_data_size
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32
ipeap_get_pkt_data_size(
Ipeap_pkt* pkt)
{
return (Ip_u32)(pkt->max_len - pkt->end);
}
/*
*===========================================================================
* ipeap_get_pkt_data_buffer
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u8*
ipeap_get_pkt_data_buffer(
Ipeap_pkt* pkt)
{
return (Ip_u8*)pkt->data + pkt->start;
}
/*
*===========================================================================
* ipeap_compare_pkt_data
*===========================================================================
*/
IP_GLOBAL Ip_bool
ipeap_compare_pkt_data(Ipeap_pkt* pkt, Ip_u8* data, Ip_u32 len)
{
if ((IP_NULL == pkt) ||
((pkt->end - pkt->start) != (int)len) ||
(ipcom_memcmp(pkt->data+pkt->start, data, len) != 0))
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipeap_memory_to_string
*===========================================================================
*/
IP_GLOBAL char*
ipeap_memory_to_string(const Ip_u8* ptr, Ip_u32 size, Ip_u8 alignment)
{
static const char hex_char[] = "0123456789abcdef";
static const int byte_per_row = 32;
char* buf;
int row_size;
int i, j, k = 0;
int ws_per_row;
int full_rows, blr;
ws_per_row = byte_per_row / alignment;
row_size = 2 * byte_per_row + ws_per_row;
full_rows = (int)size / byte_per_row;
blr = (int)size % byte_per_row;
buf = ipcom_malloc( (Ip_size_t)(full_rows * row_size + 2 * blr + blr / alignment + 1) );
if (IP_NULL == buf)
return IP_NULL;
for (i = 0; i <= full_rows; i++)
{
k = 0;
for (j = 0; j < (i == full_rows ? blr : byte_per_row); j++)
{
if (j != 0 && j % alignment == 0)
buf[i * row_size + 2 * j + k++] = ' ';
buf[i * row_size + 2 * j + k] =
hex_char[ptr[i * byte_per_row + j] >> 4];
buf[i * row_size + 2 * j + k + 1] =
hex_char[ptr[i * byte_per_row + j] & 0x0F];
}
buf[i * row_size + 2 * j + k] = '\n';
}
buf[full_rows * row_size + 2 * blr + k] = '\0';
return buf;
}
/*
*===========================================================================
* ipeap_print_memory
*===========================================================================
*/
IP_GLOBAL void
ipeap_print_memory(
const char* prefix,
const Ip_u8* data,
Ip_u32 len)
{
char* hex_mem = IP_NULL;
hex_mem = ipeap_memory_to_string(data, len, 4);
if (hex_mem == IP_NULL)
{
IPCOM_LOG0(CRIT, "ipeap_print_memory: out of memory");
}
else
{
/* Make sure fit into syslog buffer */
if ((ipcom_strlen(hex_mem) + ipcom_strlen(prefix)) >= IPCOM_SYSLOG_MAX_SIZE)
{
len = IPCOM_SYSLOG_MAX_SIZE - (Ip_u32)ipcom_strlen(prefix);
hex_mem[len-4] = '.';
hex_mem[len-3] = '.';
hex_mem[len-2] = '.';
hex_mem[len-1] = 0;
}
IPCOM_LOG2(DEBUG2, "%s%s", prefix, hex_mem);
ipcom_free(hex_mem);
}
return;
}
/*
*===========================================================================
* ipeap_sim_prf
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_prf(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* buf,
Ip_u32 buf_len)
{
Ip_u8 xkey[64] = {0};
Ip_u32 t[5] = {0};
Ip_u32 _t[5] = {0};
Ip_s32 i = 0;
Ip_s32 j = 0;
Ip_s32 m = 0;
Ip_s32 k = 0;
Ip_u8* xpos = buf;
Ip_u32 carry = 0;
/* See section 6.4
*
* Key derivation is based on the random number generation specified in
* NIST Federal Information Processing Standards (FIPS) Publication
* 186-2 [PRF]. The pseudo-random number generator is specified in the
* change notice 1 (2001 October 5) of [PRF] (Algorithm 1) */
if (key_len >= 64)
{
IPCOM_LOG1(ERR, "ipeap_sim_prf: key too long (%d >= 64)", key_len);
return IPCOM_ERR_FAILED;
}
ipcom_memcpy(xkey, key, key_len);
ipcom_memset(xkey + key_len, 0, 64 - key_len);
t[0] = 0x67452301;
t[1] = 0xEFCDAB89;
t[2] = 0x98BADCFE;
t[3] = 0x10325476;
t[4] = 0xC3D2E1F0;
m = (Ip_s32)buf_len / 40;
for (j = 0; j < m; j++)
{
for (i = 0; i < 2; i++)
{
ipcom_memcpy(_t, t, 20);
ipeap_sim_sha1_transform((Ip_u8*)_t, xkey);
_t[0] = (Ip_u32)ip_htonl(_t[0]);
_t[1] = (Ip_u32)ip_htonl(_t[1]);
_t[2] = (Ip_u32)ip_htonl(_t[2]);
_t[3] = (Ip_u32)ip_htonl(_t[3]);
_t[4] = (Ip_u32)ip_htonl(_t[4]);
ipcom_memcpy(xpos, _t, 20);
carry = 1;
for (k = 19; k >= 0; k--)
{
carry += (Ip_u32)(xkey[k] + xpos[k]);
xkey[k] = (Ip_u8)carry;
carry >>= 8;
}
xpos += 20;
}
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_generate_mac
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_generate_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len)
{
const EVP_MD* evp_md = IP_NULL;
HMAC_CTX ctx = {0};
unsigned int hmac_len = 0;
Ip_u8* hmac = IP_NULL;
evp_md = EVP_get_digestbyname("sha1");
if (IP_NULL == evp_md)
{
IPCOM_LOG0(ERR, "ipeap_sim_generate_mac: sha1 algorithm not available");
return IPCOM_ERR_FAILED;
}
hmac_len = (unsigned int)EVP_MD_size(evp_md);
if (hmac_len < mac_len)
{
IPCOM_LOG2(ERR, "ipeap_sim_generate_mac: bad mac length (%d < %d)", hmac_len, mac_len);
return IPCOM_ERR_FAILED;
}
hmac = ipcom_malloc(hmac_len);
if (IP_NULL == hmac)
{
IPCOM_LOG0(ERR, "ipeap_sim_generate_mac: out of memory");
return IPCOM_ERR_FAILED;
}
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, key, (int)key_len, evp_md);
if (data1_len > 0)
HMAC_Update(&ctx, data1, data1_len);
if (data2_len > 0)
HMAC_Update(&ctx, data2, data2_len);
HMAC_Final(&ctx, hmac, (unsigned int*)&hmac_len);
HMAC_CTX_cleanup(&ctx);
ipcom_memcpy(mac, hmac, mac_len);
ipcom_free(hmac);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_verify_mac
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_verify_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len)
{
Ip_err err = IPCOM_SUCCESS;
Ip_u8* tmp = IP_NULL;
tmp = ipcom_malloc(mac_len);
if (IP_NULL == tmp)
return IPCOM_ERR_FAILED;
err = ipeap_sim_generate_mac(key,
key_len,
data1,
data1_len,
data2,
data2_len,
tmp,
mac_len);
if (IPCOM_SUCCESS != err)
{
IPCOM_LOG0(ERR, "ipeap_sim_verify_mac: failed to generate mac");
ipcom_free(tmp);
return err;
}
if (ipcom_memcmp(tmp, mac, mac_len) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_verify_mac: bad mac value");
ipcom_free(tmp);
return IPCOM_ERR_FAILED;
}
ipcom_free(tmp);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_aes_cbc_encrypt
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_encrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len)
{
Ip_err err = IPCOM_ERR_FAILED;
if (data_len == 0)
{
err = IPCOM_SUCCESS;
}
else if ((iv_len == AES_BLOCK_SIZE) && ((data_len % AES_BLOCK_SIZE) == 0))
{
#if defined(IPMCRYPTO)
AES_KEY ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
if (AES_set_encrypt_key(key, key_len*8, &ctx) < 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_encrypt: failed to set key");
err = IPCOM_ERR_FAILED;
}
else
{
err = IPCOM_SUCCESS;
AES_cbc_encrypt(data, data, data_len, &ctx, iv, AES_ENCRYPT);
}
#else /* defined (IPCRYPTO) */
const EVP_CIPHER *cipher = IP_NULL;
EVP_CIPHER_CTX ctx;
if ((cipher = ipeap_sim_get_cipher("aes", key_len)) != IP_NULL)
{
EVP_CIPHER_CTX_init(&ctx);
if (EVP_EncryptInit(&ctx, cipher, key, iv) &&
EVP_CIPHER_CTX_set_padding(&ctx, 0) &&
EVP_EncryptUpdate(&ctx, data, (int*)&data_len, data, (int)data_len))
{
err = IPCOM_SUCCESS;
}
else
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_encrypt: failed to encrypt");
}
(void)EVP_CIPHER_CTX_cleanup(&ctx);
}
#endif
}
return err;
}
/*
*===========================================================================
* ipeap_sim_aes_cbc_decrypt
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_decrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len)
{
Ip_err err = IPCOM_ERR_FAILED;
if (data_len == 0)
{
err = IPCOM_SUCCESS;
}
else if ((iv_len == AES_BLOCK_SIZE) && ((data_len % AES_BLOCK_SIZE) == 0))
{
#if defined(IPMCRYPTO)
AES_KEY ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
if (AES_set_decrypt_key(key, key_len*8, &ctx) < 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_decrypt: failed to set key");
err = IPCOM_ERR_FAILED;
}
else
{
err = IPCOM_SUCCESS;
AES_cbc_encrypt(data, data, data_len, &ctx, iv, AES_DECRYPT);
}
#else /* defined (IPCRYPTO) */
const EVP_CIPHER *cipher = IP_NULL;
EVP_CIPHER_CTX ctx;
if ((cipher = ipeap_sim_get_cipher("aes", key_len)) != IP_NULL)
{
EVP_CIPHER_CTX_init(&ctx);
if (EVP_DecryptInit(&ctx, cipher, key, iv) &&
EVP_CIPHER_CTX_set_padding(&ctx, 0) &&
EVP_DecryptUpdate(&ctx, data, (int*)&data_len, data, (int)data_len))
{
err = IPCOM_SUCCESS;
}
else
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_decrypt: failed to decrypt");
}
(void)EVP_CIPHER_CTX_cleanup(&ctx);
}
#endif
}
return err;
}
/*
*===========================================================================
* ipeap_sim_algorithm_test
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_algorithm_test(void)
{
Ip_err err = IPCOM_SUCCESS;
#ifdef IP_DEBUG
Ip_u8 IV[16] = {0};
Ip_u8 KEY[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
Ip_u8 MSG[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
Ip_u8 ENC[16] = {0x69,0xC4,0xE0,0xD8,0x6A,0x7B,0x04,0x30,0xD8,0xCD,0xB7,0x80,0x70,0xB4,0xC5,0x5A};
Ip_u8 tmp[16] = {0};
ipcom_memcpy(tmp, MSG, sizeof(MSG));
if (IPCOM_SUCCESS != (err = ipeap_sim_aes_cbc_encrypt(
KEY, sizeof(KEY),
IV, sizeof(IV),
tmp, sizeof(tmp))))
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES encrypt not available");
}
else if (ipcom_memcmp(ENC, tmp, sizeof(ENC)) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES bad encrypt value");
err = IPCOM_ERR_FAILED;
}
else if (IPCOM_SUCCESS != (err = ipeap_sim_aes_cbc_decrypt(
KEY, sizeof(KEY),
IV, sizeof(IV),
tmp, sizeof(tmp))))
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES decrypt not available");
}
else if (ipcom_memcmp(MSG, tmp, sizeof(MSG)) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES bad decrypt value");
err = IPCOM_ERR_FAILED;
}
#endif /* IP_DEBUG */
return err;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/