]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/ms_funcs.c
This commit was generated by cvs2svn to compensate for changes in r147072,
[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
162         addr[0] = password_hash_hash;
163         addr[1] = nt_response;
164         addr[2] = magic1;
165
166         sha1_vector(3, addr, len, master_key);
167 }
168
169
170 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
171                              size_t session_key_len, int is_send,
172                              int is_server)
173 {
174         static const u8 magic2[84] = {
175                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
176                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
177                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
178                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
179                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
180                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
181                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
182                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
183                 0x6b, 0x65, 0x79, 0x2e
184         };
185         static const u8 magic3[84] = {
186                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
187                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
188                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
189                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
190                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
191                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
192                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
193                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
194                 0x6b, 0x65, 0x79, 0x2e
195         };
196         static const u8 shs_pad1[40] = {
197                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
201         };
202
203         static const u8 shs_pad2[40] = {
204                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
205                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
206                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
207                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
208         };
209         u8 digest[SHA1_MAC_LEN];
210         const unsigned char *addr[4];
211         const size_t len[4] = { 16, 40, 84, 40 };
212
213         addr[0] = master_key;
214         addr[1] = shs_pad1;
215         if (is_send) {
216                 addr[2] = is_server ? magic3 : magic2;
217         } else {
218                 addr[2] = is_server ? magic2 : magic3;
219         }
220         addr[3] = shs_pad2;
221
222         sha1_vector(4, addr, len, digest);
223
224         if (session_key_len > SHA1_MAC_LEN)
225                 session_key_len = SHA1_MAC_LEN;
226         memcpy(session_key, digest, session_key_len);
227 }
228
229
230 #ifdef TEST_MAIN_MS_FUNCS
231 int main(int argc, char *argv[])
232 {
233         /* Test vector from RFC2759 example */
234         u8 *username = "User";
235         u8 *password = "clientPass";
236         u8 auth_challenge[] = {
237                 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
238                 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
239         };
240         u8 peer_challenge[] = {
241                 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
242                 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
243         };
244         u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 };
245         u8 password_hash[] = {
246                 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
247                 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
248         };
249         u8 nt_response[] = {
250                 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
251                 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
252                 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
253         };
254         u8 password_hash_hash[] = {
255                 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
256                 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
257         };
258         u8 authenticator_response[] = {
259                 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
260                 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
261                 0x93, 0x2C, 0xDA, 0x56
262         };
263         u8 master_key[] = {
264                 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
265                 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
266         };
267         u8 send_start_key[] = {
268                 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
269                 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
270         };
271         u8 buf[32];
272
273         int errors = 0;
274
275         printf("Testing ms_funcs.c\n");
276
277         challenge_hash(peer_challenge, auth_challenge,
278                        username, strlen(username),
279                        buf);
280         if (memcmp(challenge, buf, sizeof(challenge)) != 0) {
281                 printf("challenge_hash failed\n");
282                 errors++;
283         }
284
285         nt_password_hash(password, strlen(password), buf);
286         if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
287                 printf("nt_password_hash failed\n");
288                 errors++;
289         }
290
291         generate_nt_response(auth_challenge, peer_challenge,
292                              username, strlen(username),
293                              password, strlen(password),
294                              buf);
295         if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
296                 printf("generate_nt_response failed\n");
297                 errors++;
298         }
299
300         hash_nt_password_hash(password_hash, buf);
301         if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) {
302                 printf("hash_nt_password_hash failed\n");
303                 errors++;
304         }
305
306         generate_authenticator_response(password, strlen(password),
307                                         peer_challenge, auth_challenge,
308                                         username, strlen(username),
309                                         nt_response, buf);
310         if (memcmp(authenticator_response, buf, sizeof(authenticator_response))
311             != 0) {
312                 printf("generate_authenticator_response failed\n");
313                 errors++;
314         }
315
316         get_master_key(password_hash_hash, nt_response, buf);
317         if (memcmp(master_key, buf, sizeof(master_key)) != 0) {
318                 printf("get_master_key failed\n");
319                 errors++;
320         }
321
322         get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1);
323         if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
324                 printf("get_asymetric_start_key failed\n");
325                 errors++;
326         }
327
328         if (errors)
329                 printf("FAILED! %d errors\n", errors);
330
331         return errors;
332 }
333 #endif /* TEST_MAIN_MS_FUNCS */