Click here to Skip to main content
15,881,803 members
Articles / Desktop Programming / MFC

Exile 1.8 - The Password Manager

Rate me:
Please Sign up or sign in to vote.
4.57/5 (51 votes)
6 Mar 20058 min read 254.8K   7.4K   111  
Yet another password manager.
/********************************************************************
	Created:	21/3/2004, 11:15
	File name: 	D:\Projects\Exile\RC5\RC5.cpp
	File path:	D:\Projects\Exile\RC5
	File base:	RC5
	File ext:	cpp
	Author:		Gogolev Anton
*********************************************************************/

// RC5.cpp : Defines the entry point for the DLL.
//

#include "stdafx.h"
#include "RC5.h"
#include <map>
#include <math.h>

#pragma warning(disable:4786)

// Map of all contexts acquired
typedef std::map<HRC5CONTEXT, RC5CONTEXT> RC5CONTEXTMAP;

RC5CONTEXTMAP mRc5Ctx;

// Magic constants
const RC5_WORD P = 0xB7E15163;
const RC5_WORD Q = 0X9E3779B9;

BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
	switch(dwReason) 
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	} // switch

    return TRUE;
}

RC5_API BOOL Rc5AcquireContext(HRC5CONTEXT &hRc5, BYTE cKeyBytes, BYTE cRounds)
{
	hRc5 = (HRC5CONTEXT)&hRc5;

	// Check for duplicates
	if(mRc5Ctx.end() != mRc5Ctx.find(hRc5)) 
	{
		hRc5 = (HRC5CONTEXT)0;
		return FALSE;
	} // if
	
	RC5CONTEXT cRc5;

	cRc5.lVersion = MAKELONG(1, 0);
	cRc5.cWordSize = 32; // for x86
	cRc5.cRounds = cRounds;
	cRc5.cKeyBytes = cKeyBytes;
	cRc5.cKeyWords = (BYTE)ceil(8.0 * cKeyBytes / cRc5.cWordSize);
	cRc5.nExpandedSize = 2 * (cRounds + 1);
	cRc5.pwExpanded = new RC5_WORD[cRc5.nExpandedSize];
	if(!cRc5.pwExpanded)
	{
		hRc5 = (HRC5CONTEXT)0;
		return FALSE;
	} // if

	// Adding context to map
	mRc5Ctx[hRc5] = cRc5;

	return TRUE;
}

RC5_API BOOL Rc5ReleaseContext(HRC5CONTEXT &hRc5)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		RC5CONTEXT cRc5 = mRc5i->second;		
		delete [] cRc5.pwExpanded; 

		// Cleaning up contexts
		memset((void *)&cRc5, 0, sizeof(RC5CONTEXT));
		memset((void *)&(mRc5i->second), 0, sizeof(RC5CONTEXT));

		hRc5 = (HRC5CONTEXT)0;

		mRc5Ctx.erase(mRc5i);

		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5ResetContext(HRC5CONTEXT hRc5)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		memset((void *)mRc5i->second.pwExpanded, 0, sizeof(RC5_WORD) * mRc5i->second.nExpandedSize);
		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5ValidContext(HRC5CONTEXT hRc5)
{
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	if(mRc5Ctx.end() != mRc5Ctx.find(hRc5)) 
	{
		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5SetPrivateKey(HRC5CONTEXT hRc5, TCHAR *pszKey)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		// Check if key length is appropriate
#ifdef _UNICODE
		if(wcslen(pszKey) != mRc5i->second.cKeyBytes)
			return FALSE;
#else
		size_t sz = strlen(pszKey);
		if(strlen(pszKey) != mRc5i->second.cKeyBytes)
			return FALSE;
#endif // _UNICODE

		RC5_WORD i, j, k, u = mRc5i->second.cWordSize / 8, A, B;
		RC5_WORD *pL = new RC5_WORD[mRc5i->second.cKeyWords];

		for(i = mRc5i->second.cKeyBytes - 1, pL[mRc5i->second.cKeyWords - 1] = 0; i != -1; --i)
			pL[i / u] = (pL[i / u] << 8) + pszKey[i];

		for(mRc5i->second.pwExpanded[0] = P, i = 1; i < mRc5i->second.nExpandedSize; ++i)
			mRc5i->second.pwExpanded[i] = mRc5i->second.pwExpanded[i - 1] + Q;
		
		for(i = j = k = A = B = 0; k < 3 * __max(mRc5i->second.nExpandedSize, mRc5i->second.cKeyWords); 
			++k, i = (i + 1) % mRc5i->second.nExpandedSize, j = (j + 1) % mRc5i->second.cKeyWords)
		{
				A = mRc5i->second.pwExpanded[i] = _lrotl(mRc5i->second.pwExpanded[i] + (A + B), 3);
				B = pL[j] = _lrotl(pL[j] + (A + B), A + B);
		} // for

		memset((void *)pL, 0, sizeof(RC5_WORD) * mRc5i->second.cKeyWords);
		delete []  pL;

		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5SetBinaryPrivateKey(HRC5CONTEXT hRc5, BYTE *pKey)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		RC5_WORD i, j, k, u = mRc5i->second.cWordSize / 8, A, B;
		RC5_WORD *pL = new RC5_WORD[mRc5i->second.cKeyWords];

		for(i = mRc5i->second.cKeyBytes - 1, pL[mRc5i->second.cKeyWords - 1] = 0; i != -1; --i)
			pL[i / u] = (pL[i / u] << 8) + pKey[i];

		for(mRc5i->second.pwExpanded[0] = P, i = 1; i < mRc5i->second.nExpandedSize; ++i)
			mRc5i->second.pwExpanded[i] = mRc5i->second.pwExpanded[i - 1] + Q;
		
		for(i = j = k = A = B = 0; k < 3 * __max(mRc5i->second.nExpandedSize, mRc5i->second.cKeyWords); 
			++k, i = (i + 1) % mRc5i->second.nExpandedSize, j = (j + 1) % mRc5i->second.cKeyWords)
		{
				A = mRc5i->second.pwExpanded[i] = _lrotl(mRc5i->second.pwExpanded[i] + (A + B), 3);
				B = pL[j] = _lrotl(pL[j] + (A + B), A + B);
		} // for

		memset((void *)pL, 0, sizeof(RC5_WORD) * mRc5i->second.cKeyWords);
		delete []  pL;

		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5Encrypt(HRC5CONTEXT hRc5, RC5_WORD *pwPlain, RC5_WORD *pwCipher)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		RC5_WORD A = pwPlain[0] + mRc5i->second.pwExpanded[0], B = pwPlain[1] + mRc5i->second.pwExpanded[1];

		for(RC5_WORD i = 1; i <= mRc5i->second.cRounds; ++i)
		{
			A = _lrotl(A ^ B, B) + mRc5i->second.pwExpanded[2 * i];
			B = _lrotl(B ^ A, A) + mRc5i->second.pwExpanded[2 * i + 1];
		} // for

		pwCipher[0] = A;
		pwCipher[1] = B;

		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5Decrypt(HRC5CONTEXT hRc5, RC5_WORD *pwCipher, RC5_WORD *pwPlain)
{
	// Zero context handle can not be acquired, so this indicates error
	if(0 == hRc5) 
	{
		return FALSE;
	} // if

	// If there is such context
	RC5CONTEXTMAP::iterator mRc5i;
	if(mRc5Ctx.end() != (mRc5i = mRc5Ctx.find(hRc5))) 
	{
		RC5_WORD B = pwCipher[1], A = pwCipher[0];

		for(RC5_WORD i = mRc5i->second.cRounds; i > 0; --i)
		{
			B = _lrotr(B - mRc5i->second.pwExpanded[2 * i + 1], A) ^ A;
			A = _lrotr(A - mRc5i->second.pwExpanded[2 * i], B) ^ B;
		} // for

		pwPlain[1] = B - mRc5i->second.pwExpanded[1];
		pwPlain[0] = A - mRc5i->second.pwExpanded[0];

		return TRUE;
	} // if

	return FALSE;
}

RC5_API BOOL Rc5EncryptBlock(HRC5CONTEXT hRc5, RC5_WORD *pwPlain, RC5_WORD *pwCipher, UINT nBlocks)
{
	RC5_WORD wPlain[2], wCipher[2];

	for(RC5_WORD i = 0; i < nBlocks; ++i)
	{
		wPlain[0] = pwPlain[i * 2];
		wPlain[1] = pwPlain[i * 2 + 1];

		if(!Rc5Encrypt(hRc5, wPlain, wCipher))
			return FALSE;

		pwCipher[i * 2] = wCipher[0];
		pwCipher[i * 2 + 1] = wCipher[1];
	} // for

	return TRUE;
}

RC5_API BOOL Rc5DecryptBlock(HRC5CONTEXT hRc5, RC5_WORD *pwCipher, RC5_WORD *pwPlain, UINT nBlocks)
{
	RC5_WORD wPlain[2], wCipher[2];

	for(RC5_WORD i = 0; i < nBlocks; ++i)
	{
		wCipher[0] = pwCipher[i * 2];
		wCipher[1] = pwCipher[i * 2 + 1];

		if(!Rc5Decrypt(hRc5, wCipher, wPlain))
			return FALSE;

		pwPlain[i * 2] = wPlain[0];
		pwPlain[i * 2 + 1] = wPlain[1];
	} // for

	return TRUE;
}

RC5_API BOOL Rc5Recrypt(HRC5CONTEXT hRc5Src, HRC5CONTEXT hRc5Dest, RC5_WORD *pwCipherSrc, RC5_WORD *pwCipherDest)
{
	if(!Rc5Decrypt(hRc5Src, pwCipherSrc, pwCipherDest))
		return FALSE;

	if(!Rc5Encrypt(hRc5Dest, pwCipherDest, pwCipherDest))
		return FALSE;

	return TRUE;
}

RC5_API BOOL Rc5RecryptBlock(HRC5CONTEXT hRc5Src, HRC5CONTEXT hRc5Dest, RC5_WORD *pwCipherSrc, 
							 RC5_WORD *pwCipherDest, UINT nBlocks)
{
	if(!Rc5DecryptBlock(hRc5Src, pwCipherSrc, pwCipherDest, nBlocks))
		return FALSE;

	if(!Rc5EncryptBlock(hRc5Dest, pwCipherDest, pwCipherDest, nBlocks))
		return FALSE;

	return TRUE;
}

RC5_API BOOL Rc5CbcAcquireContext(HRC5CONTEXT &hRc5, BYTE cKeyBytes, BYTE cRounds, BYTE cCbcMode)
{
	return FALSE;
}

RC5_API BOOL Rc5CbcReleaseContext(HRC5CONTEXT &hRc5)
{
	return FALSE;
}

RC5_API BOOL Rc5CbcResetContext(HRC5CONTEXT &hRc5)
{
	return FALSE;
}

RC5_API BOOL Rc5CbcSetBinaryPrivateKey(HRC5CONTEXT hRc5, BYTE *pbKey)
{
	return FALSE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
I'll think about it later on...

Comments and Discussions