PageRenderTime 37ms CodeModel.GetById 25ms app.highlight 7ms RepoModel.GetById 0ms app.codeStats 1ms

/packages/hash/src/ntlm.pas

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