1 /* 2 * Copyright 2004 Hans Leidekker 3 * 4 * Based on LMHash.c from libcifs 5 * 6 * Copyright (C) 2004 by Christopher R. Hertel 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #ifdef __REACTOS__ 24 #include <advapi32.h> 25 #else 26 #include <stdarg.h> 27 28 #include "ntstatus.h" 29 #define WIN32_NO_STATUS 30 #include "windef.h" 31 #include "winternl.h" 32 33 #include "crypt.h" 34 #endif 35 36 static const unsigned char CRYPT_LMhash_Magic[8] = 37 { 'K', 'G', 'S', '!', '@', '#', '$', '%' }; 38 39 static void CRYPT_LMhash( unsigned char *dst, const unsigned char *pwd, const int len ) 40 { 41 int i, max = 14; 42 unsigned char tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; 43 44 max = len > max ? max : len; 45 46 for (i = 0; i < max; i++) 47 tmp_pwd[i] = pwd[i]; 48 49 CRYPT_DEShash( dst, tmp_pwd, CRYPT_LMhash_Magic ); 50 CRYPT_DEShash( &dst[8], &tmp_pwd[7], CRYPT_LMhash_Magic ); 51 } 52 53 NTSTATUS WINAPI SystemFunction006( LPCSTR password, LPSTR hash ) 54 { 55 CRYPT_LMhash( (unsigned char*)hash, (const unsigned char*)password, strlen(password) ); 56 57 return STATUS_SUCCESS; 58 } 59 60 #ifndef __REACTOS__ 61 /****************************************************************************** 62 * SystemFunction008 [ADVAPI32.@] 63 * 64 * Creates a LM response from a challenge and a password hash 65 * 66 * PARAMS 67 * challenge [I] Challenge from authentication server 68 * hash [I] NTLM hash (from SystemFunction006) 69 * response [O] response to send back to the server 70 * 71 * RETURNS 72 * Success: STATUS_SUCCESS 73 * Failure: STATUS_UNSUCCESSFUL 74 * 75 * NOTES 76 * see http://davenport.sourceforge.net/ntlm.html#theLmResponse 77 * 78 */ 79 NTSTATUS WINAPI SystemFunction008(const BYTE *challenge, const BYTE *hash, LPBYTE response) 80 { 81 BYTE key[7*3]; 82 83 if (!challenge || !response) 84 return STATUS_UNSUCCESSFUL; 85 86 memset(key, 0, sizeof key); 87 memcpy(key, hash, 0x10); 88 89 CRYPT_DEShash(response, key, challenge); 90 CRYPT_DEShash(response+8, key+7, challenge); 91 CRYPT_DEShash(response+16, key+14, challenge); 92 93 return STATUS_SUCCESS; 94 } 95 96 /****************************************************************************** 97 * SystemFunction009 [ADVAPI32.@] 98 * 99 * Seems to do the same as SystemFunction008 ... 100 */ 101 NTSTATUS WINAPI SystemFunction009(const BYTE *challenge, const BYTE *hash, LPBYTE response) 102 { 103 return SystemFunction008(challenge, hash, response); 104 } 105 106 /****************************************************************************** 107 * SystemFunction001 [ADVAPI32.@] 108 * 109 * Encrypts a single block of data using DES 110 * 111 * PARAMS 112 * data [I] data to encrypt (8 bytes) 113 * key [I] key data (7 bytes) 114 * output [O] the encrypted data (8 bytes) 115 * 116 * RETURNS 117 * Success: STATUS_SUCCESS 118 * Failure: STATUS_UNSUCCESSFUL 119 * 120 */ 121 NTSTATUS WINAPI SystemFunction001(const BYTE *data, const BYTE *key, LPBYTE output) 122 { 123 if (!data || !output) 124 return STATUS_UNSUCCESSFUL; 125 CRYPT_DEShash(output, key, data); 126 return STATUS_SUCCESS; 127 } 128 129 /****************************************************************************** 130 * SystemFunction002 [ADVAPI32.@] 131 * 132 * Decrypts a single block of data using DES 133 * 134 * PARAMS 135 * data [I] data to decrypt (8 bytes) 136 * key [I] key data (7 bytes) 137 * output [O] the decrypted data (8 bytes) 138 * 139 * RETURNS 140 * Success: STATUS_SUCCESS 141 * Failure: STATUS_UNSUCCESSFUL 142 * 143 */ 144 NTSTATUS WINAPI SystemFunction002(const BYTE *data, const BYTE *key, LPBYTE output) 145 { 146 if (!data || !output) 147 return STATUS_UNSUCCESSFUL; 148 CRYPT_DESunhash(output, key, data); 149 return STATUS_SUCCESS; 150 } 151 152 /****************************************************************************** 153 * SystemFunction003 [ADVAPI32.@] 154 * 155 * Hashes a key using DES and a fixed datablock 156 * 157 * PARAMS 158 * key [I] key data (7 bytes) 159 * output [O] hashed key (8 bytes) 160 * 161 * RETURNS 162 * Success: STATUS_SUCCESS 163 * Failure: STATUS_UNSUCCESSFUL 164 * 165 */ 166 NTSTATUS WINAPI SystemFunction003(const BYTE *key, LPBYTE output) 167 { 168 if (!output) 169 return STATUS_UNSUCCESSFUL; 170 CRYPT_DEShash(output, key, CRYPT_LMhash_Magic); 171 return STATUS_SUCCESS; 172 } 173 174 /****************************************************************************** 175 * SystemFunction004 [ADVAPI32.@] 176 * 177 * Encrypts a block of data with DES in ECB mode, preserving the length 178 * 179 * PARAMS 180 * data [I] data to encrypt 181 * key [I] key data (up to 7 bytes) 182 * output [O] buffer to receive encrypted data 183 * 184 * RETURNS 185 * Success: STATUS_SUCCESS 186 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small 187 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length 188 * 189 * NOTES 190 * Encrypt buffer size should be input size rounded up to 8 bytes 191 * plus an extra 8 bytes. 192 */ 193 NTSTATUS WINAPI SystemFunction004(const struct ustring *in, 194 const struct ustring *key, 195 struct ustring *out) 196 { 197 union { 198 unsigned char uc[8]; 199 unsigned int ui[2]; 200 } data; 201 unsigned char deskey[7]; 202 unsigned int crypt_len, ofs; 203 204 if (key->Length<=0) 205 return STATUS_INVALID_PARAMETER_2; 206 207 crypt_len = ((in->Length+7)&~7); 208 if (out->MaximumLength < (crypt_len+8)) 209 return STATUS_BUFFER_TOO_SMALL; 210 211 data.ui[0] = in->Length; 212 data.ui[1] = 1; 213 214 if (key->Length<sizeof deskey) 215 { 216 memset(deskey, 0, sizeof deskey); 217 memcpy(deskey, key->Buffer, key->Length); 218 } 219 else 220 memcpy(deskey, key->Buffer, sizeof deskey); 221 222 CRYPT_DEShash(out->Buffer, deskey, data.uc); 223 224 for(ofs=0; ofs<(crypt_len-8); ofs+=8) 225 CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs); 226 227 memset(data.uc, 0, sizeof data.uc); 228 memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len); 229 CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc); 230 231 out->Length = crypt_len+8; 232 233 return STATUS_SUCCESS; 234 } 235 236 /****************************************************************************** 237 * SystemFunction005 [ADVAPI32.@] 238 * 239 * Decrypts a block of data with DES in ECB mode 240 * 241 * PARAMS 242 * data [I] data to decrypt 243 * key [I] key data (up to 7 bytes) 244 * output [O] buffer to receive decrypted data 245 * 246 * RETURNS 247 * Success: STATUS_SUCCESS 248 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small 249 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length 250 * 251 */ 252 NTSTATUS WINAPI SystemFunction005(const struct ustring *in, 253 const struct ustring *key, 254 struct ustring *out) 255 { 256 union { 257 unsigned char uc[8]; 258 unsigned int ui[2]; 259 } data; 260 unsigned char deskey[7]; 261 unsigned int ofs, crypt_len; 262 263 if (key->Length<=0) 264 return STATUS_INVALID_PARAMETER_2; 265 266 if (key->Length<sizeof deskey) 267 { 268 memset(deskey, 0, sizeof deskey); 269 memcpy(deskey, key->Buffer, key->Length); 270 } 271 else 272 memcpy(deskey, key->Buffer, sizeof deskey); 273 274 CRYPT_DESunhash(data.uc, deskey, in->Buffer); 275 276 if (data.ui[1] != 1) 277 return STATUS_UNKNOWN_REVISION; 278 279 crypt_len = data.ui[0]; 280 if (crypt_len > out->MaximumLength) 281 return STATUS_BUFFER_TOO_SMALL; 282 283 for (ofs=0; (ofs+8)<crypt_len; ofs+=8) 284 CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8); 285 286 if (ofs<crypt_len) 287 { 288 CRYPT_DESunhash(data.uc, deskey, in->Buffer+ofs+8); 289 memcpy(out->Buffer+ofs, data.uc, crypt_len-ofs); 290 } 291 292 out->Length = crypt_len; 293 294 return STATUS_SUCCESS; 295 } 296 297 /****************************************************************************** 298 * SystemFunction012 [ADVAPI32.@] 299 * SystemFunction014 [ADVAPI32.@] 300 * SystemFunction016 [ADVAPI32.@] 301 * SystemFunction018 [ADVAPI32.@] 302 * SystemFunction020 [ADVAPI32.@] 303 * SystemFunction022 [ADVAPI32.@] 304 * 305 * Encrypts two DES blocks with two keys 306 * 307 * PARAMS 308 * data [I] data to encrypt (16 bytes) 309 * key [I] key data (two lots of 7 bytes) 310 * output [O] buffer to receive encrypted data (16 bytes) 311 * 312 * RETURNS 313 * Success: STATUS_SUCCESS 314 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL 315 */ 316 NTSTATUS WINAPI SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out) 317 { 318 if (!in || !out) 319 return STATUS_UNSUCCESSFUL; 320 321 CRYPT_DEShash(out, key, in); 322 CRYPT_DEShash(out+8, key+7, in+8); 323 return STATUS_SUCCESS; 324 } 325 326 /****************************************************************************** 327 * SystemFunction013 [ADVAPI32.@] 328 * SystemFunction015 [ADVAPI32.@] 329 * SystemFunction017 [ADVAPI32.@] 330 * SystemFunction019 [ADVAPI32.@] 331 * SystemFunction021 [ADVAPI32.@] 332 * SystemFunction023 [ADVAPI32.@] 333 * 334 * Decrypts two DES blocks with two keys 335 * 336 * PARAMS 337 * data [I] data to decrypt (16 bytes) 338 * key [I] key data (two lots of 7 bytes) 339 * output [O] buffer to receive decrypted data (16 bytes) 340 * 341 * RETURNS 342 * Success: STATUS_SUCCESS 343 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL 344 */ 345 NTSTATUS WINAPI SystemFunction013(const BYTE *in, const BYTE *key, LPBYTE out) 346 { 347 if (!in || !out) 348 return STATUS_UNSUCCESSFUL; 349 350 CRYPT_DESunhash(out, key, in); 351 CRYPT_DESunhash(out+8, key+7, in+8); 352 return STATUS_SUCCESS; 353 } 354 355 /****************************************************************************** 356 * SystemFunction024 [ADVAPI32.@] 357 * 358 * Encrypts two DES blocks with a 32 bit key... 359 * 360 * PARAMS 361 * data [I] data to encrypt (16 bytes) 362 * key [I] key data (4 bytes) 363 * output [O] buffer to receive encrypted data (16 bytes) 364 * 365 * RETURNS 366 * Success: STATUS_SUCCESS 367 */ 368 NTSTATUS WINAPI SystemFunction024(const BYTE *in, const BYTE *key, LPBYTE out) 369 { 370 BYTE deskey[0x10]; 371 372 memcpy(deskey, key, 4); 373 memcpy(deskey+4, key, 4); 374 memcpy(deskey+8, key, 4); 375 memcpy(deskey+12, key, 4); 376 377 CRYPT_DEShash(out, deskey, in); 378 CRYPT_DEShash(out+8, deskey+7, in+8); 379 380 return STATUS_SUCCESS; 381 } 382 383 /****************************************************************************** 384 * SystemFunction025 [ADVAPI32.@] 385 * 386 * Decrypts two DES blocks with a 32 bit key... 387 * 388 * PARAMS 389 * data [I] data to encrypt (16 bytes) 390 * key [I] key data (4 bytes) 391 * output [O] buffer to receive encrypted data (16 bytes) 392 * 393 * RETURNS 394 * Success: STATUS_SUCCESS 395 */ 396 NTSTATUS WINAPI SystemFunction025(const BYTE *in, const BYTE *key, LPBYTE out) 397 { 398 BYTE deskey[0x10]; 399 400 memcpy(deskey, key, 4); 401 memcpy(deskey+4, key, 4); 402 memcpy(deskey+8, key, 4); 403 memcpy(deskey+12, key, 4); 404 405 CRYPT_DESunhash(out, deskey, in); 406 CRYPT_DESunhash(out+8, deskey+7, in+8); 407 408 return STATUS_SUCCESS; 409 } 410 #endif /* !__REACTOS__ */ 411