]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/ms_funcs.c
This commit was generated by cvs2svn to compensate for changes in r150765,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / ms_funcs.c
1 /*
2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 #include "common.h"
20 #include "sha1.h"
21 #include "ms_funcs.h"
22 #include "crypto.h"
23
24
25 static void challenge_hash(u8 *peer_challenge, u8 *auth_challenge,
26                            u8 *username, size_t username_len,
27                            u8 *challenge)
28 {
29         u8 hash[SHA1_MAC_LEN];
30         const unsigned char *addr[3];
31         size_t len[3];
32
33         addr[0] = peer_challenge;
34         len[0] = 16;
35         addr[1] = auth_challenge;
36         len[1] = 16;
37         addr[2] = username;
38         len[2] = username_len;
39
40         sha1_vector(3, addr, len, hash);
41         memcpy(challenge, hash, 8);
42 }
43
44
45 void nt_password_hash(u8 *password, size_t password_len, u8 *password_hash)
46 {
47         u8 *buf;
48         int i;
49
50         /* Convert password into unicode */
51         buf = malloc(password_len * 2);
52         if (buf == NULL)
53                 return;
54         memset(buf, 0, password_len * 2);
55         for (i = 0; i < password_len; i++)
56                 buf[2 * i] = password[i];
57
58         md4(buf, password_len * 2, password_hash);
59         free(buf);
60 }
61
62
63 void hash_nt_password_hash(u8 *password_hash, u8 *password_hash_hash)
64 {
65         md4(password_hash, 16, password_hash_hash);
66 }
67
68
69 void challenge_response(u8 *challenge, u8 *password_hash, u8 *response)
70 {
71         u8 zpwd[7];
72         des_encrypt(challenge, password_hash, response);
73         des_encrypt(challenge, password_hash + 7, response + 8);
74         zpwd[0] = password_hash[14];
75         zpwd[1] = password_hash[15];
76         memset(zpwd + 2, 0, 5);
77         des_encrypt(challenge, zpwd, response + 16);
78 }
79
80
81 void generate_nt_response(u8 *auth_challenge, u8 *peer_challenge,
82                           u8 *username, size_t username_len,
83                           u8 *password, size_t password_len,
84                           u8 *response)
85 {
86         u8 challenge[8];
87         u8 password_hash[16];
88
89         challenge_hash(peer_challenge, auth_challenge, username, username_len,
90                        challenge);
91         nt_password_hash(password, password_len, password_hash);
92         challenge_response(challenge, password_hash, response);
93 }
94
95
96 void generate_authenticator_response(u8 *password, size_t password_len,
97                                      u8 *peer_challenge,
98                                      u8 *auth_challenge,
99                                      u8 *username, size_t username_len,
100                                      u8 *nt_response, u8 *response)
101 {
102         static const u8 magic1[39] = {
103                 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
104                 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
105                 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
106                 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
107         };
108         static const u8 magic2[41] = {
109                 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
110                 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
111                 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
112                 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
113                 0x6E
114         };
115
116         u8 password_hash[16], password_hash_hash[16], challenge[8];
117         const unsigned char *addr1[3];
118         const size_t len1[3] = { 16, 24, sizeof(magic1) };
119         const unsigned char *addr2[3];
120         const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
121
122         addr1[0] = password_hash_hash;
123         addr1[1] = nt_response;
124         addr1[2] = magic1;
125
126         addr2[0] = response;
127         addr2[1] = challenge;
128         addr2[2] = magic2;
129
130         nt_password_hash(password, password_len, password_hash);
131         hash_nt_password_hash(password_hash, password_hash_hash);
132         sha1_vector(3, addr1, len1, response);
133
134         challenge_hash(peer_challenge, auth_challenge, username, username_len,
135                        challenge);
136         sha1_vector(3, addr2, len2, response);
137 }
138
139
140 void nt_challenge_response(u8 *challenge, u8 *password, size_t password_len,
141                            u8 *response)
142 {
143         u8 password_hash[16];
144         nt_password_hash(password, password_len, password_hash);
145         challenge_response(challenge, password_hash, response);
146 }
147
148
149 /* IN: 16-octet password_hash_hash and 24-octet nt_response
150  * OUT: 16-octet master_key */
151 void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
152                     u8 *master_key)
153 {
154         static const u8 magic1[27] = {
155                 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
156                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
157                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
158         };
159         const unsigned char *addr[3];
160         const size_t len[3] = { 16, 24, sizeof(magic1) };
161         u8 hash[SHA1_MAC_LEN];
162
163         addr[0] = password_hash_hash;
164         addr[1] = nt_response;
165         addr[2] = magic1;
166
167         sha1_vector(3, addr, len, hash);
168         memcpy(master_key, hash, 16);
169 }
170
171
172 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
173                              size_t session_key_len, int is_send,
174                              int is_server)
175 {
176         static const u8 magic2[84] = {
177                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
178                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
179                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
180                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
181                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
182                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
183                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
184                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
185                 0x6b, 0x65, 0x79, 0x2e
186         };
187         static const u8 magic3[84] = {
188                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
189                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
190                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
191                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
192                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
193                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
194                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
195                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
196                 0x6b, 0x65, 0x79, 0x2e
197         };
198         static const u8 shs_pad1[40] = {
199                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203         };
204
205         static const u8 shs_pad2[40] = {
206                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
207                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
208                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
209                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
210         };
211         u8 digest[SHA1_MAC_LEN];
212         const unsigned char *addr[4];
213         const size_t len[4] = { 16, 40, 84, 40 };
214
215         addr[0] = master_key;
216         addr[1] = shs_pad1;
217         if (is_send) {
218                 addr[2] = is_server ? magic3 : magic2;
219         } else {
220                 addr[2] = is_server ? magic2 : magic3;
221         }
222         addr[3] = shs_pad2;
223
224         sha1_vector(4, addr, len, digest);
225
226         if (session_key_len > SHA1_MAC_LEN)
227                 session_key_len = SHA1_MAC_LEN;
228         memcpy(session_key, digest, session_key_len);
229 }
230
231
232 #ifdef TEST_MAIN_MS_FUNCS
233 int main(int argc, char *argv[])
234 {
235         /* Test vector from RFC2759 example */
236         u8 *username = "User";
237         u8 *password = "clientPass";
238         u8 auth_challenge[] = {
239                 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
240                 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
241         };
242         u8 peer_challenge[] = {
243                 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
244                 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
245         };
246         u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 };
247         u8 password_hash[] = {
248                 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
249                 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
250         };
251         u8 nt_response[] = {
252                 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
253                 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
254                 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
255         };
256         u8 password_hash_hash[] = {
257                 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
258                 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
259         };
260         u8 authenticator_response[] = {
261                 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
262                 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
263                 0x93, 0x2C, 0xDA, 0x56
264         };
265         u8 master_key[] = {
266                 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
267                 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
268         };
269         u8 send_start_key[] = {
270                 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
271                 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
272         };
273         u8 buf[32];
274
275         int errors = 0;
276
277         printf("Testing ms_funcs.c\n");
278
279         challenge_hash(peer_challenge, auth_challenge,
280                        username, strlen(username),
281                        buf);
282         if (memcmp(challenge, buf, sizeof(challenge)) != 0) {
283                 printf("challenge_hash failed\n");
284                 errors++;
285         }
286
287         nt_password_hash(password, strlen(password), buf);
288         if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
289                 printf("nt_password_hash failed\n");
290                 errors++;
291         }
292
293         generate_nt_response(auth_challenge, peer_challenge,
294                              username, strlen(username),
295                              password, strlen(password),
296                              buf);
297         if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
298                 printf("generate_nt_response failed\n");
299                 errors++;
300         }
301
302         hash_nt_password_hash(password_hash, buf);
303         if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) {
304                 printf("hash_nt_password_hash failed\n");
305                 errors++;
306         }
307
308         generate_authenticator_response(password, strlen(password),
309                                         peer_challenge, auth_challenge,
310                                         username, strlen(username),
311                                         nt_response, buf);
312         if (memcmp(authenticator_response, buf, sizeof(authenticator_response))
313             != 0) {
314                 printf("generate_authenticator_response failed\n");
315                 errors++;
316         }
317
318         get_master_key(password_hash_hash, nt_response, buf);
319         if (memcmp(master_key, buf, sizeof(master_key)) != 0) {
320                 printf("get_master_key failed\n");
321                 errors++;
322         }
323
324         get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1);
325         if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
326                 printf("get_asymetric_start_key failed\n");
327                 errors++;
328         }
329
330         if (errors)
331                 printf("FAILED! %d errors\n", errors);
332
333         return errors;
334 }
335 #endif /* TEST_MAIN_MS_FUNCS */