ms_funcs.c

Go to the documentation of this file.
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         /* Convert password into unicode */
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          * PasswordLength is 4 octets, but since the maximum password length is
00341          * 256, only first two (in little endian byte order) can be non-zero.
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         /* Test vector from RFC2759 example */
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 /* TEST_MAIN_MS_FUNCS */
00518 

Generated on Sat May 6 21:13:37 2006 for wpa_supplicant by  doxygen 1.4.2