You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.4 KiB
125 lines
3.4 KiB
/* Microsoft Corporation (C) 2000 */
|
|
|
|
#include "crptkPCH.h"
|
|
#include "bv4.h"
|
|
|
|
void bv4_key_C(BV4_KEYSTRUCT *pState, DWORD dwLen, unsigned char *buf)
|
|
{
|
|
if (pState == NULL)
|
|
{
|
|
return; // Too bad we return void.
|
|
}
|
|
int keyLength = dwLen;
|
|
BYTE *key = buf;
|
|
|
|
DWORD i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
pState->p_T[i] = (unsigned char)i;
|
|
}
|
|
|
|
// fill k with the key, repeated as many times as necessary
|
|
// to fill the entire array;
|
|
DWORD k[256]; // contains only 8-bit values zero-extended to 32 bits.
|
|
int keyPos = 0;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
if (keyPos >= keyLength)
|
|
{
|
|
keyPos = 0;
|
|
}
|
|
k[i] = key[keyPos++];
|
|
}
|
|
|
|
DWORD j = 0;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
j = (j + pState->p_T[i] + k[i]) & 0xff;
|
|
DWORD tmp = pState->p_T[i];
|
|
pState->p_T[i] = pState->p_T[j];
|
|
pState->p_T[j] = (unsigned char)tmp;
|
|
}
|
|
|
|
// treat alpha and beta as one contiguous array of 33 4-byte blocks.
|
|
// see "Applied Cryptography", 1996, by Bruce Schneier, p. 397.
|
|
|
|
i = 0;
|
|
j = 0;
|
|
for (int m = 0; m < 33; m++)
|
|
{
|
|
DWORD nextDword = 0;
|
|
// gather up the next 4 bytes of keys into one DWORD
|
|
for (int n = 0; n < 4; n++)
|
|
{
|
|
i = (i+1) & 0xff;
|
|
DWORD ti = pState->p_T[i];
|
|
j = (j+ti) & 0xff;
|
|
// swap T[i] and T[j];
|
|
DWORD tj = pState->p_T[j];
|
|
pState->p_T[i] = (unsigned char)tj;
|
|
pState->p_T[j] = (unsigned char)ti;
|
|
DWORD t = (ti+tj) & 0xff;
|
|
DWORD kk = pState->p_T[t];
|
|
nextDword |= kk << (n*8);
|
|
}
|
|
if (m == 0)
|
|
{
|
|
pState->p_alpha = nextDword;
|
|
}
|
|
else
|
|
{
|
|
pState->p_beta[m-1] = nextDword;
|
|
}
|
|
}
|
|
|
|
// keep the final state as the state we need for the new algorithm.
|
|
// T has already been updated.
|
|
pState->p_R = (unsigned char)i;
|
|
pState->p_S = (unsigned char)j;
|
|
}
|
|
|
|
// cipher: generate a stream of 32-bit keys and xor them with the
|
|
// contents of buffer. This can be used to encrypt/decrypt
|
|
// a stream of data.
|
|
void bv4_C(BV4_KEYSTRUCT *pState, DWORD dwLen, unsigned char *buf)
|
|
{
|
|
if (pState == NULL)
|
|
{
|
|
return; // Too bad we return void.
|
|
}
|
|
DWORD *buffer = (DWORD *)buf;
|
|
DWORD bufferLength = dwLen / sizeof(DWORD);
|
|
|
|
DWORD *last = buffer + bufferLength;
|
|
|
|
// load field values into local variables
|
|
// the following change on every iteration of the loop
|
|
DWORD r = pState->p_R;
|
|
DWORD s = pState->p_S;
|
|
DWORD alpha = pState->p_alpha;
|
|
|
|
|
|
// the following are loop invariant
|
|
unsigned char *t = pState->p_T;
|
|
DWORD *beta = pState->p_beta;
|
|
|
|
for (last = buffer + bufferLength; buffer < last; buffer++)
|
|
{
|
|
r = (r+1) & 0xff;
|
|
DWORD tr = t[r];
|
|
s = (s+tr) & 0xff;
|
|
DWORD ts = t[s];
|
|
t[r] = (unsigned char)ts;
|
|
t[s] = (unsigned char)tr;
|
|
DWORD tmp = (ts+tr) & 0xff;
|
|
DWORD randPad = alpha * t[tmp];
|
|
*buffer = randPad^(*buffer);
|
|
alpha = alpha + beta[s & 0x1f];
|
|
}
|
|
|
|
// update the field values from the local variables
|
|
pState->p_R = (unsigned char)r;
|
|
pState->p_S = (unsigned char)s;
|
|
pState->p_alpha = alpha;
|
|
}
|