$search
00001 /* 00002 * MSCHAPV2 (RFC 2759) 00003 * Copyright (c) 2004-2008, 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 "crypto/ms_funcs.h" 00019 #include "mschapv2.h" 00020 00021 const u8 * mschapv2_remove_domain(const u8 *username, size_t *len) 00022 { 00023 size_t i; 00024 00025 /* 00026 * MSCHAPv2 does not include optional domain name in the 00027 * challenge-response calculation, so remove domain prefix 00028 * (if present). 00029 */ 00030 00031 for (i = 0; i < *len; i++) { 00032 if (username[i] == '\\') { 00033 *len -= i + 1; 00034 return username + i + 1; 00035 } 00036 } 00037 00038 return username; 00039 } 00040 00041 00042 int mschapv2_derive_response(const u8 *identity, size_t identity_len, 00043 const u8 *password, size_t password_len, 00044 int pwhash, 00045 const u8 *auth_challenge, 00046 const u8 *peer_challenge, 00047 u8 *nt_response, u8 *auth_response, 00048 u8 *master_key) 00049 { 00050 const u8 *username; 00051 size_t username_len; 00052 u8 password_hash[16], password_hash_hash[16]; 00053 00054 wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", 00055 identity, identity_len); 00056 username_len = identity_len; 00057 username = mschapv2_remove_domain(identity, &username_len); 00058 wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", 00059 username, username_len); 00060 00061 wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", 00062 auth_challenge, MSCHAPV2_CHAL_LEN); 00063 wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", 00064 peer_challenge, MSCHAPV2_CHAL_LEN); 00065 wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", 00066 username, username_len); 00067 /* Authenticator response is not really needed yet, but calculate it 00068 * here so that challenges need not be saved. */ 00069 if (pwhash) { 00070 wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", 00071 password, password_len); 00072 generate_nt_response_pwhash(auth_challenge, peer_challenge, 00073 username, username_len, 00074 password, nt_response); 00075 generate_authenticator_response_pwhash( 00076 password, peer_challenge, auth_challenge, 00077 username, username_len, nt_response, auth_response); 00078 } else { 00079 wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", 00080 password, password_len); 00081 generate_nt_response(auth_challenge, peer_challenge, 00082 username, username_len, 00083 password, password_len, nt_response); 00084 generate_authenticator_response(password, password_len, 00085 peer_challenge, auth_challenge, 00086 username, username_len, 00087 nt_response, auth_response); 00088 } 00089 wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", 00090 nt_response, MSCHAPV2_NT_RESPONSE_LEN); 00091 wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", 00092 auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); 00093 00094 /* Generate master_key here since we have the needed data available. */ 00095 if (pwhash) { 00096 if (hash_nt_password_hash(password, password_hash_hash)) 00097 return -1; 00098 } else { 00099 if (nt_password_hash(password, password_len, password_hash) || 00100 hash_nt_password_hash(password_hash, password_hash_hash)) 00101 return -1; 00102 } 00103 get_master_key(password_hash_hash, nt_response, master_key); 00104 wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", 00105 master_key, MSCHAPV2_MASTER_KEY_LEN); 00106 00107 return 0; 00108 } 00109 00110 00111 int mschapv2_verify_auth_response(const u8 *auth_response, 00112 const u8 *buf, size_t buf_len) 00113 { 00114 u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 00115 if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || 00116 buf[0] != 'S' || buf[1] != '=' || 00117 hexstr2bin((char *) (buf + 2), recv_response, 00118 MSCHAPV2_AUTH_RESPONSE_LEN) || 00119 os_memcmp(auth_response, recv_response, 00120 MSCHAPV2_AUTH_RESPONSE_LEN) != 0) 00121 return -1; 00122 return 0; 00123 }