]> git.ozlabs.org Git - ppp.git/blob - pppd/chap_ms.c
First large MPPE patch from Frank Cusack.
[ppp.git] / pppd / chap_ms.c
1 /*
2  * chap_ms.c - Microsoft MS-CHAP compatible implementation.
3  *
4  * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
5  * http://www.strataware.com/
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that the above copyright notice and this paragraph are
11  * duplicated in all such forms and that any documentation,
12  * advertising materials, and other materials related to such
13  * distribution and use acknowledge that the software was developed
14  * by Eric Rosenquist.  The name of the author may not be used to
15  * endorse or promote products derived from this software without
16  * specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22
23 /*
24  * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
25  *
26  *   Implemented LANManager type password response to MS-CHAP challenges.
27  *   Now pppd provides both NT style and LANMan style blocks, and the
28  *   prefered is set by option "ms-lanman". Default is to use NT.
29  *   The hash text (StdText) was taken from Win95 RASAPI32.DLL.
30  *
31  *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
32  */
33
34 /*
35  * Modifications by Frank Cusack, frank@google.com, March 2002.
36  *
37  *   Implemented MS-CHAPv2 functionality, heavily based on sample
38  *   implementation in RFC 2759.  Implemented MPPE functionality,
39  *   heavily based on sample implementation in RFC 3079.
40  *   Copyright (c) 2002 Google, Inc.
41  */
42
43 #define RCSID   "$Id: chap_ms.c,v 1.19 2002/04/02 13:54:59 dfs Exp $"
44
45 #ifdef CHAPMS
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/time.h>
53 #include <unistd.h>
54 #ifdef HAVE_CRYPT_H
55 #include <crypt.h>
56 #endif
57
58 #include "pppd.h"
59 #include "chap.h"
60 #include "chap_ms.h"
61 #include "md4.h"
62 #include "sha1.h"
63
64 #ifndef USE_CRYPT
65 #include <des.h>
66 #endif
67
68 static const char rcsid[] = RCSID;
69
70
71 static void     ChallengeHash __P((u_char[16], u_char *, char *, u_char[8]));
72 static void     ascii2unicode __P((char[], int, u_char[]));
73 static void     NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE]));
74 static void     ChallengeResponse __P((u_char *, u_char *, u_char[24]));
75 static void     DesEncrypt __P((u_char *, u_char *, u_char[8]));
76 static void     MakeKey __P((u_char *, u_char *));
77 static u_char   Get7Bits __P((u_char *, int));
78 static void     ChapMS_NT __P((u_char *, char *, int, u_char[24]));
79 static void     ChapMS2_NT __P((char *, u_char[16], char *, char *, int,
80                                 u_char[24]));
81 static void     GenerateAuthenticatorResponse __P((char*, int, u_char[24],
82                                                    u_char[16], u_char *,
83                                                    char *, u_char[41]));
84 #ifdef MSLANMAN
85 static void     ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *));
86 #endif
87
88 #ifdef USE_CRYPT
89 static void     Expand __P((u_char *, u_char *));
90 static void     Collapse __P((u_char *, u_char *));
91 #endif
92
93 #ifdef MPPE
94 static void     Set_Start_Key __P((u_char *, char *, int));
95 static void     SetMasterKeys __P((char *, int, u_char[24], int));
96 #endif
97
98 extern double drand48 __P((void));
99
100 #ifdef MSLANMAN
101 bool    ms_lanman = 0;          /* Use LanMan password instead of NT */
102                                 /* Has meaning only with MS-CHAP challenges */
103 #endif
104
105 #ifdef MPPE
106 u_char mppe_send_key[MPPE_MAX_KEY_LEN];
107 u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
108 #endif
109
110 static void
111 ChallengeResponse(u_char *challenge,
112                   u_char PasswordHash[MD4_SIGNATURE_SIZE],
113                   u_char response[24])
114 {
115     char    ZPasswordHash[21];
116
117     BZERO(ZPasswordHash, sizeof(ZPasswordHash));
118     BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
119
120 #if 0
121     dbglog("ChallengeResponse - ZPasswordHash %.*B",
122            sizeof(ZPasswordHash), ZPasswordHash);
123 #endif
124
125     DesEncrypt(challenge, ZPasswordHash +  0, &response[0]);
126     DesEncrypt(challenge, ZPasswordHash +  7, &response[8]);
127     DesEncrypt(challenge, ZPasswordHash + 14, &response[16]);
128
129 #if 0
130     dbglog("ChallengeResponse - response %.24B", response);
131 #endif
132 }
133
134
135 #ifdef USE_CRYPT
136 static void
137 DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
138 {
139     u_char des_key[8];
140     u_char crypt_key[66];
141     u_char des_input[66];
142
143     MakeKey(key, des_key);
144
145     Expand(des_key, crypt_key);
146     setkey(crypt_key);
147
148 #if 0
149     CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
150 #endif
151
152     Expand(clear, des_input);
153     encrypt(des_input, 0);
154     Collapse(des_input, cipher);
155
156 #if 0
157     CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
158 #endif
159 }
160
161 #else /* USE_CRYPT */
162
163 static void
164 DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
165 {
166     des_cblock          des_key;
167     des_key_schedule    key_schedule;
168
169     MakeKey(key, des_key);
170
171     des_set_key(&des_key, key_schedule);
172
173 #if 0
174     CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
175 #endif
176
177     des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
178
179 #if 0
180     CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
181 #endif
182 }
183
184 #endif /* USE_CRYPT */
185
186
187 static u_char Get7Bits(u_char *input, int startBit)
188 {
189     register unsigned int       word;
190
191     word  = (unsigned)input[startBit / 8] << 8;
192     word |= (unsigned)input[startBit / 8 + 1];
193
194     word >>= 15 - (startBit % 8 + 7);
195
196     return word & 0xFE;
197 }
198
199 #ifdef USE_CRYPT
200
201 /* in == 8-byte string (expanded version of the 56-bit key)
202  * out == 64-byte string where each byte is either 1 or 0
203  * Note that the low-order "bit" is always ignored by by setkey()
204  */
205 static void Expand(u_char *in, u_char *out)
206 {
207         int j, c;
208         int i;
209
210         for(i = 0; i < 64; in++){
211                 c = *in;
212                 for(j = 7; j >= 0; j--)
213                         *out++ = (c >> j) & 01;
214                 i += 8;
215         }
216 }
217
218 /* The inverse of Expand
219  */
220 static void Collapse(u_char *in, u_char *out)
221 {
222         int j;
223         int i;
224         unsigned int c;
225
226         for (i = 0; i < 64; i += 8, out++) {
227             c = 0;
228             for (j = 7; j >= 0; j--, in++)
229                 c |= *in << j;
230             *out = c & 0xff;
231         }
232 }
233 #endif
234
235 static void MakeKey(u_char *key, u_char *des_key)
236 {
237     des_key[0] = Get7Bits(key,  0);
238     des_key[1] = Get7Bits(key,  7);
239     des_key[2] = Get7Bits(key, 14);
240     des_key[3] = Get7Bits(key, 21);
241     des_key[4] = Get7Bits(key, 28);
242     des_key[5] = Get7Bits(key, 35);
243     des_key[6] = Get7Bits(key, 42);
244     des_key[7] = Get7Bits(key, 49);
245
246 #ifndef USE_CRYPT
247     des_set_odd_parity((des_cblock *)des_key);
248 #endif
249
250 #if 0
251     CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
252     CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
253 #endif
254 }
255
256
257 static void
258 ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge,
259               char *username, u_char Challenge[8])
260     
261 {
262     SHA1_CTX    sha1Context;
263     u_char      sha1Hash[SHA1_SIGNATURE_SIZE];
264
265     SHA1_Init(&sha1Context);
266     SHA1_Update(&sha1Context, PeerChallenge, 16);
267     SHA1_Update(&sha1Context, rchallenge, 16);
268     SHA1_Update(&sha1Context, username, strlen(username));
269     SHA1_Final(sha1Hash, &sha1Context);
270
271     BCOPY(sha1Hash, Challenge, 8);
272 }
273
274 /*
275  * Convert the ASCII version of the password to Unicode.
276  * This implicitly supports 8-bit ISO8859/1 characters.
277  * This gives us the little-endian representation, which
278  * is assumed by all M$ CHAP RFCs.  (Unicode byte ordering
279  * is machine-dependent.)
280  */
281 static void
282 ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
283 {
284     int i;
285
286     BZERO(unicode, ascii_len * 2);
287     for (i = 0; i < ascii_len; i++)
288         unicode[i * 2] = (u_char) ascii[i];
289 }
290
291 static void
292 NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
293 {
294 #ifdef __NetBSD__
295     /* NetBSD uses the libc md4 routines which take bytes instead of bits */
296     int                 mdlen = secret_len;
297 #else
298     int                 mdlen = secret_len * 8;
299 #endif
300     MD4_CTX             md4Context;
301
302     MD4Init(&md4Context);
303     MD4Update(&md4Context, secret, mdlen);
304     MD4Final(hash, &md4Context);
305
306 }
307
308 static void
309 ChapMS_NT(u_char *rchallenge, char *secret, int secret_len,
310           u_char NTResponse[24])
311 {
312     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
313     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
314
315     /* Hash the Unicode version of the secret (== password). */
316     ascii2unicode(secret, secret_len, unicodePassword);
317     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
318
319     ChallengeResponse(rchallenge, PasswordHash, NTResponse);
320 }
321
322 static void
323 ChapMS2_NT(char *rchallenge, u_char PeerChallenge[16], char *username,
324            char *secret, int secret_len, u_char NTResponse[24])
325 {
326     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
327     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
328     u_char      Challenge[8];
329
330     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
331
332     /* Hash the Unicode version of the secret (== password). */
333     ascii2unicode(secret, secret_len, unicodePassword);
334     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
335
336     ChallengeResponse(Challenge, PasswordHash, NTResponse);
337 }
338
339 #ifdef MSLANMAN
340 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
341
342 static void
343 ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
344               u_char LMResponse[24])
345 {
346     int                 i;
347     u_char              UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
348     u_char              PasswordHash[MD4_SIGNATURE_SIZE];
349
350     /* LANMan password is case insensitive */
351     BZERO(UcasePassword, sizeof(UcasePassword));
352     for (i = 0; i < secret_len; i++)
353        UcasePassword[i] = (u_char)toupper(secret[i]);
354     DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
355     DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
356     ChallengeResponse(rchallenge, PasswordHash, LMResponse);
357 }
358 #endif
359
360
361 static void
362 GenerateAuthenticatorResponse(char *secret, int secret_len,
363                               u_char NTResponse[24], u_char PeerChallenge[16],
364                               u_char *rchallenge, char *username,
365                               u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
366 {
367     /*
368      * "Magic" constants used in response generation, from RFC 2759.
369      */
370     u_char Magic1[39] = /* "Magic server to client signing constant" */
371         { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
372           0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
373           0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
374           0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
375     u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
376         { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
377           0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
378           0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
379           0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
380           0x6E };
381
382     int         i;
383     SHA1_CTX    sha1Context;
384     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
385     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
386     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
387     u_char      Digest[SHA1_SIGNATURE_SIZE];
388     u_char      Challenge[8];
389
390     /* Hash (x2) the Unicode version of the secret (== password). */
391     ascii2unicode(secret, secret_len, unicodePassword);
392     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
393     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
394
395     SHA1_Init(&sha1Context);
396     SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash));
397     SHA1_Update(&sha1Context, NTResponse, 24);
398     SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
399     SHA1_Final(Digest, &sha1Context);
400
401     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
402
403     SHA1_Init(&sha1Context);
404     SHA1_Update(&sha1Context, Digest, sizeof(Digest));
405     SHA1_Update(&sha1Context, Challenge, sizeof(Challenge));
406     SHA1_Update(&sha1Context, Magic2, sizeof(Magic2));
407     SHA1_Final(Digest, &sha1Context);
408
409     /* Convert to ASCII hex string. */
410     for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++)
411         sprintf(&authResponse[i * 2], "%02X", Digest[i]);
412 }
413
414
415 #ifdef MPPE
416 /*
417  * Set mppe_xxxx_key from the NTPasswordHashHash.
418  * RFC 2548 (RADIUS support) requires us to export this function (ugh).
419  */
420 void
421 mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
422 {
423     SHA1_CTX    sha1Context;
424     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
425
426     SHA1_Init(&sha1Context);
427     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
428     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
429     SHA1_Update(&sha1Context, rchallenge, 8);
430     SHA1_Final(Digest, &sha1Context);
431
432     /* Same key in both directions. */
433     BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
434     BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
435 }
436
437 /*
438  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
439  */
440 static void
441 Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
442 {
443     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
444     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
445     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
446
447     /* Hash (x2) the Unicode version of the secret (== password). */
448     ascii2unicode(secret, secret_len, unicodePassword);
449     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
450     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
451
452     mppe_set_keys(rchallenge, PasswordHashHash);
453 }
454
455 /*
456  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
457  */
458 static void
459 SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
460 {
461     SHA1_CTX    sha1Context;
462     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
463     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
464     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
465     u_char      MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
466     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
467
468     u_char SHApad1[40] =
469         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
473     u_char SHApad2[40] =
474         { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
475           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
476           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
477           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
478
479     /* "This is the MPPE Master Key" */
480     u_char Magic1[27] =
481         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
482           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
483           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
484     /* "On the client side, this is the send key; "
485        "on the server side, it is the receive key." */
486     u_char Magic2[84] =
487         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
488           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
489           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
490           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
491           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
492           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
493           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
494           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
495           0x6b, 0x65, 0x79, 0x2e };
496     /* "On the client side, this is the receive key; "
497        "on the server side, it is the send key." */
498     u_char Magic3[84] =
499         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
500           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
501           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
502           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
503           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
504           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
505           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
506           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
507           0x6b, 0x65, 0x79, 0x2e };
508     u_char *s;
509
510     /* Hash (x2) the Unicode version of the secret (== password). */
511     ascii2unicode(secret, secret_len, unicodePassword);
512     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
513     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
514
515     SHA1_Init(&sha1Context);
516     SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash));
517     SHA1_Update(&sha1Context, NTResponse, 24);
518     SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
519     SHA1_Final(MasterKey, &sha1Context);
520
521     /*
522      * generate send key
523      */
524     if (IsServer)
525         s = Magic3;
526     else
527         s = Magic2;
528     SHA1_Init(&sha1Context);
529     SHA1_Update(&sha1Context, MasterKey, 16);
530     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
531     SHA1_Update(&sha1Context, s, 84);
532     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
533     SHA1_Final(Digest, &sha1Context);
534
535     BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
536
537     /*
538      * generate recv key
539      */
540     if (IsServer)
541         s = Magic2;
542     else
543         s = Magic3;
544     SHA1_Init(&sha1Context);
545     SHA1_Update(&sha1Context, MasterKey, 16);
546     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
547     SHA1_Update(&sha1Context, s, 84);
548     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
549     SHA1_Final(Digest, &sha1Context);
550
551     BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
552 }
553
554 #endif /* MPPE */
555
556
557 void
558 ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
559        MS_ChapResponse *response)
560 {
561 #if 0
562     CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
563 #endif
564     BZERO(response, sizeof(*response));
565
566     /* Calculate both always */
567     ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
568
569 #ifdef MSLANMAN
570     ChapMS_LANMan(rchallenge, secret, secret_len, response);
571
572     /* prefered method is set by option  */
573     response->UseNT[0] = !ms_lanman;
574 #else
575     response->UseNT[0] = 1;
576 #endif
577
578 #ifdef MPPE
579     Set_Start_Key(rchallenge, secret, secret_len);
580 #endif
581 }
582
583
584 /*
585  * If PeerChallenge is NULL, one is generated and response->PeerChallenge
586  * is filled in.  Call this way when generating a response.
587  * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
588  * Call this way when verifying a response (or debugging).
589  * Do not call with PeerChallenge = response->PeerChallenge.
590  *
591  * response->PeerChallenge is then used for calculation of the
592  * Authenticator Response.
593  */
594 void
595 ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge,
596         char *user, char *secret, int secret_len, MS_Chap2Response *response,
597         u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1], int authenticator)
598 {
599     /* ARGSUSED */
600     u_char *p = response->PeerChallenge;
601     int i;
602
603     BZERO(response, sizeof(*response));
604
605     /* Generate the Peer-Challenge if requested, or copy it if supplied. */
606     if (!PeerChallenge)
607         for (i = 0; i < sizeof(response->PeerChallenge); i++)
608             *p++ = (u_char) (drand48() * 0xff);
609     else
610         BCOPY(PeerChallenge, response->PeerChallenge,
611               sizeof(response->PeerChallenge));
612
613     /* Generate the NT-Response */
614     ChapMS2_NT(rchallenge, response->PeerChallenge, user,
615                secret, secret_len, response->NTResp);
616
617     /* Generate the Authenticator Response. */
618     GenerateAuthenticatorResponse(secret, secret_len, response->NTResp,
619                                   response->PeerChallenge, rchallenge,
620                                   user, authResponse);
621 #ifdef MPPE
622     SetMasterKeys(secret, secret_len, response->NTResp, authenticator);
623 #endif
624 }
625
626
627 #endif /* CHAPMS */