/packages/hash/src/ntlm.pas
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.