2 * chap_ms.c - Microsoft MS-CHAP compatible implementation.
4 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
5 * http://www.strataware.com/
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.
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.
24 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
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.
31 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
35 * Modifications by Frank Cusack, frank@google.com, March 2002.
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.
43 #define RCSID "$Id: chap_ms.c,v 1.19 2002/04/02 13:54:59 dfs Exp $"
51 #include <sys/types.h>
68 static const char rcsid[] = RCSID;
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,
81 static void GenerateAuthenticatorResponse __P((char*, int, u_char[24],
85 static void ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *));
89 static void Expand __P((u_char *, u_char *));
90 static void Collapse __P((u_char *, u_char *));
94 static void Set_Start_Key __P((u_char *, char *, int));
95 static void SetMasterKeys __P((char *, int, u_char[24], int));
98 extern double drand48 __P((void));
101 bool ms_lanman = 0; /* Use LanMan password instead of NT */
102 /* Has meaning only with MS-CHAP challenges */
106 u_char mppe_send_key[MPPE_MAX_KEY_LEN];
107 u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
111 ChallengeResponse(u_char *challenge,
112 u_char PasswordHash[MD4_SIGNATURE_SIZE],
115 char ZPasswordHash[21];
117 BZERO(ZPasswordHash, sizeof(ZPasswordHash));
118 BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
121 dbglog("ChallengeResponse - ZPasswordHash %.*B",
122 sizeof(ZPasswordHash), ZPasswordHash);
125 DesEncrypt(challenge, ZPasswordHash + 0, &response[0]);
126 DesEncrypt(challenge, ZPasswordHash + 7, &response[8]);
127 DesEncrypt(challenge, ZPasswordHash + 14, &response[16]);
130 dbglog("ChallengeResponse - response %.24B", response);
137 DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
140 u_char crypt_key[66];
141 u_char des_input[66];
143 MakeKey(key, des_key);
145 Expand(des_key, crypt_key);
149 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
152 Expand(clear, des_input);
153 encrypt(des_input, 0);
154 Collapse(des_input, cipher);
157 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
161 #else /* USE_CRYPT */
164 DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
167 des_key_schedule key_schedule;
169 MakeKey(key, des_key);
171 des_set_key(&des_key, key_schedule);
174 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
177 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
180 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
184 #endif /* USE_CRYPT */
187 static u_char Get7Bits(u_char *input, int startBit)
189 register unsigned int word;
191 word = (unsigned)input[startBit / 8] << 8;
192 word |= (unsigned)input[startBit / 8 + 1];
194 word >>= 15 - (startBit % 8 + 7);
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()
205 static void Expand(u_char *in, u_char *out)
210 for(i = 0; i < 64; in++){
212 for(j = 7; j >= 0; j--)
213 *out++ = (c >> j) & 01;
218 /* The inverse of Expand
220 static void Collapse(u_char *in, u_char *out)
226 for (i = 0; i < 64; i += 8, out++) {
228 for (j = 7; j >= 0; j--, in++)
235 static void MakeKey(u_char *key, u_char *des_key)
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);
247 des_set_odd_parity((des_cblock *)des_key);
251 CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
252 CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
258 ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge,
259 char *username, u_char Challenge[8])
262 SHA1_CTX sha1Context;
263 u_char sha1Hash[SHA1_SIGNATURE_SIZE];
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);
271 BCOPY(sha1Hash, Challenge, 8);
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.)
282 ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
286 BZERO(unicode, ascii_len * 2);
287 for (i = 0; i < ascii_len; i++)
288 unicode[i * 2] = (u_char) ascii[i];
292 NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
295 /* NetBSD uses the libc md4 routines which take bytes instead of bits */
296 int mdlen = secret_len;
298 int mdlen = secret_len * 8;
302 MD4Init(&md4Context);
303 MD4Update(&md4Context, secret, mdlen);
304 MD4Final(hash, &md4Context);
309 ChapMS_NT(u_char *rchallenge, char *secret, int secret_len,
310 u_char NTResponse[24])
312 u_char unicodePassword[MAX_NT_PASSWORD * 2];
313 u_char PasswordHash[MD4_SIGNATURE_SIZE];
315 /* Hash the Unicode version of the secret (== password). */
316 ascii2unicode(secret, secret_len, unicodePassword);
317 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
319 ChallengeResponse(rchallenge, PasswordHash, NTResponse);
323 ChapMS2_NT(char *rchallenge, u_char PeerChallenge[16], char *username,
324 char *secret, int secret_len, u_char NTResponse[24])
326 u_char unicodePassword[MAX_NT_PASSWORD * 2];
327 u_char PasswordHash[MD4_SIGNATURE_SIZE];
330 ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
332 /* Hash the Unicode version of the secret (== password). */
333 ascii2unicode(secret, secret_len, unicodePassword);
334 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
336 ChallengeResponse(Challenge, PasswordHash, NTResponse);
340 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
343 ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
344 u_char LMResponse[24])
347 u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
348 u_char PasswordHash[MD4_SIGNATURE_SIZE];
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);
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])
368 * "Magic" constants used in response generation, from RFC 2759.
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,
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];
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);
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);
401 ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
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);
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]);
417 * Set mppe_xxxx_key from the NTPasswordHashHash.
418 * RFC 2548 (RADIUS support) requires us to export this function (ugh).
421 mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
423 SHA1_CTX sha1Context;
424 u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
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);
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));
438 * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
441 Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
443 u_char unicodePassword[MAX_NT_PASSWORD * 2];
444 u_char PasswordHash[MD4_SIGNATURE_SIZE];
445 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
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);
452 mppe_set_keys(rchallenge, PasswordHashHash);
456 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
459 SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
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 */
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 };
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 };
479 /* "This is the MPPE Master Key" */
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." */
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." */
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 };
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);
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);
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);
535 BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
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);
551 BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
558 ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
559 MS_ChapResponse *response)
562 CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
564 BZERO(response, sizeof(*response));
566 /* Calculate both always */
567 ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
570 ChapMS_LANMan(rchallenge, secret, secret_len, response);
572 /* prefered method is set by option */
573 response->UseNT[0] = !ms_lanman;
575 response->UseNT[0] = 1;
579 Set_Start_Key(rchallenge, secret, secret_len);
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.
591 * response->PeerChallenge is then used for calculation of the
592 * Authenticator Response.
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)
600 u_char *p = response->PeerChallenge;
603 BZERO(response, sizeof(*response));
605 /* Generate the Peer-Challenge if requested, or copy it if supplied. */
607 for (i = 0; i < sizeof(response->PeerChallenge); i++)
608 *p++ = (u_char) (drand48() * 0xff);
610 BCOPY(PeerChallenge, response->PeerChallenge,
611 sizeof(response->PeerChallenge));
613 /* Generate the NT-Response */
614 ChapMS2_NT(rchallenge, response->PeerChallenge, user,
615 secret, secret_len, response->NTResp);
617 /* Generate the Authenticator Response. */
618 GenerateAuthenticatorResponse(secret, secret_len, response->NTResp,
619 response->PeerChallenge, rchallenge,
622 SetMasterKeys(secret, secret_len, response->NTResp, authenticator);