Source code of Windows XP (NT5)
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.

394 lines
9.3 KiB

  1. // ------------------------------------------------------------------------
  2. // Crypt16.c
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. //
  5. // ------------------------------------------------------------------------
  6. #include "crypt16.h"
  7. static int check_parity();
  8. int des_check_key=0;
  9. void des_set_odd_parity(key)
  10. des_cblock *key;
  11. {
  12. int i;
  13. for (i=0; i<DES_KEY_SZ; i++)
  14. (*key)[i]=odd_parity[(*key)[i]];
  15. }
  16. static int check_parity(key)
  17. des_cblock *key;
  18. {
  19. int i;
  20. for (i=0; i<DES_KEY_SZ; i++)
  21. {
  22. if ((*key)[i] != odd_parity[(*key)[i]])
  23. return(0);
  24. }
  25. return(1);
  26. }
  27. /* Weak and semi week keys as take from
  28. * %A D.W. Davies
  29. * %A W.L. Price
  30. * %T Security for Computer Networks
  31. * %I John Wiley & Sons
  32. * %D 1984
  33. * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference
  34. * (and actual cblock values).
  35. */
  36. #define NUM_WEAK_KEY 16
  37. static des_cblock weak_keys[NUM_WEAK_KEY]={
  38. /* weak keys */
  39. 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
  40. 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
  41. 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
  42. 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
  43. /* semi-weak keys */
  44. 0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,
  45. 0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,
  46. 0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1,
  47. 0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E,
  48. 0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,
  49. 0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01,
  50. 0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE,
  51. 0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,
  52. 0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,
  53. 0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01,
  54. 0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE,
  55. 0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1};
  56. int des_is_weak_key(key)
  57. des_cblock *key;
  58. {
  59. ulong *lp;
  60. register ulong l,r;
  61. int i;
  62. c2l(key,l);
  63. c2l(key,r);
  64. /* the weak_keys bytes should be aligned */
  65. lp=(ulong *)weak_keys;
  66. for (i=0; i<NUM_WEAK_KEY; i++)
  67. {
  68. if ((l == lp[0]) && (r == lp[1]))
  69. return(1);
  70. lp+=2;
  71. }
  72. return(0);
  73. }
  74. /* See ecb_encrypt.c for a pseudo description of these macros. */
  75. #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
  76. (b)^=(t),\
  77. (a)^=((t)<<(n)))
  78. #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
  79. (a)=(a)^(t)^(t>>(16-(n))))\
  80. static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};
  81. /* return 0 if key parity is odd (correct),
  82. * return -1 if key parity error,
  83. * return -2 if illegal weak key.
  84. */
  85. int des_set_key(key,schedule)
  86. des_cblock *key;
  87. des_key_schedule schedule;
  88. {
  89. register ulong c,d,t,s;
  90. register uchar *in;
  91. register ulong *k;
  92. register int i;
  93. if (des_check_key)
  94. {
  95. if (!check_parity(key))
  96. return(-1);
  97. if (des_is_weak_key(key))
  98. return(-2);
  99. }
  100. k=(ulong *)schedule;
  101. in=(uchar *)key;
  102. c2l(in,c);
  103. c2l(in,d);
  104. /* do PC1 in 60 simple operations */
  105. PERM_OP(d,c,t,4,0x0f0f0f0f);
  106. HPERM_OP(c,t,-2, 0xcccc0000);
  107. HPERM_OP(c,t,-1, 0xaaaa0000);
  108. HPERM_OP(c,t, 8, 0x00ff0000);
  109. HPERM_OP(c,t,-1, 0xaaaa0000);
  110. HPERM_OP(d,t,-8, 0xff000000);
  111. HPERM_OP(d,t, 8, 0x00ff0000);
  112. HPERM_OP(d,t, 2, 0x33330000);
  113. d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55);
  114. d=(d>>8)|((c&0xf0000000)>>4);
  115. c&=0x0fffffff;
  116. for (i=0; i<ITERATIONS; i++)
  117. {
  118. if (shifts2[i])
  119. { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); }
  120. else
  121. { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); }
  122. c&=0x0fffffff;
  123. d&=0x0fffffff;
  124. /* could be a few less shifts but I am to lazy at this
  125. * point in time to investigate */
  126. s= des_skb[0][ (c )&0x3f ]|
  127. des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]|
  128. des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]|
  129. des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) |
  130. ((c>>22)&0x38)];
  131. t= des_skb[4][ (d )&0x3f ]|
  132. des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]|
  133. des_skb[6][ (d>>15)&0x3f ]|
  134. des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)];
  135. /* table contained 0213 4657 */
  136. *(k++)=((t<<16)|(s&0x0000ffff));
  137. s= ((s>>16)|(t&0xffff0000));
  138. s=(s<<4)|(s>>28);
  139. *(k++)=s;
  140. }
  141. return(0);
  142. }
  143. int des_key_sched(key,schedule)
  144. des_cblock *key;
  145. des_key_schedule schedule;
  146. {
  147. return(des_set_key(key,schedule));
  148. }
  149. /* The changes to this macro may help or hinder, depending on the
  150. * compiler and the achitecture. gcc2 always seems to do well :-).
  151. * Inspired by Dana How <how@isl.stanford.edu> */
  152. #ifdef ALT_ECB
  153. #define D_ENCRYPT(L,R,S) \
  154. u=((R^s[S ])<<2); \
  155. t= R^s[S+1]; \
  156. t=((t>>2)+(t<<30)); \
  157. L^= \
  158. *(ulong *)(des_SP+0x0100+((t )&0xfc))+ \
  159. *(ulong *)(des_SP+0x0300+((t>> 8)&0xfc))+ \
  160. *(ulong *)(des_SP+0x0500+((t>>16)&0xfc))+ \
  161. *(ulong *)(des_SP+0x0700+((t>>24)&0xfc))+ \
  162. *(ulong *)(des_SP+ ((u )&0xfc))+ \
  163. *(ulong *)(des_SP+0x0200+((u>> 8)&0xfc))+ \
  164. *(ulong *)(des_SP+0x0400+((u>>16)&0xfc))+ \
  165. *(ulong *)(des_SP+0x0600+((u>>24)&0xfc));
  166. #else /* original version */
  167. #define D_ENCRYPT(L,R,S) \
  168. u=(R^s[S ]); \
  169. t=R^s[S+1]; \
  170. t=((t>>4)+(t<<28)); \
  171. L^= des_SPtrans[1][(t )&0x3f]| \
  172. des_SPtrans[3][(t>> 8)&0x3f]| \
  173. des_SPtrans[5][(t>>16)&0x3f]| \
  174. des_SPtrans[7][(t>>24)&0x3f]| \
  175. des_SPtrans[0][(u )&0x3f]| \
  176. des_SPtrans[2][(u>> 8)&0x3f]| \
  177. des_SPtrans[4][(u>>16)&0x3f]| \
  178. des_SPtrans[6][(u>>24)&0x3f];
  179. #endif
  180. /* IP and FP
  181. * The problem is more of a geometric problem that random bit fiddling.
  182. 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6
  183. 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4
  184. 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2
  185. 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0
  186. 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7
  187. 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5
  188. 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3
  189. 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1
  190. The output has been subject to swaps of the form
  191. 0 1 -> 3 1 but the odd and even bits have been put into
  192. 2 3 2 0
  193. different words. The main trick is to remember that
  194. t=((l>>size)^r)&(mask);
  195. r^=t;
  196. l^=(t<<size);
  197. can be used to swap and move bits between words.
  198. So l = 0 1 2 3 r = 16 17 18 19
  199. 4 5 6 7 20 21 22 23
  200. 8 9 10 11 24 25 26 27
  201. 12 13 14 15 28 29 30 31
  202. becomes (for size == 2 and mask == 0x3333)
  203. t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19
  204. 6^20 7^21 -- -- 4 5 20 21 6 7 22 23
  205. 10^24 11^25 -- -- 8 9 24 25 10 11 24 25
  206. 14^28 15^29 -- -- 12 13 28 29 14 15 28 29
  207. Thanks for hints from Richard Outerbridge - he told me IP&FP
  208. could be done in 15 xor, 10 shifts and 5 ands.
  209. When I finally started to think of the problem in 2D
  210. I first got ~42 operations without xors. When I remembered
  211. how to use xors :-) I got it to its final state.
  212. */
  213. #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
  214. (b)^=(t),\
  215. (a)^=((t)<<(n)))
  216. int des_encrypt(input,output,ks,encrypt)
  217. ulong *input;
  218. ulong *output;
  219. des_key_schedule ks;
  220. int encrypt;
  221. {
  222. register ulong l,r,t,u;
  223. #ifdef ALT_ECB
  224. register uchar *des_SP=(uchar *)des_SPtrans;
  225. #endif
  226. register int i;
  227. register ulong *s;
  228. l=input[0];
  229. r=input[1];
  230. /* do IP */
  231. PERM_OP(r,l,t, 4,0x0f0f0f0f);
  232. PERM_OP(l,r,t,16,0x0000ffff);
  233. PERM_OP(r,l,t, 2,0x33333333);
  234. PERM_OP(l,r,t, 8,0x00ff00ff);
  235. PERM_OP(r,l,t, 1,0x55555555);
  236. /* r and l are reversed - remember that :-) - fix
  237. * it in the next step */
  238. /* Things have been modified so that the initial rotate is
  239. * done outside the loop. This required the
  240. * des_SPtrans values in sp.h to be rotated 1 bit to the right.
  241. * One perl script later and things have a 5% speed up on a sparc2.
  242. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
  243. * for pointing this out. */
  244. t=(r<<1)|(r>>31);
  245. r=(l<<1)|(l>>31);
  246. l=t;
  247. s=(ulong *)ks;
  248. /* I don't know if it is worth the effort of loop unrolling the
  249. * inner loop */
  250. if (encrypt)
  251. {
  252. for (i=0; i<32; i+=4)
  253. {
  254. D_ENCRYPT(l,r,i+0); /* 1 */
  255. D_ENCRYPT(r,l,i+2); /* 2 */
  256. }
  257. }
  258. else
  259. {
  260. for (i=30; i>0; i-=4)
  261. {
  262. D_ENCRYPT(l,r,i-0); /* 16 */
  263. D_ENCRYPT(r,l,i-2); /* 15 */
  264. }
  265. }
  266. l=(l>>1)|(l<<31);
  267. r=(r>>1)|(r<<31);
  268. /* swap l and r
  269. * we will not do the swap so just remember they are
  270. * reversed for the rest of the subroutine
  271. * luckily FP fixes this problem :-) */
  272. PERM_OP(r,l,t, 1,0x55555555);
  273. PERM_OP(l,r,t, 8,0x00ff00ff);
  274. PERM_OP(r,l,t, 2,0x33333333);
  275. PERM_OP(l,r,t,16,0x0000ffff);
  276. PERM_OP(r,l,t, 4,0x0f0f0f0f);
  277. output[0]=l;
  278. output[1]=r;
  279. return(0);
  280. }
  281. int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt)
  282. des_cblock *input;
  283. des_cblock *output;
  284. long length;
  285. des_key_schedule schedule;
  286. des_cblock *ivec;
  287. int encrypt;
  288. {
  289. register ulong tin0,tin1;
  290. register ulong tout0,tout1,xor0,xor1;
  291. register uchar *in,*out;
  292. register long l=length;
  293. ulong tout[2],tin[2];
  294. uchar *iv;
  295. in=(uchar *)input;
  296. out=(uchar *)output;
  297. iv=(uchar *)ivec;
  298. if (encrypt)
  299. {
  300. c2l(iv,tout0);
  301. c2l(iv,tout1);
  302. for (; l>0; l-=8)
  303. {
  304. if (l >= 8)
  305. {
  306. c2l(in,tin0);
  307. c2l(in,tin1);
  308. }
  309. else
  310. c2ln(in,tin0,tin1,l);
  311. tin0^=tout0;
  312. tin1^=tout1;
  313. tin[0]=tin0;
  314. tin[1]=tin1;
  315. des_encrypt((ulong *)tin,(ulong *)tout,
  316. schedule,encrypt);
  317. tout0=tout[0];
  318. tout1=tout[1];
  319. l2c(tout0,out);
  320. l2c(tout1,out);
  321. }
  322. }
  323. else
  324. {
  325. c2l(iv,xor0);
  326. c2l(iv,xor1);
  327. for (; l>0; l-=8)
  328. {
  329. c2l(in,tin0);
  330. c2l(in,tin1);
  331. tin[0]=tin0;
  332. tin[1]=tin1;
  333. des_encrypt((ulong *)tin,(ulong *)tout,
  334. schedule,encrypt);
  335. tout0=tout[0]^xor0;
  336. tout1=tout[1]^xor1;
  337. if (l >= 8)
  338. {
  339. l2c(tout0,out);
  340. l2c(tout1,out);
  341. }
  342. else
  343. l2cn(tout0,tout1,out,l);
  344. xor0=tin0;
  345. xor1=tin1;
  346. }
  347. }
  348. tin0=tin1=tout0=tout1=xor0=xor1=0;
  349. return(0);
  350. }