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.20 2002/04/02 14:15:07 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];
266 /* remove domain from "domain\username" */
267 if ((user = strrchr(username, '\\')) != NULL)
272 SHA1_Init(&sha1Context);
273 SHA1_Update(&sha1Context, PeerChallenge, 16);
274 SHA1_Update(&sha1Context, rchallenge, 16);
275 SHA1_Update(&sha1Context, user, strlen(user));
276 SHA1_Final(sha1Hash, &sha1Context);
278 BCOPY(sha1Hash, Challenge, 8);
282 * Convert the ASCII version of the password to Unicode.
283 * This implicitly supports 8-bit ISO8859/1 characters.
284 * This gives us the little-endian representation, which
285 * is assumed by all M$ CHAP RFCs. (Unicode byte ordering
286 * is machine-dependent.)
289 ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
293 BZERO(unicode, ascii_len * 2);
294 for (i = 0; i < ascii_len; i++)
295 unicode[i * 2] = (u_char) ascii[i];
299 NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
302 /* NetBSD uses the libc md4 routines which take bytes instead of bits */
303 int mdlen = secret_len;
305 int mdlen = secret_len * 8;
309 MD4Init(&md4Context);
310 MD4Update(&md4Context, secret, mdlen);
311 MD4Final(hash, &md4Context);
316 ChapMS_NT(u_char *rchallenge, char *secret, int secret_len,
317 u_char NTResponse[24])
319 u_char unicodePassword[MAX_NT_PASSWORD * 2];
320 u_char PasswordHash[MD4_SIGNATURE_SIZE];
322 /* Hash the Unicode version of the secret (== password). */
323 ascii2unicode(secret, secret_len, unicodePassword);
324 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
326 ChallengeResponse(rchallenge, PasswordHash, NTResponse);
330 ChapMS2_NT(char *rchallenge, u_char PeerChallenge[16], char *username,
331 char *secret, int secret_len, u_char NTResponse[24])
333 u_char unicodePassword[MAX_NT_PASSWORD * 2];
334 u_char PasswordHash[MD4_SIGNATURE_SIZE];
337 ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
339 /* Hash the Unicode version of the secret (== password). */
340 ascii2unicode(secret, secret_len, unicodePassword);
341 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
343 ChallengeResponse(Challenge, PasswordHash, NTResponse);
347 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
350 ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
351 u_char LMResponse[24])
354 u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
355 u_char PasswordHash[MD4_SIGNATURE_SIZE];
357 /* LANMan password is case insensitive */
358 BZERO(UcasePassword, sizeof(UcasePassword));
359 for (i = 0; i < secret_len; i++)
360 UcasePassword[i] = (u_char)toupper(secret[i]);
361 DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
362 DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
363 ChallengeResponse(rchallenge, PasswordHash, LMResponse);
369 GenerateAuthenticatorResponse(char *secret, int secret_len,
370 u_char NTResponse[24], u_char PeerChallenge[16],
371 u_char *rchallenge, char *username,
372 u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
375 * "Magic" constants used in response generation, from RFC 2759.
377 u_char Magic1[39] = /* "Magic server to client signing constant" */
378 { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
379 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
380 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
381 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
382 u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
383 { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
384 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
385 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
386 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
390 SHA1_CTX sha1Context;
391 u_char unicodePassword[MAX_NT_PASSWORD * 2];
392 u_char PasswordHash[MD4_SIGNATURE_SIZE];
393 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
394 u_char Digest[SHA1_SIGNATURE_SIZE];
397 /* Hash (x2) the Unicode version of the secret (== password). */
398 ascii2unicode(secret, secret_len, unicodePassword);
399 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
400 NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
402 SHA1_Init(&sha1Context);
403 SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash));
404 SHA1_Update(&sha1Context, NTResponse, 24);
405 SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
406 SHA1_Final(Digest, &sha1Context);
408 ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
410 SHA1_Init(&sha1Context);
411 SHA1_Update(&sha1Context, Digest, sizeof(Digest));
412 SHA1_Update(&sha1Context, Challenge, sizeof(Challenge));
413 SHA1_Update(&sha1Context, Magic2, sizeof(Magic2));
414 SHA1_Final(Digest, &sha1Context);
416 /* Convert to ASCII hex string. */
417 for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++)
418 sprintf(&authResponse[i * 2], "%02X", Digest[i]);
424 * Set mppe_xxxx_key from the NTPasswordHashHash.
425 * RFC 2548 (RADIUS support) requires us to export this function (ugh).
428 mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
430 SHA1_CTX sha1Context;
431 u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
433 SHA1_Init(&sha1Context);
434 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
435 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
436 SHA1_Update(&sha1Context, rchallenge, 8);
437 SHA1_Final(Digest, &sha1Context);
439 /* Same key in both directions. */
440 BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
441 BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
445 * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
448 Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
450 u_char unicodePassword[MAX_NT_PASSWORD * 2];
451 u_char PasswordHash[MD4_SIGNATURE_SIZE];
452 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
454 /* Hash (x2) the Unicode version of the secret (== password). */
455 ascii2unicode(secret, secret_len, unicodePassword);
456 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
457 NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
459 mppe_set_keys(rchallenge, PasswordHashHash);
463 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
466 SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
468 SHA1_CTX sha1Context;
469 u_char unicodePassword[MAX_NT_PASSWORD * 2];
470 u_char PasswordHash[MD4_SIGNATURE_SIZE];
471 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
472 u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
473 u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
476 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
481 { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
482 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
483 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
484 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
486 /* "This is the MPPE Master Key" */
488 { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
489 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
490 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
491 /* "On the client side, this is the send key; "
492 "on the server side, it is the receive key." */
494 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
495 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
496 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
497 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
498 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
499 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
500 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
501 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
502 0x6b, 0x65, 0x79, 0x2e };
503 /* "On the client side, this is the receive key; "
504 "on the server side, it is the send key." */
506 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
507 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
508 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
509 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
510 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
511 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
512 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
513 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
514 0x6b, 0x65, 0x79, 0x2e };
517 /* Hash (x2) the Unicode version of the secret (== password). */
518 ascii2unicode(secret, secret_len, unicodePassword);
519 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
520 NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
522 SHA1_Init(&sha1Context);
523 SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash));
524 SHA1_Update(&sha1Context, NTResponse, 24);
525 SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
526 SHA1_Final(MasterKey, &sha1Context);
535 SHA1_Init(&sha1Context);
536 SHA1_Update(&sha1Context, MasterKey, 16);
537 SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
538 SHA1_Update(&sha1Context, s, 84);
539 SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
540 SHA1_Final(Digest, &sha1Context);
542 BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
551 SHA1_Init(&sha1Context);
552 SHA1_Update(&sha1Context, MasterKey, 16);
553 SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
554 SHA1_Update(&sha1Context, s, 84);
555 SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
556 SHA1_Final(Digest, &sha1Context);
558 BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
565 ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
566 MS_ChapResponse *response)
569 CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
571 BZERO(response, sizeof(*response));
573 /* Calculate both always */
574 ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
577 ChapMS_LANMan(rchallenge, secret, secret_len, response);
579 /* prefered method is set by option */
580 response->UseNT[0] = !ms_lanman;
582 response->UseNT[0] = 1;
586 Set_Start_Key(rchallenge, secret, secret_len);
592 * If PeerChallenge is NULL, one is generated and response->PeerChallenge
593 * is filled in. Call this way when generating a response.
594 * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
595 * Call this way when verifying a response (or debugging).
596 * Do not call with PeerChallenge = response->PeerChallenge.
598 * response->PeerChallenge is then used for calculation of the
599 * Authenticator Response.
602 ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge,
603 char *user, char *secret, int secret_len, MS_Chap2Response *response,
604 u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1], int authenticator)
607 u_char *p = response->PeerChallenge;
610 BZERO(response, sizeof(*response));
612 /* Generate the Peer-Challenge if requested, or copy it if supplied. */
614 for (i = 0; i < sizeof(response->PeerChallenge); i++)
615 *p++ = (u_char) (drand48() * 0xff);
617 BCOPY(PeerChallenge, response->PeerChallenge,
618 sizeof(response->PeerChallenge));
620 /* Generate the NT-Response */
621 ChapMS2_NT(rchallenge, response->PeerChallenge, user,
622 secret, secret_len, response->NTResp);
624 /* Generate the Authenticator Response. */
625 GenerateAuthenticatorResponse(secret, secret_len, response->NTResp,
626 response->PeerChallenge, rchallenge,
629 SetMasterKeys(secret, secret_len, response->NTResp, authenticator);