www.pudn.com > cast_src.rar > mycast.cpp
/* CAST-256 Strong Encryption Plugin for Back Orifice 2000 Copyright (C) 1999, Daniel Roethlisberger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA The author of this program may be contacted at admin@roe.ch. */ #include#include #include #include "bo_cast.h" #include "md5.h" #include "cast256.h" #include "mycast.h" ENCRYPTION_ENGINE g_CASTengine = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; // called when engine is inserted into handler int __cdecl CAST_Insert(void) { if(GetCfgStr(g_szCASTEncryptOptions, CAST_CONFIG_KEY_STRING) == NULL) return -1; return 0; } // called when engine is removed from handler int __cdecl CAST_Remove(void) { return 0; } // returns the ID string of the engine char * __cdecl CAST_Query(void) { return CAST_QUERY_STRING; } // called before any key or encryption takes place to initialise void * __cdecl CAST_Startup(void) { // read the configuration char *svKey = GetCfgStr(g_szCASTEncryptOptions, CAST_CONFIG_KEY_STRING); if(svKey == NULL) return NULL; if(svKey[0] == '\0') return NULL; BOOL bCBC = GetCfgBool(g_szCASTEncryptOptions, CAST_CONFIG_CBC_MODE); // allocate a context structure CAST_CTX *data; data = (CAST_CTX*)malloc(sizeof(CAST_CTX)); if(data == NULL) return NULL; // let the CAST256 engine fill in internal tables CAST256TableInit(); // set the configuration data->bCASTCBC = bCBC; CAST_SetKey((void*)data, svKey); return data; } // called after encryption has been finished to clean up int __cdecl CAST_Shutdown(void *pInternal) { CAST_CTX *data = (CAST_CTX*)pInternal; free(data); return 0; } // called to set key string int __cdecl CAST_SetKey(void *pInternal, char *svKey) { CAST_CTX *data = (CAST_CTX*)pInternal; MD5_CTX ctx; char buf1[] = CAST_MDSTRING1; char buf2[] = CAST_MDSTRING2; char buf3[] = CAST_MDSTRING3; char buf4[] = CAST_MDSTRING4; // generate user key from key string and magic strings MD5Init(&ctx); MD5Update(&ctx, (BYTE*)buf1, strlen(buf1)); MD5Update(&ctx, (BYTE*)svKey, strlen(svKey)); MD5Final((BYTE*)&data->CASTUserKey, &ctx); MD5Init(&ctx); MD5Update(&ctx, (BYTE*)svKey, strlen(svKey)); MD5Update(&ctx, (BYTE*)buf2, strlen(buf2)); MD5Final((((BYTE*)&data->CASTUserKey) + 16), &ctx); // generate initialisation vector from key string MD5Init(&ctx); MD5Update(&ctx, (BYTE*)buf3, strlen(buf3)); MD5Update(&ctx, (BYTE*)svKey, strlen(svKey)); MD5Update(&ctx, (BYTE*)buf4, strlen(buf4)); MD5Final((BYTE*)&data->CASTInitVect, &ctx); strcpy(data->svCASTKey, svKey); // let the CAST256 engine initialise the key context CAST256KeyInit(data->CASTKr, data->CASTKm, data->CASTUserKey); return 0; } // returns key string char * __cdecl CAST_GetKey(void *pInternal) { CAST_CTX *data = (CAST_CTX*)pInternal; return data->svCASTKey; } // returns encrypted buffer that must be freed BYTE * __cdecl CAST_Encrypt(void *pInternal, BYTE *pBuffer, int nBufLen, int *pnOutBufLen) { CAST_CTX *data = (CAST_CTX*)pInternal; BYTE *buf; int blocks, baselen, leftover; // check on length (must be a multiple of 128) leftover = nBufLen & 15; baselen = nBufLen + (leftover ? 16-leftover : 0); // add padding if(leftover) { buf = (BYTE*)malloc(baselen); memset(buf, 0, baselen); buf[baselen-1] = 16 - leftover; } else { baselen = nBufLen + 16; buf = (BYTE*)malloc(baselen); memset(buf, 0, baselen); buf[baselen-1] = 16; } memcpy(buf, pBuffer, nBufLen); // number of blocks to encode blocks = baselen >> 4; if(data->bCASTCBC) { // CBC Mode: cypherblock = enc(plainblock XOR lastcypherblock) for(int i = 0; i < blocks; i++) { for(int j = 0; j < CAST_BLOCK_SIZE; j++) { buf[i*CAST_BLOCK_SIZE+j] = buf[i*CAST_BLOCK_SIZE+j] ^ data->CASTInitVect[j]; } CAST256Encrypt(data->CASTKr, data->CASTKm, (BETA*)&buf[i*CAST_BLOCK_SIZE]); memcpy(&data->CASTInitVect, &buf[i*CAST_BLOCK_SIZE], CAST_BLOCK_SIZE); } } else { // ECB Mode: cypherblock = enc(plainblock XOR initvect) for(int i = 0; i < blocks; i++) { for(int j = 0; j < CAST_BLOCK_SIZE; j++) { buf[i*CAST_BLOCK_SIZE+j] = buf[i*CAST_BLOCK_SIZE+j] ^ data->CASTInitVect[j]; } CAST256Encrypt(data->CASTKr, data->CASTKm, (BETA*)&buf[i*CAST_BLOCK_SIZE]); } } *pnOutBufLen = baselen; return buf; } // returns decrypted buffer that must be freed BYTE * __cdecl CAST_Decrypt(void *pInternal, BYTE *pBuffer, int nBufLen, int *pnOutBufLen) { CAST_CTX *data = (CAST_CTX*)pInternal; BYTE *buf; int blocks = 0; BYTE NewInitVect[CAST_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // check on length (must be a multiple of 128) if (nBufLen & 15) return NULL; buf = (BYTE*)malloc(nBufLen); memcpy(buf, pBuffer, nBufLen); // number of blocks to encode blocks = nBufLen >> 4; if(data->bCASTCBC) { // CBC Mode: plainblock = dec(cypherblock) XOR lastcypherblock for(int i = 0; i < blocks; i++) { memcpy(NewInitVect, &buf[i*CAST_BLOCK_SIZE], CAST_BLOCK_SIZE); CAST256Decrypt(data->CASTKr, data->CASTKm, (BETA*)&buf[i*CAST_BLOCK_SIZE]); for(int j = 0; j < CAST_BLOCK_SIZE; j++) { buf[i*CAST_BLOCK_SIZE+j] = buf[i*CAST_BLOCK_SIZE+j] ^ data->CASTInitVect[j]; } memcpy(data->CASTInitVect, NewInitVect, CAST_BLOCK_SIZE); } } else { // ECB Mode: plainblock = dec(cypherblock) XOR initvect for(int i = 0; i < blocks; i++) { CAST256Decrypt(data->CASTKr, data->CASTKm, (BETA*)&buf[i*CAST_BLOCK_SIZE]); for(int j = 0; j < CAST_BLOCK_SIZE; j++) { buf[i*CAST_BLOCK_SIZE+j] = buf[i*CAST_BLOCK_SIZE+j] ^ data->CASTInitVect[j]; } } } // remove padding nBufLen -= buf[nBufLen-1]; // crop buf here if the extra trailing zero bytes turn out to be fatal // cannot imagine how they could though *pnOutBufLen = nBufLen; return buf; } // generate new keys, we just get them from the config string int __cdecl CAST_CreateNewKeys(void *pInternal) { char *svKey = GetCfgStr(g_szCASTEncryptOptions, CAST_CONFIG_KEY_STRING); if(svKey == NULL) return -1; if(svKey[0] == '\0') return -1; CAST_CTX *data = (CAST_CTX*)pInternal; free(data); data = (CAST_CTX*)malloc(sizeof(CAST_CTX)); if(data == NULL) return -1; CAST_SetKey((void*)data, svKey); return 0; } // free buffers returned by CAST_Encrypt or CAST_Decrypt void __cdecl CAST_Free(void *pInternal, BYTE *pBuffer) { free(pBuffer); } // returns a struct containing the function addresses ENCRYPTION_ENGINE *GetCASTEncryptionEngine(void) { g_CASTengine.pInsert = CAST_Insert; g_CASTengine.pRemove = CAST_Remove; g_CASTengine.pQuery = CAST_Query; g_CASTengine.pStartup = CAST_Startup; g_CASTengine.pShutdown = CAST_Shutdown; g_CASTengine.pSetEncryptKey = CAST_SetKey; g_CASTengine.pSetDecryptKey = CAST_SetKey; g_CASTengine.pGetEncryptKey = CAST_GetKey; g_CASTengine.pGetDecryptKey = CAST_GetKey; g_CASTengine.pEncrypt = CAST_Encrypt; g_CASTengine.pDecrypt = CAST_Decrypt; g_CASTengine.pCreateNewKeys = CAST_CreateNewKeys; g_CASTengine.pFree = CAST_Free; return &g_CASTengine; }