remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / crypto / ms_funcs.c
1 /*
2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
3  * Copyright (c) 2004-2009, 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 "sha1.h"
19 #include "ms_funcs.h"
20 #include "crypto.h"
21
22
23 /**
24  * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
25  * @peer_challenge: 16-octet PeerChallenge (IN)
26  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
27  * @username: 0-to-256-char UserName (IN)
28  * @username_len: Length of username
29  * @challenge: 8-octet Challenge (OUT)
30  * Returns: 0 on success, -1 on failure
31  */
32 static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
33                           const u8 *username, size_t username_len,
34                           u8 *challenge)
35 {
36         u8 hash[SHA1_MAC_LEN];
37         const unsigned char *addr[3];
38         size_t len[3];
39
40         addr[0] = peer_challenge;
41         len[0] = 16;
42         addr[1] = auth_challenge;
43         len[1] = 16;
44         addr[2] = username;
45         len[2] = username_len;
46
47         if (sha1_vector(3, addr, len, hash))
48                 return -1;
49         os_memcpy(challenge, hash, 8);
50         return 0;
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  * Returns: 0 on success, -1 on failure
60  */
61 int nt_password_hash(const u8 *password, size_t password_len,
62                       u8 *password_hash)
63 {
64         u8 buf[512], *pos;
65         size_t i, len;
66
67         if (password_len > 256)
68                 password_len = 256;
69
70         /* Convert password into unicode */
71         for (i = 0; i < password_len; i++) {
72                 buf[2 * i] = password[i];
73                 buf[2 * i + 1] = 0;
74         }
75
76         len = password_len * 2;
77         pos = buf;
78         return md4_vector(1, (const u8 **) &pos, &len, password_hash);
79 }
80
81
82 /**
83  * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
84  * @password_hash: 16-octet PasswordHash (IN)
85  * @password_hash_hash: 16-octet PasswordHashHash (OUT)
86  * Returns: 0 on success, -1 on failure
87  */
88 int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
89 {
90         size_t len = 16;
91         return md4_vector(1, &password_hash, &len, password_hash_hash);
92 }
93
94
95 /**
96  * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
97  * @challenge: 8-octet Challenge (IN)
98  * @password_hash: 16-octet PasswordHash (IN)
99  * @response: 24-octet Response (OUT)
100  */
101 void challenge_response(const u8 *challenge, const u8 *password_hash,
102                         u8 *response)
103 {
104         u8 zpwd[7];
105         des_encrypt(challenge, password_hash, response);
106         des_encrypt(challenge, password_hash + 7, response + 8);
107         zpwd[0] = password_hash[14];
108         zpwd[1] = password_hash[15];
109         os_memset(zpwd + 2, 0, 5);
110         des_encrypt(challenge, zpwd, response + 16);
111 }
112
113
114 /**
115  * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
116  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
117  * @peer_challenge: 16-octet PeerChallenge (IN)
118  * @username: 0-to-256-char UserName (IN)
119  * @username_len: Length of username
120  * @password: 0-to-256-unicode-char Password (IN; ASCII)
121  * @password_len: Length of password
122  * @response: 24-octet Response (OUT)
123  * Returns: 0 on success, -1 on failure
124  */
125 int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
126                          const u8 *username, size_t username_len,
127                          const u8 *password, size_t password_len,
128                          u8 *response)
129 {
130         u8 challenge[8];
131         u8 password_hash[16];
132
133         challenge_hash(peer_challenge, auth_challenge, username, username_len,
134                        challenge);
135         if (nt_password_hash(password, password_len, password_hash))
136                 return -1;
137         challenge_response(challenge, password_hash, response);
138         return 0;
139 }
140
141
142 /**
143  * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
144  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
145  * @peer_challenge: 16-octet PeerChallenge (IN)
146  * @username: 0-to-256-char UserName (IN)
147  * @username_len: Length of username
148  * @password_hash: 16-octet PasswordHash (IN)
149  * @response: 24-octet Response (OUT)
150  * Returns: 0 on success, -1 on failure
151  */
152 int generate_nt_response_pwhash(const u8 *auth_challenge,
153                                 const u8 *peer_challenge,
154                                 const u8 *username, size_t username_len,
155                                 const u8 *password_hash,
156                                 u8 *response)
157 {
158         u8 challenge[8];
159
160         if (challenge_hash(peer_challenge, auth_challenge,
161                            username, username_len,
162                            challenge))
163                 return -1;
164         challenge_response(challenge, password_hash, response);
165         return 0;
166 }
167
168
169 /**
170  * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
171  * @password_hash: 16-octet PasswordHash (IN)
172  * @nt_response: 24-octet NT-Response (IN)
173  * @peer_challenge: 16-octet PeerChallenge (IN)
174  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
175  * @username: 0-to-256-char UserName (IN)
176  * @username_len: Length of username
177  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
178  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
179  * Returns: 0 on success, -1 on failure
180  */
181 int generate_authenticator_response_pwhash(
182         const u8 *password_hash,
183         const u8 *peer_challenge, const u8 *auth_challenge,
184         const u8 *username, size_t username_len,
185         const u8 *nt_response, u8 *response)
186 {
187         static const u8 magic1[39] = {
188                 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
189                 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
190                 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
191                 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
192         };
193         static const u8 magic2[41] = {
194                 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
195                 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
196                 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
197                 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
198                 0x6E
199         };
200
201         u8 password_hash_hash[16], challenge[8];
202         const unsigned char *addr1[3];
203         const size_t len1[3] = { 16, 24, sizeof(magic1) };
204         const unsigned char *addr2[3];
205         const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
206
207         addr1[0] = password_hash_hash;
208         addr1[1] = nt_response;
209         addr1[2] = magic1;
210
211         addr2[0] = response;
212         addr2[1] = challenge;
213         addr2[2] = magic2;
214
215         if (hash_nt_password_hash(password_hash, password_hash_hash))
216                 return -1;
217         if (sha1_vector(3, addr1, len1, response))
218                 return -1;
219
220         challenge_hash(peer_challenge, auth_challenge, username, username_len,
221                        challenge);
222         return sha1_vector(3, addr2, len2, response);
223 }
224
225
226 /**
227  * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
228  * @password: 0-to-256-unicode-char Password (IN; ASCII)
229  * @password_len: Length of password
230  * @nt_response: 24-octet NT-Response (IN)
231  * @peer_challenge: 16-octet PeerChallenge (IN)
232  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
233  * @username: 0-to-256-char UserName (IN)
234  * @username_len: Length of username
235  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
236  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
237  * Returns: 0 on success, -1 on failure
238  */
239 int generate_authenticator_response(const u8 *password, size_t password_len,
240                                     const u8 *peer_challenge,
241                                     const u8 *auth_challenge,
242                                     const u8 *username, size_t username_len,
243                                     const u8 *nt_response, u8 *response)
244 {
245         u8 password_hash[16];
246         if (nt_password_hash(password, password_len, password_hash))
247                 return -1;
248         return generate_authenticator_response_pwhash(
249                 password_hash, peer_challenge, auth_challenge,
250                 username, username_len, nt_response, response);
251 }
252
253
254 /**
255  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
256  * @challenge: 8-octet Challenge (IN)
257  * @password: 0-to-256-unicode-char Password (IN; ASCII)
258  * @password_len: Length of password
259  * @response: 24-octet Response (OUT)
260  * Returns: 0 on success, -1 on failure
261  */
262 int nt_challenge_response(const u8 *challenge, const u8 *password,
263                           size_t password_len, u8 *response)
264 {
265         u8 password_hash[16];
266         if (nt_password_hash(password, password_len, password_hash))
267                 return -1;
268         challenge_response(challenge, password_hash, response);
269         return 0;
270 }
271
272
273 /**
274  * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
275  * @password_hash_hash: 16-octet PasswordHashHash (IN)
276  * @nt_response: 24-octet NTResponse (IN)
277  * @master_key: 16-octet MasterKey (OUT)
278  * Returns: 0 on success, -1 on failure
279  */
280 int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
281                    u8 *master_key)
282 {
283         static const u8 magic1[27] = {
284                 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
285                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
286                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
287         };
288         const unsigned char *addr[3];
289         const size_t len[3] = { 16, 24, sizeof(magic1) };
290         u8 hash[SHA1_MAC_LEN];
291
292         addr[0] = password_hash_hash;
293         addr[1] = nt_response;
294         addr[2] = magic1;
295
296         if (sha1_vector(3, addr, len, hash))
297                 return -1;
298         os_memcpy(master_key, hash, 16);
299         return 0;
300 }
301
302
303 /**
304  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
305  * @master_key: 16-octet MasterKey (IN)
306  * @session_key: 8-to-16 octet SessionKey (OUT)
307  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
308  * @is_send: IsSend (IN, BOOLEAN)
309  * @is_server: IsServer (IN, BOOLEAN)
310  * Returns: 0 on success, -1 on failure
311  */
312 int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
313                             size_t session_key_len, int is_send,
314                             int is_server)
315 {
316         static const u8 magic2[84] = {
317                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
318                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
319                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
320                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
321                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
322                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
323                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
324                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
325                 0x6b, 0x65, 0x79, 0x2e
326         };
327         static const u8 magic3[84] = {
328                 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
329                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
330                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
331                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
332                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
333                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
334                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
335                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
336                 0x6b, 0x65, 0x79, 0x2e
337         };
338         static const u8 shs_pad1[40] = {
339                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
343         };
344
345         static const u8 shs_pad2[40] = {
346                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
347                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
348                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
349                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
350         };
351         u8 digest[SHA1_MAC_LEN];
352         const unsigned char *addr[4];
353         const size_t len[4] = { 16, 40, 84, 40 };
354
355         addr[0] = master_key;
356         addr[1] = shs_pad1;
357         if (is_send) {
358                 addr[2] = is_server ? magic3 : magic2;
359         } else {
360                 addr[2] = is_server ? magic2 : magic3;
361         }
362         addr[3] = shs_pad2;
363
364         if (sha1_vector(4, addr, len, digest))
365                 return -1;
366
367         if (session_key_len > SHA1_MAC_LEN)
368                 session_key_len = SHA1_MAC_LEN;
369         os_memcpy(session_key, digest, session_key_len);
370         return 0;
371 }
372
373
374 #define PWBLOCK_LEN 516
375
376 /**
377  * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
378  * @password: 0-to-256-unicode-char Password (IN; ASCII)
379  * @password_len: Length of password
380  * @password_hash: 16-octet PasswordHash (IN)
381  * @pw_block: 516-byte PwBlock (OUT)
382  * Returns: 0 on success, -1 on failure
383  */
384 int encrypt_pw_block_with_password_hash(
385         const u8 *password, size_t password_len,
386         const u8 *password_hash, u8 *pw_block)
387 {
388         size_t i, offset;
389         u8 *pos;
390
391         if (password_len > 256)
392                 return -1;
393
394         os_memset(pw_block, 0, PWBLOCK_LEN);
395         offset = (256 - password_len) * 2;
396         if (os_get_random(pw_block, offset) < 0)
397                 return -1;
398         for (i = 0; i < password_len; i++)
399                 pw_block[offset + i * 2] = password[i];
400         /*
401          * PasswordLength is 4 octets, but since the maximum password length is
402          * 256, only first two (in little endian byte order) can be non-zero.
403          */
404         pos = &pw_block[2 * 256];
405         WPA_PUT_LE16(pos, password_len * 2);
406         rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
407         return 0;
408 }
409
410
411 /**
412  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
413  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
414  * @new_password_len: Length of new_password
415  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
416  * @old_password_len: Length of old_password
417  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
418  * Returns: 0 on success, -1 on failure
419  */
420 int new_password_encrypted_with_old_nt_password_hash(
421         const u8 *new_password, size_t new_password_len,
422         const u8 *old_password, size_t old_password_len,
423         u8 *encrypted_pw_block)
424 {
425         u8 password_hash[16];
426
427         if (nt_password_hash(old_password, old_password_len, password_hash))
428                 return -1;
429         if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
430                                                 password_hash,
431                                                 encrypted_pw_block))
432                 return -1;
433         return 0;
434 }
435
436
437 /**
438  * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
439  * @password_hash: 16-octer PasswordHash (IN)
440  * @block: 16-octet Block (IN)
441  * @cypher: 16-octer Cypher (OUT)
442  */
443 void nt_password_hash_encrypted_with_block(const u8 *password_hash,
444                                            const u8 *block, u8 *cypher)
445 {
446         des_encrypt(password_hash, block, cypher);
447         des_encrypt(password_hash + 8, block + 7, cypher + 8);
448 }
449
450
451 /**
452  * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
453  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
454  * @new_password_len: Length of new_password
455  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
456  * @old_password_len: Length of old_password
457  * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
458  * Returns: 0 on success, -1 on failure
459  */
460 int old_nt_password_hash_encrypted_with_new_nt_password_hash(
461         const u8 *new_password, size_t new_password_len,
462         const u8 *old_password, size_t old_password_len,
463         u8 *encrypted_password_hash)
464 {
465         u8 old_password_hash[16], new_password_hash[16];
466
467         if (nt_password_hash(old_password, old_password_len,
468                              old_password_hash) ||
469             nt_password_hash(new_password, new_password_len,
470                              new_password_hash))
471                 return -1;
472         nt_password_hash_encrypted_with_block(old_password_hash,
473                                               new_password_hash,
474                                               encrypted_password_hash);
475         return 0;
476 }