Merge from vendor branch LESS:
[dragonfly.git] / contrib / hostapd-0.4.9 / ms_funcs.c
1 /*
2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
3  * Copyright (c) 2004-2006, 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 #include "rc4.h"
24
25
26 /**
27  * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
28  * @peer_challenge: 16-octet PeerChallenge (IN)
29  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
30  * @username: 0-to-256-char UserName (IN)
31  * @username_len: Length of username
32  * @challenge: 8-octet Challenge (OUT)
33  */
34 static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
35                            const u8 *username, size_t username_len,
36                            u8 *challenge)
37 {
38         u8 hash[SHA1_MAC_LEN];
39         const unsigned char *addr[3];
40         size_t len[3];
41
42         addr[0] = peer_challenge;
43         len[0] = 16;
44         addr[1] = auth_challenge;
45         len[1] = 16;
46         addr[2] = username;
47         len[2] = username_len;
48
49         sha1_vector(3, addr, len, hash);
50         memcpy(challenge, hash, 8);
51 }
52
53
54 /**
55  * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
56  * @password: 0-to-256-unicode-char Password (IN; ASCII)
57  * @password_len: Length of password
58  * @password_hash: 16-octet PasswordHash (OUT)
59  */
60 void nt_password_hash(const u8 *password, size_t password_len,
61                       u8 *password_hash)
62 {
63         u8 buf[512], *pos;
64         size_t i, len;
65
66         if (password_len > 256)
67                 return;
68
69         /* Convert password into unicode */
70         for (i = 0; i < password_len; i++) {
71                 buf[2 * i] = password[i];
72                 buf[2 * i + 1] = 0;
73         }
74
75         len = password_len * 2;
76         pos = buf;
77         md4_vector(1, (const u8 **) &pos, &len, password_hash);
78 }
79
80
81 /**
82  * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
83  * @password_hash: 16-octet PasswordHash (IN)
84  * @password_hash_hash: 16-octet PasswordHashHash (OUT)
85  */
86 void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
87 {
88         size_t len = 16;
89         md4_vector(1, &password_hash, &len, password_hash_hash);
90 }
91
92
93 /**
94  * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
95  * @challenge: 8-octet Challenge (IN)
96  * @password_hash: 16-octet PasswordHash (IN)
97  * @response: 24-octet Response (OUT)
98  */
99 void challenge_response(const u8 *challenge, const u8 *password_hash,
100                         u8 *response)
101 {
102         u8 zpwd[7];
103         des_encrypt(challenge, password_hash, response);
104         des_encrypt(challenge, password_hash + 7, response + 8);
105         zpwd[0] = password_hash[14];
106         zpwd[1] = password_hash[15];
107         memset(zpwd + 2, 0, 5);
108         des_encrypt(challenge, zpwd, response + 16);
109 }
110
111
112 /**
113  * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
114  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
115  * @peer_hallenge: 16-octet PeerChallenge (IN)
116  * @username: 0-to-256-char UserName (IN)
117  * @username_len: Length of username
118  * @password: 0-to-256-unicode-char Password (IN; ASCII)
119  * @password_len: Length of password
120  * @response: 24-octet Response (OUT)
121  */
122 void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
123                           const u8 *username, size_t username_len,
124                           const u8 *password, size_t password_len,
125                           u8 *response)
126 {
127         u8 challenge[8];
128         u8 password_hash[16];
129
130         challenge_hash(peer_challenge, auth_challenge, username, username_len,
131                        challenge);
132         nt_password_hash(password, password_len, password_hash);
133         challenge_response(challenge, password_hash, response);
134 }
135
136
137 /**
138  * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
139  * @password: 0-to-256-unicode-char Password (IN)
140  * @password_len: Length of password
141  * @nt_response: 24-octet NT-Response (IN)
142  * @peer_challenge: 16-octet PeerChallenge (IN)
143  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
144  * @username: 0-to-256-char UserName (IN)
145  * @username_len: Length of username
146  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
147  * encoded as a 42-octet ASCII string (S=<hexdump of response>)
148  */
149 void generate_authenticator_response(const u8 *password, size_t password_len,
150                                      const u8 *peer_challenge,
151                                      const u8 *auth_challenge,
152                                      const u8 *username, size_t username_len,
153                                      const u8 *nt_response, u8 *response)
154 {
155         static const u8 magic1[39] = {
156                 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
157                 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
158                 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
159                 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
160         };
161         static const u8 magic2[41] = {
162                 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
163                 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
164                 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
165                 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
166                 0x6E
167         };
168
169         u8 password_hash[16], password_hash_hash[16], challenge[8];
170         const unsigned char *addr1[3];
171         const size_t len1[3] = { 16, 24, sizeof(magic1) };
172         const unsigned char *addr2[3];
173         const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
174
175         addr1[0] = password_hash_hash;
176         addr1[1] = nt_response;
177         addr1[2] = magic1;
178
179         addr2[0] = response;
180         addr2[1] = challenge;
181         addr2[2] = magic2;
182
183         nt_password_hash(password, password_len, password_hash);
184         hash_nt_password_hash(password_hash, password_hash_hash);
185         sha1_vector(3, addr1, len1, response);
186
187         challenge_hash(peer_challenge, auth_challenge, username, username_len,
188                        challenge);
189         sha1_vector(3, addr2, len2, response);
190 }
191
192
193 /**
194  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
195  * @challenge: 8-octet Challenge (IN)
196  * @password: 0-to-256-unicode-char Password (IN; ASCII)
197  * @password_len: Length of password
198  * @response: 24-octet Response (OUT)
199  */
200 void nt_challenge_response(const u8 *challenge, const u8 *password,
201                            size_t password_len, u8 *response)
202 {
203         u8 password_hash[16];
204         nt_password_hash(password, password_len, password_hash);
205         challenge_response(challenge, password_hash, response);
206 }
207
208
209 /**
210  * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
211  * @password_hash_hash: 16-octet PasswordHashHash (IN)
212  * @nt_response: 24-octet NTResponse (IN)
213  * @master_key: 16-octet MasterKey (OUT)
214  */
215 void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
216                     u8 *master_key)
217 {
218         static const u8 magic1[27] = {
219                 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
220                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
221                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
222         };
223         const unsigned char *addr[3];
224         const size_t len[3] = { 16, 24, sizeof(magic1) };
225         u8 hash[SHA1_MAC_LEN];
226
227         addr[0] = password_hash_hash;
228         addr[1] = nt_response;
229         addr[2] = magic1;
230
231         sha1_vector(3, addr, len, hash);
232         memcpy(master_key, hash, 16);
233 }
234
235
236 /**
237  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
238  * @master_key: 16-octet MasterKey (IN)
239  * @session_key: 8-to-16 octet SessionKey (OUT)
240  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
241  * @is_send: IsSend (IN, BOOLEAN)
242  * @is_server: IsServer (IN, BOOLEAN)
243  */
244 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
245                              size_t session_key_len, int is_send,
246                              int is_server)
247 {
248         static const u8 magic2[84] = {
249                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
250                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
251                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
252                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
253                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
254                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
255                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
256                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
257                 0x6b, 0x65, 0x79, 0x2e
258         };
259         static const u8 magic3[84] = {
260                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
261                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
262                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
263                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
264                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
265                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
266                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
267                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
268                 0x6b, 0x65, 0x79, 0x2e
269         };
270         static const u8 shs_pad1[40] = {
271                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
275         };
276
277         static const u8 shs_pad2[40] = {
278                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
279                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
280                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
281                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
282         };
283         u8 digest[SHA1_MAC_LEN];
284         const unsigned char *addr[4];
285         const size_t len[4] = { 16, 40, 84, 40 };
286
287         addr[0] = master_key;
288         addr[1] = shs_pad1;
289         if (is_send) {
290                 addr[2] = is_server ? magic3 : magic2;
291         } else {
292                 addr[2] = is_server ? magic2 : magic3;
293         }
294         addr[3] = shs_pad2;
295
296         sha1_vector(4, addr, len, digest);
297
298         if (session_key_len > SHA1_MAC_LEN)
299                 session_key_len = SHA1_MAC_LEN;
300         memcpy(session_key, digest, session_key_len);
301 }
302
303
304 #define PWBLOCK_LEN 516
305
306 /**
307  * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
308  * @password: 0-to-256-unicode-char Password (IN; ASCII)
309  * @password_len: Length of password
310  * @password_hash: 16-octet PasswordHash (IN)
311  * @pw_block: 516-byte PwBlock (OUT)
312  */
313 static void encrypt_pw_block_with_password_hash(
314         const u8 *password, size_t password_len,
315         const u8 *password_hash, u8 *pw_block)
316 {
317         size_t i, offset;
318         u8 *pos;
319
320         if (password_len > 256)
321                 return;
322
323         memset(pw_block, 0, PWBLOCK_LEN);
324         offset = (256 - password_len) * 2;
325         hostapd_get_rand(pw_block, offset);
326         for (i = 0; i < password_len; i++)
327                 pw_block[offset + i * 2] = password[i];
328         /*
329          * PasswordLength is 4 octets, but since the maximum password length is
330          * 256, only first two (in little endian byte order) can be non-zero.
331          */
332         pos = &pw_block[2 * 256];
333         WPA_PUT_LE16(pos, password_len * 2);
334         rc4(pw_block, PWBLOCK_LEN, password_hash, 16);
335 }
336
337
338 /**
339  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
340  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
341  * @new_password_len: Length of new_password
342  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
343  * @old_password_len: Length of old_password
344  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
345  */
346 void new_password_encrypted_with_old_nt_password_hash(
347         const u8 *new_password, size_t new_password_len,
348         const u8 *old_password, size_t old_password_len,
349         u8 *encrypted_pw_block)
350 {
351         u8 password_hash[16];
352
353         nt_password_hash(old_password, old_password_len, password_hash);
354         encrypt_pw_block_with_password_hash(new_password, new_password_len,
355                                             password_hash, encrypted_pw_block);
356 }
357
358
359 /**
360  * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
361  * @password_hash: 16-octer PasswordHash (IN)
362  * @block: 16-octet Block (IN)
363  * @cypher: 16-octer Cypher (OUT)
364  */
365 static void nt_password_hash_encrypted_with_block(const u8 *password_hash,
366                                                   const u8 *block,
367                                                   u8 *cypher)
368 {
369         des_encrypt(password_hash, block, cypher);
370         des_encrypt(password_hash + 8, block + 7, cypher + 8);
371 }
372
373
374 /**
375  * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
376  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
377  * @new_password_len: Length of new_password
378  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
379  * @old_password_len: Length of old_password
380  * @encrypted_password_ash: 16-octet EncryptedPasswordHash (OUT)
381  */
382 void old_nt_password_hash_encrypted_with_new_nt_password_hash(
383         const u8 *new_password, size_t new_password_len,
384         const u8 *old_password, size_t old_password_len,
385         u8 *encrypted_password_hash)
386 {
387         u8 old_password_hash[16], new_password_hash[16];
388
389         nt_password_hash(old_password, old_password_len, old_password_hash);
390         nt_password_hash(new_password, new_password_len, new_password_hash);
391         nt_password_hash_encrypted_with_block(old_password_hash,
392                                               new_password_hash,
393                                               encrypted_password_hash);
394 }
395
396
397 #ifdef TEST_MAIN_MS_FUNCS
398
399 #include "rc4.c"
400
401 int main(int argc, char *argv[])
402 {
403         /* Test vector from RFC2759 example */
404         u8 *username = "User";
405         u8 *password = "clientPass";
406         u8 auth_challenge[] = {
407                 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
408                 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
409         };
410         u8 peer_challenge[] = {
411                 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
412                 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
413         };
414         u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 };
415         u8 password_hash[] = {
416                 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
417                 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
418         };
419         u8 nt_response[] = {
420                 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
421                 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
422                 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
423         };
424         u8 password_hash_hash[] = {
425                 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
426                 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
427         };
428         u8 authenticator_response[] = {
429                 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
430                 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
431                 0x93, 0x2C, 0xDA, 0x56
432         };
433         u8 master_key[] = {
434                 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
435                 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
436         };
437         u8 send_start_key[] = {
438                 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
439                 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
440         };
441         u8 buf[32];
442
443         int errors = 0;
444
445         printf("Testing ms_funcs.c\n");
446
447         challenge_hash(peer_challenge, auth_challenge,
448                        username, strlen(username),
449                        buf);
450         if (memcmp(challenge, buf, sizeof(challenge)) != 0) {
451                 printf("challenge_hash failed\n");
452                 errors++;
453         }
454
455         nt_password_hash(password, strlen(password), buf);
456         if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
457                 printf("nt_password_hash failed\n");
458                 errors++;
459         }
460
461         generate_nt_response(auth_challenge, peer_challenge,
462                              username, strlen(username),
463                              password, strlen(password),
464                              buf);
465         if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
466                 printf("generate_nt_response failed\n");
467                 errors++;
468         }
469
470         hash_nt_password_hash(password_hash, buf);
471         if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) {
472                 printf("hash_nt_password_hash failed\n");
473                 errors++;
474         }
475
476         generate_authenticator_response(password, strlen(password),
477                                         peer_challenge, auth_challenge,
478                                         username, strlen(username),
479                                         nt_response, buf);
480         if (memcmp(authenticator_response, buf, sizeof(authenticator_response))
481             != 0) {
482                 printf("generate_authenticator_response failed\n");
483                 errors++;
484         }
485
486         get_master_key(password_hash_hash, nt_response, buf);
487         if (memcmp(master_key, buf, sizeof(master_key)) != 0) {
488                 printf("get_master_key failed\n");
489                 errors++;
490         }
491
492         get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1);
493         if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
494                 printf("get_asymetric_start_key failed\n");
495                 errors++;
496         }
497
498         if (errors)
499                 printf("FAILED! %d errors\n", errors);
500
501         return errors;
502 }
503 #endif /* TEST_MAIN_MS_FUNCS */