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

  1. #include "crptkPCH.h"
  2. //-----------------------------------------------------------------------------
  3. //
  4. // File: CBC64WS4.cpp
  5. //
  6. // Microsoft Digital Rights Management
  7. // Copyright (C) 1998-1999 Microsoft Corporation, All Rights Reserved
  8. //
  9. // Description:
  10. //
  11. //-----------------------------------------------------------------------------
  12. /*
  13. chain-sum MAC scheme 4.5: multiply-&-swap rounds plus sum (reversible -- reversal code included)
  14. 6/15/98 mj
  15. 8/22/98 mj
  16. 8/31/98 mj
  17. 9/21/98 mj
  18. 2/4/99 mj
  19. */
  20. #include "cbckey.h"
  21. #ifndef SHCLASS
  22. #define SHCLASS
  23. #endif
  24. //
  25. // C version
  26. //
  27. #define WORDSWAP(d) \
  28. ((d >> 16) + (d << 16))
  29. // pairwise independent function and summing step
  30. #define C_STEP(L1, L2, L3, L4, L5, L6) \
  31. t += *Data++; \
  32. t *= L1; \
  33. t = WORDSWAP(t); \
  34. t *= L2; \
  35. t = WORDSWAP(t); \
  36. t *= L3; \
  37. t = WORDSWAP(t); \
  38. t *= L4; \
  39. t = WORDSWAP(t); \
  40. t *= L5; \
  41. t += L6; \
  42. sum += t;
  43. // MAC function
  44. // returns half of 64-bit MAC, and places other half in *pKey2
  45. UINT32 CBC64WS4_asm(
  46. UINT32 *Data,
  47. unsigned NumDWORDBlocks,
  48. UINT32 *pKey2,
  49. CBCKey key)
  50. {
  51. UINT32 sum = 0, t = 0;
  52. while (NumDWORDBlocks > 0) {
  53. C_STEP(key.a1, key.b1, key.c1, key.d1, key.e1, key.f1);
  54. C_STEP(key.a2, key.b2, key.c2, key.d2, key.e2, key.f2);
  55. NumDWORDBlocks -= 2;
  56. }
  57. *pKey2 = t;
  58. return sum;
  59. }
  60. //
  61. // inverse MAC
  62. //
  63. // compute gcd(a, b) = x*a + y*b
  64. static void egcd(UINT64 a, UINT64 b, __int64 &gcd, __int64 &x, __int64 &y)
  65. {
  66. if (b == 0) {
  67. gcd = a; x = 1; y = 1;
  68. }
  69. else {
  70. egcd(b, a % b, gcd, x, y);
  71. __int64 t = y;
  72. y = x - y*(a/b);
  73. x = t;
  74. }
  75. }
  76. // invert n mod 2^32
  77. UINT32 inv32(UINT32 n)
  78. {
  79. __int64 gcd, in, x;
  80. __int64 modulus = (__int64)1<<32;
  81. egcd(modulus, n, gcd, x, in);
  82. while (in < 0)
  83. in += modulus;
  84. return (UINT32) in;
  85. }
  86. // step to reverse action of multiply-&-swap rounds
  87. #define INV_STEP_C(iL1, iL2, iL3, iL4, iL5) \
  88. tmp *= iL5; \
  89. tmp = WORDSWAP(tmp); \
  90. tmp *= iL4; \
  91. tmp = WORDSWAP(tmp); \
  92. tmp *= iL3; \
  93. tmp = WORDSWAP(tmp); \
  94. tmp *= iL2; \
  95. tmp = WORDSWAP(tmp); \
  96. tmp *= iL1;
  97. // inverse MAC function
  98. // decrypts last two blocks of Data
  99. // (replaces 64-bit ciphertext Data[NumDWORDBlocks - 1] and Data[NumDWORDBlocks - 2] with
  100. // plaintext, and returns the plaintext in the return value and *pKey2 -- change as required)
  101. UINT32 InvCBC64WS4_asm(
  102. UINT32 *Data,
  103. unsigned NumDWORDBlocks,
  104. UINT32 *pKey2,
  105. CBCKey key,
  106. CBCKey ikey )
  107. {
  108. UINT32 yn, yn1, yn2, xn, xn1;
  109. UINT32 sum32, tmp;
  110. // Invert last two blocks (sum and 32-bit MAC). This requires the encrypted last two
  111. // blocks and the (NumDWORDBlocks-2) plaintext blocks.
  112. sum32 = CBC64WS4_asm(Data, NumDWORDBlocks - 2, &yn2, key) + Data[NumDWORDBlocks - 1];
  113. yn = Data[NumDWORDBlocks - 1];
  114. yn1 = Data[NumDWORDBlocks - 2] - sum32;
  115. // last word
  116. tmp = yn - key.f2;
  117. INV_STEP_C(ikey.a2, ikey.b2, ikey.c2, ikey.d2, ikey.e2);
  118. xn = tmp - yn1;
  119. // next-to-last word
  120. tmp = yn1 - key.f1;
  121. INV_STEP_C(ikey.a1, ikey.b1, ikey.c1, ikey.d1, ikey.e1);
  122. xn1 = tmp - yn2;
  123. Data[NumDWORDBlocks - 2] = *pKey2 = (UINT32) xn1;
  124. Data[NumDWORDBlocks - 1] = (UINT32) xn;
  125. return (UINT32) xn;
  126. }
  127. void CBC64InitState( CBCState *cbcstate ) {
  128. cbcstate->sum = 0; cbcstate->t = 0; cbcstate->dwBufLen = 0;
  129. }
  130. void CBC64Init( CBCKey *cbckey, CBCState *cbcstate, BYTE *pKey ) {
  131. UINT32 *p;
  132. cbcstate->sum = 0; cbcstate->t = 0; cbcstate->dwBufLen = 0;
  133. p = (UINT32 *)pKey;
  134. cbckey->a1 = *p++ | 0x00000001;
  135. cbckey->b1 = *p++ | 0x00000001;
  136. cbckey->c1 = *p++ | 0x00000001;
  137. cbckey->d1 = *p++ | 0x00000001;
  138. cbckey->e1 = *p++ | 0x00000001;
  139. cbckey->f1 = *p++ | 0x00000001;
  140. cbckey->a2 = *p++ | 0x00000001;
  141. cbckey->b2 = *p++ | 0x00000001;
  142. cbckey->c2 = *p++ | 0x00000001;
  143. cbckey->d2 = *p++ | 0x00000001;
  144. cbckey->e2 = *p++ | 0x00000001;
  145. cbckey->f2 = *p++ | 0x00000001;
  146. }
  147. void CBC64InvKey( CBCKey *cbckey, CBCKey *cbcInvKey ) {
  148. cbcInvKey->a1 = inv32( cbckey->a1 );
  149. cbcInvKey->a2 = inv32( cbckey->a2 );
  150. cbcInvKey->b1 = inv32( cbckey->b1 );
  151. cbcInvKey->b2 = inv32( cbckey->b2 );
  152. cbcInvKey->c1 = inv32( cbckey->c1 );
  153. cbcInvKey->c2 = inv32( cbckey->c2 );
  154. cbcInvKey->d1 = inv32( cbckey->d1 );
  155. cbcInvKey->d2 = inv32( cbckey->d2 );
  156. cbcInvKey->e1 = inv32( cbckey->e1 );
  157. cbcInvKey->e2 = inv32( cbckey->e2 );
  158. cbcInvKey->f1 = inv32( cbckey->f1 );
  159. cbcInvKey->f2 = inv32( cbckey->f2 );
  160. }
  161. // pairwise independent function and summing step
  162. #define MP_C_STEP(Data,L1, L2, L3, L4, L5, L6) \
  163. t += *Data++; \
  164. t *= L1; \
  165. t = WORDSWAP(t); \
  166. t *= L2; \
  167. t = WORDSWAP(t); \
  168. t *= L3; \
  169. t = WORDSWAP(t); \
  170. t *= L4; \
  171. t = WORDSWAP(t); \
  172. t *= L5; \
  173. t += L6; \
  174. sum += t;
  175. void CBC64Update( CBCKey *key, CBCState *cbcstate,DWORD dwLen, BYTE *pData )
  176. {
  177. DWORD i, copylen=0, tmp;
  178. DWORD *p;
  179. UINT32 sum,t;
  180. sum = cbcstate->sum; t = cbcstate->t;
  181. if ( cbcstate->dwBufLen > 0 ) {
  182. copylen = min( dwLen, 8 - cbcstate->dwBufLen );
  183. for ( i=0; i<copylen; i++ )
  184. cbcstate->buf[ cbcstate->dwBufLen + i ] = pData[i];
  185. cbcstate->dwBufLen += copylen;
  186. if ( cbcstate->dwBufLen == 8 ) {
  187. p = (DWORD *)cbcstate->buf;
  188. MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1 );
  189. MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2 );
  190. cbcstate->dwBufLen = 0;
  191. }
  192. }
  193. tmp = (dwLen - copylen) / 8;
  194. p = (DWORD *)(pData + copylen);
  195. #ifndef WIN32
  196. #define ARMBUG
  197. #endif
  198. #ifndef ARMBUG
  199. while (tmp > 0) {
  200. MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1);
  201. MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2);
  202. tmp--;
  203. }
  204. #else
  205. DWORD AllignedDWORD( DWORD * );
  206. DWORD *q;
  207. while (tmp > 0) {
  208. q = (DWORD *)cbcstate->buf;
  209. *q = AllignedDWORD( p++ );
  210. MP_C_STEP( q, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1);
  211. *q = AllignedDWORD( p++ );
  212. MP_C_STEP( q, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2);
  213. tmp--;
  214. }
  215. #endif
  216. tmp = copylen + ((dwLen-copylen) / 8) * 8;
  217. if ( tmp < dwLen ) {
  218. for ( i=tmp; i<dwLen; i++ )
  219. cbcstate->buf[ i - tmp ] = pData[i];
  220. cbcstate->dwBufLen = dwLen - tmp;
  221. }
  222. cbcstate->sum = sum; cbcstate->t = t;
  223. }
  224. UINT32 CBC64Finalize( CBCKey *key, CBCState *cbcstate, UINT32 *pKey2 ) {
  225. DWORD i, *p;
  226. UINT32 sum,t;
  227. if ( cbcstate->dwBufLen > 0 ) {
  228. for ( i=cbcstate->dwBufLen; i<8; i++ )
  229. cbcstate->buf[ i ] = 0;
  230. sum = cbcstate->sum; t = cbcstate->t;
  231. p = (DWORD *)cbcstate->buf;
  232. MP_C_STEP( p, key->a1, key->b1, key->c1, key->d1, key->e1, key->f1 );
  233. MP_C_STEP( p, key->a2, key->b2, key->c2, key->d2, key->e2, key->f2 );
  234. cbcstate->dwBufLen = 0;
  235. cbcstate->sum = sum; cbcstate->t = t;
  236. }
  237. *pKey2 = cbcstate->t;
  238. return cbcstate->sum;
  239. }
  240. UINT32 CBC64Invert( CBCKey *key, CBCKey *ikey, UINT32 MacA1, UINT32 MacA2,
  241. UINT32 MacB1, UINT32 MacB2, UINT32 *pInvKey2 )
  242. {
  243. UINT32 tmp;
  244. UINT32 yn, yn1, xn, xn1;
  245. MacA1 += MacB2;
  246. yn = MacB2;
  247. yn1 = MacB1 - MacA1;
  248. // last word
  249. tmp = yn - key->f2;
  250. INV_STEP_C(ikey->a2, ikey->b2, ikey->c2, ikey->d2, ikey->e2);
  251. xn = tmp - yn1;
  252. // next-to-last word
  253. tmp = yn1 - key->f1;
  254. INV_STEP_C(ikey->a1, ikey->b1, ikey->c1, ikey->d1, ikey->e1);
  255. xn1 = tmp - MacA2;
  256. *pInvKey2 = (UINT32) xn1;
  257. return (UINT32) xn;
  258. }