ntlm.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. {
  2. This file is part of the Free Pascal packages.
  3. Copyright (c) 1999-2006 by the Free Pascal development team
  4. Implements a NTLM password hash algorithm.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit ntlm;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode objfpc}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. System.Math, System.Strings, System.Hash.Md5;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. Math, Strings, md5;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. function LMGenerate(const Password: PAnsiChar): TMDDigest;
  24. function NTGenerate(const Password: PAnsiChar): TMDDigest;
  25. implementation
  26. const
  27. perm1: array[0..55] of Byte = (
  28. 57, 49, 41, 33, 25, 17, 9,
  29. 1, 58, 50, 42, 34, 26, 18,
  30. 10, 2, 59, 51, 43, 35, 27,
  31. 19, 11, 3, 60, 52, 44, 36,
  32. 63, 55, 47, 39, 31, 23, 15,
  33. 7, 62, 54, 46, 38, 30, 22,
  34. 14, 6, 61, 53, 45, 37, 29,
  35. 21, 13, 5, 28, 20, 12, 4);
  36. perm2: array[0..47] of Byte = (
  37. 14, 17, 11, 24, 1, 5,
  38. 3, 28, 15, 6, 21, 10,
  39. 23, 19, 12, 4, 26, 8,
  40. 16, 7, 27, 20, 13, 2,
  41. 41, 52, 31, 37, 47, 55,
  42. 30, 40, 51, 45, 33, 48,
  43. 44, 49, 39, 56, 34, 53,
  44. 46, 42, 50, 36, 29, 32);
  45. perm3: array[0..63] of Byte = (
  46. 58, 50, 42, 34, 26, 18, 10, 2,
  47. 60, 52, 44, 36, 28, 20, 12, 4,
  48. 62, 54, 46, 38, 30, 22, 14, 6,
  49. 64, 56, 48, 40, 32, 24, 16, 8,
  50. 57, 49, 41, 33, 25, 17, 9, 1,
  51. 59, 51, 43, 35, 27, 19, 11, 3,
  52. 61, 53, 45, 37, 29, 21, 13, 5,
  53. 63, 55, 47, 39, 31, 23, 15, 7);
  54. perm4: array[0..47] of Byte = (
  55. 32, 1, 2, 3, 4, 5,
  56. 4, 5, 6, 7, 8, 9,
  57. 8, 9, 10, 11, 12, 13,
  58. 12, 13, 14, 15, 16, 17,
  59. 16, 17, 18, 19, 20, 21,
  60. 20, 21, 22, 23, 24, 25,
  61. 24, 25, 26, 27, 28, 29,
  62. 28, 29, 30, 31, 32, 1);
  63. perm5: array[0..31] of Byte = (
  64. 16, 7, 20, 21,
  65. 29, 12, 28, 17,
  66. 1, 15, 23, 26,
  67. 5, 18, 31, 10,
  68. 2, 8, 24, 14,
  69. 32, 27, 3, 9,
  70. 19, 13, 30, 6,
  71. 22, 11, 4, 25);
  72. perm6: array[0..63] of Byte = (
  73. 40, 8, 48, 16, 56, 24, 64, 32,
  74. 39, 7, 47, 15, 55, 23, 63, 31,
  75. 38, 6, 46, 14, 54, 22, 62, 30,
  76. 37, 5, 45, 13, 53, 21, 61, 29,
  77. 36, 4, 44, 12, 52, 20, 60, 28,
  78. 35, 3, 43, 11, 51, 19, 59, 27,
  79. 34, 2, 42, 10, 50, 18, 58, 26,
  80. 33, 1, 41, 9, 49, 17, 57, 25);
  81. sc: array[0..15] of Byte = (1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);
  82. sbox: array[0..7, 0..3, 0..15] of Byte = (
  83. ((14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7),
  84. (0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8),
  85. (4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0),
  86. (15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13)),
  87. ((15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10),
  88. (3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5),
  89. (0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15),
  90. (13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9)),
  91. ((10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8),
  92. (13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1),
  93. (13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7),
  94. (1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12)),
  95. ((7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15),
  96. (13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9),
  97. (10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4),
  98. (3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14)),
  99. ((2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9),
  100. (14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6),
  101. (4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14),
  102. (11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3)),
  103. ((12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11),
  104. (10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8),
  105. (9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6),
  106. (4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13)),
  107. ((4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1),
  108. (13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6),
  109. (1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2),
  110. (6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12)),
  111. ((13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7),
  112. (1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2),
  113. (7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8),
  114. (2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11)));
  115. procedure permute({out} const _out: PByte; {in} const _in: PByte; {in} const p: PByte; {in} const n: Integer);
  116. var
  117. i: Integer;
  118. begin
  119. for i := 0 to n-1 do
  120. _out[i] := _in[p[i]-1];
  121. end;
  122. procedure lshift({in/out} const d: PByte; {in} const count: Integer; {in} const n: Integer);
  123. var
  124. _out : array[0..63] of Byte;
  125. i : Integer;
  126. begin
  127. for i := 0 to n-1 do
  128. _out[i] := d[(i+count) mod n];
  129. for i := 0 to n-1 do
  130. d[i] := _out[i];
  131. end;
  132. procedure concat({out} const _out: PByte; {in} const _in1, _in2: PByte; {in} const l1, l2: Integer);
  133. var
  134. i: Integer;
  135. begin
  136. for i := 0 to l1-1 do
  137. _out[i] := _in1[i];
  138. for i := 0 to l2-1 do
  139. _out[i+l1] := _in2[i];
  140. end;
  141. procedure mxor({out} const _out: PByte; {in} const _in1, _in2: PByte; {in} const n: Integer);
  142. var
  143. i: Integer;
  144. begin
  145. for i := 0 to n-1 do
  146. _out[i] := _in1[i] xor _in2[i];
  147. end;
  148. procedure dohash({out} const _out: PByte; {in} const _in: PByte; {in} const key: PByte; {in} const forw: Boolean);
  149. var
  150. i : Integer;
  151. j : Integer;
  152. k : Integer;
  153. pk1 : array[0..55] of Byte;
  154. c : array[0..27] of Byte;
  155. d : array[0..27] of Byte;
  156. cd : array[0..55] of Byte;
  157. ki : array[0..15,0..47] of Byte;
  158. pd1 : array[0..63] of Byte;
  159. l : array[0..31] of Byte;
  160. r : array[0..31] of Byte;
  161. rl : array[0..63] of Byte;
  162. er : array[0..47] of Byte;
  163. erk : array[0..47] of Byte;
  164. b : array[0..7,0..5] of Byte;
  165. cb : array[0..31] of Byte;
  166. pcb : array[0..31] of Byte;
  167. r2 : array[0..31] of Byte;
  168. m : Integer;
  169. n : Integer;
  170. begin
  171. permute(@pk1[0], key, @perm1[0], 56);
  172. for i := 0 to 27 do
  173. begin
  174. c[i] := pk1[i];
  175. d[i] := pk1[i+28];
  176. end;
  177. for i := 0 to 15 do
  178. begin
  179. lshift(@c[0], sc[i], 28);
  180. lshift(@d[0], sc[i], 28);
  181. concat(@cd[0], @c[0], @d[0], 28, 28);
  182. permute(@ki[i][0], @cd[0], @perm2[0], 48);
  183. end;
  184. permute(@pd1[0], _in, @perm3[0], 64);
  185. for i := 0 to 31 do
  186. begin
  187. l[i] := pd1[i];
  188. r[i] := pd1[i+32];
  189. end;
  190. for i := 0 to 15 do
  191. begin
  192. permute(@er[0], @r[0], @perm4[0], 48);
  193. if forw then
  194. mxor(@erk[0], @er[0], @ki[i][0], 48) else
  195. mxor(@erk[0], @er[0], @ki[15-i][0], 48);
  196. for j := 0 to 7 do
  197. for k := 0 to 5 do
  198. b[j][k] := erk[j*6 + k];
  199. for j := 0 to 7 do
  200. begin
  201. m := (b[j][0] shl 1) or b[j][5];
  202. n := (b[j][1] shl 3) or (b[j][2] shl 2) or (b[j][3] shl 1) or (b[j][4]);
  203. for k := 0 to 3 do
  204. b[j][k] := min(sbox[j][m][n] and (1 shl (3-k)), 1); // store binary
  205. end;
  206. for j := 0 to 7 do
  207. for k := 0 to 3 do
  208. cb[j*4+k] := b[j][k];
  209. permute(@pcb[0], @cb[0], @perm5[0], 32);
  210. mxor(@r2[0], @l[0], @pcb[0], 32);
  211. for j := 0 to 31 do
  212. begin
  213. l[j] := r[j];
  214. r[j] := r2[j];
  215. end;
  216. end;
  217. concat(@rl[0], @r[0], @l[0], 32, 32);
  218. permute(_out, @rl[0], @perm6[0], 64);
  219. end;
  220. procedure str_to_key({in} const str: PByte; {out} const key: PByte);
  221. var
  222. i: Integer;
  223. begin
  224. key[0] := str[0] shr 1;
  225. key[1] := ((str[0] and $01) shl 6) or (str[1] shr 2);
  226. key[2] := ((str[1] and $03) shl 5) or (str[2] shr 3);
  227. key[3] := ((str[2] and $07) shl 4) or (str[3] shr 4);
  228. key[4] := ((str[3] and $0F) shl 3) or (str[4] shr 5);
  229. key[5] := ((str[4] and $1F) shl 2) or (str[5] shr 6);
  230. key[6] := ((str[5] and $3F) shl 1) or (str[6] shr 7);
  231. key[7] := str[6] and $7F;
  232. for i := 0 to 7 do
  233. key[i] := key[i] shl 1;
  234. end;
  235. procedure smbhash({out} const _out: PByte; {in} const _in: PByte; {in} const key: PByte; {in} const forw: Boolean);
  236. var
  237. i : Integer;
  238. outb : array[0..63] of Byte;
  239. inb : array[0..63] of Byte;
  240. keyb : array[0..63] of Byte;
  241. key2 : array[0..7] of Byte;
  242. begin
  243. str_to_key(key, @key2[0]);
  244. for i := 0 to 63 do
  245. begin
  246. inb[i] := min( _in[i div 8] and (1 shl (7-(i mod 8))), 1); // store binary
  247. keyb[i] := min(key2[i div 8] and (1 shl (7-(i mod 8))), 1); // store binary
  248. outb[i] := 0;
  249. end;
  250. dohash(@outb[0], @inb[0], @keyb[0], forw);
  251. for i := 0 to 7 do
  252. _out[I] := 0;
  253. for i := 0 to 63 do
  254. begin
  255. if outb[i] <> 0 then
  256. _out[i div 8] := _out[i div 8] or (1 shl (7-(i mod 8)));
  257. end;
  258. end;
  259. procedure E_P16({in} const p14: PByte; {out} const p16: PByte);
  260. const
  261. sp8: array[0..7] of Byte = ($4b, $47, $53, $21, $40, $23, $24, $25);
  262. begin
  263. smbhash(@p16[0], @sp8[0], @p14[0], True);
  264. smbhash(@p16[8], @sp8[0], @p14[7], True);
  265. end;
  266. (*procedure E_P24({in} const p21: PByte; {in} const c8: PByte; {out} const p24: PByte);
  267. begin
  268. smbhash(@p24[0], c8, @p21[0], True);
  269. smbhash(@p24[8], c8, @p21[7], True);
  270. smbhash(@p24[16], c8, @p21[14], True);
  271. end;*)
  272. function LMGenerate(const Password: PAnsiChar): TMDDigest;
  273. var
  274. dospwd: array[0..14] of Byte;
  275. begin
  276. if not Assigned(Password) then
  277. Exit;
  278. FillChar(dospwd, Sizeof(dospwd), 0);
  279. (* Password must be converted to DOS charset - null terminated, uppercase *)
  280. StrLCopy(PAnsiChar(@dospwd[0]), PAnsiChar(@Password[0]), SizeOf(dospwd)-1);
  281. StrUpper(PAnsiChar(@dospwd[0]));
  282. (* Only the first 14 chars are considered, password need not be null terminated *)
  283. E_P16(@dospwd[0], @Result);
  284. FillChar(dospwd, Sizeof(dospwd), 0);
  285. end;
  286. function NTGenerate(const Password: PAnsiChar): TMDDigest;
  287. var
  288. pos: Integer;
  289. wpwd: array[0..127] of WideChar;
  290. begin
  291. if not Assigned(Password) then
  292. Exit;
  293. pos := 0;
  294. while (pos < 128) and (Password[pos] <> #0) do
  295. begin
  296. wpwd[pos] := Password[pos];
  297. inc(pos);
  298. end;
  299. Result := MDBuffer(wpwd, 2*pos, MD_VERSION_4);
  300. FillChar(wpwd, Sizeof(wpwd), 0);
  301. end;
  302. end.