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