00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 #include "common.h"
00021 #include "sha1.h"
00022 #include "ms_funcs.h"
00023 #include "crypto.h"
00024 #include "rc4.h"
00025
00026
00036 static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
00037 const u8 *username, size_t username_len,
00038 u8 *challenge)
00039 {
00040 u8 hash[SHA1_MAC_LEN];
00041 const unsigned char *addr[3];
00042 size_t len[3];
00043
00044 addr[0] = peer_challenge;
00045 len[0] = 16;
00046 addr[1] = auth_challenge;
00047 len[1] = 16;
00048 addr[2] = username;
00049 len[2] = username_len;
00050
00051 sha1_vector(3, addr, len, hash);
00052 memcpy(challenge, hash, 8);
00053 }
00054
00055
00063 void nt_password_hash(const u8 *password, size_t password_len,
00064 u8 *password_hash)
00065 {
00066 u8 buf[512], *pos;
00067 size_t i, len;
00068
00069 if (password_len > 256)
00070 return;
00071
00072
00073 for (i = 0; i < password_len; i++) {
00074 buf[2 * i] = password[i];
00075 buf[2 * i + 1] = 0;
00076 }
00077
00078 len = password_len * 2;
00079 pos = buf;
00080 md4_vector(1, (const u8 **) &pos, &len, password_hash);
00081 }
00082
00083
00090 void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
00091 {
00092 size_t len = 16;
00093 md4_vector(1, &password_hash, &len, password_hash_hash);
00094 }
00095
00096
00104 void challenge_response(const u8 *challenge, const u8 *password_hash,
00105 u8 *response)
00106 {
00107 u8 zpwd[7];
00108 des_encrypt(challenge, password_hash, response);
00109 des_encrypt(challenge, password_hash + 7, response + 8);
00110 zpwd[0] = password_hash[14];
00111 zpwd[1] = password_hash[15];
00112 memset(zpwd + 2, 0, 5);
00113 des_encrypt(challenge, zpwd, response + 16);
00114 }
00115
00116
00128 void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
00129 const u8 *username, size_t username_len,
00130 const u8 *password, size_t password_len,
00131 u8 *response)
00132 {
00133 u8 challenge[8];
00134 u8 password_hash[16];
00135
00136 challenge_hash(peer_challenge, auth_challenge, username, username_len,
00137 challenge);
00138 nt_password_hash(password, password_len, password_hash);
00139 challenge_response(challenge, password_hash, response);
00140 }
00141
00142
00156 void generate_authenticator_response(const u8 *password, size_t password_len,
00157 const u8 *peer_challenge,
00158 const u8 *auth_challenge,
00159 const u8 *username, size_t username_len,
00160 const u8 *nt_response, u8 *response)
00161 {
00162 static const u8 magic1[39] = {
00163 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
00164 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
00165 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
00166 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
00167 };
00168 static const u8 magic2[41] = {
00169 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
00170 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
00171 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
00172 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
00173 0x6E
00174 };
00175
00176 u8 password_hash[16], password_hash_hash[16], challenge[8];
00177 const unsigned char *addr1[3];
00178 const size_t len1[3] = { 16, 24, sizeof(magic1) };
00179 const unsigned char *addr2[3];
00180 const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
00181
00182 addr1[0] = password_hash_hash;
00183 addr1[1] = nt_response;
00184 addr1[2] = magic1;
00185
00186 addr2[0] = response;
00187 addr2[1] = challenge;
00188 addr2[2] = magic2;
00189
00190 nt_password_hash(password, password_len, password_hash);
00191 hash_nt_password_hash(password_hash, password_hash_hash);
00192 sha1_vector(3, addr1, len1, response);
00193
00194 challenge_hash(peer_challenge, auth_challenge, username, username_len,
00195 challenge);
00196 sha1_vector(3, addr2, len2, response);
00197 }
00198
00199
00208 void nt_challenge_response(const u8 *challenge, const u8 *password,
00209 size_t password_len, u8 *response)
00210 {
00211 u8 password_hash[16];
00212 nt_password_hash(password, password_len, password_hash);
00213 challenge_response(challenge, password_hash, response);
00214 }
00215
00216
00224 void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
00225 u8 *master_key)
00226 {
00227 static const u8 magic1[27] = {
00228 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
00229 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
00230 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
00231 };
00232 const unsigned char *addr[3];
00233 const size_t len[3] = { 16, 24, sizeof(magic1) };
00234 u8 hash[SHA1_MAC_LEN];
00235
00236 addr[0] = password_hash_hash;
00237 addr[1] = nt_response;
00238 addr[2] = magic1;
00239
00240 sha1_vector(3, addr, len, hash);
00241 memcpy(master_key, hash, 16);
00242 }
00243
00244
00254 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
00255 size_t session_key_len, int is_send,
00256 int is_server)
00257 {
00258 static const u8 magic2[84] = {
00259 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00260 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00261 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00262 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
00263 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
00264 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
00265 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00266 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00267 0x6b, 0x65, 0x79, 0x2e
00268 };
00269 static const u8 magic3[84] = {
00270 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00271 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00272 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00273 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00274 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
00275 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
00276 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
00277 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
00278 0x6b, 0x65, 0x79, 0x2e
00279 };
00280 static const u8 shs_pad1[40] = {
00281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00285 };
00286
00287 static const u8 shs_pad2[40] = {
00288 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00289 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00290 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00291 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
00292 };
00293 u8 digest[SHA1_MAC_LEN];
00294 const unsigned char *addr[4];
00295 const size_t len[4] = { 16, 40, 84, 40 };
00296
00297 addr[0] = master_key;
00298 addr[1] = shs_pad1;
00299 if (is_send) {
00300 addr[2] = is_server ? magic3 : magic2;
00301 } else {
00302 addr[2] = is_server ? magic2 : magic3;
00303 }
00304 addr[3] = shs_pad2;
00305
00306 sha1_vector(4, addr, len, digest);
00307
00308 if (session_key_len > SHA1_MAC_LEN)
00309 session_key_len = SHA1_MAC_LEN;
00310 memcpy(session_key, digest, session_key_len);
00311 }
00312
00313
00314 #define PWBLOCK_LEN 516
00315
00324 static void encrypt_pw_block_with_password_hash(
00325 const u8 *password, size_t password_len,
00326 const u8 *password_hash, u8 *pw_block)
00327 {
00328 size_t i, offset;
00329 u8 *pos;
00330
00331 if (password_len > 256)
00332 return;
00333
00334 memset(pw_block, 0, PWBLOCK_LEN);
00335 offset = (256 - password_len) * 2;
00336 hostapd_get_rand(pw_block, offset);
00337 for (i = 0; i < password_len; i++)
00338 pw_block[offset + i * 2] = password[i];
00339
00340
00341
00342
00343 pos = &pw_block[2 * 256];
00344 WPA_PUT_LE16(pos, password_len * 2);
00345 rc4(pw_block, PWBLOCK_LEN, password_hash, 16);
00346 }
00347
00348
00358 void new_password_encrypted_with_old_nt_password_hash(
00359 const u8 *new_password, size_t new_password_len,
00360 const u8 *old_password, size_t old_password_len,
00361 u8 *encrypted_pw_block)
00362 {
00363 u8 password_hash[16];
00364
00365 nt_password_hash(old_password, old_password_len, password_hash);
00366 encrypt_pw_block_with_password_hash(new_password, new_password_len,
00367 password_hash, encrypted_pw_block);
00368 }
00369
00370
00378 static void nt_password_hash_encrypted_with_block(const u8 *password_hash,
00379 const u8 *block,
00380 u8 *cypher)
00381 {
00382 des_encrypt(password_hash, block, cypher);
00383 des_encrypt(password_hash + 8, block + 7, cypher + 8);
00384 }
00385
00386
00396 void old_nt_password_hash_encrypted_with_new_nt_password_hash(
00397 const u8 *new_password, size_t new_password_len,
00398 const u8 *old_password, size_t old_password_len,
00399 u8 *encrypted_password_hash)
00400 {
00401 u8 old_password_hash[16], new_password_hash[16];
00402
00403 nt_password_hash(old_password, old_password_len, old_password_hash);
00404 nt_password_hash(new_password, new_password_len, new_password_hash);
00405 nt_password_hash_encrypted_with_block(old_password_hash,
00406 new_password_hash,
00407 encrypted_password_hash);
00408 }
00409
00410
00411 #ifdef TEST_MAIN_MS_FUNCS
00412
00413 #include "rc4.c"
00414
00415 int main(int argc, char *argv[])
00416 {
00417
00418 u8 *username = "User";
00419 u8 *password = "clientPass";
00420 u8 auth_challenge[] = {
00421 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
00422 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
00423 };
00424 u8 peer_challenge[] = {
00425 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
00426 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
00427 };
00428 u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 };
00429 u8 password_hash[] = {
00430 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
00431 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
00432 };
00433 u8 nt_response[] = {
00434 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
00435 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
00436 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
00437 };
00438 u8 password_hash_hash[] = {
00439 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
00440 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
00441 };
00442 u8 authenticator_response[] = {
00443 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
00444 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
00445 0x93, 0x2C, 0xDA, 0x56
00446 };
00447 u8 master_key[] = {
00448 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
00449 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
00450 };
00451 u8 send_start_key[] = {
00452 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
00453 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
00454 };
00455 u8 buf[32];
00456
00457 int errors = 0;
00458
00459 printf("Testing ms_funcs.c\n");
00460
00461 challenge_hash(peer_challenge, auth_challenge,
00462 username, strlen(username),
00463 buf);
00464 if (memcmp(challenge, buf, sizeof(challenge)) != 0) {
00465 printf("challenge_hash failed\n");
00466 errors++;
00467 }
00468
00469 nt_password_hash(password, strlen(password), buf);
00470 if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
00471 printf("nt_password_hash failed\n");
00472 errors++;
00473 }
00474
00475 generate_nt_response(auth_challenge, peer_challenge,
00476 username, strlen(username),
00477 password, strlen(password),
00478 buf);
00479 if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
00480 printf("generate_nt_response failed\n");
00481 errors++;
00482 }
00483
00484 hash_nt_password_hash(password_hash, buf);
00485 if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) {
00486 printf("hash_nt_password_hash failed\n");
00487 errors++;
00488 }
00489
00490 generate_authenticator_response(password, strlen(password),
00491 peer_challenge, auth_challenge,
00492 username, strlen(username),
00493 nt_response, buf);
00494 if (memcmp(authenticator_response, buf, sizeof(authenticator_response))
00495 != 0) {
00496 printf("generate_authenticator_response failed\n");
00497 errors++;
00498 }
00499
00500 get_master_key(password_hash_hash, nt_response, buf);
00501 if (memcmp(master_key, buf, sizeof(master_key)) != 0) {
00502 printf("get_master_key failed\n");
00503 errors++;
00504 }
00505
00506 get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1);
00507 if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
00508 printf("get_asymetric_start_key failed\n");
00509 errors++;
00510 }
00511
00512 if (errors)
00513 printf("FAILED! %d errors\n", errors);
00514
00515 return errors;
00516 }
00517 #endif
00518