1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/* 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * MSCHAPV2 (RFC 2759) 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * This software may be distributed under the terms of the BSD license. 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * See README for more details. 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "includes.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "common.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "crypto/ms_funcs.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mschapv2.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst u8 * mschapv2_remove_domain(const u8 *username, size_t *len) 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles){ 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t i; 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /* 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * MSCHAPv2 does not include optional domain name in the 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * challenge-response calculation, so remove domain prefix 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * (if present). 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (i = 0; i < *len; i++) { 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (username[i] == '\\') { 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *len -= i + 1; 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return username + i + 1; 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return username; 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint mschapv2_derive_response(const u8 *identity, size_t identity_len, 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const u8 *password, size_t password_len, 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int pwhash, 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const u8 *auth_challenge, 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const u8 *peer_challenge, 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) u8 *nt_response, u8 *auth_response, 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) u8 *master_key) 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles){ 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const u8 *username; 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t username_len; 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci u8 password_hash[16], password_hash_hash[16]; 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) identity, identity_len); 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) username_len = identity_len; 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch username = mschapv2_remove_domain(identity, &username_len); 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci username, username_len); 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci auth_challenge, MSCHAPV2_CHAL_LEN); 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch peer_challenge, MSCHAPV2_CHAL_LEN); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) username, username_len); 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /* Authenticator response is not really needed yet, but calculate it 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * here so that challenges need not be saved. */ 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pwhash) { 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) password, password_len); 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (generate_nt_response_pwhash(auth_challenge, peer_challenge, 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch username, username_len, 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password, nt_response) || 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) generate_authenticator_response_pwhash( 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) password, peer_challenge, auth_challenge, 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) username, username_len, nt_response, 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) auth_response)) 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return -1; 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password, password_len); 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (generate_nt_response(auth_challenge, peer_challenge, 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch username, username_len, 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password, password_len, 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nt_response) || 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch generate_authenticator_response(password, password_len, 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch peer_challenge, 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch auth_challenge, 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch username, username_len, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nt_response, 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci auth_response)) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return -1; 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nt_response, MSCHAPV2_NT_RESPONSE_LEN); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /* Generate master_key here since we have the needed data available. */ 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pwhash) { 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (hash_nt_password_hash(password, password_hash_hash)) 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return -1; 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (nt_password_hash(password, password_len, password_hash) || 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) hash_nt_password_hash(password_hash, password_hash_hash)) 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return -1; 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (get_master_key(password_hash_hash, nt_response, master_key)) 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return -1; 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci master_key, MSCHAPV2_MASTER_KEY_LEN); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return 0; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint mschapv2_verify_auth_response(const u8 *auth_response, 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const u8 *buf, size_t buf_len) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buf[0] != 'S' || buf[1] != '=' || 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hexstr2bin((char *) (buf + 2), recv_response, 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MSCHAPV2_AUTH_RESPONSE_LEN) || 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) os_memcmp_const(auth_response, recv_response, 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MSCHAPV2_AUTH_RESPONSE_LEN) != 0) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return -1; 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)