ms_funcs.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
00003  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "sha1.h"
00019 #include "ms_funcs.h"
00020 #include "crypto.h"
00021 
00022 
00032 static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
00033                           const u8 *username, size_t username_len,
00034                           u8 *challenge)
00035 {
00036         u8 hash[SHA1_MAC_LEN];
00037         const unsigned char *addr[3];
00038         size_t len[3];
00039 
00040         addr[0] = peer_challenge;
00041         len[0] = 16;
00042         addr[1] = auth_challenge;
00043         len[1] = 16;
00044         addr[2] = username;
00045         len[2] = username_len;
00046 
00047         if (sha1_vector(3, addr, len, hash))
00048                 return -1;
00049         os_memcpy(challenge, hash, 8);
00050         return 0;
00051 }
00052 
00053 
00061 int 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                 password_len = 256;
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         return md4_vector(1, (const u8 **) &pos, &len, password_hash);
00079 }
00080 
00081 
00088 int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
00089 {
00090         size_t len = 16;
00091         return md4_vector(1, &password_hash, &len, password_hash_hash);
00092 }
00093 
00094 
00101 void challenge_response(const u8 *challenge, const u8 *password_hash,
00102                         u8 *response)
00103 {
00104         u8 zpwd[7];
00105         des_encrypt(challenge, password_hash, response);
00106         des_encrypt(challenge, password_hash + 7, response + 8);
00107         zpwd[0] = password_hash[14];
00108         zpwd[1] = password_hash[15];
00109         os_memset(zpwd + 2, 0, 5);
00110         des_encrypt(challenge, zpwd, response + 16);
00111 }
00112 
00113 
00125 int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
00126                          const u8 *username, size_t username_len,
00127                          const u8 *password, size_t password_len,
00128                          u8 *response)
00129 {
00130         u8 challenge[8];
00131         u8 password_hash[16];
00132 
00133         challenge_hash(peer_challenge, auth_challenge, username, username_len,
00134                        challenge);
00135         if (nt_password_hash(password, password_len, password_hash))
00136                 return -1;
00137         challenge_response(challenge, password_hash, response);
00138         return 0;
00139 }
00140 
00141 
00152 int generate_nt_response_pwhash(const u8 *auth_challenge,
00153                                 const u8 *peer_challenge,
00154                                 const u8 *username, size_t username_len,
00155                                 const u8 *password_hash,
00156                                 u8 *response)
00157 {
00158         u8 challenge[8];
00159 
00160         if (challenge_hash(peer_challenge, auth_challenge,
00161                            username, username_len,
00162                            challenge))
00163                 return -1;
00164         challenge_response(challenge, password_hash, response);
00165         return 0;
00166 }
00167 
00168 
00181 int generate_authenticator_response_pwhash(
00182         const u8 *password_hash,
00183         const u8 *peer_challenge, const u8 *auth_challenge,
00184         const u8 *username, size_t username_len,
00185         const u8 *nt_response, u8 *response)
00186 {
00187         static const u8 magic1[39] = {
00188                 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
00189                 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
00190                 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
00191                 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
00192         };
00193         static const u8 magic2[41] = {
00194                 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
00195                 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
00196                 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
00197                 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
00198                 0x6E
00199         };
00200 
00201         u8 password_hash_hash[16], challenge[8];
00202         const unsigned char *addr1[3];
00203         const size_t len1[3] = { 16, 24, sizeof(magic1) };
00204         const unsigned char *addr2[3];
00205         const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
00206 
00207         addr1[0] = password_hash_hash;
00208         addr1[1] = nt_response;
00209         addr1[2] = magic1;
00210 
00211         addr2[0] = response;
00212         addr2[1] = challenge;
00213         addr2[2] = magic2;
00214 
00215         if (hash_nt_password_hash(password_hash, password_hash_hash))
00216                 return -1;
00217         if (sha1_vector(3, addr1, len1, response))
00218                 return -1;
00219 
00220         challenge_hash(peer_challenge, auth_challenge, username, username_len,
00221                        challenge);
00222         return sha1_vector(3, addr2, len2, response);
00223 }
00224 
00225 
00239 int generate_authenticator_response(const u8 *password, size_t password_len,
00240                                     const u8 *peer_challenge,
00241                                     const u8 *auth_challenge,
00242                                     const u8 *username, size_t username_len,
00243                                     const u8 *nt_response, u8 *response)
00244 {
00245         u8 password_hash[16];
00246         if (nt_password_hash(password, password_len, password_hash))
00247                 return -1;
00248         return generate_authenticator_response_pwhash(
00249                 password_hash, peer_challenge, auth_challenge,
00250                 username, username_len, nt_response, response);
00251 }
00252 
00253 
00262 int nt_challenge_response(const u8 *challenge, const u8 *password,
00263                           size_t password_len, u8 *response)
00264 {
00265         u8 password_hash[16];
00266         if (nt_password_hash(password, password_len, password_hash))
00267                 return -1;
00268         challenge_response(challenge, password_hash, response);
00269         return 0;
00270 }
00271 
00272 
00280 int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
00281                    u8 *master_key)
00282 {
00283         static const u8 magic1[27] = {
00284                 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
00285                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
00286                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
00287         };
00288         const unsigned char *addr[3];
00289         const size_t len[3] = { 16, 24, sizeof(magic1) };
00290         u8 hash[SHA1_MAC_LEN];
00291 
00292         addr[0] = password_hash_hash;
00293         addr[1] = nt_response;
00294         addr[2] = magic1;
00295 
00296         if (sha1_vector(3, addr, len, hash))
00297                 return -1;
00298         os_memcpy(master_key, hash, 16);
00299         return 0;
00300 }
00301 
00302 
00312 int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
00313                             size_t session_key_len, int is_send,
00314                             int is_server)
00315 {
00316         static const u8 magic2[84] = {
00317                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00318                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00319                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00320                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
00321                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
00322                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
00323                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00324                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00325                 0x6b, 0x65, 0x79, 0x2e
00326         };
00327         static const u8 magic3[84] = {
00328                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
00329                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
00330                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
00331                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
00332                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
00333                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
00334                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
00335                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
00336                 0x6b, 0x65, 0x79, 0x2e
00337         };
00338         static const u8 shs_pad1[40] = {
00339                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00340                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00341                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00342                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00343         };
00344 
00345         static const u8 shs_pad2[40] = {
00346                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00347                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00348                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
00349                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
00350         };
00351         u8 digest[SHA1_MAC_LEN];
00352         const unsigned char *addr[4];
00353         const size_t len[4] = { 16, 40, 84, 40 };
00354 
00355         addr[0] = master_key;
00356         addr[1] = shs_pad1;
00357         if (is_send) {
00358                 addr[2] = is_server ? magic3 : magic2;
00359         } else {
00360                 addr[2] = is_server ? magic2 : magic3;
00361         }
00362         addr[3] = shs_pad2;
00363 
00364         if (sha1_vector(4, addr, len, digest))
00365                 return -1;
00366 
00367         if (session_key_len > SHA1_MAC_LEN)
00368                 session_key_len = SHA1_MAC_LEN;
00369         os_memcpy(session_key, digest, session_key_len);
00370         return 0;
00371 }
00372 
00373 
00374 #define PWBLOCK_LEN 516
00375 
00384 int encrypt_pw_block_with_password_hash(
00385         const u8 *password, size_t password_len,
00386         const u8 *password_hash, u8 *pw_block)
00387 {
00388         size_t i, offset;
00389         u8 *pos;
00390 
00391         if (password_len > 256)
00392                 return -1;
00393 
00394         os_memset(pw_block, 0, PWBLOCK_LEN);
00395         offset = (256 - password_len) * 2;
00396         if (os_get_random(pw_block, offset) < 0)
00397                 return -1;
00398         for (i = 0; i < password_len; i++)
00399                 pw_block[offset + i * 2] = password[i];
00400         /*
00401          * PasswordLength is 4 octets, but since the maximum password length is
00402          * 256, only first two (in little endian byte order) can be non-zero.
00403          */
00404         pos = &pw_block[2 * 256];
00405         WPA_PUT_LE16(pos, password_len * 2);
00406         rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
00407         return 0;
00408 }
00409 
00410 
00420 int new_password_encrypted_with_old_nt_password_hash(
00421         const u8 *new_password, size_t new_password_len,
00422         const u8 *old_password, size_t old_password_len,
00423         u8 *encrypted_pw_block)
00424 {
00425         u8 password_hash[16];
00426 
00427         if (nt_password_hash(old_password, old_password_len, password_hash))
00428                 return -1;
00429         if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
00430                                                 password_hash,
00431                                                 encrypted_pw_block))
00432                 return -1;
00433         return 0;
00434 }
00435 
00436 
00443 void nt_password_hash_encrypted_with_block(const u8 *password_hash,
00444                                            const u8 *block, u8 *cypher)
00445 {
00446         des_encrypt(password_hash, block, cypher);
00447         des_encrypt(password_hash + 8, block + 7, cypher + 8);
00448 }
00449 
00450 
00460 int old_nt_password_hash_encrypted_with_new_nt_password_hash(
00461         const u8 *new_password, size_t new_password_len,
00462         const u8 *old_password, size_t old_password_len,
00463         u8 *encrypted_password_hash)
00464 {
00465         u8 old_password_hash[16], new_password_hash[16];
00466 
00467         if (nt_password_hash(old_password, old_password_len,
00468                              old_password_hash) ||
00469             nt_password_hash(new_password, new_password_len,
00470                              new_password_hash))
00471                 return -1;
00472         nt_password_hash_encrypted_with_block(old_password_hash,
00473                                               new_password_hash,
00474                                               encrypted_password_hash);
00475         return 0;
00476 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:38