AES 加密解密的原理我就不说了, 弟兄们自己上百度去查, 文章很多。
我这里只列出从网上获取的代码的实现, 我修改了一些, 可以很方便的使用到你的代码里面。
AES 比DES算法的强度更强。AES使用128位的加密密钥就足够了, 不需要使用更长的密钥。毕竟密钥太长浪费CPU资源。
AES.h头文件
- #ifndef _AES_H
- #define _AES_H
- /*************** Header files *********************************************/
- #include <stdlib.h>
- #include <string.h>
- #include <memory.h>
- //#include "cryptcom.h"
- #define AES_ModeType AI_ECB
- #define AES_PadType AI_PKCS_PADDING
- /*************** Assertions ***********************************************/
- Define the Endianness
- #undef BIG_ENDIAN
- #undef LITTLE_ENDIAN
- #define USER_LITTLE_ENDIAN
- #if defined(USER_BIG_ENDIAN)
- #define BIG_ENDIAN
- #elif defined(USER_LITTLE_ENDIAN)
- #define LITTLE_ENDIAN
- #else
- #if 0
- #define BIG_ENDIAN // Big-Endian machine with pointer casting
- #elif defined(_MSC_VER)
- #define LITTLE_ENDIAN // Little-Endian machine with pointer casting
- #else
- #error
- #endif
- #endif
- /*************** Macros ***************************************************/
- rotate by using shift operations
- #if defined(_MSC_VER)
- #define ROTL_DWORD(x, n) _lrotl((x), (n))
- #define ROTR_DWORD(x, n) _lrotr((x), (n))
- #else
- #define ROTL_DWORD(x, n) ( (DWORD)((x) << (n)) | (DWORD)((x) >> (32-(n))) )
- #define ROTR_DWORD(x, n) ( (DWORD)((x) >> (n)) | (DWORD)((x) << (32-(n))) )
- #endif
- reverse the byte order of DWORD(DWORD:4-bytes integer) and WORD.
- #define ENDIAN_REVERSE_DWORD(dwS) ( (ROTL_DWORD((dwS), 8) & 0x00ff00ff) | (ROTL_DWORD((dwS), 24) & 0xff00ff00) )
- move DWORD type to BYTE type and BYTE type to DWORD type
- #if defined(BIG_ENDIAN) Big-Endian machine
- #define BIG_B2D(B, D) D = *(DWORD *)(B)
- #define BIG_D2B(D, B) *(DWORD *)(B) = (DWORD)(D)
- #define LITTLE_B2D(B, D) D = ENDIAN_REVERSE_DWORD(*(DWORD *)(B))
- #define LITTLE_D2B(D, B) *(DWORD *)(B) = ENDIAN_REVERSE_DWORD(D)
- #elif defined(LITTLE_ENDIAN) Little-Endian machine
- #define BIG_B2D(B, D) D = ENDIAN_REVERSE_DWORD(*(DWORD *)(B))
- #define BIG_D2B(D, B) *(DWORD *)(B) = ENDIAN_REVERSE_DWORD(D)
- #define LITTLE_B2D(B, D) D = *(DWORD *)(B)
- #define LITTLE_D2B(D, B) *(DWORD *)(B) = (DWORD)(D)
- #else
- #error ERROR : Invalid DataChangeType
- #endif
- /*************** Definitions / Macros *************************************/
- 泅犁 酒贰狼 4俺 规侥阑 瘤盔茄促.
- #define AI_ECB 1
- #define AI_CBC 2
- #define AI_OFB 3
- #define AI_CFB 4
- 泅犁 酒贰狼 滴 padding阑 瘤盔茄促.
- #define AI_NO_PADDING 1 // Padding 绝澜(涝仿捞 16官捞飘狼 硅荐)
- #define AI_PKCS_PADDING 2 // padding登绰 官捞飘 荐肺 padding
- AES俊 包访等 惑荐甸
- #define AES_BLOCK_LEN 16 // in BYTEs
- #define AES_USER_KEY_LEN 32 // (16,24,32) in BYTEs
- #define AES_NO_ROUNDS 10
- #define AES_NO_ROUNDKEY 68 // in DWORDs
- /*************** New Data Types *******************************************/
- Determine data types depand on the processor and compiler.
- #define BOOL int // 1-bit data type
- #define BYTE unsigned char // unsigned 1-byte data type
- #define WORD unsigned short int // unsigned 2-bytes data type
- #define DWORD unsigned int // unsigned 4-bytes data type
- #define RET_VAL DWORD // return values
- AES..
- typedef struct{
- DWORD ModeID; // ECB or CBC
- DWORD PadType; // 喉废鞠龋狼 Padding type
- BYTE IV[AES_BLOCK_LEN]; // Initial Vector
- BYTE ChainVar[AES_BLOCK_LEN]; // Chaining Variable
- BYTE Buffer[AES_BLOCK_LEN]; // Buffer for unfilled block
- DWORD BufLen; // Buffer狼 蜡瓤 官捞飘 荐
- DWORD RoundKey[AES_NO_ROUNDKEY]; // 扼款靛 虐狼 DWORD 荐
- } AES_ALG_INFO;
- /*************** Constant (Error Code) ************************************/
- Error Code - 沥府窍绊, 利寸洒 免仿秦具 窃.
- #define CTR_SUCCESS 0
- #define CTR_FATAL_ERROR 0x1001
- #define CTR_INVALID_USERKEYLEN 0x1002 // 厚剐虐狼 辨捞啊 何利例窃.
- #define CTR_PAD_CHECK_ERROR 0x1003 //
- #define CTR_DATA_LEN_ERROR 0x1004 // 乞巩狼 辨捞啊 何利例窃.
- #define CTR_CIPHER_LEN_ERROR 0x1005 // 鞠龋巩捞 喉废狼 硅荐啊 酒丛.
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*************** Prototypes ***********************************************/
- 单捞鸥 鸥涝 AES_ALG_INFO俊 mode, padding 辆幅 棺 IV 蔼阑 檬扁拳茄促.
- void AES_SetAlgInfo(
- DWORD ModeID,
- DWORD PadType,
- BYTE *IV,
- AES_ALG_INFO *AlgInfo);
- 涝仿等 AES_USER_KEY_LEN官牢飘狼 厚剐虐肺 扼款靛 虐 积己
- RET_VAL AES_EncKeySchedule(
- BYTE *UserKey, // 荤侩磊 厚剐虐甫 涝仿窃.
- DWORD UserKeyLen,
- AES_ALG_INFO *AlgInfo); // 鞠汗龋侩 Round Key啊 历厘凳.
- RET_VAL AES_DecKeySchedule(
- BYTE *UserKey, // 荤侩磊 厚剐虐甫 涝仿窃.
- DWORD UserKeyLen,
- AES_ALG_INFO *AlgInfo); // 鞠汗龋侩 Round Key啊 历厘凳.
- Init/Update/Final 屈侥阑 鞠龋拳.
- RET_VAL AES_EncInit(
- AES_ALG_INFO *AlgInfo);
- RET_VAL AES_EncUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 乞巩捞 涝仿凳.
- DWORD PlainTxtLen,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿凳.
- DWORD *CipherTxtLen);
- RET_VAL AES_EncFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿凳.
- DWORD *CipherTxtLen);
- Init/Update/Final 屈侥阑 汗龋拳.
- RET_VAL AES_DecInit(
- AES_ALG_INFO *AlgInfo);
- RET_VAL AES_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 涝仿凳.
- DWORD CipherTxtLen,
- BYTE *PlainTxt, // 汗龋巩捞 免仿凳.
- DWORD *PlainTxtLen);
- RET_VAL AES_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 汗龋巩捞 免仿凳.
- DWORD *PlainTxtLen);
- /*************** END OF FILE **********************************************/
- #ifdef __cplusplus
- }
- #endif
- #endif // _AES_H
AESENC.C文件
- /*************** Header files *********************************************/
- #include "aes.h"
- /*************** Assertions ***********************************************/
- /*************** Definitions / Macros ************************************/
- #define BlockCopy(pbDst, pbSrc) { /
- ((DWORD *)(pbDst))[0] = ((DWORD *)(pbSrc))[0]; /
- ((DWORD *)(pbDst))[1] = ((DWORD *)(pbSrc))[1]; /
- ((DWORD *)(pbDst))[2] = ((DWORD *)(pbSrc))[2]; /
- ((DWORD *)(pbDst))[3] = ((DWORD *)(pbSrc))[3]; /
- }
- #define BlockXor(pbDst, phSrc1, phSrc2) { /
- ((DWORD *)(pbDst))[0] = ((DWORD *)(phSrc1))[0] /
- ^ ((DWORD *)(phSrc2))[0]; /
- ((DWORD *)(pbDst))[1] = ((DWORD *)(phSrc1))[1] /
- ^ ((DWORD *)(phSrc2))[1]; /
- ((DWORD *)(pbDst))[2] = ((DWORD *)(phSrc1))[2] /
- ^ ((DWORD *)(phSrc2))[2]; /
- ((DWORD *)(pbDst))[3] = ((DWORD *)(phSrc1))[3] /
- ^ ((DWORD *)(phSrc2))[3]; /
- }
- /*************** New Data Types *******************************************/
- /*************** Global Variables *****************************************/
- /*************** Prototypes ***********************************************/
- void AES_Encrypt(
- void *CipherKey, // 鞠/汗龋侩 Round Key
- BYTE *Data); // 涝免仿阑 困茄 喉废阑 啊府虐绰 pointer
- void AES_Decrypt(
- void *CipherKey, // 鞠/汗龋侩 Round Key
- BYTE *Data); // 涝免仿阑 困茄 喉废阑 啊府虐绰 pointer
- /*************** Constants ************************************************/
- /*************** Constants ************************************************/
- /*************** Macros ***************************************************/
- /*************** Global Variables *****************************************/
- /*************** Function *************************************************
- *
- */
- void AES_SetAlgInfo(
- DWORD ModeID,
- DWORD PadType,
- BYTE *IV,
- AES_ALG_INFO *AlgInfo)
- {
- AlgInfo->ModeID = ModeID;
- AlgInfo->PadType = PadType;
- if( IV!=NULL )
- memcpy(AlgInfo->IV, IV, AES_BLOCK_LEN);
- else
- memset(AlgInfo->IV, 0, AES_BLOCK_LEN);
- }
- /*************** Function *************************************************
- *
- */
- static RET_VAL PaddSet(
- BYTE *pbOutBuffer,
- DWORD dRmdLen,
- DWORD dBlockLen,
- DWORD dPaddingType)
- {
- DWORD dPadLen;
- switch( dPaddingType )
- {
- case AI_NO_PADDING :
- if( dRmdLen==0 ) return 0;
- else return CTR_DATA_LEN_ERROR;
- case AI_PKCS_PADDING :
- dPadLen = dBlockLen - dRmdLen;
- memset(pbOutBuffer+dRmdLen, (char)dPadLen, (int)dPadLen);
- return dPadLen;
- default :
- return CTR_FATAL_ERROR;
- }
- }
- /*************** Function *************************************************
- *
- */
- static RET_VAL PaddCheck(
- BYTE *pbOutBuffer,
- DWORD dBlockLen,
- DWORD dPaddingType)
- {
- DWORD i, dPadLen;
- switch( dPaddingType ) {
- case AI_NO_PADDING :
- return 0; // padding等 单捞鸥啊 0官捞飘烙.
- case AI_PKCS_PADDING :
- dPadLen = pbOutBuffer[dBlockLen-1];
- if( ((int)dPadLen<=0) || (dPadLen>(int)dBlockLen) )
- return CTR_PAD_CHECK_ERROR;
- for( i=1; i<=dPadLen; i++)
- if( pbOutBuffer[dBlockLen-i] != dPadLen )
- return CTR_PAD_CHECK_ERROR;
- return dPadLen;
- default :
- return CTR_FATAL_ERROR;
- }
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_EncInit(
- AES_ALG_INFO *AlgInfo)
- {
- AlgInfo->BufLen = 0;
- if( AlgInfo->ModeID!=AI_ECB )
- memcpy(AlgInfo->ChainVar, AlgInfo->IV, AES_BLOCK_LEN);
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL ECB_EncUpdate(
- AES_ALG_INFO *AlgInfo, //
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD PlainTxtLen, // 涝仿登绰 乞巩狼 官捞飘 荐
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- //
- *CipherTxtLen = BufLen + PlainTxtLen;
- // No one block
- if( *CipherTxtLen<BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen += PlainTxtLen;
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that PlainTxt and CipherTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)(BlockLen - BufLen));
- PlainTxt += BlockLen - BufLen;
- PlainTxtLen -= BlockLen - BufLen;
- // core part
- BlockCopy(CipherTxt, AlgInfo->Buffer);
- AES_Encrypt(ScheduledKey, CipherTxt);
- CipherTxt += BlockLen;
- while( PlainTxtLen>=BlockLen )
- {
- BlockCopy(CipherTxt, PlainTxt);
- AES_Encrypt(ScheduledKey, CipherTxt);
- PlainTxt += BlockLen;
- CipherTxt += BlockLen;
- PlainTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen = PlainTxtLen;
- *CipherTxtLen -= PlainTxtLen;
- // control the case that PlainTxt and CipherTxt are the same buffer
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CBC_EncUpdate(
- AES_ALG_INFO *AlgInfo, //
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD PlainTxtLen, // 涝仿登绰 乞巩狼 官捞飘 荐
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- //
- *CipherTxtLen = BufLen + PlainTxtLen;
- // No one block
- if( *CipherTxtLen<BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen += PlainTxtLen;
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that PlainTxt and CipherTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)(BlockLen - BufLen));
- PlainTxt += BlockLen - BufLen;
- PlainTxtLen -= BlockLen - BufLen;
- // core part
- BlockXor(CipherTxt, AlgInfo->ChainVar, AlgInfo->Buffer);
- AES_Encrypt(ScheduledKey, CipherTxt);
- CipherTxt += BlockLen;
- while( PlainTxtLen>=BlockLen )
- {
- BlockXor(CipherTxt, CipherTxt-BlockLen, PlainTxt);
- AES_Encrypt(ScheduledKey, CipherTxt);
- PlainTxt += BlockLen;
- CipherTxt += BlockLen;
- PlainTxtLen -= BlockLen;
- }
- BlockCopy(AlgInfo->ChainVar, CipherTxt-BlockLen);
- // save remained data
- memcpy(AlgInfo->Buffer, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen = PlainTxtLen;
- *CipherTxtLen -= PlainTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL OFB_EncUpdate(
- AES_ALG_INFO *AlgInfo, //
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD PlainTxtLen, // 涝仿登绰 乞巩狼 官捞飘 荐
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *CipherTxtLen = BufLen + PlainTxtLen;
- // No one block
- if( *CipherTxtLen<BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen += PlainTxtLen;
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that PlainTxt and CipherTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)(BlockLen - BufLen));
- PlainTxt += BlockLen - BufLen;
- PlainTxtLen -= BlockLen - BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(CipherTxt, AlgInfo->ChainVar, AlgInfo->Buffer);
- CipherTxt += BlockLen;
- while( PlainTxtLen>=BlockLen )
- {
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(CipherTxt, AlgInfo->ChainVar, PlainTxt);
- PlainTxt += BlockLen;
- CipherTxt += BlockLen;
- PlainTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + PlainTxtLen;
- *CipherTxtLen -= PlainTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CFB_EncUpdate(
- AES_ALG_INFO *AlgInfo, //
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD PlainTxtLen, // 涝仿登绰 乞巩狼 官捞飘 荐
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *CipherTxtLen = BufLen + PlainTxtLen;
- // No one block
- if( *CipherTxtLen<BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen += PlainTxtLen;
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that PlainTxt and CipherTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- memcpy(AlgInfo->Buffer+BufLen, PlainTxt, (int)(BlockLen - BufLen));
- PlainTxt += BlockLen - BufLen;
- PlainTxtLen -= BlockLen - BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(AlgInfo->ChainVar, AlgInfo->ChainVar, AlgInfo->Buffer);
- BlockCopy(CipherTxt, AlgInfo->ChainVar);
- CipherTxt += BlockLen;
- while( PlainTxtLen>=BlockLen )
- {
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(AlgInfo->ChainVar, AlgInfo->ChainVar, PlainTxt);
- BlockCopy(CipherTxt, AlgInfo->ChainVar);
- PlainTxt += BlockLen;
- CipherTxt += BlockLen;
- PlainTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, PlainTxt, (int)PlainTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + PlainTxtLen;
- *CipherTxtLen -= PlainTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_EncUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD PlainTxtLen, // 涝仿登绰 乞巩狼 官捞飘 荐
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- switch( AlgInfo->ModeID )
- {
- case AI_ECB : return ECB_EncUpdate(AlgInfo, PlainTxt, PlainTxtLen, CipherTxt, CipherTxtLen);
- case AI_CBC : return CBC_EncUpdate(AlgInfo, PlainTxt, PlainTxtLen, CipherTxt, CipherTxtLen);
- case AI_OFB : return OFB_EncUpdate(AlgInfo, PlainTxt, PlainTxtLen, CipherTxt, CipherTxtLen);
- case AI_CFB : return CFB_EncUpdate(AlgInfo, PlainTxt, PlainTxtLen, CipherTxt, CipherTxtLen);
- default : return CTR_FATAL_ERROR;
- }
- }
- /**************************************************************************
- *
- */
- static RET_VAL ECB_EncFinal(
- AES_ALG_INFO *AlgInfo, //
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- DWORD PaddByte;
- // Padding
- PaddByte = PaddSet(AlgInfo->Buffer, BufLen, BlockLen, AlgInfo->PadType);
- if( PaddByte>BlockLen ) return PaddByte;
- if( PaddByte==0 )
- {
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // core part
- BlockCopy(CipherTxt, AlgInfo->Buffer);
- AES_Encrypt(ScheduledKey, CipherTxt);
- //
- *CipherTxtLen = BlockLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CBC_EncFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- DWORD PaddByte;
- // Padding
- PaddByte = PaddSet(AlgInfo->Buffer, BufLen, BlockLen, AlgInfo->PadType);
- if( PaddByte>BlockLen ) return PaddByte;
- if( PaddByte==0 )
- {
- *CipherTxtLen = 0;
- return CTR_SUCCESS;
- }
- // core part
- BlockXor(CipherTxt, AlgInfo->Buffer, AlgInfo->ChainVar);
- AES_Encrypt(ScheduledKey, CipherTxt);
- BlockCopy(AlgInfo->ChainVar, CipherTxt);
- //
- *CipherTxtLen = BlockLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL OFB_EncFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- DWORD i;
- // Check Output Memory Size
- *CipherTxtLen = BlockLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- for( i=0; i<BufLen; i++)
- CipherTxt[i] = (BYTE) (AlgInfo->Buffer[i] ^ AlgInfo->ChainVar[i]);
- //
- *CipherTxtLen = BufLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CFB_EncFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *CipherTxtLen = BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(AlgInfo->ChainVar, AlgInfo->ChainVar, AlgInfo->Buffer);
- memcpy(CipherTxt, AlgInfo->ChainVar, BufLen);
- //
- *CipherTxtLen = BufLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_EncFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD *CipherTxtLen) // 免仿登绰 鞠龋巩狼 官捞飘 荐
- {
- switch( AlgInfo->ModeID )
- {
- case AI_ECB : return ECB_EncFinal(AlgInfo, CipherTxt, CipherTxtLen);
- case AI_CBC : return CBC_EncFinal(AlgInfo, CipherTxt, CipherTxtLen);
- case AI_OFB : return OFB_EncFinal(AlgInfo, CipherTxt, CipherTxtLen);
- case AI_CFB : return CFB_EncFinal(AlgInfo, CipherTxt, CipherTxtLen);
- default : return CTR_FATAL_ERROR;
- }
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_DecInit(AES_ALG_INFO *AlgInfo)
- {
- AlgInfo->BufLen = 0;
- if( AlgInfo->ModeID!=AI_ECB )
- memcpy(AlgInfo->ChainVar, AlgInfo->IV, AES_BLOCK_LEN);
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL ECB_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 涝仿登绰 鞠龋巩狼 pointer
- DWORD CipherTxtLen, // 涝仿登绰 鞠龋巩狼 官捞飘 荐
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- //
- *PlainTxtLen = BufLen + CipherTxtLen;
- // No one block
- if( BufLen+CipherTxtLen <= BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen += CipherTxtLen;
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that CipherTxt and PlainTxt are the same buffer
- if( CipherTxt==PlainTxt ) return CTR_FATAL_ERROR;
- // first block
- *PlainTxtLen = BufLen + CipherTxtLen;
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)(BlockLen - BufLen));
- CipherTxt += BlockLen - BufLen;
- CipherTxtLen -= BlockLen - BufLen;
- // core part
- BlockCopy(PlainTxt, AlgInfo->Buffer);
- AES_Decrypt(ScheduledKey, PlainTxt);
- PlainTxt += BlockLen;
- while( CipherTxtLen>BlockLen )
- {
- BlockCopy(PlainTxt, CipherTxt);
- AES_Decrypt(ScheduledKey, PlainTxt);
- CipherTxt += BlockLen;
- PlainTxt += BlockLen;
- CipherTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + CipherTxtLen;
- *PlainTxtLen -= CipherTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CBC_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 涝仿登绰 鞠龋巩狼 pointer
- DWORD CipherTxtLen, // 涝仿登绰 鞠龋巩狼 官捞飘 荐
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *PlainTxtLen = BufLen + CipherTxtLen;
- // No one block
- if( BufLen+CipherTxtLen <= BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen += CipherTxtLen;
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that CipherTxt and PlainTxt are the same buffer
- if( CipherTxt==PlainTxt ) return CTR_FATAL_ERROR;
- // first block
- *PlainTxtLen = BufLen + CipherTxtLen;
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)(BlockLen - BufLen));
- CipherTxt += BlockLen - BufLen;
- CipherTxtLen -= BlockLen - BufLen;
- // core part
- BlockCopy(PlainTxt, AlgInfo->Buffer);
- AES_Decrypt(ScheduledKey, PlainTxt);
- BlockXor(PlainTxt, PlainTxt, AlgInfo->ChainVar);
- PlainTxt += BlockLen;
- if( CipherTxtLen<=BlockLen )
- {
- BlockCopy(AlgInfo->ChainVar, AlgInfo->Buffer);
- }
- else
- {
- if( CipherTxtLen>BlockLen )
- {
- BlockCopy(PlainTxt, CipherTxt);
- AES_Decrypt(ScheduledKey, PlainTxt);
- BlockXor(PlainTxt, PlainTxt, AlgInfo->Buffer);
- CipherTxt += BlockLen;
- PlainTxt += BlockLen;
- CipherTxtLen -= BlockLen;
- }
- while( CipherTxtLen>BlockLen )
- {
- BlockCopy(PlainTxt, CipherTxt);
- AES_Decrypt(ScheduledKey, PlainTxt);
- BlockXor(PlainTxt, PlainTxt, CipherTxt-BlockLen);
- CipherTxt += BlockLen;
- PlainTxt += BlockLen;
- CipherTxtLen -= BlockLen;
- }
- BlockCopy(AlgInfo->ChainVar, CipherTxt-BlockLen);
- }
- // save remained data
- memcpy(AlgInfo->Buffer, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + CipherTxtLen;
- *PlainTxtLen -= CipherTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL OFB_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 涝仿登绰 鞠龋巩狼 pointer
- DWORD CipherTxtLen, // 涝仿登绰 鞠龋巩狼 官捞飘 荐
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *PlainTxtLen = BufLen + CipherTxtLen;
- // No one block
- if( BufLen+CipherTxtLen <= BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen += CipherTxtLen;
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that CipherTxt and PlainTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- *PlainTxtLen = BufLen + CipherTxtLen;
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)(BlockLen - BufLen));
- CipherTxt += BlockLen - BufLen;
- CipherTxtLen -= BlockLen - BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(PlainTxt, AlgInfo->ChainVar, AlgInfo->Buffer);
- PlainTxt += BlockLen;
- while( CipherTxtLen>BlockLen )
- {
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(PlainTxt, AlgInfo->ChainVar, CipherTxt);
- CipherTxt += BlockLen;
- PlainTxt += BlockLen;
- CipherTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + CipherTxtLen;
- *PlainTxtLen -= CipherTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- static RET_VAL CFB_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 涝仿登绰 鞠龋巩狼 pointer
- DWORD CipherTxtLen, // 涝仿登绰 鞠龋巩狼 官捞飘 荐
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *PlainTxtLen = BufLen + CipherTxtLen;
- // No one block
- if( BufLen+CipherTxtLen <= BlockLen )
- {
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen += CipherTxtLen;
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- // control the case that CipherTxt and PlainTxt are the same buffer
- if( PlainTxt==CipherTxt )
- return CTR_FATAL_ERROR;
- // first block
- *PlainTxtLen = BufLen + CipherTxtLen;
- memcpy(AlgInfo->Buffer+BufLen, CipherTxt, (int)(BlockLen - BufLen));
- CipherTxt += BlockLen - BufLen;
- CipherTxtLen -= BlockLen - BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(PlainTxt, AlgInfo->ChainVar, AlgInfo->Buffer);
- BlockCopy(AlgInfo->ChainVar, AlgInfo->Buffer);
- PlainTxt += BlockLen;
- while( CipherTxtLen>BlockLen )
- {
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(PlainTxt, AlgInfo->ChainVar, CipherTxt);
- BlockCopy(AlgInfo->ChainVar, CipherTxt);
- CipherTxt += BlockLen;
- PlainTxt += BlockLen;
- CipherTxtLen -= BlockLen;
- }
- // save remained data
- memcpy(AlgInfo->Buffer, CipherTxt, (int)CipherTxtLen);
- AlgInfo->BufLen = (AlgInfo->BufLen&0xF0000000) + CipherTxtLen;
- *PlainTxtLen -= CipherTxtLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_DecUpdate(
- AES_ALG_INFO *AlgInfo,
- BYTE *CipherTxt, // 鞠龋巩捞 免仿瞪 pointer
- DWORD CipherTxtLen, // 免仿登绰 鞠龋巩狼 官捞飘 荐
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD *PlainTxtLen) // 涝仿登绰 乞巩狼 官捞飘 荐
- {
- switch( AlgInfo->ModeID )
- {
- case AI_ECB : return ECB_DecUpdate(AlgInfo, CipherTxt, CipherTxtLen, PlainTxt, PlainTxtLen);
- case AI_CBC : return CBC_DecUpdate(AlgInfo, CipherTxt, CipherTxtLen, PlainTxt, PlainTxtLen);
- case AI_OFB : return OFB_DecUpdate(AlgInfo, CipherTxt, CipherTxtLen, PlainTxt, PlainTxtLen);
- case AI_CFB : return CFB_DecUpdate(AlgInfo, CipherTxt, CipherTxtLen, PlainTxt, PlainTxtLen);
- default : return CTR_FATAL_ERROR;
- }
- }
- /**************************************************************************
- *
- */
- RET_VAL ECB_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- RET_VAL ret;
- // Check Output Memory Size
- if( BufLen==0 )
- {
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- *PlainTxtLen = BlockLen;
- if( BufLen!=BlockLen ) return CTR_CIPHER_LEN_ERROR;
- // core part
- BlockCopy(PlainTxt, AlgInfo->Buffer);
- AES_Decrypt(ScheduledKey, PlainTxt);
- // Padding Check
- ret = PaddCheck(PlainTxt, BlockLen, AlgInfo->PadType);
- if( ret==(DWORD)-3 ) return CTR_PAD_CHECK_ERROR;
- if( ret==(DWORD)-1 ) return CTR_FATAL_ERROR;
- *PlainTxtLen = BlockLen - ret;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL CBC_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BlockLen=AES_BLOCK_LEN, BufLen=AlgInfo->BufLen;
- RET_VAL ret;
- // Check Output Memory Size
- if( BufLen==0 )
- {
- *PlainTxtLen = 0;
- return CTR_SUCCESS;
- }
- *PlainTxtLen = BlockLen;
- if( BufLen!=BlockLen ) return CTR_CIPHER_LEN_ERROR;
- // core part
- BlockCopy(PlainTxt, AlgInfo->Buffer);
- AES_Decrypt(ScheduledKey, PlainTxt);
- BlockXor(PlainTxt, PlainTxt, AlgInfo->ChainVar);
- BlockCopy(AlgInfo->ChainVar, AlgInfo->Buffer);
- // Padding Check
- ret = PaddCheck(PlainTxt, BlockLen, AlgInfo->PadType);
- if( ret==(DWORD)-3 ) return CTR_PAD_CHECK_ERROR;
- if( ret==(DWORD)-1 ) return CTR_FATAL_ERROR;
- *PlainTxtLen = BlockLen - ret;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL OFB_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD i, BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *PlainTxtLen = BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- for( i=0; i<BufLen; i++)
- PlainTxt[i] = (BYTE) (AlgInfo->Buffer[i] ^ AlgInfo->ChainVar[i]);
- *PlainTxtLen = BufLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL CFB_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 乞巩捞 免仿瞪 pointer
- DWORD *PlainTxtLen) // 免仿登绰 乞巩狼 官捞飘 荐
- {
- DWORD *ScheduledKey=AlgInfo->RoundKey;
- DWORD BufLen=AlgInfo->BufLen;
- // Check Output Memory Size
- *PlainTxtLen = BufLen;
- // core part
- AES_Encrypt(ScheduledKey, AlgInfo->ChainVar);
- BlockXor(AlgInfo->ChainVar, AlgInfo->ChainVar, AlgInfo->Buffer);
- memcpy(PlainTxt, AlgInfo->ChainVar, BufLen);
- *PlainTxtLen = BufLen;
- //
- return CTR_SUCCESS;
- }
- /**************************************************************************
- *
- */
- RET_VAL AES_DecFinal(
- AES_ALG_INFO *AlgInfo,
- BYTE *PlainTxt, // 涝仿登绰 乞巩狼 pointer
- DWORD *PlainTxtLen) // 涝仿登绰 乞巩狼 官捞飘 荐
- {
- switch( AlgInfo->ModeID )
- {
- case AI_ECB : return ECB_DecFinal(AlgInfo, PlainTxt, PlainTxtLen);
- case AI_CBC : return CBC_DecFinal(AlgInfo, PlainTxt, PlainTxtLen);
- case AI_OFB : return OFB_DecFinal(AlgInfo, PlainTxt, PlainTxtLen);
- case AI_CFB : return CFB_DecFinal(AlgInfo, PlainTxt, PlainTxtLen);
- default : return CTR_FATAL_ERROR;
- }
- }
- /*************** END OF FILE **********************************************/
AES.C文件
- /*************** Header files *********************************************/
- #include "aes.h"
- /*************** Assertions ***********************************************/
- /*************** New Data Types *******************************************/
- typedef struct {
- DWORD k_len;
- DWORD RK[64];
- } RIJNDAEL_CIPHER_KEY;
- /*************** Definitions / Macros ************************************/
- #define u1byte BYTE
- #define u4byte DWORD
- #define rotl ROTL_DWORD
- #define rotr ROTR_DWORD
- #define byte(x,n) ((u1byte)((x) >> (8 * n)))
- #define LARGE_TABLES
- #define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)
- #ifdef LARGE_TABLES
- #define ls_box(x) /
- ( fl_tab[0][byte(x, 0)] ^ /
- fl_tab[1][byte(x, 1)] ^ /
- fl_tab[2][byte(x, 2)] ^ /
- fl_tab[3][byte(x, 3)] )
- #else
- #define ls_box(x) /
- ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ /
- ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ /
- ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ /
- ((u4byte)sbx_tab[byte(x, 3)] << 24)
- #endif
- /*************** Global Variables *****************************************/
- static u1byte log_tab[256];
- static u1byte pow_tab[256];
- static u1byte sbx_tab[256];
- static u1byte isb_tab[256];
- static u4byte rco_tab[ 10];
- static u4byte ft_tab[4][256];
- static u4byte it_tab[4][256];
- #ifdef LARGE_TABLES
- static u4byte fl_tab[4][256];
- static u4byte il_tab[4][256];
- #endif
- static u4byte tab_gen = 0;
- /*************** Prototypes ***********************************************/
- static void gen_tabs(void)
- {
- u4byte i, t;
- u1byte p, q;
- /* log and power tables for GF(2**8) finite field with */
- /* 0x11b as modular polynomial - the simplest prmitive */
- /* root is 0x11, used here to generate the tables */
- log_tab[7] = 0;
- for(i = 0,p = 1; i < 256; ++i)
- {
- pow_tab[i] = (BYTE)p;
- log_tab[p] = (BYTE)i;
- p = (BYTE)(p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0));
- }
- log_tab[1] = 0;
- p = 1;
- for(i = 0; i < 10; ++i)
- {
- rco_tab[i] = p;
- p = (BYTE)((p << 1) ^ (p & 0x80 ? 0x1b : 0));
- }
- /* note that the affine byte transformation matrix in */
- /* rijndael specification is in big endian format with */
- /* bit 0 as the most significant bit. In the remainder */
- /* of the specification the bits are numbered from the */
- /* least significant end of a byte. */
- for(i = 0; i < 256; ++i)
- {
- p = (BYTE)(i ? pow_tab[255 - log_tab[i]] : 0);
- q = p;
- q = (BYTE)((q >> 7) | (q << 1));
- p ^= q;
- q = (BYTE)((q >> 7) | (q << 1));
- p ^= q;
- q = (BYTE)((q >> 7) | (q << 1));
- p ^= q;
- q = (BYTE)((q >> 7) | (q << 1));
- p ^= q ^ 0x63;
- sbx_tab[i] = (u1byte)p;
- isb_tab[p] = (u1byte)i;
- }
- for(i = 0; i < 256; ++i)
- {
- p = sbx_tab[i];
- #ifdef LARGE_TABLES
- t = p;
- fl_tab[0][i] = t;
- fl_tab[1][i] = rotl(t, 8);
- fl_tab[2][i] = rotl(t, 16);
- fl_tab[3][i] = rotl(t, 24);
- #endif
- t = ((u4byte)ff_mult(2, p)) |
- ((u4byte)p << 8) |
- ((u4byte)p << 16) |
- ((u4byte)ff_mult(3, p) << 24);
- ft_tab[0][i] = t;
- ft_tab[1][i] = rotl(t, 8);
- ft_tab[2][i] = rotl(t, 16);
- ft_tab[3][i] = rotl(t, 24);
- p = isb_tab[i];
- #ifdef LARGE_TABLES
- t = p; il_tab[0][i] = t;
- il_tab[1][i] = rotl(t, 8);
- il_tab[2][i] = rotl(t, 16);
- il_tab[3][i] = rotl(t, 24);
- #endif
- t = ((u4byte)ff_mult(14, p)) |
- ((u4byte)ff_mult( 9, p) << 8) |
- ((u4byte)ff_mult(13, p) << 16) |
- ((u4byte)ff_mult(11, p) << 24);
- it_tab[0][i] = t;
- it_tab[1][i] = rotl(t, 8);
- it_tab[2][i] = rotl(t, 16);
- it_tab[3][i] = rotl(t, 24);
- }
- tab_gen = 1;
- };
- #define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
- #define imix_col(y,x) /
- u = star_x(x); /
- v = star_x(u); /
- w = star_x(v); /
- t = w ^ (x); /
- (y) = u ^ v ^ w; /
- (y) ^= rotr(u ^ t, 8) ^ /
- rotr(v ^ t, 16) ^ /
- rotr(t,24)
- /**************************************************************************
- *
- * Function Description ...
- *
- * Return values:
- * - CTR_SUCCESS 窃荐啊 己傍利栏肺 荐青凳.
- * ...
- */
- static void RIJNDAEL_KeySchedule(
- BYTE *UserKey, // 荤侩磊 厚剐虐 涝仿
- DWORD k_len, // 荤侩磊 厚剐虐狼 DWORD 荐
- DWORD *e_key) // 鞠龋侩 Round Key 积己/免仿
- {
- u4byte i, t;
- if(!tab_gen)
- gen_tabs();
- LITTLE_B2D(&(UserKey[ 0]), e_key[0]);
- LITTLE_B2D(&(UserKey[ 4]), e_key[1]);
- LITTLE_B2D(&(UserKey[ 8]), e_key[2]);
- LITTLE_B2D(&(UserKey[12]), e_key[3]);
- switch(k_len)
- {
- case 4:
- t = e_key[3];
- for(i = 0; i < 10; ++i) {
- t = ls_box(rotr(t, 8)) ^ rco_tab[i];
- t ^= e_key[4 * i]; e_key[4 * i + 4] = t;
- t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t;
- t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t;
- t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t;
- }
- break;
- case 6:
- LITTLE_B2D(&(UserKey[16]), e_key[4]);
- LITTLE_B2D(&(UserKey[20]), e_key[5]);
- t = e_key[5];
- for(i = 0; i < 8; ++i) {
- t = ls_box(rotr(t, 8)) ^ rco_tab[i];
- t ^= e_key[6 * i]; e_key[6 * i + 6] = t;
- t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t;
- t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t;
- t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t;
- t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t;
- t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t;
- }
- // loop6(i);
- break;
- case 8:
- LITTLE_B2D(&(UserKey[16]), e_key[4]);
- LITTLE_B2D(&(UserKey[20]), e_key[5]);
- LITTLE_B2D(&(UserKey[24]), e_key[6]);
- LITTLE_B2D(&(UserKey[28]), e_key[7]);
- t = e_key[7];
- for(i = 0; i < 7; ++i) {
- t = ls_box(rotr(t, 8)) ^ rco_tab[i];
- t ^= e_key[8 * i]; e_key[8 * i + 8] = t;
- t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t;
- t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t;
- t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t;
- t = e_key[8 * i + 4] ^ ls_box(t);
- e_key[8 * i + 12] = t;
- t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t;
- t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t;
- t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t;
- }
- // loop8(i);
- break;
- }
- }
- /*************** Function *************************************************
- *
- */
- RET_VAL AES_EncKeySchedule(
- BYTE *UserKey, // 荤侩磊 厚剐虐 涝仿
- DWORD UserKeyLen, // 荤侩磊 厚剐虐狼 官捞飘 荐
- AES_ALG_INFO *AlgInfo) // 鞠龋侩/汗龋侩 Round Key 积己/历厘
- {
- RIJNDAEL_CIPHER_KEY *RK_Struct=(RIJNDAEL_CIPHER_KEY *) AlgInfo->RoundKey;
- DWORD *e_key=RK_Struct->RK; // 64 DWORDs
- DWORD k_len;
- // UserKey狼 辨捞啊 何利例茄 版快 error 贸府
- if( (UserKeyLen!=16) && (UserKeyLen!=24) && (UserKeyLen!=32) )
- return CTR_INVALID_USERKEYLEN;
- k_len = (UserKeyLen + 3) / 4;
- RK_Struct->k_len = k_len;
- RIJNDAEL_KeySchedule(UserKey, k_len, e_key);
- return CTR_SUCCESS;
- }
- /*************** Function *************************************************
- *
- */
- RET_VAL AES_DecKeySchedule(
- BYTE *UserKey, // 荤侩磊 厚剐虐 涝仿
- DWORD UserKeyLen, // 荤侩磊 厚剐虐狼 官捞飘 荐
- AES_ALG_INFO *AlgInfo) // 鞠龋侩/汗龋侩 Round Key 积己/历厘
- {
- RIJNDAEL_CIPHER_KEY *RK_Struct=(RIJNDAEL_CIPHER_KEY *) AlgInfo->RoundKey;
- DWORD *d_key=RK_Struct->RK; // 64 DWORDs
- DWORD k_len, t_key[64];
- u4byte i, t, u, v, w;
- // UserKey狼 辨捞啊 何利例茄 版快 error 贸府
- if( (UserKeyLen!=16) && (UserKeyLen!=24) && (UserKeyLen!=32) )
- return CTR_INVALID_USERKEYLEN;
- k_len = (UserKeyLen + 3) / 4;
- RK_Struct->k_len = k_len;
- RIJNDAEL_KeySchedule(UserKey, k_len, t_key);
- d_key[0] = t_key[4 * k_len + 24];
- d_key[1] = t_key[4 * k_len + 25];
- d_key[2] = t_key[4 * k_len + 26];
- d_key[3] = t_key[4 * k_len + 27];
- for( i=4; i<4*(k_len+6); i+=4) {
- imix_col(d_key[i+0], t_key[4*k_len+24-i+0]);
- imix_col(d_key[i+1], t_key[4*k_len+24-i+1]);
- imix_col(d_key[i+2], t_key[4*k_len+24-i+2]);
- imix_col(d_key[i+3], t_key[4*k_len+24-i+3]);
- }
- d_key[i+0] = t_key[4*k_len+24-i+0];
- d_key[i+1] = t_key[4*k_len+24-i+1];
- d_key[i+2] = t_key[4*k_len+24-i+2];
- d_key[i+3] = t_key[4*k_len+24-i+3];
- return CTR_SUCCESS;
- }
- /*
- DWORD A, B, C, D, T0, T1, *K=AlgInfo->RoundKey;
- if( UserKeyLen!=SEED_USER_KEY_LEN )
- return CTR_INVALID_USERKEYLEN;
- BIG_B2D( &(UserKey[0]), A);
- BIG_B2D( &(UserKey[4]), B);
- BIG_B2D( &(UserKey[8]), C);
- BIG_B2D( &(UserKey[12]), D);
- T0 = A + C - KC0;
- T1 = B - D + KC0;
- K[0] = SEED_SL[0][(T0 )&0xFF] ^ SEED_SL[1][(T0>> 8)&0xFF]
- ^ SEED_SL[2][(T0>>16)&0xFF] ^ SEED_SL[3][(T0>>24)&0xFF];
- K[1] = SEED_SL[0][(T1 )&0xFF] ^ SEED_SL[1][(T1>> 8)&0xFF]
- ^ SEED_SL[2][(T1>>16)&0xFF] ^ SEED_SL[3][(T1>>24)&0xFF];;
- EncRoundKeyUpdate0(K+ 2, A, B, C, D, KC1 );
- EncRoundKeyUpdate1(K+ 4, A, B, C, D, KC2 );
- EncRoundKeyUpdate0(K+ 6, A, B, C, D, KC3 );
- EncRoundKeyUpdate1(K+ 8, A, B, C, D, KC4 );
- EncRoundKeyUpdate0(K+10, A, B, C, D, KC5 );
- EncRoundKeyUpdate1(K+12, A, B, C, D, KC6 );
- EncRoundKeyUpdate0(K+14, A, B, C, D, KC7 );
- EncRoundKeyUpdate1(K+16, A, B, C, D, KC8 );
- EncRoundKeyUpdate0(K+18, A, B, C, D, KC9 );
- EncRoundKeyUpdate1(K+20, A, B, C, D, KC10);
- EncRoundKeyUpdate0(K+22, A, B, C, D, KC11);
- EncRoundKeyUpdate1(K+24, A, B, C, D, KC12);
- EncRoundKeyUpdate0(K+26, A, B, C, D, KC13);
- EncRoundKeyUpdate1(K+28, A, B, C, D, KC14);
- EncRoundKeyUpdate0(K+30, A, B, C, D, KC15);
- // Remove sensitive data
- A = B = C = D = T0 = T1 = 0;
- K = NULL;
- //
- return CTR_SUCCESS;
- */
- /*************** Macros ***************************************************/
- #define f_nround(bo, bi, k) { /
- bo[0] = ft_tab[0][byte(bi[0],0)] /
- ^ ft_tab[1][byte(bi[1],1)] /
- ^ ft_tab[2][byte(bi[2],2)] /
- ^ ft_tab[3][byte(bi[3],3)] ^ k[0];/
- bo[1] = ft_tab[0][byte(bi[1],0)] /
- ^ ft_tab[1][byte(bi[2],1)] /
- ^ ft_tab[2][byte(bi[3],2)] /
- ^ ft_tab[3][byte(bi[0],3)] ^ k[1];/
- bo[2] = ft_tab[0][byte(bi[2],0)] /
- ^ ft_tab[1][byte(bi[3],1)] /
- ^ ft_tab[2][byte(bi[0],2)] /
- ^ ft_tab[3][byte(bi[1],3)] ^ k[2];/
- bo[3] = ft_tab[0][byte(bi[3],0)] /
- ^ ft_tab[1][byte(bi[0],1)] /
- ^ ft_tab[2][byte(bi[1],2)] /
- ^ ft_tab[3][byte(bi[2],3)] ^ k[3];/
- k += 4; /
- }
- #define i_nround(bo, bi, k) { /
- bo[0] = it_tab[0][byte(bi[0],0)] /
- ^ it_tab[1][byte(bi[3],1)] /
- ^ it_tab[2][byte(bi[2],2)] /
- ^ it_tab[3][byte(bi[1],3)] ^ k[0];/
- bo[1] = it_tab[0][byte(bi[1],0)] /
- ^ it_tab[1][byte(bi[0],1)] /
- ^ it_tab[2][byte(bi[3],2)] /
- ^ it_tab[3][byte(bi[2],3)] ^ k[1];/
- bo[2] = it_tab[0][byte(bi[2],0)] /
- ^ it_tab[1][byte(bi[1],1)] /
- ^ it_tab[2][byte(bi[0],2)] /
- ^ it_tab[3][byte(bi[3],3)] ^ k[2];/
- bo[3] = it_tab[0][byte(bi[3],0)] /
- ^ it_tab[1][byte(bi[2],1)] /
- ^ it_tab[2][byte(bi[1],2)] /
- ^ it_tab[3][byte(bi[0],3)] ^ k[3];/
- k += 4; /
- }
- #ifdef LARGE_TABLES
- #define f_lround(bo, bi, k) { /
- bo[0] = fl_tab[0][byte(bi[0],0)] /
- ^ fl_tab[1][byte(bi[1],1)] /
- ^ fl_tab[2][byte(bi[2],2)] /
- ^ fl_tab[3][byte(bi[3],3)] ^ k[0];/
- bo[1] = fl_tab[0][byte(bi[1],0)] /
- ^ fl_tab[1][byte(bi[2],1)] /
- ^ fl_tab[2][byte(bi[3],2)] /
- ^ fl_tab[3][byte(bi[0],3)] ^ k[1];/
- bo[2] = fl_tab[0][byte(bi[2],0)] /
- ^ fl_tab[1][byte(bi[3],1)] /
- ^ fl_tab[2][byte(bi[0],2)] /
- ^ fl_tab[3][byte(bi[1],3)] ^ k[2];/
- bo[3] = fl_tab[0][byte(bi[3],0)] /
- ^ fl_tab[1][byte(bi[0],1)] /
- ^ fl_tab[2][byte(bi[1],2)] /
- ^ fl_tab[3][byte(bi[2],3)] ^ k[3];/
- }
- #define i_lround(bo, bi, k) { /
- bo[0] = il_tab[0][byte(bi[0],0)] /
- ^ il_tab[1][byte(bi[3],1)] /
- ^ il_tab[2][byte(bi[2],2)] /
- ^ il_tab[3][byte(bi[1],3)] ^ k[0];/
- bo[1] = il_tab[0][byte(bi[1],0)] /
- ^ il_tab[1][byte(bi[0],1)] /
- ^ il_tab[2][byte(bi[3],2)] /
- ^ il_tab[3][byte(bi[2],3)] ^ k[1];/
- bo[2] = il_tab[0][byte(bi[2],0)] /
- ^ il_tab[1][byte(bi[1],1)] /
- ^ il_tab[2][byte(bi[0],2)] /
- ^ il_tab[3][byte(bi[3],3)] ^ k[2];/
- bo[3] = il_tab[0][byte(bi[3],0)] /
- ^ il_tab[1][byte(bi[2],1)] /
- ^ il_tab[2][byte(bi[1],2)] /
- ^ il_tab[3][byte(bi[0],3)] ^ k[3];/
- }
- #else
- #define f_rl(bo, bi, n, k) /
- bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ /
- rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ /
- rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ /
- rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n)
- #define i_rl(bo, bi, n, k) /
- bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ /
- rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ /
- rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ /
- rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)
- #define f_lround(bo, bi, k) /
- f_rl(bo, bi, 0, k); /
- f_rl(bo, bi, 1, k); /
- f_rl(bo, bi, 2, k); /
- f_rl(bo, bi, 3, k)
- #define i_lround(bo, bi, k) /
- i_rl(bo, bi, 0, k); /
- i_rl(bo, bi, 1, k); /
- i_rl(bo, bi, 2, k); /
- i_rl(bo, bi, 3, k)
- #endif
- /*************** Function *************************************************
- *
- */
- void AES_Encrypt(
- void *CipherKey, // 鞠/汗龋侩 Round Key
- BYTE *Data) // 涝免仿阑 困茄 喉废阑 啊府虐绰 pointer
- {
- RIJNDAEL_CIPHER_KEY *RK_Struct=CipherKey;
- DWORD *e_key=RK_Struct->RK; // 64 DWORDs
- DWORD k_len=RK_Struct->k_len;
- u4byte b0[4], b1[4], *kp;
- LITTLE_B2D(&(Data[ 0]), b0[0]);
- LITTLE_B2D(&(Data[ 4]), b0[1]);
- LITTLE_B2D(&(Data[ 8]), b0[2]);
- LITTLE_B2D(&(Data[12]), b0[3]);
- //
- b0[0] ^= e_key[0];
- b0[1] ^= e_key[1];
- b0[2] ^= e_key[2];
- b0[3] ^= e_key[3];
- kp = e_key + 4;
- switch( k_len ) {
- case 8 :
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- case 6 :
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- case 4 :
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- f_nround(b1, b0, kp); f_nround(b0, b1, kp);
- f_nround(b1, b0, kp); f_lround(b0, b1, kp);
- }
- //
- LITTLE_D2B(b0[0], &(Data[ 0]));
- LITTLE_D2B(b0[1], &(Data[ 4]));
- LITTLE_D2B(b0[2], &(Data[ 8]));
- LITTLE_D2B(b0[3], &(Data[12]));
- }
- /*************** Function *************************************************
- *
- */
- void AES_Decrypt(
- void *CipherKey, // 鞠/汗龋侩 Round Key
- BYTE *Data) // 涝免仿阑 困茄 喉废阑 啊府虐绰 pointer
- {
- RIJNDAEL_CIPHER_KEY *RK_Struct=CipherKey;
- DWORD *d_key=RK_Struct->RK; // 64 DWORDs
- DWORD k_len=RK_Struct->k_len;
- u4byte b0[4], b1[4], *kp;
- LITTLE_B2D(&(Data[ 0]), b0[0]);
- LITTLE_B2D(&(Data[ 4]), b0[1]);
- LITTLE_B2D(&(Data[ 8]), b0[2]);
- LITTLE_B2D(&(Data[12]), b0[3]);
- //
- b0[0] ^= d_key[0];
- b0[1] ^= d_key[1];
- b0[2] ^= d_key[2];
- b0[3] ^= d_key[3];
- kp = d_key + 4;
- switch( k_len ) {
- case 8 :
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- case 6 :
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- case 4 :
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- i_nround(b1, b0, kp); i_nround(b0, b1, kp);
- i_nround(b1, b0, kp); i_lround(b0, b1, kp);
- }
- //
- LITTLE_D2B(b0[0], &(Data[ 0]));
- LITTLE_D2B(b0[1], &(Data[ 4]));
- LITTLE_D2B(b0[2], &(Data[ 8]));
- LITTLE_D2B(b0[3], &(Data[12]));
- }
- /*************** END OF FILE **********************************************/
下面是我针对上面封装的两个加密解密函数的实现, 很简单的, 密钥是固定的
你可以固定一个16个Byte的字符串, 也可以用我代码里面写死的东西, 0x10 到 0x1F
- static int AESEncode (const char* srcString, int srcLen, char** dstString, int* dstLen)
- {
- //16 * (trunc(string_length / 16) + 1)。
- char *pOut=0;
- unsigned int len = 16 * (srcLen/16 + 1);
- BYTE UserKey[AES_USER_KEY_LEN]={0};
- BYTE IV[AES_BLOCK_LEN]={0};
- DWORD UKLen, IVLen, SrcLen, DstLen;
- RET_VAL ret;
- AES_ALG_INFO AlgInfo;
- int eelen = 0;
- UKLen = 16;
- IVLen = 16;
- #ifdef _DEBUG
- int t = 0x10;
- for (int i=0; i<16; i++)
- {
- UserKey[i] = t+i;
- }
- #else
- snprintf ((char*)UserKey, sizeof(UserKey)-1, "%s", g_Config.encryptKey);
- #endif
- pOut = (char*)calloc (1, len+4);
- if (pOut == NULL)
- return -1;
- DstLen = len;
- //
- AES_SetAlgInfo(AES_ModeType, AES_PadType, IV, &AlgInfo);
- // Encryption
- ret = AES_EncKeySchedule(UserKey, UKLen, &AlgInfo);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_EncKeySchedule() returns.");
- safe_free (pOut);
- return -1;
- }
- ret = AES_EncInit(&AlgInfo);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_EncInit() returns.");
- safe_free (pOut);
- return -1;
- }
- ret = AES_EncUpdate(&AlgInfo, (unsigned char*)srcString, SrcLen, (unsigned char*)pOut, &DstLen);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_EncUpdate() returns.");
- safe_free (pOut);
- return -1;
- }
- eelen = DstLen;
- ret = AES_EncFinal(&AlgInfo, (unsigned char*)pOut+eelen, &DstLen);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_EncFinal() returns.");
- safe_free (pOut);
- return -1;
- }
- eelen += DstLen;
- *dstLen = eelen;
- *dstString = pOut;
- return 0;
- }
- static int AESDecode (const char* srcString, int srcLen, char** dstString, int* dstLen)
- {
- //FILE *pIn, *pOut;
- char* pOut = 0;
- unsigned char UserKey[AES_USER_KEY_LEN]={0};
- unsigned char IV[AES_BLOCK_LEN]={0};
- //unsigned char SrcData[1024+32], DstData[1024+32];
- unsigned int UKLen, IVLen;
- unsigned int SrcLen, DstLen;
- RET_VAL ret;
- AES_ALG_INFO AlgInfo;
- int ddlen = 0;
- SrcLen = srcLen;
- pOut = (char*)calloc(1, SrcLen+2);
- if (pOut == NULL) return -1;
- DstLen = SrcLen;
- UKLen = 16;
- IVLen = 16;
- #ifdef _DEBUG
- int t = 0x10;
- for (int i=0; i<16; i++)
- {
- UserKey[i] = t+i;
- }
- #else
- snprintf ((char*)UserKey, sizeof(UserKey)-1, "%s", g_Config.encryptKey);
- #endif
- AES_SetAlgInfo(AES_ModeType, AES_PadType, IV, &AlgInfo);
- //Decryption
- //if( ModeType==AI_ECB || ModeType==AI_CBC )
- ret = AES_DecKeySchedule(UserKey, UKLen, &AlgInfo);
- //else if( ModeType==AI_OFB || ModeType==AI_CFB )
- // ret = AES_EncKeySchedule(UserKey, UKLen, &AlgInfo);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_DecKeySchedule() returns.");
- safe_free (pOut);
- return -1;
- }
- ret = AES_DecInit(&AlgInfo);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_DecInit() returns.");
- safe_free (pOut);
- return -1;
- }
- ret = AES_DecUpdate(&AlgInfo, (unsigned char*)srcString, SrcLen, (unsigned char*)pOut, &DstLen);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_DecUpdate() returns.");
- safe_free (pOut);
- return -1;
- }
- ddlen = DstLen;
- ret = AES_DecFinal(&AlgInfo, (unsigned char*)pOut+ddlen, &DstLen);
- if( ret!=CTR_SUCCESS )
- {
- writelog(LOG_DEBUG, "AES_DecFinal() returns.");
- safe_free (pOut);
- return -1;
- }
- ddlen += DstLen;
- *dstLen = ddlen;
- *dstString = pOut;
- return 0;
- }