18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MSCHAPV2 (RFC 2759) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/ms_funcs.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "mschapv2.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * mschapv2_remove_domain(const u8 *username, size_t *len) 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MSCHAPv2 does not include optional domain name in the 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge-response calculation, so remove domain prefix 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (if present). 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < *len; i++) { 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (username[i] == '\\') { 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len -= i + 1; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return username + i + 1; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return username; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint mschapv2_derive_response(const u8 *identity, size_t identity_len, 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, size_t password_len, 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pwhash, 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth_challenge, 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *nt_response, u8 *auth_response, 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *master_key) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t username_len; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16], password_hash_hash[16]; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username_len = identity_len; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username = mschapv2_remove_domain(identity, &username_len); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge, MSCHAPV2_CHAL_LEN); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, MSCHAPV2_CHAL_LEN); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Authenticator response is not really needed yet, but calculate it 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * here so that challenges need not be saved. */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pwhash) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len); 6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (generate_nt_response_pwhash(auth_challenge, peer_challenge, 6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username, username_len, 6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt password, nt_response) || 6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt generate_authenticator_response_pwhash( 7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt password, peer_challenge, auth_challenge, 7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username, username_len, nt_response, 7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt auth_response)) 7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len); 7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (generate_nt_response(auth_challenge, peer_challenge, 7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username, username_len, 7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt password, password_len, 8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nt_response) || 8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt generate_authenticator_response(password, password_len, 8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt peer_challenge, 8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt auth_challenge, 8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username, username_len, 8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nt_response, 8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt auth_response)) 8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response, MSCHAPV2_NT_RESPONSE_LEN); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Generate master_key here since we have the needed data available. */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pwhash) { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hash_nt_password_hash(password, password_hash_hash)) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash) || 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_nt_password_hash(password_hash, password_hash_hash)) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (get_master_key(password_hash_hash, nt_response, master_key)) 10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt master_key, MSCHAPV2_MASTER_KEY_LEN); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint mschapv2_verify_auth_response(const u8 *auth_response, 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t buf_len) 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] != 'S' || buf[1] != '=' || 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hexstr2bin((char *) (buf + 2), recv_response, 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MSCHAPV2_AUTH_RESPONSE_LEN) || 120c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(auth_response, recv_response, 121c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt MSCHAPV2_AUTH_RESPONSE_LEN) != 0) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 125