remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / eap_peer / mschapv2.c
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
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 int 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
111 int 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 }