Home | History | Annotate | Download | only in eap_peer
      1 /*
      2  * MSCHAPV2 (RFC 2759)
      3  * Copyright (c) 2004-2008, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "crypto/ms_funcs.h"
     19 #include "mschapv2.h"
     20 
     21 const u8 * mschapv2_remove_domain(const u8 *username, size_t *len)
     22 {
     23 	size_t i;
     24 
     25 	/*
     26 	 * MSCHAPv2 does not include optional domain name in the
     27 	 * challenge-response calculation, so remove domain prefix
     28 	 * (if present).
     29 	 */
     30 
     31 	for (i = 0; i < *len; i++) {
     32 		if (username[i] == '\\') {
     33 			*len -= i + 1;
     34 			return username + i + 1;
     35 		}
     36 	}
     37 
     38 	return username;
     39 }
     40 
     41 
     42 void mschapv2_derive_response(const u8 *identity, size_t identity_len,
     43 			      const u8 *password, size_t password_len,
     44 			      int pwhash,
     45 			      const u8 *auth_challenge,
     46 			      const u8 *peer_challenge,
     47 			      u8 *nt_response, u8 *auth_response,
     48 			      u8 *master_key)
     49 {
     50 	const u8 *username;
     51 	size_t username_len;
     52 	u8 password_hash[16], password_hash_hash[16];
     53 
     54 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity",
     55 			  identity, identity_len);
     56 	username_len = identity_len;
     57 	username = mschapv2_remove_domain(identity, &username_len);
     58 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username",
     59 			  username, username_len);
     60 
     61 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge",
     62 		    auth_challenge, MSCHAPV2_CHAL_LEN);
     63 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge",
     64 		    peer_challenge, MSCHAPV2_CHAL_LEN);
     65 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username",
     66 			  username, username_len);
     67 	/* Authenticator response is not really needed yet, but calculate it
     68 	 * here so that challenges need not be saved. */
     69 	if (pwhash) {
     70 		wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash",
     71 				password, password_len);
     72 		generate_nt_response_pwhash(auth_challenge, peer_challenge,
     73 					    username, username_len,
     74 					    password, nt_response);
     75 		generate_authenticator_response_pwhash(
     76 			password, peer_challenge, auth_challenge,
     77 			username, username_len, nt_response, auth_response);
     78 	} else {
     79 		wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password",
     80 				      password, password_len);
     81 		generate_nt_response(auth_challenge, peer_challenge,
     82 				     username, username_len,
     83 				     password, password_len, nt_response);
     84 		generate_authenticator_response(password, password_len,
     85 						peer_challenge, auth_challenge,
     86 						username, username_len,
     87 						nt_response, auth_response);
     88 	}
     89 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response",
     90 		    nt_response, MSCHAPV2_NT_RESPONSE_LEN);
     91 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response",
     92 		    auth_response, MSCHAPV2_AUTH_RESPONSE_LEN);
     93 
     94 	/* Generate master_key here since we have the needed data available. */
     95 	if (pwhash) {
     96 		hash_nt_password_hash(password, password_hash_hash);
     97 	} else {
     98 		nt_password_hash(password, password_len, password_hash);
     99 		hash_nt_password_hash(password_hash, password_hash_hash);
    100 	}
    101 	get_master_key(password_hash_hash, nt_response, master_key);
    102 	wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key",
    103 			master_key, MSCHAPV2_MASTER_KEY_LEN);
    104 }
    105 
    106 
    107 int mschapv2_verify_auth_response(const u8 *auth_response,
    108 				  const u8 *buf, size_t buf_len)
    109 {
    110 	u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN];
    111 	if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN ||
    112 	    buf[0] != 'S' || buf[1] != '=' ||
    113 	    hexstr2bin((char *) (buf + 2), recv_response,
    114 		       MSCHAPV2_AUTH_RESPONSE_LEN) ||
    115 	    os_memcmp(auth_response, recv_response,
    116 		      MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
    117 		return -1;
    118 	return 0;
    119 }
    120