1*10465441SEvalZero /*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
2*10465441SEvalZero /*** The original PPPD code is written in a way to require either the UNIX DES
3*10465441SEvalZero encryption functions encrypt(3) and setkey(3) or the DES library libdes.
4*10465441SEvalZero Since both is not included in lwIP, MSCHAP currently does not work! */
5*10465441SEvalZero /*****************************************************************************
6*10465441SEvalZero * chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
7*10465441SEvalZero *
8*10465441SEvalZero * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
9*10465441SEvalZero * Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
10*10465441SEvalZero *
11*10465441SEvalZero * The authors hereby grant permission to use, copy, modify, distribute,
12*10465441SEvalZero * and license this software and its documentation for any purpose, provided
13*10465441SEvalZero * that existing copyright notices are retained in all copies and that this
14*10465441SEvalZero * notice and the following disclaimer are included verbatim in any
15*10465441SEvalZero * distributions. No written agreement, license, or royalty fee is required
16*10465441SEvalZero * for any of the authorized uses.
17*10465441SEvalZero *
18*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
19*10465441SEvalZero * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*10465441SEvalZero * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*10465441SEvalZero * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22*10465441SEvalZero * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*10465441SEvalZero * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*10465441SEvalZero * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*10465441SEvalZero * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*10465441SEvalZero * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*10465441SEvalZero * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*10465441SEvalZero *
29*10465441SEvalZero ******************************************************************************
30*10465441SEvalZero * REVISION HISTORY
31*10465441SEvalZero *
32*10465441SEvalZero * 03-01-01 Marc Boucher <[email protected]>
33*10465441SEvalZero * Ported to lwIP.
34*10465441SEvalZero * 97-12-08 Guy Lancaster <[email protected]>, Global Election Systems Inc.
35*10465441SEvalZero * Original based on BSD chap_ms.c.
36*10465441SEvalZero *****************************************************************************/
37*10465441SEvalZero /*
38*10465441SEvalZero * chap_ms.c - Microsoft MS-CHAP compatible implementation.
39*10465441SEvalZero *
40*10465441SEvalZero * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
41*10465441SEvalZero * http://www.strataware.com/
42*10465441SEvalZero *
43*10465441SEvalZero * All rights reserved.
44*10465441SEvalZero *
45*10465441SEvalZero * Redistribution and use in source and binary forms are permitted
46*10465441SEvalZero * provided that the above copyright notice and this paragraph are
47*10465441SEvalZero * duplicated in all such forms and that any documentation,
48*10465441SEvalZero * advertising materials, and other materials related to such
49*10465441SEvalZero * distribution and use acknowledge that the software was developed
50*10465441SEvalZero * by Eric Rosenquist. The name of the author may not be used to
51*10465441SEvalZero * endorse or promote products derived from this software without
52*10465441SEvalZero * specific prior written permission.
53*10465441SEvalZero *
54*10465441SEvalZero * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
55*10465441SEvalZero * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56*10465441SEvalZero * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
57*10465441SEvalZero */
58*10465441SEvalZero
59*10465441SEvalZero /*
60*10465441SEvalZero * Modifications by Lauri Pesonen / [email protected], april 1997
61*10465441SEvalZero *
62*10465441SEvalZero * Implemented LANManager type password response to MS-CHAP challenges.
63*10465441SEvalZero * Now pppd provides both NT style and LANMan style blocks, and the
64*10465441SEvalZero * prefered is set by option "ms-lanman". Default is to use NT.
65*10465441SEvalZero * The hash text (StdText) was taken from Win95 RASAPI32.DLL.
66*10465441SEvalZero *
67*10465441SEvalZero * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
68*10465441SEvalZero */
69*10465441SEvalZero
70*10465441SEvalZero #define USE_CRYPT
71*10465441SEvalZero
72*10465441SEvalZero #include "lwip/opt.h"
73*10465441SEvalZero
74*10465441SEvalZero #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
75*10465441SEvalZero
76*10465441SEvalZero #if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
77*10465441SEvalZero
78*10465441SEvalZero #include "ppp_impl.h"
79*10465441SEvalZero #include "pppdebug.h"
80*10465441SEvalZero
81*10465441SEvalZero #include "md4.h"
82*10465441SEvalZero #ifndef USE_CRYPT
83*10465441SEvalZero #include "des.h"
84*10465441SEvalZero #endif
85*10465441SEvalZero #include "chap.h"
86*10465441SEvalZero #include "chpms.h"
87*10465441SEvalZero
88*10465441SEvalZero #include <string.h>
89*10465441SEvalZero
90*10465441SEvalZero
91*10465441SEvalZero /*************************/
92*10465441SEvalZero /*** LOCAL DEFINITIONS ***/
93*10465441SEvalZero /*************************/
94*10465441SEvalZero
95*10465441SEvalZero
96*10465441SEvalZero /************************/
97*10465441SEvalZero /*** LOCAL DATA TYPES ***/
98*10465441SEvalZero /************************/
99*10465441SEvalZero typedef struct {
100*10465441SEvalZero u_char LANManResp[24];
101*10465441SEvalZero u_char NTResp[24];
102*10465441SEvalZero u_char UseNT; /* If 1, ignore the LANMan response field */
103*10465441SEvalZero } MS_ChapResponse;
104*10465441SEvalZero /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
105*10465441SEvalZero in case this struct gets padded. */
106*10465441SEvalZero
107*10465441SEvalZero
108*10465441SEvalZero
109*10465441SEvalZero /***********************************/
110*10465441SEvalZero /*** LOCAL FUNCTION DECLARATIONS ***/
111*10465441SEvalZero /***********************************/
112*10465441SEvalZero
113*10465441SEvalZero /* XXX Don't know what to do with these. */
114*10465441SEvalZero extern void setkey(const char *);
115*10465441SEvalZero extern void encrypt(char *, int);
116*10465441SEvalZero
117*10465441SEvalZero static void DesEncrypt (u_char *, u_char *, u_char *);
118*10465441SEvalZero static void MakeKey (u_char *, u_char *);
119*10465441SEvalZero
120*10465441SEvalZero #ifdef USE_CRYPT
121*10465441SEvalZero static void Expand (u_char *, u_char *);
122*10465441SEvalZero static void Collapse (u_char *, u_char *);
123*10465441SEvalZero #endif
124*10465441SEvalZero
125*10465441SEvalZero static void ChallengeResponse(
126*10465441SEvalZero u_char *challenge, /* IN 8 octets */
127*10465441SEvalZero u_char *pwHash, /* IN 16 octets */
128*10465441SEvalZero u_char *response /* OUT 24 octets */
129*10465441SEvalZero );
130*10465441SEvalZero static void ChapMS_NT(
131*10465441SEvalZero char *rchallenge,
132*10465441SEvalZero int rchallenge_len,
133*10465441SEvalZero char *secret,
134*10465441SEvalZero int secret_len,
135*10465441SEvalZero MS_ChapResponse *response
136*10465441SEvalZero );
137*10465441SEvalZero static u_char Get7Bits(
138*10465441SEvalZero u_char *input,
139*10465441SEvalZero int startBit
140*10465441SEvalZero );
141*10465441SEvalZero
142*10465441SEvalZero static void
ChallengeResponse(u_char * challenge,u_char * pwHash,u_char * response)143*10465441SEvalZero ChallengeResponse( u_char *challenge, /* IN 8 octets */
144*10465441SEvalZero u_char *pwHash, /* IN 16 octets */
145*10465441SEvalZero u_char *response /* OUT 24 octets */)
146*10465441SEvalZero {
147*10465441SEvalZero u_char ZPasswordHash[21];
148*10465441SEvalZero
149*10465441SEvalZero BZERO(ZPasswordHash, sizeof(ZPasswordHash));
150*10465441SEvalZero BCOPY(pwHash, ZPasswordHash, 16);
151*10465441SEvalZero
152*10465441SEvalZero #if 0
153*10465441SEvalZero log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
154*10465441SEvalZero #endif
155*10465441SEvalZero
156*10465441SEvalZero DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
157*10465441SEvalZero DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
158*10465441SEvalZero DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
159*10465441SEvalZero
160*10465441SEvalZero #if 0
161*10465441SEvalZero log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
162*10465441SEvalZero #endif
163*10465441SEvalZero }
164*10465441SEvalZero
165*10465441SEvalZero
166*10465441SEvalZero #ifdef USE_CRYPT
167*10465441SEvalZero static void
DesEncrypt(u_char * clear,u_char * key,u_char * cipher)168*10465441SEvalZero DesEncrypt( u_char *clear, /* IN 8 octets */
169*10465441SEvalZero u_char *key, /* IN 7 octets */
170*10465441SEvalZero u_char *cipher /* OUT 8 octets */)
171*10465441SEvalZero {
172*10465441SEvalZero u_char des_key[8];
173*10465441SEvalZero u_char crypt_key[66];
174*10465441SEvalZero u_char des_input[66];
175*10465441SEvalZero
176*10465441SEvalZero MakeKey(key, des_key);
177*10465441SEvalZero
178*10465441SEvalZero Expand(des_key, crypt_key);
179*10465441SEvalZero setkey((char*)crypt_key);
180*10465441SEvalZero
181*10465441SEvalZero #if 0
182*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
183*10465441SEvalZero clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
184*10465441SEvalZero #endif
185*10465441SEvalZero
186*10465441SEvalZero Expand(clear, des_input);
187*10465441SEvalZero encrypt((char*)des_input, 0);
188*10465441SEvalZero Collapse(des_input, cipher);
189*10465441SEvalZero
190*10465441SEvalZero #if 0
191*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
192*10465441SEvalZero cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
193*10465441SEvalZero #endif
194*10465441SEvalZero }
195*10465441SEvalZero
196*10465441SEvalZero #else /* USE_CRYPT */
197*10465441SEvalZero
198*10465441SEvalZero static void
DesEncrypt(u_char * clear,u_char * key,u_char * cipher)199*10465441SEvalZero DesEncrypt( u_char *clear, /* IN 8 octets */
200*10465441SEvalZero u_char *key, /* IN 7 octets */
201*10465441SEvalZero u_char *cipher /* OUT 8 octets */)
202*10465441SEvalZero {
203*10465441SEvalZero des_cblock des_key;
204*10465441SEvalZero des_key_schedule key_schedule;
205*10465441SEvalZero
206*10465441SEvalZero MakeKey(key, des_key);
207*10465441SEvalZero
208*10465441SEvalZero des_set_key(&des_key, key_schedule);
209*10465441SEvalZero
210*10465441SEvalZero #if 0
211*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
212*10465441SEvalZero clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
213*10465441SEvalZero #endif
214*10465441SEvalZero
215*10465441SEvalZero des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
216*10465441SEvalZero
217*10465441SEvalZero #if 0
218*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
219*10465441SEvalZero cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
220*10465441SEvalZero #endif
221*10465441SEvalZero }
222*10465441SEvalZero
223*10465441SEvalZero #endif /* USE_CRYPT */
224*10465441SEvalZero
225*10465441SEvalZero
226*10465441SEvalZero static u_char
Get7Bits(u_char * input,int startBit)227*10465441SEvalZero Get7Bits( u_char *input, int startBit)
228*10465441SEvalZero {
229*10465441SEvalZero register unsigned int word;
230*10465441SEvalZero
231*10465441SEvalZero word = (unsigned)input[startBit / 8] << 8;
232*10465441SEvalZero word |= (unsigned)input[startBit / 8 + 1];
233*10465441SEvalZero
234*10465441SEvalZero word >>= 15 - (startBit % 8 + 7);
235*10465441SEvalZero
236*10465441SEvalZero return word & 0xFE;
237*10465441SEvalZero }
238*10465441SEvalZero
239*10465441SEvalZero #ifdef USE_CRYPT
240*10465441SEvalZero
241*10465441SEvalZero /* in == 8-byte string (expanded version of the 56-bit key)
242*10465441SEvalZero * out == 64-byte string where each byte is either 1 or 0
243*10465441SEvalZero * Note that the low-order "bit" is always ignored by by setkey()
244*10465441SEvalZero */
245*10465441SEvalZero static void
Expand(u_char * in,u_char * out)246*10465441SEvalZero Expand(u_char *in, u_char *out)
247*10465441SEvalZero {
248*10465441SEvalZero int j, c;
249*10465441SEvalZero int i;
250*10465441SEvalZero
251*10465441SEvalZero for(i = 0; i < 64; in++){
252*10465441SEvalZero c = *in;
253*10465441SEvalZero for(j = 7; j >= 0; j--) {
254*10465441SEvalZero *out++ = (c >> j) & 01;
255*10465441SEvalZero }
256*10465441SEvalZero i += 8;
257*10465441SEvalZero }
258*10465441SEvalZero }
259*10465441SEvalZero
260*10465441SEvalZero /* The inverse of Expand
261*10465441SEvalZero */
262*10465441SEvalZero static void
Collapse(u_char * in,u_char * out)263*10465441SEvalZero Collapse(u_char *in, u_char *out)
264*10465441SEvalZero {
265*10465441SEvalZero int j;
266*10465441SEvalZero int i;
267*10465441SEvalZero unsigned int c;
268*10465441SEvalZero
269*10465441SEvalZero for (i = 0; i < 64; i += 8, out++) {
270*10465441SEvalZero c = 0;
271*10465441SEvalZero for (j = 7; j >= 0; j--, in++) {
272*10465441SEvalZero c |= *in << j;
273*10465441SEvalZero }
274*10465441SEvalZero *out = c & 0xff;
275*10465441SEvalZero }
276*10465441SEvalZero }
277*10465441SEvalZero #endif
278*10465441SEvalZero
279*10465441SEvalZero static void
MakeKey(u_char * key,u_char * des_key)280*10465441SEvalZero MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */
281*10465441SEvalZero u_char *des_key /* OUT 64 bit DES key with parity bits added */)
282*10465441SEvalZero {
283*10465441SEvalZero des_key[0] = Get7Bits(key, 0);
284*10465441SEvalZero des_key[1] = Get7Bits(key, 7);
285*10465441SEvalZero des_key[2] = Get7Bits(key, 14);
286*10465441SEvalZero des_key[3] = Get7Bits(key, 21);
287*10465441SEvalZero des_key[4] = Get7Bits(key, 28);
288*10465441SEvalZero des_key[5] = Get7Bits(key, 35);
289*10465441SEvalZero des_key[6] = Get7Bits(key, 42);
290*10465441SEvalZero des_key[7] = Get7Bits(key, 49);
291*10465441SEvalZero
292*10465441SEvalZero #ifndef USE_CRYPT
293*10465441SEvalZero des_set_odd_parity((des_cblock *)des_key);
294*10465441SEvalZero #endif
295*10465441SEvalZero
296*10465441SEvalZero #if 0
297*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
298*10465441SEvalZero key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
299*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
300*10465441SEvalZero des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
301*10465441SEvalZero #endif
302*10465441SEvalZero }
303*10465441SEvalZero
304*10465441SEvalZero static void
ChapMS_NT(char * rchallenge,int rchallenge_len,char * secret,int secret_len,MS_ChapResponse * response)305*10465441SEvalZero ChapMS_NT( char *rchallenge,
306*10465441SEvalZero int rchallenge_len,
307*10465441SEvalZero char *secret,
308*10465441SEvalZero int secret_len,
309*10465441SEvalZero MS_ChapResponse *response)
310*10465441SEvalZero {
311*10465441SEvalZero int i;
312*10465441SEvalZero MDstruct md4Context;
313*10465441SEvalZero u_char unicodePassword[MAX_NT_PASSWORD * 2];
314*10465441SEvalZero static int low_byte_first = -1;
315*10465441SEvalZero
316*10465441SEvalZero LWIP_UNUSED_ARG(rchallenge_len);
317*10465441SEvalZero
318*10465441SEvalZero /* Initialize the Unicode version of the secret (== password). */
319*10465441SEvalZero /* This implicitly supports 8-bit ISO8859/1 characters. */
320*10465441SEvalZero BZERO(unicodePassword, sizeof(unicodePassword));
321*10465441SEvalZero for (i = 0; i < secret_len; i++) {
322*10465441SEvalZero unicodePassword[i * 2] = (u_char)secret[i];
323*10465441SEvalZero }
324*10465441SEvalZero MDbegin(&md4Context);
325*10465441SEvalZero MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
326*10465441SEvalZero
327*10465441SEvalZero if (low_byte_first == -1) {
328*10465441SEvalZero low_byte_first = (PP_HTONS((unsigned short int)1) != 1);
329*10465441SEvalZero }
330*10465441SEvalZero if (low_byte_first == 0) {
331*10465441SEvalZero /* @todo: arg type - u_long* or u_int* ? */
332*10465441SEvalZero MDreverse((unsigned int*)&md4Context); /* sfb 961105 */
333*10465441SEvalZero }
334*10465441SEvalZero
335*10465441SEvalZero MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
336*10465441SEvalZero
337*10465441SEvalZero ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp);
338*10465441SEvalZero }
339*10465441SEvalZero
340*10465441SEvalZero #ifdef MSLANMAN
341*10465441SEvalZero static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
342*10465441SEvalZero
343*10465441SEvalZero static void
ChapMS_LANMan(char * rchallenge,int rchallenge_len,char * secret,int secret_len,MS_ChapResponse * response)344*10465441SEvalZero ChapMS_LANMan( char *rchallenge,
345*10465441SEvalZero int rchallenge_len,
346*10465441SEvalZero char *secret,
347*10465441SEvalZero int secret_len,
348*10465441SEvalZero MS_ChapResponse *response)
349*10465441SEvalZero {
350*10465441SEvalZero int i;
351*10465441SEvalZero u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
352*10465441SEvalZero u_char PasswordHash[16];
353*10465441SEvalZero
354*10465441SEvalZero /* LANMan password is case insensitive */
355*10465441SEvalZero BZERO(UcasePassword, sizeof(UcasePassword));
356*10465441SEvalZero for (i = 0; i < secret_len; i++) {
357*10465441SEvalZero UcasePassword[i] = (u_char)toupper(secret[i]);
358*10465441SEvalZero }
359*10465441SEvalZero DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
360*10465441SEvalZero DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
361*10465441SEvalZero ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
362*10465441SEvalZero }
363*10465441SEvalZero #endif
364*10465441SEvalZero
365*10465441SEvalZero void
ChapMS(chap_state * cstate,char * rchallenge,int rchallenge_len,char * secret,int secret_len)366*10465441SEvalZero ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
367*10465441SEvalZero {
368*10465441SEvalZero MS_ChapResponse response;
369*10465441SEvalZero #ifdef MSLANMAN
370*10465441SEvalZero extern int ms_lanman;
371*10465441SEvalZero #endif
372*10465441SEvalZero
373*10465441SEvalZero #if 0
374*10465441SEvalZero CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret));
375*10465441SEvalZero #endif
376*10465441SEvalZero BZERO(&response, sizeof(response));
377*10465441SEvalZero
378*10465441SEvalZero /* Calculate both always */
379*10465441SEvalZero ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
380*10465441SEvalZero
381*10465441SEvalZero #ifdef MSLANMAN
382*10465441SEvalZero ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
383*10465441SEvalZero
384*10465441SEvalZero /* prefered method is set by option */
385*10465441SEvalZero response.UseNT = !ms_lanman;
386*10465441SEvalZero #else
387*10465441SEvalZero response.UseNT = 1;
388*10465441SEvalZero #endif
389*10465441SEvalZero
390*10465441SEvalZero BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
391*10465441SEvalZero cstate->resp_length = MS_CHAP_RESPONSE_LEN;
392*10465441SEvalZero }
393*10465441SEvalZero
394*10465441SEvalZero #endif /* MSCHAP_SUPPORT */
395*10465441SEvalZero
396*10465441SEvalZero #endif /* PPP_SUPPORT */
397