Leaked source code of windows server 2003
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.
 
 
 
 
 
 

325 lines
7.3 KiB

#include "crptkPCH.h"
//-----------------------------------------------------------------------------
//
// File: CBC64WS4.cpp
//
// Microsoft Digital Rights Management
// Copyright (C) 1998-1999 Microsoft Corporation, All Rights Reserved
//
// Description:
//
//-----------------------------------------------------------------------------
/*
chain-sum MAC scheme 4.5: multiply-&-swap rounds plus sum (reversible -- reversal code included)
6/15/98 mj
8/22/98 mj
8/31/98 mj
9/21/98 mj
2/4/99 mj
*/
#include "cbckey.h"
#ifndef SHCLASS
#define SHCLASS
#endif
//
// C version
//
#define WORDSWAP(d) \
((d >> 16) + (d << 16))
// pairwise independent function and summing step
#define C_STEP(L1, L2, L3, L4, L5, L6) \
t += *Data++; \
t *= L1; \
t = WORDSWAP(t); \
t *= L2; \
t = WORDSWAP(t); \
t *= L3; \
t = WORDSWAP(t); \
t *= L4; \
t = WORDSWAP(t); \
t *= L5; \
t += L6; \
sum += t;
// MAC function
// returns half of 64-bit MAC, and places other half in *pKey2
UINT32 CBC64WS4_asm(
UINT32 *Data,
unsigned NumDWORDBlocks,
UINT32 *pKey2,
CBCKey key)
{
UINT32 sum = 0, t = 0;
while (NumDWORDBlocks > 0) {
C_STEP(key.a1, key.b1, key.c1, key.d1, key.e1, key.f1);
C_STEP(key.a2, key.b2, key.c2, key.d2, key.e2, key.f2);
NumDWORDBlocks -= 2;
}
*pKey2 = t;
return sum;
}
//
// inverse MAC
//
// compute gcd(a, b) = x*a + y*b
static void egcd(UINT64 a, UINT64 b, __int64 &gcd, __int64 &x, __int64 &y)
{
if (b == 0) {
gcd = a; x = 1; y = 1;
}
else {
egcd(b, a % b, gcd, x, y);
__int64 t = y;
y = x - y*(a/b);
x = t;
}
}
// invert n mod 2^32
UINT32 inv32(UINT32 n)
{
__int64 gcd, in, x;
__int64 modulus = (__int64)1<<32;
egcd(modulus, n, gcd, x, in);
while (in < 0)
in += modulus;
return (UINT32) in;
}
// step to reverse action of multiply-&-swap rounds
#define INV_STEP_C(iL1, iL2, iL3, iL4, iL5) \
tmp *= iL5; \
tmp = WORDSWAP(tmp); \
tmp *= iL4; \
tmp = WORDSWAP(tmp); \
tmp *= iL3; \
tmp = WORDSWAP(tmp); \
tmp *= iL2; \
tmp = WORDSWAP(tmp); \
tmp *= iL1;
// inverse MAC function
// decrypts last two blocks of Data
// (replaces 64-bit ciphertext Data[NumDWORDBlocks - 1] and Data[NumDWORDBlocks - 2] with
// plaintext, and returns the plaintext in the return value and *pKey2 -- change as required)
UINT32 InvCBC64WS4_asm(
UINT32 *Data,
unsigned NumDWORDBlocks,
UINT32 *pKey2,
CBCKey key,
CBCKey ikey )
{
UINT32 yn, yn1, yn2, xn, xn1;
UINT32 sum32, tmp;
// Invert last two blocks (sum and 32-bit MAC). This requires the encrypted last two
// blocks and the (NumDWORDBlocks-2) plaintext blocks.
sum32 = CBC64WS4_asm(Data, NumDWORDBlocks - 2, &yn2, key) + Data[NumDWORDBlocks - 1];
yn = Data[NumDWORDBlocks - 1];
yn1 = Data[NumDWORDBlocks - 2] - sum32;
// last word
tmp = yn - key.f2;
INV_STEP_C(ikey.a2, ikey.b2, ikey.c2, ikey.d2, ikey.e2);
xn = tmp - yn1;
// next-to-last word
tmp = yn1 - key.f1;
INV_STEP_C(ikey.a1, ikey.b1, ikey.c1, ikey.d1, ikey.e1);
xn1 = tmp - yn2;
Data[NumDWORDBlocks - 2] = *pKey2 = (UINT32) xn1;
Data[NumDWORDBlocks - 1] = (UINT32) xn;
return (UINT32) xn;
}
void CBC64InitState( CBCState *cbcstate ) {
cbcstate->sum = 0; cbcstate->t = 0; cbcstate->dwBufLen = 0;
}
void CBC64Init( CBCKey *cbckey, CBCState *cbcstate, BYTE *pKey ) {
UINT32 *p;
cbcstate->sum = 0; cbcstate->t = 0; cbcstate->dwBufLen = 0;
p = (UINT32 *)pKey;
cbckey->a1 = *p++ | 0x00000001;
cbckey->b1 = *p++ | 0x00000001;
cbckey->c1 = *p++ | 0x00000001;
cbckey->d1 = *p++ | 0x00000001;
cbckey->e1 = *p++ | 0x00000001;
cbckey->f1 = *p++ | 0x00000001;
cbckey->a2 = *p++ | 0x00000001;
cbckey->b2 = *p++ | 0x00000001;
cbckey->c2 = *p++ | 0x00000001;
cbckey->d2 = *p++ | 0x00000001;
cbckey->e2 = *p++ | 0x00000001;
cbckey->f2 = *p++ | 0x00000001;
}
void CBC64InvKey( CBCKey *cbckey, CBCKey *cbcInvKey ) {
cbcInvKey->a1 = inv32( cbckey->a1 );
cbcInvKey->a2 = inv32( cbckey->a2 );
cbcInvKey->b1 = inv32( cbckey->b1 );
cbcInvKey->b2 = inv32( cbckey->b2 );
cbcInvKey->c1 = inv32( cbckey->c1 );
cbcInvKey->c2 = inv32( cbckey->c2 );
cbcInvKey->d1 = inv32( cbckey->d1 );
cbcInvKey->d2 = inv32( cbckey->d2 );
cbcInvKey->e1 = inv32( cbckey->e1 );
cbcInvKey->e2 = inv32( cbckey->e2 );
cbcInvKey->f1 = inv32( cbckey->f1 );
cbcInvKey->f2 = inv32( cbckey->f2 );
}
// pairwise independent function and summing step
#define MP_C_STEP(Data,L1, L2, L3, L4, L5, L6) \
t += *Data++; \
t *= L1; \
t = WORDSWAP(t); \
t *= L2; \
t = WORDSWAP(t); \
t *= L3; \
t = WORDSWAP(t); \
t *= L4; \
t = WORDSWAP(t); \
t *= L5; \
t += L6; \
sum += t;
void CBC64Update( CBCKey *key, CBCState *cbcstate,DWORD dwLen, BYTE *pData )
{
DWORD i, copylen=0, tmp;
DWORD *p;
UINT32 sum,t;
sum = cbcstate->sum; t = cbcstate->t;
if ( cbcstate->dwBufLen > 0 ) {
copylen = min( dwLen, 8 - cbcstate->dwBufLen );
for ( i=0; i<copylen; i++ )
cbcstate->buf[ cbcstate->dwBufLen + i ] = pData[i];
cbcstate->dwBufLen += copylen;
if ( cbcstate->dwBufLen == 8 ) {
p = (DWORD *)cbcstate->buf;
MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1 );
MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2 );
cbcstate->dwBufLen = 0;
}
}
tmp = (dwLen - copylen) / 8;
p = (DWORD *)(pData + copylen);
#ifndef WIN32
#define ARMBUG
#endif
#ifndef ARMBUG
while (tmp > 0) {
MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1);
MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2);
tmp--;
}
#else
DWORD AllignedDWORD( DWORD * );
DWORD *q;
while (tmp > 0) {
q = (DWORD *)cbcstate->buf;
*q = AllignedDWORD( p++ );
MP_C_STEP( q, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1);
*q = AllignedDWORD( p++ );
MP_C_STEP( q, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2);
tmp--;
}
#endif
tmp = copylen + ((dwLen-copylen) / 8) * 8;
if ( tmp < dwLen ) {
for ( i=tmp; i<dwLen; i++ )
cbcstate->buf[ i - tmp ] = pData[i];
cbcstate->dwBufLen = dwLen - tmp;
}
cbcstate->sum = sum; cbcstate->t = t;
}
UINT32 CBC64Finalize( CBCKey *key, CBCState *cbcstate, UINT32 *pKey2 ) {
DWORD i, *p;
UINT32 sum,t;
if ( cbcstate->dwBufLen > 0 ) {
for ( i=cbcstate->dwBufLen; i<8; i++ )
cbcstate->buf[ i ] = 0;
sum = cbcstate->sum; t = cbcstate->t;
p = (DWORD *)cbcstate->buf;
MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1 );
MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2 );
cbcstate->dwBufLen = 0;
cbcstate->sum = sum; cbcstate->t = t;
}
*pKey2 = cbcstate->t;
return cbcstate->sum;
}
UINT32 CBC64Invert( CBCKey *key, CBCKey *ikey, UINT32 MacA1, UINT32 MacA2,
UINT32 MacB1, UINT32 MacB2, UINT32 *pInvKey2 )
{
UINT32 tmp;
UINT32 yn, yn1, xn, xn1;
MacA1 += MacB2;
yn = MacB2;
yn1 = MacB1 - MacA1;
// last word
tmp = yn - key->f2;
INV_STEP_C(ikey->a2, ikey->b2, ikey->c2, ikey->d2, ikey->e2);
xn = tmp - yn1;
// next-to-last word
tmp = yn1 - key->f1;
INV_STEP_C(ikey->a1, ikey->b1, ikey->c1, ikey->d1, ikey->e1);
xn1 = tmp - MacA2;
*pInvKey2 = (UINT32) xn1;
return (UINT32) xn;
}