Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / lwip / repo / lwip / src / netif / ppp / chap_ms.c
1 /*
2  * chap_ms.c - Microsoft MS-CHAP compatible implementation.
3  *
4  * Copyright (c) 1995 Eric Rosenquist.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name(s) of the authors of this software must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission.
21  *
22  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  */
30
31 /*
32  * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
33  *
34  *   Implemented LANManager type password response to MS-CHAP challenges.
35  *   Now pppd provides both NT style and LANMan style blocks, and the
36  *   prefered is set by option "ms-lanman". Default is to use NT.
37  *   The hash text (StdText) was taken from Win95 RASAPI32.DLL.
38  *
39  *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
40  */
41
42 /*
43  * Modifications by Frank Cusack, frank@google.com, March 2002.
44  *
45  *   Implemented MS-CHAPv2 functionality, heavily based on sample
46  *   implementation in RFC 2759.  Implemented MPPE functionality,
47  *   heavily based on sample implementation in RFC 3079.
48  *
49  * Copyright (c) 2002 Google, Inc.  All rights reserved.
50  *
51  * Redistribution and use in source and binary forms, with or without
52  * modification, are permitted provided that the following conditions
53  * are met:
54  *
55  * 1. Redistributions of source code must retain the above copyright
56  *    notice, this list of conditions and the following disclaimer.
57  *
58  * 2. Redistributions in binary form must reproduce the above copyright
59  *    notice, this list of conditions and the following disclaimer in
60  *    the documentation and/or other materials provided with the
61  *    distribution.
62  *
63  * 3. The name(s) of the authors of this software must not be used to
64  *    endorse or promote products derived from this software without
65  *    prior written permission.
66  *
67  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
68  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
69  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
70  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
71  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
72  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
73  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
74  *
75  */
76
77 #include "netif/ppp/ppp_opts.h"
78 #if PPP_SUPPORT && MSCHAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
79
80 #if 0 /* UNUSED */
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <ctype.h>
85 #include <sys/types.h>
86 #include <sys/time.h>
87 #include <unistd.h>
88 #endif /* UNUSED */
89
90 #include "netif/ppp/ppp_impl.h"
91
92 #include "netif/ppp/chap-new.h"
93 #include "netif/ppp/chap_ms.h"
94 #include "netif/ppp/pppcrypt.h"
95 #include "netif/ppp/magic.h"
96 #if MPPE_SUPPORT
97 #include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */
98 #endif /* MPPE_SUPPORT */
99
100 #define SHA1_SIGNATURE_SIZE     20
101 #define MD4_SIGNATURE_SIZE      16      /* 16 bytes in a MD4 message digest */
102 #define MAX_NT_PASSWORD         256     /* Max (Unicode) chars in an NT pass */
103
104 #define MS_CHAP_RESPONSE_LEN    49      /* Response length for MS-CHAP */
105 #define MS_CHAP2_RESPONSE_LEN   49      /* Response length for MS-CHAPv2 */
106 #define MS_AUTH_RESPONSE_LENGTH 40      /* MS-CHAPv2 authenticator response, */
107                                         /* as ASCII */
108
109 /* Error codes for MS-CHAP failure messages. */
110 #define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS    646
111 #define MS_CHAP_ERROR_ACCT_DISABLED             647
112 #define MS_CHAP_ERROR_PASSWD_EXPIRED            648
113 #define MS_CHAP_ERROR_NO_DIALIN_PERMISSION      649
114 #define MS_CHAP_ERROR_AUTHENTICATION_FAILURE    691
115 #define MS_CHAP_ERROR_CHANGING_PASSWORD         709
116
117 /*
118  * Offsets within the response field for MS-CHAP
119  */
120 #define MS_CHAP_LANMANRESP      0
121 #define MS_CHAP_LANMANRESP_LEN  24
122 #define MS_CHAP_NTRESP          24
123 #define MS_CHAP_NTRESP_LEN      24
124 #define MS_CHAP_USENT           48
125
126 /*
127  * Offsets within the response field for MS-CHAP2
128  */
129 #define MS_CHAP2_PEER_CHALLENGE 0
130 #define MS_CHAP2_PEER_CHAL_LEN  16
131 #define MS_CHAP2_RESERVED_LEN   8
132 #define MS_CHAP2_NTRESP         24
133 #define MS_CHAP2_NTRESP_LEN     24
134 #define MS_CHAP2_FLAGS          48
135
136 #if MPPE_SUPPORT
137 #if 0 /* UNUSED */
138 /* These values are the RADIUS attribute values--see RFC 2548. */
139 #define MPPE_ENC_POL_ENC_ALLOWED 1
140 #define MPPE_ENC_POL_ENC_REQUIRED 2
141 #define MPPE_ENC_TYPES_RC4_40 2
142 #define MPPE_ENC_TYPES_RC4_128 4
143
144 /* used by plugins (using above values) */
145 extern void set_mppe_enc_types(int, int);
146 #endif /* UNUSED */
147 #endif /* MPPE_SUPPORT */
148
149 /* Are we the authenticator or authenticatee?  For MS-CHAPv2 key derivation. */
150 #define MS_CHAP2_AUTHENTICATEE 0
151 #define MS_CHAP2_AUTHENTICATOR 1
152
153 static void     ascii2unicode (const char[], int, u_char[]);
154 static void     NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]);
155 static void     ChallengeResponse (const u_char *, const u_char *, u_char[24]);
156 static void     ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]);
157 static void     ChapMS_NT (const u_char *, const char *, int, u_char[24]);
158 static void     ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int,
159                                 u_char[24]);
160 static void     GenerateAuthenticatorResponsePlain
161                         (const char*, int, u_char[24], const u_char[16], const u_char *,
162                              const char *, u_char[41]);
163 #ifdef MSLANMAN
164 static void     ChapMS_LANMan (u_char *, char *, int, u_char *);
165 #endif
166
167 static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
168                         u_char NTResponse[24], const u_char PeerChallenge[16],
169                         const u_char *rchallenge, const char *username,
170                         u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]);
171
172 #if MPPE_SUPPORT
173 static void     Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int);
174 static void     SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int);
175 #endif /* MPPE_SUPPORT */
176
177 static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *);
178 static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int,
179                   u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int);
180
181 #ifdef MSLANMAN
182 bool    ms_lanman = 0;          /* Use LanMan password instead of NT */
183                                 /* Has meaning only with MS-CHAP challenges */
184 #endif
185
186 #if MPPE_SUPPORT
187 #ifdef DEBUGMPPEKEY
188 /* For MPPE debug */
189 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
190 static char *mschap_challenge = NULL;
191 /* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */
192 static char *mschap2_peer_challenge = NULL;
193 #endif
194
195 #include "netif/ppp/fsm.h"              /* Need to poke MPPE options */
196 #include "netif/ppp/ccp.h"
197 #endif /* MPPE_SUPPORT */
198
199 #if PPP_OPTIONS
200 /*
201  * Command-line options.
202  */
203 static option_t chapms_option_list[] = {
204 #ifdef MSLANMAN
205         { "ms-lanman", o_bool, &ms_lanman,
206           "Use LanMan passwd when using MS-CHAP", 1 },
207 #endif
208 #ifdef DEBUGMPPEKEY
209         { "mschap-challenge", o_string, &mschap_challenge,
210           "specify CHAP challenge" },
211         { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge,
212           "specify CHAP peer challenge" },
213 #endif
214         { NULL }
215 };
216 #endif /* PPP_OPTIONS */
217
218 #if PPP_SERVER
219 /*
220  * chapms_generate_challenge - generate a challenge for MS-CHAP.
221  * For MS-CHAP the challenge length is fixed at 8 bytes.
222  * The length goes in challenge[0] and the actual challenge starts
223  * at challenge[1].
224  */
225 static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) {
226         LWIP_UNUSED_ARG(pcb);
227
228         *challenge++ = 8;
229 #ifdef DEBUGMPPEKEY
230         if (mschap_challenge && strlen(mschap_challenge) == 8)
231                 memcpy(challenge, mschap_challenge, 8);
232         else
233 #endif
234                 magic_random_bytes(challenge, 8);
235 }
236
237 static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) {
238         LWIP_UNUSED_ARG(pcb);
239
240         *challenge++ = 16;
241 #ifdef DEBUGMPPEKEY
242         if (mschap_challenge && strlen(mschap_challenge) == 16)
243                 memcpy(challenge, mschap_challenge, 16);
244         else
245 #endif
246                 magic_random_bytes(challenge, 16);
247 }
248
249 static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name,
250                        const unsigned char *secret, int secret_len,
251                        const unsigned char *challenge, const unsigned char *response,
252                        char *message, int message_space) {
253         unsigned char md[MS_CHAP_RESPONSE_LEN];
254         int diff;
255         int challenge_len, response_len;
256         LWIP_UNUSED_ARG(id);
257         LWIP_UNUSED_ARG(name);
258
259         challenge_len = *challenge++;   /* skip length, is 8 */
260         response_len = *response++;
261         if (response_len != MS_CHAP_RESPONSE_LEN)
262                 goto bad;
263
264 #ifndef MSLANMAN
265         if (!response[MS_CHAP_USENT]) {
266                 /* Should really propagate this into the error packet. */
267                 ppp_notice("Peer request for LANMAN auth not supported");
268                 goto bad;
269         }
270 #endif
271
272         /* Generate the expected response. */
273         ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md);
274
275 #ifdef MSLANMAN
276         /* Determine which part of response to verify against */
277         if (!response[MS_CHAP_USENT])
278                 diff = memcmp(&response[MS_CHAP_LANMANRESP],
279                               &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN);
280         else
281 #endif
282                 diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP],
283                               MS_CHAP_NTRESP_LEN);
284
285         if (diff == 0) {
286                 ppp_slprintf(message, message_space, "Access granted");
287                 return 1;
288         }
289
290  bad:
291         /* See comments below for MS-CHAP V2 */
292         ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0",
293                  challenge_len, challenge);
294         return 0;
295 }
296
297 static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name,
298                         const unsigned char *secret, int secret_len,
299                         const unsigned char *challenge, const unsigned char *response,
300                         char *message, int message_space) {
301         unsigned char md[MS_CHAP2_RESPONSE_LEN];
302         char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
303         int challenge_len, response_len;
304         LWIP_UNUSED_ARG(id);
305
306         challenge_len = *challenge++;   /* skip length, is 16 */
307         response_len = *response++;
308         if (response_len != MS_CHAP2_RESPONSE_LEN)
309                 goto bad;       /* not even the right length */
310
311         /* Generate the expected response and our mutual auth. */
312         ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name,
313                 (const char *)secret, secret_len, md,
314                 (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
315
316         /* compare MDs and send the appropriate status */
317         /*
318          * Per RFC 2759, success message must be formatted as
319          *     "S=<auth_string> M=<message>"
320          * where
321          *     <auth_string> is the Authenticator Response (mutual auth)
322          *     <message> is a text message
323          *
324          * However, some versions of Windows (win98 tested) do not know
325          * about the M=<message> part (required per RFC 2759) and flag
326          * it as an error (reported incorrectly as an encryption error
327          * to the user).  Since the RFC requires it, and it can be
328          * useful information, we supply it if the peer is a conforming
329          * system.  Luckily (?), win98 sets the Flags field to 0x04
330          * (contrary to RFC requirements) so we can use that to
331          * distinguish between conforming and non-conforming systems.
332          *
333          * Special thanks to Alex Swiridov <say@real.kharkov.ua> for
334          * help debugging this.
335          */
336         if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP],
337                    MS_CHAP2_NTRESP_LEN) == 0) {
338                 if (response[MS_CHAP2_FLAGS])
339                         ppp_slprintf(message, message_space, "S=%s", saresponse);
340                 else
341                         ppp_slprintf(message, message_space, "S=%s M=%s",
342                                  saresponse, "Access granted");
343                 return 1;
344         }
345
346  bad:
347         /*
348          * Failure message must be formatted as
349          *     "E=e R=r C=c V=v M=m"
350          * where
351          *     e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE)
352          *     r = retry (we use 1, ok to retry)
353          *     c = challenge to use for next response, we reuse previous
354          *     v = Change Password version supported, we use 0
355          *     m = text message
356          *
357          * The M=m part is only for MS-CHAPv2.  Neither win2k nor
358          * win98 (others untested) display the message to the user anyway.
359          * They also both ignore the E=e code.
360          *
361          * Note that it's safe to reuse the same challenge as we don't
362          * actually accept another response based on the error message
363          * (and no clients try to resend a response anyway).
364          *
365          * Basically, this whole bit is useless code, even the small
366          * implementation here is only because of overspecification.
367          */
368         ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s",
369                  challenge_len, challenge, "Access denied");
370         return 0;
371 }
372 #endif /* PPP_SERVER */
373
374 static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name,
375                      const unsigned char *challenge, const char *secret, int secret_len,
376                      unsigned char *private_) {
377         LWIP_UNUSED_ARG(id);
378         LWIP_UNUSED_ARG(our_name);
379         LWIP_UNUSED_ARG(private_);
380         challenge++;    /* skip length, should be 8 */
381         *response++ = MS_CHAP_RESPONSE_LEN;
382         ChapMS(pcb, challenge, secret, secret_len, response);
383 }
384
385 static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name,
386                       const unsigned char *challenge, const char *secret, int secret_len,
387                       unsigned char *private_) {
388         LWIP_UNUSED_ARG(id);
389         challenge++;    /* skip length, should be 16 */
390         *response++ = MS_CHAP2_RESPONSE_LEN;
391         ChapMS2(pcb, challenge,
392 #ifdef DEBUGMPPEKEY
393                 mschap2_peer_challenge,
394 #else
395                 NULL,
396 #endif
397                 our_name, secret, secret_len, response, private_,
398                 MS_CHAP2_AUTHENTICATEE);
399 }
400
401 static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) {
402         LWIP_UNUSED_ARG(pcb);
403
404         if ((len < MS_AUTH_RESPONSE_LENGTH + 2) ||
405             strncmp((char *)msg, "S=", 2) != 0) {
406                 /* Packet does not start with "S=" */
407                 ppp_error("MS-CHAPv2 Success packet is badly formed.");
408                 return 0;
409         }
410         msg += 2;
411         len -= 2;
412         if (len < MS_AUTH_RESPONSE_LENGTH
413             || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) {
414                 /* Authenticator Response did not match expected. */
415                 ppp_error("MS-CHAPv2 mutual authentication failed.");
416                 return 0;
417         }
418         /* Authenticator Response matches. */
419         msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */
420         len -= MS_AUTH_RESPONSE_LENGTH;
421         if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) {
422                 msg += 3; /* Eat the delimiter */
423         } else if (len) {
424                 /* Packet has extra text which does not begin " M=" */
425                 ppp_error("MS-CHAPv2 Success packet is badly formed.");
426                 return 0;
427         }
428         return 1;
429 }
430
431 static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) {
432         int err;
433         const char *p;
434         char msg[64];
435         LWIP_UNUSED_ARG(pcb);
436
437         /* We want a null-terminated string for strxxx(). */
438         len = LWIP_MIN(len, 63);
439         MEMCPY(msg, inp, len);
440         msg[len] = 0;
441         p = msg;
442
443         /*
444          * Deal with MS-CHAP formatted failure messages; just print the
445          * M=<message> part (if any).  For MS-CHAP we're not really supposed
446          * to use M=<message>, but it shouldn't hurt.  See
447          * chapms[2]_verify_response.
448          */
449         if (!strncmp(p, "E=", 2))
450                 err = strtol(p+2, NULL, 10); /* Remember the error code. */
451         else
452                 goto print_msg; /* Message is badly formatted. */
453
454         if (len && ((p = strstr(p, " M=")) != NULL)) {
455                 /* M=<message> field found. */
456                 p += 3;
457         } else {
458                 /* No M=<message>; use the error code. */
459                 switch (err) {
460                 case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS:
461                         p = "E=646 Restricted logon hours";
462                         break;
463
464                 case MS_CHAP_ERROR_ACCT_DISABLED:
465                         p = "E=647 Account disabled";
466                         break;
467
468                 case MS_CHAP_ERROR_PASSWD_EXPIRED:
469                         p = "E=648 Password expired";
470                         break;
471
472                 case MS_CHAP_ERROR_NO_DIALIN_PERMISSION:
473                         p = "E=649 No dialin permission";
474                         break;
475
476                 case MS_CHAP_ERROR_AUTHENTICATION_FAILURE:
477                         p = "E=691 Authentication failure";
478                         break;
479
480                 case MS_CHAP_ERROR_CHANGING_PASSWORD:
481                         /* Should never see this, we don't support Change Password. */
482                         p = "E=709 Error changing password";
483                         break;
484
485                 default:
486                         ppp_error("Unknown MS-CHAP authentication failure: %.*v",
487                               len, inp);
488                         return;
489                 }
490         }
491 print_msg:
492         if (p != NULL)
493                 ppp_error("MS-CHAP authentication failed: %v", p);
494 }
495
496 static void ChallengeResponse(const u_char *challenge,
497                   const u_char PasswordHash[MD4_SIGNATURE_SIZE],
498                   u_char response[24]) {
499     u_char    ZPasswordHash[21];
500     lwip_des_context des;
501     u_char des_key[8];
502
503     BZERO(ZPasswordHash, sizeof(ZPasswordHash));
504     MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE);
505
506 #if 0
507     dbglog("ChallengeResponse - ZPasswordHash %.*B",
508            sizeof(ZPasswordHash), ZPasswordHash);
509 #endif
510
511     pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key);
512     lwip_des_init(&des);
513     lwip_des_setkey_enc(&des, des_key);
514     lwip_des_crypt_ecb(&des, challenge, response +0);
515     lwip_des_free(&des);
516
517     pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key);
518     lwip_des_init(&des);
519     lwip_des_setkey_enc(&des, des_key);
520     lwip_des_crypt_ecb(&des, challenge, response +8);
521     lwip_des_free(&des);
522
523     pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key);
524     lwip_des_init(&des);
525     lwip_des_setkey_enc(&des, des_key);
526     lwip_des_crypt_ecb(&des, challenge, response +16);
527     lwip_des_free(&des);
528
529 #if 0
530     dbglog("ChallengeResponse - response %.24B", response);
531 #endif
532 }
533
534 static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge,
535               const char *username, u_char Challenge[8]) {
536     lwip_sha1_context   sha1Context;
537     u_char      sha1Hash[SHA1_SIGNATURE_SIZE];
538     const char  *user;
539
540     /* remove domain from "domain\username" */
541     if ((user = strrchr(username, '\\')) != NULL)
542         ++user;
543     else
544         user = username;
545
546     lwip_sha1_init(&sha1Context);
547     lwip_sha1_starts(&sha1Context);
548     lwip_sha1_update(&sha1Context, PeerChallenge, 16);
549     lwip_sha1_update(&sha1Context, rchallenge, 16);
550     lwip_sha1_update(&sha1Context, (const unsigned char*)user, strlen(user));
551     lwip_sha1_finish(&sha1Context, sha1Hash);
552     lwip_sha1_free(&sha1Context);
553
554     MEMCPY(Challenge, sha1Hash, 8);
555 }
556
557 /*
558  * Convert the ASCII version of the password to Unicode.
559  * This implicitly supports 8-bit ISO8859/1 characters.
560  * This gives us the little-endian representation, which
561  * is assumed by all M$ CHAP RFCs.  (Unicode byte ordering
562  * is machine-dependent.)
563  */
564 static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) {
565     int i;
566
567     BZERO(unicode, ascii_len * 2);
568     for (i = 0; i < ascii_len; i++)
569         unicode[i * 2] = (u_char) ascii[i];
570 }
571
572 static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) {
573     lwip_md4_context            md4Context;
574
575     lwip_md4_init(&md4Context);
576     lwip_md4_starts(&md4Context);
577     lwip_md4_update(&md4Context, secret, secret_len);
578     lwip_md4_finish(&md4Context, hash);
579     lwip_md4_free(&md4Context);
580 }
581
582 static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len,
583           u_char NTResponse[24]) {
584     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
585     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
586
587     /* Hash the Unicode version of the secret (== password). */
588     ascii2unicode(secret, secret_len, unicodePassword);
589     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
590
591     ChallengeResponse(rchallenge, PasswordHash, NTResponse);
592 }
593
594 static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username,
595            const char *secret, int secret_len, u_char NTResponse[24]) {
596     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
597     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
598     u_char      Challenge[8];
599
600     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
601
602     /* Hash the Unicode version of the secret (== password). */
603     ascii2unicode(secret, secret_len, unicodePassword);
604     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
605
606     ChallengeResponse(Challenge, PasswordHash, NTResponse);
607 }
608
609 #ifdef MSLANMAN
610 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
611
612 static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
613               unsigned char *response) {
614     int                 i;
615     u_char              UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
616     u_char              PasswordHash[MD4_SIGNATURE_SIZE];
617     lwip_des_context des;
618     u_char des_key[8];
619
620     /* LANMan password is case insensitive */
621     BZERO(UcasePassword, sizeof(UcasePassword));
622     for (i = 0; i < secret_len; i++)
623        UcasePassword[i] = (u_char)toupper(secret[i]);
624
625     pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key);
626     lwip_des_init(&des);
627     lwip_des_setkey_enc(&des, des_key);
628     lwip_des_crypt_ecb(&des, StdText, PasswordHash +0);
629     lwip_des_free(&des);
630
631     pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key);
632     lwip_des_init(&des);
633     lwip_des_setkey_enc(&des, des_key);
634     lwip_des_crypt_ecb(&des, StdText, PasswordHash +8);
635     lwip_des_free(&des);
636
637     ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]);
638 }
639 #endif
640
641
642 static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
643                               u_char NTResponse[24], const u_char PeerChallenge[16],
644                               const u_char *rchallenge, const char *username,
645                               u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) {
646     /*
647      * "Magic" constants used in response generation, from RFC 2759.
648      */
649     static const u_char Magic1[39] = /* "Magic server to client signing constant" */
650         { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
651           0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
652           0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
653           0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
654     static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
655         { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
656           0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
657           0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
658           0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
659           0x6E };
660
661     int         i;
662     lwip_sha1_context   sha1Context;
663     u_char      Digest[SHA1_SIGNATURE_SIZE];
664     u_char      Challenge[8];
665
666     lwip_sha1_init(&sha1Context);
667     lwip_sha1_starts(&sha1Context);
668     lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
669     lwip_sha1_update(&sha1Context, NTResponse, 24);
670     lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1));
671     lwip_sha1_finish(&sha1Context, Digest);
672     lwip_sha1_free(&sha1Context);
673
674     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
675
676     lwip_sha1_init(&sha1Context);
677     lwip_sha1_starts(&sha1Context);
678     lwip_sha1_update(&sha1Context, Digest, sizeof(Digest));
679     lwip_sha1_update(&sha1Context, Challenge, sizeof(Challenge));
680     lwip_sha1_update(&sha1Context, Magic2, sizeof(Magic2));
681     lwip_sha1_finish(&sha1Context, Digest);
682     lwip_sha1_free(&sha1Context);
683
684     /* Convert to ASCII hex string. */
685     for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++)
686         sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]);
687 }
688
689
690 static void GenerateAuthenticatorResponsePlain(
691                  const char *secret, int secret_len,
692                  u_char NTResponse[24], const u_char PeerChallenge[16],
693                  const u_char *rchallenge, const char *username,
694                  u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) {
695     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
696     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
697     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
698
699     /* Hash (x2) the Unicode version of the secret (== password). */
700     ascii2unicode(secret, secret_len, unicodePassword);
701     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
702     NTPasswordHash(PasswordHash, sizeof(PasswordHash),
703                    PasswordHashHash);
704
705     GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge,
706                                   rchallenge, username, authResponse);
707 }
708
709
710 #if MPPE_SUPPORT
711 /*
712  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
713  */
714 static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) {
715     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
716     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
717     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
718     lwip_sha1_context   sha1Context;
719     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
720
721     /* Hash (x2) the Unicode version of the secret (== password). */
722     ascii2unicode(secret, secret_len, unicodePassword);
723     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
724     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
725
726     lwip_sha1_init(&sha1Context);
727     lwip_sha1_starts(&sha1Context);
728     lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
729     lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
730     lwip_sha1_update(&sha1Context, rchallenge, 8);
731     lwip_sha1_finish(&sha1Context, Digest);
732     lwip_sha1_free(&sha1Context);
733
734     /* Same key in both directions. */
735     mppe_set_key(pcb, &pcb->mppe_comp, Digest);
736     mppe_set_key(pcb, &pcb->mppe_decomp, Digest);
737
738     pcb->mppe_keys_set = 1;
739 }
740
741 /*
742  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
743  */
744 static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) {
745     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
746     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
747     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
748     lwip_sha1_context   sha1Context;
749     u_char      MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
750     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
751     const u_char *s;
752
753     /* "This is the MPPE Master Key" */
754     static const u_char Magic1[27] =
755         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
756           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
757           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
758     /* "On the client side, this is the send key; "
759        "on the server side, it is the receive key." */
760     static const u_char Magic2[84] =
761         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
762           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
763           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
764           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
765           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
766           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
767           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
768           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
769           0x6b, 0x65, 0x79, 0x2e };
770     /* "On the client side, this is the receive key; "
771        "on the server side, it is the send key." */
772     static const u_char Magic3[84] =
773         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
774           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
775           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
776           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
777           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
778           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
779           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
780           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
781           0x6b, 0x65, 0x79, 0x2e };
782
783     /* Hash (x2) the Unicode version of the secret (== password). */
784     ascii2unicode(secret, secret_len, unicodePassword);
785     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
786     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
787
788     lwip_sha1_init(&sha1Context);
789     lwip_sha1_starts(&sha1Context);
790     lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
791     lwip_sha1_update(&sha1Context, NTResponse, 24);
792     lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1));
793     lwip_sha1_finish(&sha1Context, MasterKey);
794     lwip_sha1_free(&sha1Context);
795
796     /*
797      * generate send key
798      */
799     if (IsServer)
800         s = Magic3;
801     else
802         s = Magic2;
803     lwip_sha1_init(&sha1Context);
804     lwip_sha1_starts(&sha1Context);
805     lwip_sha1_update(&sha1Context, MasterKey, 16);
806     lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE);
807     lwip_sha1_update(&sha1Context, s, 84);
808     lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE);
809     lwip_sha1_finish(&sha1Context, Digest);
810     lwip_sha1_free(&sha1Context);
811
812     mppe_set_key(pcb, &pcb->mppe_comp, Digest);
813
814     /*
815      * generate recv key
816      */
817     if (IsServer)
818         s = Magic2;
819     else
820         s = Magic3;
821     lwip_sha1_init(&sha1Context);
822     lwip_sha1_starts(&sha1Context);
823     lwip_sha1_update(&sha1Context, MasterKey, 16);
824     lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE);
825     lwip_sha1_update(&sha1Context, s, 84);
826     lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE);
827     lwip_sha1_finish(&sha1Context, Digest);
828     lwip_sha1_free(&sha1Context);
829
830     mppe_set_key(pcb, &pcb->mppe_decomp, Digest);
831
832     pcb->mppe_keys_set = 1;
833 }
834
835 #endif /* MPPE_SUPPORT */
836
837
838 static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len,
839        unsigned char *response) {
840 #if !MPPE_SUPPORT
841     LWIP_UNUSED_ARG(pcb);
842 #endif /* !MPPE_SUPPORT */
843     BZERO(response, MS_CHAP_RESPONSE_LEN);
844
845     ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);
846
847 #ifdef MSLANMAN
848     ChapMS_LANMan(rchallenge, secret, secret_len,
849                   &response[MS_CHAP_LANMANRESP]);
850
851     /* preferred method is set by option  */
852     response[MS_CHAP_USENT] = !ms_lanman;
853 #else
854     response[MS_CHAP_USENT] = 1;
855 #endif
856
857 #if MPPE_SUPPORT
858     Set_Start_Key(pcb, rchallenge, secret, secret_len);
859 #endif /* MPPE_SUPPORT */
860 }
861
862
863 /*
864  * If PeerChallenge is NULL, one is generated and the PeerChallenge
865  * field of response is filled in.  Call this way when generating a response.
866  * If PeerChallenge is supplied, it is copied into the PeerChallenge field.
867  * Call this way when verifying a response (or debugging).
868  * Do not call with PeerChallenge = response.
869  *
870  * The PeerChallenge field of response is then used for calculation of the
871  * Authenticator Response.
872  */
873 static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge,
874         const char *user, const char *secret, int secret_len, unsigned char *response,
875         u_char authResponse[], int authenticator) {
876     /* ARGSUSED */
877     LWIP_UNUSED_ARG(authenticator);
878 #if !MPPE_SUPPORT
879     LWIP_UNUSED_ARG(pcb);
880 #endif /* !MPPE_SUPPORT */
881
882     BZERO(response, MS_CHAP2_RESPONSE_LEN);
883
884     /* Generate the Peer-Challenge if requested, or copy it if supplied. */
885     if (!PeerChallenge)
886         magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN);
887     else
888         MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge,
889               MS_CHAP2_PEER_CHAL_LEN);
890
891     /* Generate the NT-Response */
892     ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user,
893                secret, secret_len, &response[MS_CHAP2_NTRESP]);
894
895     /* Generate the Authenticator Response. */
896     GenerateAuthenticatorResponsePlain(secret, secret_len,
897                                        &response[MS_CHAP2_NTRESP],
898                                        &response[MS_CHAP2_PEER_CHALLENGE],
899                                        rchallenge, user, authResponse);
900
901 #if MPPE_SUPPORT
902     SetMasterKeys(pcb, secret, secret_len,
903                   &response[MS_CHAP2_NTRESP], authenticator);
904 #endif /* MPPE_SUPPORT */
905 }
906
907 #if 0 /* UNUSED */
908 #if MPPE_SUPPORT
909 /*
910  * Set MPPE options from plugins.
911  */
912 void set_mppe_enc_types(int policy, int types) {
913     /* Early exit for unknown policies. */
914     if (policy != MPPE_ENC_POL_ENC_ALLOWED ||
915         policy != MPPE_ENC_POL_ENC_REQUIRED)
916         return;
917
918     /* Don't modify MPPE if it's optional and wasn't already configured. */
919     if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
920         return;
921
922     /*
923      * Disable undesirable encryption types.  Note that we don't ENABLE
924      * any encryption types, to avoid overriding manual configuration.
925      */
926     switch(types) {
927         case MPPE_ENC_TYPES_RC4_40:
928             ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
929             break;
930         case MPPE_ENC_TYPES_RC4_128:
931             ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
932             break;
933         default:
934             break;
935     }
936 }
937 #endif /* MPPE_SUPPORT */
938 #endif /* UNUSED */
939
940 const struct chap_digest_type chapms_digest = {
941         CHAP_MICROSOFT,         /* code */
942 #if PPP_SERVER
943         chapms_generate_challenge,
944         chapms_verify_response,
945 #endif /* PPP_SERVER */
946         chapms_make_response,
947         NULL,                   /* check_success */
948         chapms_handle_failure,
949 };
950
951 const struct chap_digest_type chapms2_digest = {
952         CHAP_MICROSOFT_V2,      /* code */
953 #if PPP_SERVER
954         chapms2_generate_challenge,
955         chapms2_verify_response,
956 #endif /* PPP_SERVER */
957         chapms2_make_response,
958         chapms2_check_success,
959         chapms_handle_failure,
960 };
961
962 #endif /* PPP_SUPPORT && MSCHAP_SUPPORT */