mschapv2.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
1/*
2 * MSCHAPV2 (RFC 2759)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@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
21const 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
42int 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		if (hash_nt_password_hash(password, password_hash_hash))
97			return -1;
98	} else {
99		if (nt_password_hash(password, password_len, password_hash) ||
100		    hash_nt_password_hash(password_hash, password_hash_hash))
101			return -1;
102	}
103	get_master_key(password_hash_hash, nt_response, master_key);
104	wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key",
105			master_key, MSCHAPV2_MASTER_KEY_LEN);
106
107	return 0;
108}
109
110
111int mschapv2_verify_auth_response(const u8 *auth_response,
112				  const u8 *buf, size_t buf_len)
113{
114	u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN];
115	if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN ||
116	    buf[0] != 'S' || buf[1] != '=' ||
117	    hexstr2bin((char *) (buf + 2), recv_response,
118		       MSCHAPV2_AUTH_RESPONSE_LEN) ||
119	    os_memcmp(auth_response, recv_response,
120		      MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
121		return -1;
122	return 0;
123}
124