ms_funcs.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "sha1.h"
00020 #include "ms_funcs.h"
00021 #include "crypto.h"
00022 #include "rc4.h"
00023 
00024 
00034 static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
00035                            const u8 *username, size_t username_len,
00036                            u8 *challenge)
00037 {
00038         u8 hash[SHA1_MAC_LEN];
00039         const unsigned char *addr[3];
00040         size_t len[3];
00041 
00042         addr[0] = peer_challenge;
00043         len[0] = 16;
00044         addr[1] = auth_challenge;
00045         len[1] = 16;
00046         addr[2] = username;
00047         len[2] = username_len;
00048 
00049         sha1_vector(3, addr, len, hash);
00050         os_memcpy(challenge, hash, 8);
00051 }
00052 
00053 
00061 void nt_password_hash(const u8 *password, size_t password_len,
00062                       u8 *password_hash)
00063 {
00064         u8 buf[512], *pos;
00065         size_t i, len;
00066 
00067         if (password_len > 256)
00068                 return;
00069 
00070         /* Convert password into unicode */
00071         for (i = 0; i < password_len; i++) {
00072                 buf[2 * i] = password[i];
00073                 buf[2 * i + 1] = 0;
00074         }
00075 
00076         len = password_len * 2;
00077         pos = buf;
00078         md4_vector(1, (const u8 **) &pos, &len, password_hash);
00079 }
00080 
00081 
00088 void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
00089 {
00090         size_t len = 16;
00091         md4_vector(1, &password_hash, &len, password_hash_hash);
00092 }
00093 
00094 
00102 void challenge_response(const u8 *challenge, const u8 *password_hash,
00103                         u8 *response)
00104 {
00105         u8 zpwd[7];
00106         des_encrypt(challenge, password_hash, response);
00107         des_encrypt(challenge, password_hash + 7, response + 8);
00108         zpwd[0] = password_hash[14];
00109         zpwd[1] = password_hash[15];
00110         os_memset(zpwd + 2, 0, 5);
00111         des_encrypt(challenge, zpwd, response + 16);
00112 }
00113 
00114 
00126 void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
00127                           const u8 *username, size_t username_len,
00128                           const u8 *password, size_t password_len,
00129                           u8 *response)
00130 {
00131         u8 challenge[8];
00132         u8 password_hash[16];
00133 
00134         challenge_hash(peer_challenge, auth_challenge, username, username_len,
00135                        challenge);
00136         nt_password_hash(password, password_len, password_hash);
00137         challenge_response(challenge, password_hash, response);
00138 }
00139 
00140 
00151 void generate_nt_response_pwhash(const u8 *auth_challenge,
00152                                  const u8 *peer_challenge,
00153                                  const u8 *username, size_t username_len,
00154                                  const u8 *password_hash,
00155                                  u8 *response)
00156 {
00157         u8 challenge[8];
00158 
00159         challenge_hash(peer_challenge, auth_challenge, username, username_len,
00160                        challenge);
00161         challenge_response(challenge, password_hash, response);
00162 }
00163 
00164 
00177 void generate_authenticator_response_pwhash(
00178         const u8 *password_hash,
00179         const u8 *peer_challenge, const u8 *auth_challenge,
00180         const u8 *username, size_t username_len,
00181         const u8 *nt_response, u8 *response)
00182 {
00183         static const u8 magic1[39] = {
00184                 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
00185                 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
00186                 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
00187                 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
00188         };
00189         static const u8 magic2[41] = {
00190                 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
00191                 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
00192                 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
00193                 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
00194                 0x6E
00195         };
00196 
00197         u8 password_hash_hash[16], challenge[8];
00198         const unsigned char *addr1[3];
00199         const size_t len1[3] = { 16, 24, sizeof(magic1) };
00200         const unsigned char *addr2[3];
00201         const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
00202 
00203         addr1[0] = password_hash_hash;
00204         addr1[1] = nt_response;
00205         addr1[2] = magic1;
00206 
00207         addr2[0] = response;
00208         addr2[1] = challenge;
00209         addr2[2] = magic2;
00210 
00211         hash_nt_password_hash(password_hash, password_hash_hash);
00212         sha1_vector(3, addr1, len1, response);
00213 
00214         challenge_hash(peer_challenge, auth_challenge, username, username_len,
00215                        challenge);
00216         sha1_vector(3, addr2, len2, response);
00217 }
00218 
00219 
00233 void generate_authenticator_response(const u8 *password, size_t password_len,
00234                                      const u8 *peer_challenge,
00235                                      const u8 *auth_challenge,
00236                                      const u8 *username, size_t username_len,
00237                                      const u8 *nt_response, u8 *response)
00238 {
00239         u8 password_hash[16];
00240         nt_password_hash(password, password_len, password_hash);
00241         generate_authenticator_response_pwhash(password_hash,
00242                                                peer_challenge, auth_challenge,
00243                                                username, username_len,
00244                                                nt_response, response);
00245 }
00246 
00247 
00256 void nt_challenge_response(const u8 *challenge, const u8 *password,
00257                            size_t password_len, u8 *response)
00258 {
00259         u8 password_hash[16];
00260         nt_password_hash(password, password_len, password_hash);
00261         challenge_response(challenge, password_hash, response);
00262 }
00263 
00264 
00272 void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
00273                     u8 *master_key)
00274 {
00275         static const u8 magic1[27] = {
00276                 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
00277                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
00278                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
00279         };
00280         const unsigned char *addr[3];
00281         const size_t len[3] = { 16, 24, sizeof(magic1) };
00282         u8 hash[SHA1_MAC_LEN];
00283 
00284         addr[0] = password_hash_hash;
00285         addr[1] = nt_response;
00286         addr[2] = magic1;
00287 
00288         sha1_vector(3, addr, len, hash);
00289         os_memcpy(master_key, hash, 16);
00290 }
00291 
00292 
00302 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
00303                              size_t session_key_len, int is_send,
00304                              int is_server)
00305 {
00306         static const u8 magic2[84] = {
00307                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00308                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00309                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00310                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
00311                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
00312                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
00313                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00314                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00315                 0x6b, 0x65, 0x79, 0x2e
00316         };
00317         static const u8 magic3[84] = {
00318                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00319                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00320                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00321                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00322                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
00323                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
00324                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
00325                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
00326                 0x6b, 0x65, 0x79, 0x2e
00327         };
00328         static const u8 shs_pad1[40] = {
00329                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00330                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00331                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00332                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00333         };
00334 
00335         static const u8 shs_pad2[40] = {
00336                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00337                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00338                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00339                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
00340         };
00341         u8 digest[SHA1_MAC_LEN];
00342         const unsigned char *addr[4];
00343         const size_t len[4] = { 16, 40, 84, 40 };
00344 
00345         addr[0] = master_key;
00346         addr[1] = shs_pad1;
00347         if (is_send) {
00348                 addr[2] = is_server ? magic3 : magic2;
00349         } else {
00350                 addr[2] = is_server ? magic2 : magic3;
00351         }
00352         addr[3] = shs_pad2;
00353 
00354         sha1_vector(4, addr, len, digest);
00355 
00356         if (session_key_len > SHA1_MAC_LEN)
00357                 session_key_len = SHA1_MAC_LEN;
00358         os_memcpy(session_key, digest, session_key_len);
00359 }
00360 
00361 
00362 #define PWBLOCK_LEN 516
00363 
00372 static void encrypt_pw_block_with_password_hash(
00373         const u8 *password, size_t password_len,
00374         const u8 *password_hash, u8 *pw_block)
00375 {
00376         size_t i, offset;
00377         u8 *pos;
00378 
00379         if (password_len > 256)
00380                 return;
00381 
00382         os_memset(pw_block, 0, PWBLOCK_LEN);
00383         offset = (256 - password_len) * 2;
00384         os_get_random(pw_block, offset);
00385         for (i = 0; i < password_len; i++)
00386                 pw_block[offset + i * 2] = password[i];
00387         /*
00388          * PasswordLength is 4 octets, but since the maximum password length is
00389          * 256, only first two (in little endian byte order) can be non-zero.
00390          */
00391         pos = &pw_block[2 * 256];
00392         WPA_PUT_LE16(pos, password_len * 2);
00393         rc4(pw_block, PWBLOCK_LEN, password_hash, 16);
00394 }
00395 
00396 
00406 void new_password_encrypted_with_old_nt_password_hash(
00407         const u8 *new_password, size_t new_password_len,
00408         const u8 *old_password, size_t old_password_len,
00409         u8 *encrypted_pw_block)
00410 {
00411         u8 password_hash[16];
00412 
00413         nt_password_hash(old_password, old_password_len, password_hash);
00414         encrypt_pw_block_with_password_hash(new_password, new_password_len,
00415                                             password_hash, encrypted_pw_block);
00416 }
00417 
00418 
00426 static void nt_password_hash_encrypted_with_block(const u8 *password_hash,
00427                                                   const u8 *block,
00428                                                   u8 *cypher)
00429 {
00430         des_encrypt(password_hash, block, cypher);
00431         des_encrypt(password_hash + 8, block + 7, cypher + 8);
00432 }
00433 
00434 
00444 void old_nt_password_hash_encrypted_with_new_nt_password_hash(
00445         const u8 *new_password, size_t new_password_len,
00446         const u8 *old_password, size_t old_password_len,
00447         u8 *encrypted_password_hash)
00448 {
00449         u8 old_password_hash[16], new_password_hash[16];
00450 
00451         nt_password_hash(old_password, old_password_len, old_password_hash);
00452         nt_password_hash(new_password, new_password_len, new_password_hash);
00453         nt_password_hash_encrypted_with_block(old_password_hash,
00454                                               new_password_hash,
00455                                               encrypted_password_hash);
00456 }
00457 

Generated on Sun Dec 31 13:43:28 2006 for hostapd by  doxygen 1.4.2