1357 lines
44 KiB
C
1357 lines
44 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipipsec_crypt.c,v $ $Revision: 1.36.10.7 $
|
|
* $Source: /home/interpeak/CVSRoot/ipipsec2/src/ipipsec_crypt.c,v $
|
|
* $Author: jwang9 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Lennart Bang <lob@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifndef IPCOM_KERNEL
|
|
#define IPCOM_KERNEL
|
|
#endif
|
|
#include "ipipsec_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_clib.h>
|
|
|
|
#include "ipipsec_h.h"
|
|
#include "ipipsec_pfkeyv2.h"
|
|
#ifdef OPENSSL_FIPS
|
|
#include <openssl/fips.h>
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_EXTERN Ipipsec_data ipipsec;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_SYSLOG_PRIORITY IPIPSEC_SYSTEM_PRIORITY
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPIPSEC
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPIPSEC_USE_AESMAC
|
|
IP_STATIC int AESMAC_Init(Ipipsec_auth_ctx *ctx);
|
|
IP_STATIC void AESMAC_Update(Ipipsec_auth_ctx *ctx, IP_CONST Ip_u8 *data, Ip_u32 length);
|
|
IP_STATIC void AESMAC_Final(Ip_u8 *digest, Ipipsec_auth_ctx *ctx);
|
|
#endif
|
|
|
|
#if defined(IPIPSEC_USE_AES) || defined(IPIPSEC_USE_AESMAC)
|
|
IP_STATIC Ip_s32 ipipsec_aes_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
IP_STATIC void ipipsec_aes_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_AES
|
|
IP_STATIC void ipipsec_aes_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_AESCTR
|
|
IP_STATIC Ip_s32 ipipsec_aesctr_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
IP_STATIC void ipipsec_aesctr_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_DES
|
|
IP_STATIC void ipipsec_descbc_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC void ipipsec_descbc_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC Ip_s32 ipipsec_descbc_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_3DES
|
|
IP_STATIC void ipipsec_3descbc_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC void ipipsec_3descbc_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC Ip_s32 ipipsec_3descbc_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_CAST
|
|
IP_STATIC void ipipsec_cast_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC void ipipsec_cast_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC Ip_s32 ipipsec_cast_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
#endif
|
|
|
|
#ifdef IPIPSEC_USE_BLOWFISH
|
|
IP_STATIC void ipipsec_blowfish_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC void ipipsec_blowfish_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv);
|
|
IP_STATIC Ip_s32 ipipsec_blowfish_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *ekey);
|
|
#endif
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_auth_method
|
|
*===========================================================================
|
|
*/
|
|
|
|
IP_GLOBAL IP_CONST Ipipsec_auth_method ipipsec_auth_method[SADB_AALG_NUM] =
|
|
{
|
|
/*********** MD5HMAC96 ***********/
|
|
{
|
|
SADB_AALG_MD5HMAC,
|
|
#ifdef IPIPSEC_USE_MD5
|
|
MD5_CBLOCK,
|
|
MD5_DIGEST_LENGTH /* 16 */ , MD5_DIGEST_LENGTH /* 16 */ ,
|
|
MD5_DIGEST_LENGTH /* 16 */ , IPIPSEC_HMAC_AUTHLEN /* 12 */,
|
|
(Hash_init)MD5_Init,
|
|
(Hash_update)MD5_Update,
|
|
(Hash_final)MD5_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** SHA1HMAC96 ***********/
|
|
{
|
|
SADB_AALG_SHA1HMAC,
|
|
#ifdef IPIPSEC_USE_SHA
|
|
SHA_CBLOCK,
|
|
SHA_DIGEST_LENGTH /* 20 */, SHA_DIGEST_LENGTH /* 20 */,
|
|
SHA_DIGEST_LENGTH /* 20 */, IPIPSEC_HMAC_AUTHLEN /* 12 */,
|
|
(Hash_init)SHA1_Init,
|
|
(Hash_update)SHA1_Update,
|
|
(Hash_final)SHA1_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
/*********** SHA2_256_HMAC ***********/
|
|
{
|
|
SADB_X_AALG_SHA2_256_HMAC,
|
|
#ifdef IPIPSEC_USE_SHA256
|
|
SHA256_CBLOCK,
|
|
SHA256_DIGEST_LENGTH /* 32 */, SHA256_DIGEST_LENGTH /* 32 */,
|
|
SHA256_DIGEST_LENGTH /* 32 */, SHA256_DIGEST_LENGTH / 2 /* 16 */,
|
|
(Hash_init)SHA256_Init,
|
|
(Hash_update)SHA256_Update,
|
|
(Hash_final)SHA256_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
/*********** SHA2_384_HMAC ***********/
|
|
{
|
|
SADB_X_AALG_SHA2_384_HMAC,
|
|
#ifdef IPIPSEC_USE_SHA384
|
|
SHA512_CBLOCK,
|
|
SHA384_DIGEST_LENGTH /* 48 */, SHA384_DIGEST_LENGTH /* 48 */,
|
|
SHA384_DIGEST_LENGTH /* 48 */, SHA384_DIGEST_LENGTH / 2 /* 24*/,
|
|
(Hash_init)SHA384_Init,
|
|
(Hash_update)SHA384_Update,
|
|
(Hash_final)SHA384_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
/*********** SHA2_512_HMAC ***********/
|
|
{
|
|
SADB_X_AALG_SHA2_512_HMAC,
|
|
#ifdef IPIPSEC_USE_SHA512
|
|
SHA512_CBLOCK,
|
|
SHA512_DIGEST_LENGTH /* 64 */, SHA512_DIGEST_LENGTH /* 64 */,
|
|
SHA512_DIGEST_LENGTH /* 64 */, SHA512_DIGEST_LENGTH / 2 /* 32 */,
|
|
(Hash_init)SHA512_Init,
|
|
(Hash_update)SHA512_Update,
|
|
(Hash_final)SHA512_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** RIPEMD160HMAC96 ***********/
|
|
{
|
|
SADB_X_AALG_RIPEMD160HMAC,
|
|
#ifdef IPIPSEC_USE_RIPEMD
|
|
RIPEMD160_CBLOCK,
|
|
RIPEMD160_DIGEST_LENGTH /* 20 */, RIPEMD160_DIGEST_LENGTH /* 20 */,
|
|
RIPEMD160_DIGEST_LENGTH /* 20 */, IPIPSEC_HMAC_AUTHLEN /* 12 */,
|
|
(Hash_init)RIPEMD160_Init,
|
|
(Hash_update)RIPEMD160_Update,
|
|
(Hash_final)RIPEMD160_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** SADB_X_AALG_AESXCBCMAC96 ***********/
|
|
{
|
|
SADB_X_AALG_AES_XCBC_MAC,
|
|
#ifdef IPIPSEC_USE_AESMAC
|
|
AES_BLOCK_SIZE,
|
|
AES_BLOCK_SIZE /* 16 */, AES_BLOCK_SIZE /* 16 */,
|
|
AES_BLOCK_SIZE /* 16 */, IPIPSEC_HMAC_AUTHLEN /* 12 */,
|
|
(Hash_init)AESMAC_Init,
|
|
(Hash_update)AESMAC_Update,
|
|
(Hash_final)AESMAC_Final
|
|
#else
|
|
0, 0, 0, 0, 0, IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
};
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_encrypt_method
|
|
*===========================================================================
|
|
* Crypt entry:
|
|
* {
|
|
* id,
|
|
* key_size,
|
|
* minkey_bytes, maxkey_bytes, block_bytes, iv_bytes,
|
|
* encrypt function,
|
|
* decrypt function,
|
|
* setkey function
|
|
* }
|
|
*
|
|
*/
|
|
IP_GLOBAL IP_CONST Ipipsec_encrypt_method ipipsec_encrypt_method[SADB_EALG_NUM] =
|
|
{
|
|
/*********** DESCBC (64 bits -acctually 56 bits key) ***********/
|
|
{
|
|
SADB_EALG_DESCBC,
|
|
#ifdef IPIPSEC_USE_DES
|
|
sizeof(des_key_schedule) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
8, 8, 8, 8,
|
|
ipipsec_descbc_encrypt,
|
|
ipipsec_descbc_decrypt,
|
|
ipipsec_descbc_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
8, 8, 8, 8,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** 3DESCBC ***********/
|
|
{
|
|
SADB_EALG_3DESCBC,
|
|
#ifdef IPIPSEC_USE_3DES
|
|
3 * sizeof(des_key_schedule) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
24, 24, 8, 8,
|
|
ipipsec_3descbc_encrypt,
|
|
ipipsec_3descbc_decrypt,
|
|
ipipsec_3descbc_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
24, 24, 8, 8,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** BLOWFISH ***********/
|
|
{
|
|
SADB_X_EALG_BLOWFISHCBC,
|
|
#ifdef IPIPSEC_USE_BLOWFISH
|
|
sizeof(BF_KEY) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
5, IPIPSEC_BLF_MAXKEYLEN, 8, 8,
|
|
ipipsec_blowfish_encrypt,
|
|
ipipsec_blowfish_decrypt,
|
|
ipipsec_blowfish_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
5, IPIPSEC_BLF_MAXKEYLEN, 8, 8,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** CAST ***********/
|
|
{
|
|
SADB_X_EALG_CASTCBC,
|
|
#ifdef IPIPSEC_USE_CAST
|
|
sizeof(CAST_KEY) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
5, 16, 8, 8,
|
|
ipipsec_cast_encrypt,
|
|
ipipsec_cast_decrypt,
|
|
ipipsec_cast_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
5, 16, 8, 8,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** AESCBC (128,192,256 bits only) ***********/
|
|
{
|
|
SADB_X_EALG_AESCBC,
|
|
#ifdef IPIPSEC_USE_AES
|
|
2 * sizeof(AES_KEY) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
16, 32, 16, 16,
|
|
ipipsec_aes_encrypt,
|
|
ipipsec_aes_decrypt,
|
|
ipipsec_aes_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
16, 32, 16, 16,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
},
|
|
|
|
|
|
/*********** AESCTR (128,192,256 bits + 32 bits nonce) ***********/
|
|
{
|
|
SADB_X_EALG_AESCTR,
|
|
#ifdef IPIPSEC_USE_AESCTR
|
|
sizeof(struct aesctr_struct) + sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
20, 36, 16, 8,
|
|
ipipsec_aesctr_encrypt,
|
|
ipipsec_aesctr_encrypt,
|
|
ipipsec_aesctr_setkey
|
|
#else
|
|
sizeof(Ipipsec_sa_encrypt) - sizeof(Ipipsec_encrypt_key),
|
|
16, 16, 16, 8,
|
|
IP_NULL, IP_NULL, IP_NULL
|
|
#endif
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 ENCRYPTION FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_descbc_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_DES
|
|
IP_STATIC void
|
|
ipipsec_descbc_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
des_cbc_encrypt(data, data, length, key->des, (des_cblock *)iv, DES_ENCRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_descbc_decrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_descbc_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
des_cbc_encrypt(data, data, length, key->des, (des_cblock *)iv, DES_DECRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_descbc_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_descbc_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
if (length != DES_KEY_SZ)
|
|
return -1;
|
|
|
|
if (des_set_key((const_des_cblock *)secret, key->des) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_DES */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_3descbc_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_3DES
|
|
IP_STATIC void
|
|
ipipsec_3descbc_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
des_ede3_cbc_encrypt(data, data, length,
|
|
key->des3.key1, key->des3.key2, key->des3.key3,
|
|
(des_cblock *)iv, DES_ENCRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_3descbc_decrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_3descbc_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
des_ede3_cbc_encrypt(data, data, length,
|
|
key->des3.key1, key->des3.key2, key->des3.key3,
|
|
(des_cblock *)iv, DES_DECRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_3descbc_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_3descbc_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
/* 3 keys a 8 bytes */
|
|
if (length != 24)
|
|
return -1;
|
|
|
|
/* Check that the 3 des keys differ */
|
|
if (ipcom_memcmp(secret, secret + DES_KEY_SZ, DES_KEY_SZ) == 0
|
|
|| ipcom_memcmp(secret, secret + 2*DES_KEY_SZ, DES_KEY_SZ) == 0
|
|
|| ipcom_memcmp(secret + DES_KEY_SZ, secret + 2*DES_KEY_SZ, DES_KEY_SZ) == 0)
|
|
return -1;
|
|
|
|
/* Set the 3 keys */
|
|
if (des_set_key((const_des_cblock *)secret, key->des3.key1) != 0
|
|
|| des_set_key((const_des_cblock *)(secret + 8), key->des3.key2) != 0
|
|
|| des_set_key((const_des_cblock *)(secret + 16), key->des3.key3) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_3DES */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_cast_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_CAST
|
|
IP_STATIC void
|
|
ipipsec_cast_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
CAST_cbc_encrypt(data, data, length, &key->cast, iv, CAST_ENCRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_cast_decrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_cast_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
CAST_cbc_encrypt(data, data, length, &key->cast, iv, CAST_DECRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_cast_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_cast_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
CAST_set_key(&key->cast, length, secret);
|
|
return 0;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_CAST */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_blowfish_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_BLOWFISH
|
|
IP_STATIC void
|
|
ipipsec_blowfish_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
BF_cbc_encrypt(data, data, length, &key->bf, iv, BF_ENCRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_blowfish_decrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_blowfish_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
BF_cbc_encrypt(data, data, length, &key->bf, iv, BF_DECRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_blowfish_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_blowfish_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
BF_set_key(&key->bf, length, secret);
|
|
return 0;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_BLOWFISH */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_crypt_random_fill
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipipsec_crypt_random_fill(Ip_u8 *buf, int length)
|
|
{
|
|
int i;
|
|
|
|
/*!!FIXME: too expensive! */
|
|
for (i = 0; i < length; i++)
|
|
buf[i] = (Ip_u8)ipcom_random();
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_aes_decrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_AES
|
|
IP_STATIC void
|
|
ipipsec_aes_decrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
AES_cbc_encrypt(data, data, (unsigned long)length, (AES_KEY *)&key->aes[1],
|
|
(unsigned char *)iv, AES_DECRYPT);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(IPIPSEC_USE_AES) || defined(IPIPSEC_USE_AESMAC)
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_aes_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_aes_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
AES_cbc_encrypt(data, data, (unsigned long)length, (AES_KEY *)&key->aes[0],
|
|
(unsigned char *)iv, AES_ENCRYPT);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_aes_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_aes_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
if (length != 16 && length != 24 && length != 32)
|
|
return -1;
|
|
|
|
(void)AES_set_encrypt_key(secret, length * 8, &key->aes[0]);
|
|
(void)AES_set_decrypt_key(secret, length * 8, &key->aes[1]);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* defined(IPIPSEC_USE_AES) || defined(IPIPSEC_USE_AESMAC) */
|
|
|
|
|
|
#ifdef IPIPSEC_USE_AESCTR
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_incr_64bit
|
|
*===========================================================================
|
|
* Description: increace iv
|
|
* Parameters: iv
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_incr_64bit(Ip_u8* ptr)
|
|
{
|
|
int i = 8;
|
|
Ip_u8 c;
|
|
|
|
do
|
|
{
|
|
i--;
|
|
c = ptr[i];
|
|
++c;
|
|
ptr[i] = c;
|
|
if (c)
|
|
return;
|
|
} while (i);
|
|
return;
|
|
}
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_aesctr_encrypt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipipsec_aesctr_encrypt(Ip_u8 *data, Ip_u32 length, Ipipsec_encrypt_key *key, Ip_u8 *iv)
|
|
{
|
|
unsigned char ivec[AES_BLOCK_SIZE];
|
|
unsigned char ecount_buf[AES_BLOCK_SIZE]={0};
|
|
unsigned int num = 0;
|
|
ivec[0] = key->aesctr.nonce[0];
|
|
ivec[1] = key->aesctr.nonce[1];
|
|
ivec[2] = key->aesctr.nonce[2];
|
|
ivec[3] = key->aesctr.nonce[3];
|
|
ipcom_memcpy(ivec + 4, iv, 8);
|
|
ivec[12] = 0; ivec[13] = 0; ivec[14] = 0; ivec[15] = 1;
|
|
|
|
/* Must use data lock because AESCTR encrypt is non-reentrant */
|
|
IPIPSEC_DATA_LOCK();
|
|
|
|
AES_ctr128_encrypt(data, data, (unsigned long)length, (AES_KEY *)&key->aesctr.key,
|
|
ivec,
|
|
ecount_buf,
|
|
&num);
|
|
ipipsec_incr_64bit(iv);
|
|
|
|
IPIPSEC_DATA_UNLOCK();
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_aesctr_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipipsec_aesctr_setkey(Ip_u8 *secret, Ip_u32 length, Ipipsec_encrypt_key *key)
|
|
{
|
|
length -= 4; /* remove nonce 32-bits */
|
|
|
|
if (length != 16 && length != 24 && length != 32)
|
|
return -1;
|
|
|
|
/* Clear aesctr structure (important for ecount_buf and num) */
|
|
ipcom_memset(&key->aesctr, 0, sizeof(key->aesctr));
|
|
|
|
/* Save nonce */
|
|
ipcom_memcpy(key->aesctr.nonce, secret + length, 4);
|
|
|
|
/* Store key */
|
|
if (AES_set_encrypt_key(secret, length * 8, &key->aesctr.key) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* IPIPSEC_USE_AESCTR */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_auth_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_s32
|
|
ipipsec_auth_setkey(Ipipsec_sa_auth ** auth, Ip_u8 id, Ip_u8 *key, Ip_u32 bytes)
|
|
{
|
|
Ipipsec_sa_auth * a;
|
|
Ip_u32 i;
|
|
int aalg;
|
|
|
|
*auth = IP_NULL;
|
|
|
|
/* Check if the authentication algorithm is supported/implemented. */
|
|
for (aalg = 0; aalg < SADB_AALG_NUM; aalg++)
|
|
if (ipipsec_auth_method[aalg].id == id
|
|
&& ipipsec_auth_method[aalg].init != IP_NULL)
|
|
{
|
|
#ifdef OPENSSL_FIPS
|
|
if (ipipsec_auth_method[aalg].init == (Hash_init)MD5_Init && FIPS_mode())
|
|
return -IP_ERRNO_EINVAL;
|
|
#endif
|
|
goto found;
|
|
}
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
found:
|
|
/* Check the authentication key length. */
|
|
if (bytes < ipipsec_auth_method[aalg].minkey_bytes ||
|
|
bytes > ipipsec_auth_method[aalg].maxkey_bytes ||
|
|
(bytes & 0x3L)) /* key-length must be multiple of 32 bits. */
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
ip_assert(bytes <= IPIPSEC_AUTH_MAXKEYLEN);
|
|
|
|
/* Get memory to store the key. */
|
|
a = (Ipipsec_sa_auth *)ipipsec_shm_calloc(1, sizeof(Ipipsec_sa_auth));
|
|
if (a == IP_NULL)
|
|
return -IP_ERRNO_ENOMEM;
|
|
|
|
/* Save key length but not the raw key. */
|
|
a->keyLen = bytes;
|
|
a->aindex = aalg;
|
|
|
|
#ifdef IPIPSEC_USE_AESMAC
|
|
/*** AES MAC ***/
|
|
if (id == SADB_X_AALG_AES_XCBC_MAC)
|
|
{
|
|
ipcom_memcpy(a->i_ctx.aes.key, key, a->keyLen);
|
|
if (!ipipsec_auth_method[aalg].init(&a->i_ctx))
|
|
{
|
|
ipipsec_shm_free(a);
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
}
|
|
else
|
|
#endif /* IPIPSEC_USE_AESMAC */
|
|
|
|
/*** HMAC ***/
|
|
{
|
|
Ip_u8 keybuf[IPIPSEC_AUTH_MAXKEYLEN];
|
|
|
|
ipcom_memcpy(keybuf, key, bytes); /* No need to save key for HMAC */
|
|
|
|
/* HMAC - precompute the I pad. */
|
|
for (i = 0; i < bytes; i++)
|
|
keybuf[i] ^= HMAC_IPAD;
|
|
if (!ipipsec_auth_method[aalg].init(&a->i_ctx))
|
|
{
|
|
ipipsec_shm_free(a);
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
ipipsec_auth_method[aalg].update(&a->i_ctx, keybuf, bytes);
|
|
ipipsec_auth_method[aalg].update(&a->i_ctx, ipipsec.i_buffer,
|
|
ipipsec_auth_method[aalg].block_size - bytes);
|
|
|
|
/* HMAC - precompute the O pad. */
|
|
for (i = 0; i < bytes; i++)
|
|
keybuf[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
|
|
if (!ipipsec_auth_method[aalg].init(&a->o_ctx))
|
|
{
|
|
ipipsec_shm_free(a);
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
ipipsec_auth_method[aalg].update(&a->o_ctx, keybuf, bytes);
|
|
ipipsec_auth_method[aalg].update(&a->o_ctx, ipipsec.o_buffer,
|
|
ipipsec_auth_method[aalg].block_size - bytes);
|
|
|
|
ipcom_memset(keybuf, 0, sizeof(keybuf)); /* paranoia */
|
|
}
|
|
|
|
*auth = a;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_auth_digest_len
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_u16
|
|
ipipsec_auth_digest_len(Ip_u8 id)
|
|
{
|
|
int aalg;
|
|
|
|
/* Check if the authentication algorithm is supported/implemented. */
|
|
for (aalg = 0; aalg < SADB_AALG_NUM; aalg++)
|
|
if (ipipsec_auth_method[aalg].id == id
|
|
&& ipipsec_auth_method[aalg].init != IP_NULL)
|
|
{
|
|
#ifdef OPENSSL_FIPS
|
|
if (ipipsec_auth_method[aalg].init == (Hash_init)MD5_Init && FIPS_mode())
|
|
return 0;
|
|
#endif
|
|
return ipipsec_auth_method[aalg].hash_bytes;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_encrypt_setkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_s32
|
|
ipipsec_encrypt_setkey(Ipipsec_sa *sa, Ip_u8 id, Ip_u8 *key, Ip_u32 bytes)
|
|
{
|
|
int ealg;
|
|
|
|
/* Check if the encryption algorithm is supported/implemented. */
|
|
for (ealg = 0; ealg < SADB_EALG_NUM; ealg++)
|
|
if (ipipsec_encrypt_method[ealg].id == id
|
|
&& ipipsec_encrypt_method[ealg].setkey != IP_NULL)
|
|
goto found;
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
found:
|
|
/* Check the encryption key length. */
|
|
if (bytes < ipipsec_encrypt_method[ealg].minkey_bytes
|
|
|| bytes > ipipsec_encrypt_method[ealg].maxkey_bytes)
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
/* Get memory to store the key. */
|
|
sa->encrypt = (Ipipsec_sa_encrypt *)ipipsec_shm_calloc(1, ipipsec_encrypt_method[ealg].key_size);
|
|
if (sa->encrypt == IP_NULL)
|
|
return -IP_ERRNO_ENOMEM;
|
|
|
|
/* IV */
|
|
ip_assert(ipipsec_encrypt_method[ealg].iv_bytes <= IPIPSEC_MAX_IV_SIZE);
|
|
sa->encrypt->iv_length = ipipsec_encrypt_method[ealg].iv_bytes;
|
|
sa->header_space += ipipsec_encrypt_method[ealg].iv_bytes;
|
|
|
|
/* Initialize IV with random bytes. */
|
|
ipipsec_crypt_random_fill(sa->encrypt->iv, sa->encrypt->iv_length);
|
|
|
|
/* Save encryption method pointer. */
|
|
sa->encrypt->eindex = ealg;
|
|
|
|
/* ESP trailer space. */
|
|
sa->trailer_space += ipipsec_encrypt_method[ealg].block_bytes;
|
|
if (ipipsec_encrypt_method[ealg].block_bytes >= 2)
|
|
{
|
|
/* Reduce trailer space since length+protocol fits within the block size. */
|
|
sa->trailer_space -= 2;
|
|
}
|
|
|
|
/* Store encryption key SA. */
|
|
sa->encrypt->keyLen = bytes;
|
|
if (ipipsec_encrypt_method[ealg].setkey != IP_NULL)
|
|
{
|
|
if (ipipsec_encrypt_method[ealg].setkey(key, bytes, &sa->encrypt->key) != 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipipsec_encrypt_setkey() :: failed to set encryption key for EALG=%d", ealg);
|
|
ipcom_memset(sa->encrypt, 0, ipipsec_encrypt_method[ealg].key_size); /* clear enc key. */
|
|
ipcom_free(sa->encrypt);
|
|
sa->encrypt = IP_NULL;
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_crypt_get_algs
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipipsec_crypt_get_algs(struct sadb_supported *supported)
|
|
{
|
|
struct sadb_alg *alg;
|
|
Ip_s32 i, tot;
|
|
|
|
tot = 0;
|
|
alg = (struct sadb_alg *)((Ip_u8 *)supported + sizeof(struct sadb_supported));
|
|
|
|
/* Fill in encryption algorithms */
|
|
for (i = 0; i < SADB_EALG_NUM; i++)
|
|
if (ipipsec_encrypt_method[i].setkey)
|
|
{
|
|
alg->sadb_alg_id = ipipsec_encrypt_method[i].id;
|
|
alg->sadb_alg_ivlen = (uint8_t)(ipipsec_encrypt_method[i].iv_bytes << 3);
|
|
alg->sadb_alg_minbits = (uint16_t)(ipipsec_encrypt_method[i].minkey_bytes << 3);
|
|
alg->sadb_alg_maxbits = (uint16_t)(ipipsec_encrypt_method[i].maxkey_bytes << 3);
|
|
alg->sadb_alg_reserved = 0;
|
|
tot++;
|
|
alg++;
|
|
}
|
|
supported->sadb_supported_nencrypt = (uint8_t)tot;
|
|
|
|
/* Fill in authentication algorithms */
|
|
for (i = 0; i < SADB_AALG_NUM; i++)
|
|
if (ipipsec_auth_method[i].init)
|
|
{
|
|
#if defined(OPENSSL_FIPS) && defined(IPIPSEC_USE_MD5)
|
|
/* MD5 not possible/allowed to use when the system is in FIPS 140-2 mode */
|
|
if (ipipsec_auth_method[i].init == (Hash_init)MD5_Init && FIPS_mode())
|
|
continue;
|
|
#endif
|
|
alg->sadb_alg_id = ipipsec_auth_method[i].id;
|
|
alg->sadb_alg_ivlen = 0;
|
|
alg->sadb_alg_minbits = (uint16_t)(ipipsec_auth_method[i].minkey_bytes << 3);
|
|
alg->sadb_alg_maxbits = (uint16_t)(ipipsec_auth_method[i].maxkey_bytes << 3);
|
|
alg->sadb_alg_reserved = 0;
|
|
tot++;
|
|
alg++;
|
|
}
|
|
supported->sadb_supported_nauth = (uint8_t)tot;
|
|
|
|
supported->sadb_supported_len = (uint16_t)(1 + tot);
|
|
supported->sadb_supported_exttype = SADB_EXT_SUPPORTED;
|
|
supported->sadb_supported_reserved = 0;
|
|
}
|
|
|
|
|
|
#ifdef IPIPSEC_USE_AESMAC
|
|
/*
|
|
*===========================================================================
|
|
* AESMAC_Init
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
AESMAC_Init(Ipipsec_auth_ctx *ctx)
|
|
{
|
|
AES_KEY aes[2];
|
|
Ip_u8 iv[AES_BLOCK_SIZE];
|
|
|
|
ipcom_memset(ctx->aes.e, 0, sizeof(ctx->aes.e));
|
|
ipcom_memset(ctx->aes.msg, 0, sizeof(ctx->aes.msg));
|
|
ctx->aes.msgLen = 0;
|
|
ipcom_memset(ctx->aes.k1, 0x01, sizeof(ctx->aes.k1));
|
|
ipcom_memset(ctx->aes.k2, 0x02, sizeof(ctx->aes.k2));
|
|
ipcom_memset(ctx->aes.k3, 0x03, sizeof(ctx->aes.k3));
|
|
(void)ipipsec_aes_setkey(ctx->aes.key, sizeof(ctx->aes.key), (Ipipsec_encrypt_key *)&aes[0]);
|
|
ipcom_memset(iv, 0, sizeof(iv));
|
|
(void)ipipsec_aes_encrypt(ctx->aes.k1, sizeof(ctx->aes.k1), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
ipcom_memset(iv, 0, sizeof(iv));
|
|
(void)ipipsec_aes_encrypt(ctx->aes.k2, sizeof(ctx->aes.k2), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
ipcom_memset(iv, 0, sizeof(iv));
|
|
(void)ipipsec_aes_encrypt(ctx->aes.k3, sizeof(ctx->aes.k3), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* AESMAC_Update
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
AESMAC_Update(Ipipsec_auth_ctx *ctx, IP_CONST Ip_u8 *data, Ip_u32 length)
|
|
{
|
|
Ip_u8 *e;
|
|
Ip_u8 iv[AES_BLOCK_SIZE];
|
|
int i;
|
|
AES_KEY aes[2];
|
|
|
|
/* This algoritm is specified in RFC3566 */
|
|
e = ctx->aes.e;
|
|
(void)ipipsec_aes_setkey(ctx->aes.k1, sizeof(ctx->aes.k1), (Ipipsec_encrypt_key *)&aes[0]);
|
|
|
|
/* Append data to context data buffer, digest data when buffer is full */
|
|
while ((ctx->aes.msgLen + length) > sizeof(ctx->aes.msg))
|
|
{
|
|
/* append so we have full buffer */
|
|
i = sizeof(ctx->aes.msg) - ctx->aes.msgLen;
|
|
ipcom_memcpy(&ctx->aes.msg[ctx->aes.msgLen], data, i);
|
|
/* jump handled data */
|
|
data += i;
|
|
length -= i;
|
|
ctx->aes.msgLen = 0;
|
|
/* Encrypt e buffer with k1 */
|
|
for (i = 0; i<(int)sizeof(ctx->aes.msg); i++)
|
|
e[i] = e[i] ^ (ctx->aes.msg[i]);
|
|
ipcom_memset(iv, 0, sizeof(iv));
|
|
ipipsec_aes_encrypt(e, sizeof(ctx->aes.msg), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
}
|
|
|
|
/* Append unhandled data to context data */
|
|
ipcom_memcpy(&ctx->aes.msg[ctx->aes.msgLen], data, length);
|
|
ctx->aes.msgLen += length;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* AESMAC_Final
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
AESMAC_Final(Ip_u8 *digest, Ipipsec_auth_ctx *ctx)
|
|
{
|
|
int i;
|
|
Ip_u8 iv[AES_BLOCK_SIZE];
|
|
AES_KEY aes[2];
|
|
|
|
ipcom_memset(iv, 0, sizeof(iv));
|
|
(void)ipipsec_aes_setkey(ctx->aes.k1, sizeof(ctx->aes.k1), (Ipipsec_encrypt_key *)&aes[0]);
|
|
|
|
if (sizeof(ctx->aes.msg) > ctx->aes.msgLen)
|
|
{
|
|
ctx->aes.msg[ctx->aes.msgLen] = 0x80;
|
|
i = sizeof(ctx->aes.msg) - ctx->aes.msgLen - 1;
|
|
if (i > 0)
|
|
ipcom_memset(&ctx->aes.msg[ctx->aes.msgLen+1], 0, i);
|
|
for (i = 0; i < (int)sizeof(ctx->aes.e); i++)
|
|
ctx->aes.e[i] = ctx->aes.e[i] ^ ctx->aes.msg[i] ^ ctx->aes.k3[i];
|
|
ipipsec_aes_encrypt(ctx->aes.e, sizeof(ctx->aes.msg), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < (int)sizeof(ctx->aes.e); i++)
|
|
ctx->aes.e[i] = ctx->aes.e[i] ^ ctx->aes.msg[i] ^ ctx->aes.k2[i];
|
|
ipipsec_aes_encrypt(ctx->aes.e, sizeof(ctx->aes.msg), (Ipipsec_encrypt_key *)&aes[0], iv);
|
|
}
|
|
ipcom_memcpy(digest, ctx->aes.e, sizeof(ctx->aes.e));
|
|
}
|
|
#endif /* IPIPSEC_USE_AESMAC */
|
|
|
|
|
|
#ifdef IPIPSEC_USE_CRYPTO_SELF_TEST
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_crypt_self_test
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipipsec_crypt_self_test(void)
|
|
{
|
|
/* RFC 4868: Test Case 1: */
|
|
static IP_CONST Ip_u8 SHA_512_KEY_1[64] = {0x0b, 0x0b, 0x0b, 0x0b ,0x0b ,0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b ,0x0b ,0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b ,0x0b ,0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b ,0x0b ,0x0b, 0x0b, 0x0b,
|
|
0x0b, 0x0b, 0x0b, 0x0b ,0x0b ,0x0b, 0x0b, 0x0b};
|
|
static IP_CONST Ip_u8 SHA_X_DATA_1[8] = {'H', 'i', ' ', 'T', 'h', 'e', 'r', 'e'};
|
|
static IP_CONST Ip_u8 SHA_256_MAC_1[16] = {0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
|
|
0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5};
|
|
static IP_CONST Ip_u8 SHA_384_MAC_1[24] = {0xb6, 0xa8, 0xd5, 0x63, 0x6f, 0x5c, 0x6a, 0x72,
|
|
0x24, 0xf9, 0x97, 0x7d, 0xcf, 0x7e, 0xe6, 0xc7,
|
|
0xfb, 0x6d, 0x0c, 0x48, 0xcb, 0xde, 0xe9, 0x73};
|
|
static IP_CONST Ip_u8 SHA_512_MAC_1[32] = {0x63, 0x7e, 0xdc, 0x6e, 0x01, 0xdc, 0xe7, 0xe6,
|
|
0x74, 0x2a, 0x99, 0x45, 0x1a, 0xae, 0x82, 0xdf,
|
|
0x23, 0xda, 0x3e, 0x92, 0x43, 0x9e, 0x59, 0x0e,
|
|
0x43, 0xe7, 0x61, 0xb3, 0x3e, 0x91, 0x0f, 0xb8};
|
|
/* RFC 4868: Test Case 3: */
|
|
static IP_CONST Ip_u8 SHA_512_KEY_3[64] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
|
|
static IP_CONST Ip_u8 SHA_X_DATA_3[50] = {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
|
0xdd, 0xdd};
|
|
static IP_CONST Ip_u8 SHA_256_MAC_3[16] = {0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
|
|
0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62};
|
|
static IP_CONST Ip_u8 SHA_384_MAC_3[24] = {0x80, 0x9f, 0x43, 0x9b, 0xe0, 0x02, 0x74, 0x32,
|
|
0x1d, 0x4a, 0x53, 0x86, 0x52, 0x16, 0x4b, 0x53,
|
|
0x55, 0x4a, 0x50, 0x81, 0x84, 0xa0, 0xc3, 0x16};
|
|
static IP_CONST Ip_u8 SHA_512_MAC_3[32] = {0x2e, 0xe7, 0xac, 0xd7, 0x83, 0x62, 0x4c, 0xa9,
|
|
0x39, 0x87, 0x10, 0xf3, 0xee, 0x05, 0xae, 0x41,
|
|
0xb9, 0xf9, 0xb0, 0x51, 0x0c, 0x87, 0xe4, 0x9e,
|
|
0x58, 0x6c, 0xc9, 0xbf, 0x96, 0x17, 0x33, 0xd8};
|
|
|
|
struct ipipsec_crypt_self_test_auth_alg_struct
|
|
{
|
|
Ip_u8 alg;
|
|
IP_CONST char * name;
|
|
IP_CONST Ip_u8 * key;
|
|
Ip_size_t key_len;
|
|
IP_CONST Ip_u8 * data;
|
|
Ip_size_t data_len;
|
|
IP_CONST Ip_u8 * mac;
|
|
Ip_size_t mac_len;
|
|
} self_test_auth_algs[] =
|
|
{
|
|
#ifdef IPIPSEC_USE_SHA256
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_256_HMAC,
|
|
.name = "hmac(sha2-256-128) RFC-4858 AUTH256-1",
|
|
.key = SHA_512_KEY_1,
|
|
.key_len = 32, /* Only use 256 of the key */
|
|
.data = SHA_X_DATA_1,
|
|
.data_len = sizeof(SHA_X_DATA_1),
|
|
.mac = SHA_256_MAC_1,
|
|
.mac_len = sizeof(SHA_256_MAC_1),
|
|
},
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_256_HMAC,
|
|
.name = "hmac(sha2-256-128) RFC-4858 AUTH256-3",
|
|
.key = SHA_512_KEY_3,
|
|
.key_len = 32, /* Only use 256 of the key */
|
|
.data = SHA_X_DATA_3,
|
|
.data_len = sizeof(SHA_X_DATA_3),
|
|
.mac = SHA_256_MAC_3,
|
|
.mac_len = sizeof(SHA_256_MAC_3),
|
|
},
|
|
#endif
|
|
#ifdef IPIPSEC_USE_SHA384
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_384_HMAC,
|
|
.name = "hmac(sha2-384-192) RFC-4858 AUTH384-1",
|
|
.key = SHA_512_KEY_1,
|
|
.key_len = 48,
|
|
.data = SHA_X_DATA_1,
|
|
.data_len = sizeof(SHA_X_DATA_1),
|
|
.mac = SHA_384_MAC_1,
|
|
.mac_len = sizeof(SHA_384_MAC_1),
|
|
},
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_384_HMAC,
|
|
.name = "hmac(sha2-384-192) RFC-4858 AUTH384-3",
|
|
.key = SHA_512_KEY_3,
|
|
.key_len = 48,
|
|
.data = SHA_X_DATA_3,
|
|
.data_len = sizeof(SHA_X_DATA_3),
|
|
.mac = SHA_384_MAC_3,
|
|
.mac_len = sizeof(SHA_384_MAC_3),
|
|
},
|
|
#endif
|
|
#ifdef IPIPSEC_USE_SHA512
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_512_HMAC,
|
|
.name = "hmac(sha2-512-256) RFC-4858 AUTH512-1",
|
|
.key = SHA_512_KEY_1,
|
|
.key_len = sizeof(SHA_512_KEY_1),
|
|
.data = SHA_X_DATA_1,
|
|
.data_len = sizeof(SHA_X_DATA_1),
|
|
.mac = SHA_512_MAC_1,
|
|
.mac_len = sizeof(SHA_512_MAC_1),
|
|
},
|
|
{
|
|
.alg = SADB_X_AALG_SHA2_512_HMAC,
|
|
.name = "hmac(sha2-512-256) RFC-4858 AUTH512-3",
|
|
.key = SHA_512_KEY_3,
|
|
.key_len = sizeof(SHA_512_KEY_3),
|
|
.data = SHA_X_DATA_3,
|
|
.data_len = sizeof(SHA_X_DATA_3),
|
|
.mac = SHA_512_MAC_3,
|
|
.mac_len = sizeof(SHA_512_MAC_3),
|
|
},
|
|
#endif
|
|
};
|
|
IP_CONST Ipipsec_auth_method * aalg;
|
|
Ipcom_pkt dummy_pkt;
|
|
Ipipsec_sa dummy_sa;
|
|
Ip_u8 calc_digest[IPIPSEC_AUTH_MAXKEYLEN];
|
|
Ip_size_t i = 0;
|
|
|
|
ipcom_memset(&dummy_sa, 0, sizeof(Ipipsec_sa));
|
|
|
|
for (i = 0;
|
|
i < (sizeof(self_test_auth_algs)/sizeof(self_test_auth_algs[0]));
|
|
i++)
|
|
{
|
|
|
|
/* Prepare dummy packet */
|
|
dummy_pkt.data = (Ip_u8 *)self_test_auth_algs[i].data;
|
|
dummy_pkt.start = 0;
|
|
dummy_pkt.end = (int) self_test_auth_algs[i].data_len;
|
|
|
|
/* Prepare dummy SA */
|
|
dummy_sa.sadb_sa_auth = self_test_auth_algs[i].alg;
|
|
|
|
/* Set the key */
|
|
if ( 0 == ipipsec_auth_setkey(&dummy_sa.auth,
|
|
self_test_auth_algs[i].alg,
|
|
(Ip_u8 *) self_test_auth_algs[i].key,
|
|
(Ip_u32) self_test_auth_algs[i].key_len))
|
|
{
|
|
/* Get auth method */
|
|
aalg = &ipipsec_auth_method[dummy_sa.auth->aindex];
|
|
|
|
/* Calculate digest */
|
|
ipipsec_calc_digest(&dummy_sa, &dummy_pkt, 0, calc_digest);
|
|
|
|
if ( ipcom_memcmp(self_test_auth_algs[i].mac, calc_digest, aalg->auth_bytes) != 0 )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipipsec_crypt_self_test() :: %s FAILED",
|
|
self_test_auth_algs[i].name);
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(ERR, "ipipsec_crypt_self_test() :: %s PASSED",
|
|
self_test_auth_algs[i].name);
|
|
}
|
|
}
|
|
|
|
/* Free auth object allocated by ipipsec_auth_setkey */
|
|
if ( dummy_sa.auth != IP_NULL )
|
|
{
|
|
ipipsec_shm_free(dummy_sa.auth);
|
|
dummy_sa.auth = IP_NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif /* IPIPSEC_USE_CRYPTO_SELF_TEST */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|