159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * MSCHAPV2 (RFC 2759) 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This program is free software; you can redistribute it and/or modify 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * it under the terms of the GNU General Public License version 2 as 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * published by the Free Software Foundation. 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Alternatively, this software may be distributed under the terms of BSD 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * license. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * See README and COPYING for more details. 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta#include "includes.h" 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta#include "common.h" 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta#include "crypto/ms_funcs.h" 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta#include "mschapv2.h" 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaconst u8 * mschapv2_remove_domain(const u8 *username, size_t *len) 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta{ 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta size_t i; 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /* 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * MSCHAPv2 does not include optional domain name in the 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * challenge-response calculation, so remove domain prefix 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * (if present). 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (i = 0; i < *len; i++) { 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (username[i] == '\\') { 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *len -= i + 1; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return username + i + 1; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return username; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartavoid mschapv2_derive_response(const u8 *identity, size_t identity_len, 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta const u8 *password, size_t password_len, 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int pwhash, 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta const u8 *auth_challenge, 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta const u8 *peer_challenge, 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta u8 *nt_response, u8 *auth_response, 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta u8 *master_key) 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta{ 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta const u8 *username; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta size_t username_len; 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta u8 password_hash[16], password_hash_hash[16]; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta identity, identity_len); 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username_len = identity_len; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username = mschapv2_remove_domain(identity, &username_len); 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len); 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta auth_challenge, MSCHAPV2_CHAL_LEN); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta peer_challenge, MSCHAPV2_CHAL_LEN); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /* Authenticator response is not really needed yet, but calculate it 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * here so that challenges need not be saved. */ 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pwhash) { 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta password, password_len); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta generate_nt_response_pwhash(auth_challenge, peer_challenge, 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len, 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta password, nt_response); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta generate_authenticator_response_pwhash( 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta password, peer_challenge, auth_challenge, 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len, nt_response, auth_response); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta password, password_len); 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta generate_nt_response(auth_challenge, peer_challenge, 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len, 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta password, password_len, nt_response); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta generate_authenticator_response(password, password_len, 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta peer_challenge, auth_challenge, 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta username, username_len, 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nt_response, auth_response); 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nt_response, MSCHAPV2_NT_RESPONSE_LEN); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /* Generate master_key here since we have the needed data available. */ 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pwhash) { 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hash_nt_password_hash(password, password_hash_hash); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nt_password_hash(password, password_len, password_hash); 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hash_nt_password_hash(password_hash, password_hash_hash); 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta get_master_key(password_hash_hash, nt_response, master_key); 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta master_key, MSCHAPV2_MASTER_KEY_LEN); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaint mschapv2_verify_auth_response(const u8 *auth_response, 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta const u8 *buf, size_t buf_len) 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta{ 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta buf[0] != 'S' || buf[1] != '=' || 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hexstr2bin((char *) (buf + 2), recv_response, 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MSCHAPV2_AUTH_RESPONSE_LEN) || 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta os_memcmp(auth_response, recv_response, 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MSCHAPV2_AUTH_RESPONSE_LEN) != 0) 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return -1; 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return 0; 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta