xref: /freebsd/usr.sbin/ppp/chap_ms.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1915ce3bcSBrian Somers /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4915ce3bcSBrian Somers  * Copyright (c) 1997        Gabor Kincses <gabor@acm.org>
5915ce3bcSBrian Somers  *               1997 - 2001 Brian Somers <brian@Awfulhak.org>
6915ce3bcSBrian Somers  *          based on work by Eric Rosenquist
7915ce3bcSBrian Somers  *                           Strata Software Limited.
80f8e0938SBrian Somers  * All rights reserved.
90f8e0938SBrian Somers  *
10915ce3bcSBrian Somers  * Redistribution and use in source and binary forms, with or without
11915ce3bcSBrian Somers  * modification, are permitted provided that the following conditions
12915ce3bcSBrian Somers  * are met:
13915ce3bcSBrian Somers  * 1. Redistributions of source code must retain the above copyright
14915ce3bcSBrian Somers  *    notice, this list of conditions and the following disclaimer.
15915ce3bcSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
16915ce3bcSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
17915ce3bcSBrian Somers  *    documentation and/or other materials provided with the distribution.
180f8e0938SBrian Somers  *
19915ce3bcSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20915ce3bcSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21915ce3bcSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22915ce3bcSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23915ce3bcSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24915ce3bcSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25915ce3bcSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26915ce3bcSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27915ce3bcSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28915ce3bcSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29915ce3bcSBrian Somers  * SUCH DAMAGE.
300f8e0938SBrian Somers  */
310f8e0938SBrian Somers 
325e315498SBrian Somers #include <ctype.h>
33499640f1SBrian Somers #ifdef __FreeBSD__
34512182f3SMark Murray #include <openssl/des.h>
35a8d604abSBrian Somers #include <sha.h>
361c25c5e0SBrian Somers #else
3703a2501aSBrian Somers #include <sys/types.h>
381c25c5e0SBrian Somers #include <stdlib.h>
3935bed99bSBrian Somers #ifdef __NetBSD__
4035bed99bSBrian Somers #include <openssl/des.h>
4135bed99bSBrian Somers #else
421c25c5e0SBrian Somers #include <des.h>
4335bed99bSBrian Somers #endif
441c25c5e0SBrian Somers #include <openssl/sha.h>
451c25c5e0SBrian Somers #endif
46a8d604abSBrian Somers #include <md4.h>
4775240ed1SBrian Somers #include <string.h>
4875240ed1SBrian Somers 
4975240ed1SBrian Somers #include "chap_ms.h"
500f8e0938SBrian Somers 
51a8d604abSBrian Somers /*
52a8d604abSBrian Somers  * Documentation & specifications:
53a8d604abSBrian Somers  *
54a8d604abSBrian Somers  * MS-CHAP (CHAP80)	rfc2433
55a8d604abSBrian Somers  * MS-CHAP-V2 (CHAP81)	rfc2759
56a8d604abSBrian Somers  * MPPE key management	draft-ietf-pppext-mppe-keys-02.txt
57a8d604abSBrian Somers  */
58a8d604abSBrian Somers 
59a8d604abSBrian Somers static char SHA1_Pad1[40] =
60a8d604abSBrian Somers   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61a8d604abSBrian Somers    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62a8d604abSBrian Somers    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63a8d604abSBrian Somers    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
64a8d604abSBrian Somers 
65a8d604abSBrian Somers static char SHA1_Pad2[40] =
66a8d604abSBrian Somers   {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
67a8d604abSBrian Somers    0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
68a8d604abSBrian Somers    0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
69a8d604abSBrian Somers    0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
70a8d604abSBrian Somers 
710f8e0938SBrian Somers /* unused, for documentation only */
720f8e0938SBrian Somers /* only NTResp is filled in for FreeBSD */
73a0cbd833SBrian Somers struct MS_ChapResponse {
740f8e0938SBrian Somers     u_char LANManResp[24];
750f8e0938SBrian Somers     u_char NTResp[24];
760f8e0938SBrian Somers     u_char UseNT;	/* If 1, ignore the LANMan response field */
77a0cbd833SBrian Somers };
780f8e0938SBrian Somers 
799b996792SBrian Somers static u_char
Get7Bits(u_char * input,int startBit)809b996792SBrian Somers Get7Bits(u_char *input, int startBit)
810f8e0938SBrian Somers {
820f8e0938SBrian Somers     register unsigned int	word;
830f8e0938SBrian Somers 
840f8e0938SBrian Somers     word  = (unsigned)input[startBit / 8] << 8;
850f8e0938SBrian Somers     word |= (unsigned)input[startBit / 8 + 1];
860f8e0938SBrian Somers 
870f8e0938SBrian Somers     word >>= 15 - (startBit % 8 + 7);
880f8e0938SBrian Somers 
890f8e0938SBrian Somers     return word & 0xFE;
900f8e0938SBrian Somers }
910f8e0938SBrian Somers 
920f8e0938SBrian Somers /* IN  56 bit DES key missing parity bits
930f8e0938SBrian Somers    OUT 64 bit DES key with parity bits added */
949b996792SBrian Somers static void
MakeKey(u_char * key,u_char * des_key)959b996792SBrian Somers MakeKey(u_char *key, u_char *des_key)
960f8e0938SBrian Somers {
970f8e0938SBrian Somers     des_key[0] = Get7Bits(key,  0);
980f8e0938SBrian Somers     des_key[1] = Get7Bits(key,  7);
990f8e0938SBrian Somers     des_key[2] = Get7Bits(key, 14);
1000f8e0938SBrian Somers     des_key[3] = Get7Bits(key, 21);
1010f8e0938SBrian Somers     des_key[4] = Get7Bits(key, 28);
1020f8e0938SBrian Somers     des_key[5] = Get7Bits(key, 35);
1030f8e0938SBrian Somers     des_key[6] = Get7Bits(key, 42);
1040f8e0938SBrian Somers     des_key[7] = Get7Bits(key, 49);
1050f8e0938SBrian Somers 
10616e26562SJung-uk Kim     DES_set_odd_parity((DES_cblock *)des_key);
1070f8e0938SBrian Somers }
1080f8e0938SBrian Somers 
1095e315498SBrian Somers static void /* IN 8 octets IN 7 octest OUT 8 octets */
DesEncrypt(u_char * clear,u_char * key,u_char * cipher)1105e315498SBrian Somers DesEncrypt(u_char *clear, u_char *key, u_char *cipher)
1115e315498SBrian Somers {
11216e26562SJung-uk Kim     DES_cblock		des_key;
11316e26562SJung-uk Kim     DES_key_schedule	key_schedule;
1145e315498SBrian Somers 
1155e315498SBrian Somers     MakeKey(key, des_key);
11616e26562SJung-uk Kim     DES_set_key(&des_key, &key_schedule);
11716e26562SJung-uk Kim     DES_ecb_encrypt((DES_cblock *)clear, (DES_cblock *)cipher, &key_schedule, 1);
1185e315498SBrian Somers }
1195e315498SBrian Somers 
1205e315498SBrian Somers static void      /* IN 8 octets      IN 16 octets     OUT 24 octets */
ChallengeResponse(u_char * challenge,u_char * pwHash,u_char * response)1215e315498SBrian Somers ChallengeResponse(u_char *challenge, u_char *pwHash, u_char *response)
1225e315498SBrian Somers {
1235e315498SBrian Somers     char    ZPasswordHash[21];
1245e315498SBrian Somers 
1255e315498SBrian Somers     memset(ZPasswordHash, '\0', sizeof ZPasswordHash);
1265e315498SBrian Somers     memcpy(ZPasswordHash, pwHash, 16);
1275e315498SBrian Somers 
1285e315498SBrian Somers     DesEncrypt(challenge, ZPasswordHash +  0, response + 0);
1295e315498SBrian Somers     DesEncrypt(challenge, ZPasswordHash +  7, response + 8);
1305e315498SBrian Somers     DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
1315e315498SBrian Somers }
1325e315498SBrian Somers 
133a8d604abSBrian Somers void
NtPasswordHash(char * key,int keylen,char * hash)1349b996792SBrian Somers NtPasswordHash(char *key, int keylen, char *hash)
1359b996792SBrian Somers {
136a8d604abSBrian Somers   MD4_CTX MD4context;
137a8d604abSBrian Somers 
138a8d604abSBrian Somers   MD4Init(&MD4context);
139a8d604abSBrian Somers   MD4Update(&MD4context, key, keylen);
140a8d604abSBrian Somers   MD4Final(hash, &MD4context);
141a8d604abSBrian Somers }
142a8d604abSBrian Somers 
143a8d604abSBrian Somers void
HashNtPasswordHash(char * hash,char * hashhash)1449b996792SBrian Somers HashNtPasswordHash(char *hash, char *hashhash)
1459b996792SBrian Somers {
146a8d604abSBrian Somers   MD4_CTX MD4context;
147a8d604abSBrian Somers 
148a8d604abSBrian Somers   MD4Init(&MD4context);
149a8d604abSBrian Somers   MD4Update(&MD4context, hash, 16);
150a8d604abSBrian Somers   MD4Final(hashhash, &MD4context);
151a8d604abSBrian Somers }
152a8d604abSBrian Somers 
153057f1760SBrian Somers static void
ChallengeHash(char * PeerChallenge,char * AuthenticatorChallenge,char * UserName,char * Challenge)1549b996792SBrian Somers ChallengeHash(char *PeerChallenge, char *AuthenticatorChallenge,
155057f1760SBrian Somers               char *UserName, char *Challenge)
1569b996792SBrian Somers {
157a8d604abSBrian Somers   SHA_CTX Context;
158a8d604abSBrian Somers   char Digest[SHA_DIGEST_LENGTH];
159a8d604abSBrian Somers   char *Name;
160a8d604abSBrian Somers 
161a8d604abSBrian Somers   Name = strrchr(UserName, '\\');
162a8d604abSBrian Somers   if(NULL == Name)
163a8d604abSBrian Somers     Name = UserName;
164a8d604abSBrian Somers   else
165a8d604abSBrian Somers     Name++;
166a8d604abSBrian Somers 
167a8d604abSBrian Somers   SHA1_Init(&Context);
168a8d604abSBrian Somers 
169a8d604abSBrian Somers   SHA1_Update(&Context, PeerChallenge, 16);
170a8d604abSBrian Somers   SHA1_Update(&Context, AuthenticatorChallenge, 16);
17117aa4afbSBrian Somers   SHA1_Update(&Context, Name, strlen(Name));
172a8d604abSBrian Somers 
173a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
174a8d604abSBrian Somers   memcpy(Challenge, Digest, 8);
175a8d604abSBrian Somers }
176a8d604abSBrian Somers 
177a8d604abSBrian Somers void
GenerateNTResponse(char * AuthenticatorChallenge,char * PeerChallenge,char * UserName,char * Password,int PasswordLen,char * Response)1789b996792SBrian Somers GenerateNTResponse(char *AuthenticatorChallenge, char *PeerChallenge,
179057f1760SBrian Somers                    char *UserName, char *Password,
1809b996792SBrian Somers                    int PasswordLen, char *Response)
1819b996792SBrian Somers {
182a8d604abSBrian Somers   char Challenge[8];
183a8d604abSBrian Somers   char PasswordHash[16];
184a8d604abSBrian Somers 
185057f1760SBrian Somers   ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge);
186a8d604abSBrian Somers   NtPasswordHash(Password, PasswordLen, PasswordHash);
187a8d604abSBrian Somers   ChallengeResponse(Challenge, PasswordHash, Response);
188a8d604abSBrian Somers }
189a8d604abSBrian Somers 
1901c25c5e0SBrian Somers #ifndef __FreeBSD__
1911c25c5e0SBrian Somers #define LENGTH 20
192543b7124SBrian Somers static char *
SHA1_End(SHA_CTX * ctx,char * buf)1931c25c5e0SBrian Somers SHA1_End(SHA_CTX *ctx, char *buf)
1941c25c5e0SBrian Somers {
1951c25c5e0SBrian Somers     int i;
1961c25c5e0SBrian Somers     unsigned char digest[LENGTH];
1971c25c5e0SBrian Somers     static const char hex[]="0123456789abcdef";
1981c25c5e0SBrian Somers 
1991c25c5e0SBrian Somers     if (!buf)
2001c25c5e0SBrian Somers         buf = malloc(2*LENGTH + 1);
2011c25c5e0SBrian Somers     if (!buf)
2021c25c5e0SBrian Somers         return 0;
2031c25c5e0SBrian Somers     SHA1_Final(digest, ctx);
2041c25c5e0SBrian Somers     for (i = 0; i < LENGTH; i++) {
2051c25c5e0SBrian Somers         buf[i+i] = hex[digest[i] >> 4];
2061c25c5e0SBrian Somers         buf[i+i+1] = hex[digest[i] & 0x0f];
2071c25c5e0SBrian Somers     }
2081c25c5e0SBrian Somers     buf[i+i] = '\0';
2091c25c5e0SBrian Somers     return buf;
2101c25c5e0SBrian Somers }
2111c25c5e0SBrian Somers #endif
2121c25c5e0SBrian Somers 
213a8d604abSBrian Somers void
GenerateAuthenticatorResponse(char * Password,int PasswordLen,char * NTResponse,char * PeerChallenge,char * AuthenticatorChallenge,char * UserName,char * AuthenticatorResponse)2149b996792SBrian Somers GenerateAuthenticatorResponse(char *Password, int PasswordLen,
2159b996792SBrian Somers                               char *NTResponse, char *PeerChallenge,
2169b996792SBrian Somers                               char *AuthenticatorChallenge, char *UserName,
217057f1760SBrian Somers                               char *AuthenticatorResponse)
2189b996792SBrian Somers {
219a8d604abSBrian Somers   SHA_CTX Context;
220a8d604abSBrian Somers   char PasswordHash[16];
221a8d604abSBrian Somers   char PasswordHashHash[16];
222a8d604abSBrian Somers   char Challenge[8];
223a8d604abSBrian Somers   u_char Digest[SHA_DIGEST_LENGTH];
224a8d604abSBrian Somers   int i;
225a8d604abSBrian Somers 
226a8d604abSBrian Somers       /*
227a8d604abSBrian Somers        * "Magic" constants used in response generation
228a8d604abSBrian Somers        */
229a8d604abSBrian Somers   char Magic1[39] =
230a8d604abSBrian Somers          {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
231a8d604abSBrian Somers           0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
232a8d604abSBrian Somers           0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
233a8d604abSBrian Somers           0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
234a8d604abSBrian Somers 
235a8d604abSBrian Somers 
236a8d604abSBrian Somers   char Magic2[41] =
237a8d604abSBrian Somers          {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
238a8d604abSBrian Somers           0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
239a8d604abSBrian Somers           0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
240a8d604abSBrian Somers           0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
241a8d604abSBrian Somers           0x6E};
242a8d604abSBrian Somers       /*
243a8d604abSBrian Somers        * Hash the password with MD4
244a8d604abSBrian Somers        */
245a8d604abSBrian Somers   NtPasswordHash(Password, PasswordLen, PasswordHash);
246a8d604abSBrian Somers       /*
247a8d604abSBrian Somers        * Now hash the hash
248a8d604abSBrian Somers        */
249a8d604abSBrian Somers   HashNtPasswordHash(PasswordHash, PasswordHashHash);
250a8d604abSBrian Somers 
251a8d604abSBrian Somers   SHA1_Init(&Context);
252a8d604abSBrian Somers   SHA1_Update(&Context, PasswordHashHash, 16);
253a8d604abSBrian Somers   SHA1_Update(&Context, NTResponse, 24);
254a8d604abSBrian Somers   SHA1_Update(&Context, Magic1, 39);
255a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
256057f1760SBrian Somers   ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge);
257a8d604abSBrian Somers   SHA1_Init(&Context);
258a8d604abSBrian Somers   SHA1_Update(&Context, Digest, 20);
259a8d604abSBrian Somers   SHA1_Update(&Context, Challenge, 8);
260a8d604abSBrian Somers   SHA1_Update(&Context, Magic2, 41);
261a8d604abSBrian Somers 
262a8d604abSBrian Somers       /*
263a8d604abSBrian Somers        * Encode the value of 'Digest' as "S=" followed by
264a8d604abSBrian Somers        * 40 ASCII hexadecimal digits and return it in
265a8d604abSBrian Somers        * AuthenticatorResponse.
266a8d604abSBrian Somers        * For example,
267a8d604abSBrian Somers        *   "S=0123456789ABCDEF0123456789ABCDEF01234567"
268a8d604abSBrian Somers        */
269a8d604abSBrian Somers   AuthenticatorResponse[0] = 'S';
270a8d604abSBrian Somers   AuthenticatorResponse[1] = '=';
271a8d604abSBrian Somers   SHA1_End(&Context, AuthenticatorResponse + 2);
272a8d604abSBrian Somers   for (i=2; i<42; i++)
273a8d604abSBrian Somers     AuthenticatorResponse[i] = toupper(AuthenticatorResponse[i]);
274a8d604abSBrian Somers 
275a8d604abSBrian Somers }
276a8d604abSBrian Somers 
277a8d604abSBrian Somers void
GetMasterKey(char * PasswordHashHash,char * NTResponse,char * MasterKey)2789b996792SBrian Somers GetMasterKey(char *PasswordHashHash, char *NTResponse, char *MasterKey)
2799b996792SBrian Somers {
280a8d604abSBrian Somers   char Digest[SHA_DIGEST_LENGTH];
281a8d604abSBrian Somers   SHA_CTX Context;
282a8d604abSBrian Somers   static char Magic1[27] =
283a8d604abSBrian Somers       {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
284a8d604abSBrian Somers        0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
285a8d604abSBrian Somers        0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79};
286a8d604abSBrian Somers 
287a8d604abSBrian Somers   SHA1_Init(&Context);
288a8d604abSBrian Somers   SHA1_Update(&Context, PasswordHashHash, 16);
289a8d604abSBrian Somers   SHA1_Update(&Context, NTResponse, 24);
290a8d604abSBrian Somers   SHA1_Update(&Context, Magic1, 27);
291a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
292a8d604abSBrian Somers   memcpy(MasterKey, Digest, 16);
293a8d604abSBrian Somers }
294a8d604abSBrian Somers 
295a8d604abSBrian Somers void
GetAsymetricStartKey(char * MasterKey,char * SessionKey,int SessionKeyLength,int IsSend,int IsServer)2969b996792SBrian Somers GetAsymetricStartKey(char *MasterKey, char *SessionKey, int SessionKeyLength,
2979b996792SBrian Somers                      int IsSend, int IsServer)
2989b996792SBrian Somers {
299a8d604abSBrian Somers   char Digest[SHA_DIGEST_LENGTH];
300a8d604abSBrian Somers   SHA_CTX Context;
301a8d604abSBrian Somers   char *s;
302a8d604abSBrian Somers 
303a8d604abSBrian Somers   static char Magic2[84] =
304a8d604abSBrian Somers       {0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
305a8d604abSBrian Somers        0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
306a8d604abSBrian Somers        0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
307a8d604abSBrian Somers        0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
308a8d604abSBrian Somers        0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
309a8d604abSBrian Somers        0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
310a8d604abSBrian Somers        0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
311a8d604abSBrian Somers        0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
312a8d604abSBrian Somers        0x6b, 0x65, 0x79, 0x2e};
313a8d604abSBrian Somers 
314a8d604abSBrian Somers   static char Magic3[84] =
315a8d604abSBrian Somers       {0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
316a8d604abSBrian Somers        0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
317a8d604abSBrian Somers        0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
318a8d604abSBrian Somers        0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
319a8d604abSBrian Somers        0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
320a8d604abSBrian Somers        0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
321a8d604abSBrian Somers        0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
322a8d604abSBrian Somers        0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
323a8d604abSBrian Somers        0x6b, 0x65, 0x79, 0x2e};
324a8d604abSBrian Somers 
325a8d604abSBrian Somers   if (IsSend) {
326a8d604abSBrian Somers      if (IsServer) {
327a8d604abSBrian Somers         s = Magic3;
328a8d604abSBrian Somers      } else {
329a8d604abSBrian Somers         s = Magic2;
330a8d604abSBrian Somers      }
331a8d604abSBrian Somers   } else {
332a8d604abSBrian Somers      if (IsServer) {
333a8d604abSBrian Somers         s = Magic2;
334a8d604abSBrian Somers      } else {
335a8d604abSBrian Somers         s = Magic3;
336a8d604abSBrian Somers      }
337a8d604abSBrian Somers   }
338a8d604abSBrian Somers 
339a8d604abSBrian Somers   SHA1_Init(&Context);
340a8d604abSBrian Somers   SHA1_Update(&Context, MasterKey, 16);
341a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad1, 40);
342a8d604abSBrian Somers   SHA1_Update(&Context, s, 84);
343a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad2, 40);
344a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
345a8d604abSBrian Somers 
346a8d604abSBrian Somers   memcpy(SessionKey, Digest, SessionKeyLength);
347a8d604abSBrian Somers }
348a8d604abSBrian Somers 
349a8d604abSBrian Somers void
GetNewKeyFromSHA(char * StartKey,char * SessionKey,long SessionKeyLength,char * InterimKey)3509b996792SBrian Somers GetNewKeyFromSHA(char *StartKey, char *SessionKey, long SessionKeyLength,
3519b996792SBrian Somers                  char *InterimKey)
3529b996792SBrian Somers {
353a8d604abSBrian Somers   SHA_CTX Context;
354a8d604abSBrian Somers   char Digest[SHA_DIGEST_LENGTH];
355a8d604abSBrian Somers 
356a8d604abSBrian Somers   SHA1_Init(&Context);
357a8d604abSBrian Somers   SHA1_Update(&Context, StartKey, SessionKeyLength);
358a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad1, 40);
359a8d604abSBrian Somers   SHA1_Update(&Context, SessionKey, SessionKeyLength);
360a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad2, 40);
361a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
362a8d604abSBrian Somers 
363a8d604abSBrian Somers   memcpy(InterimKey, Digest, SessionKeyLength);
364a8d604abSBrian Somers }
365a8d604abSBrian Somers 
3669b996792SBrian Somers #if 0
3679b996792SBrian Somers static void
3689b996792SBrian Somers Get_Key(char *InitialSessionKey, char *CurrentSessionKey,
3699b996792SBrian Somers         int LengthOfDesiredKey)
3709b996792SBrian Somers {
371a8d604abSBrian Somers   SHA_CTX Context;
372a8d604abSBrian Somers   char Digest[SHA_DIGEST_LENGTH];
373a8d604abSBrian Somers 
374a8d604abSBrian Somers   SHA1_Init(&Context);
375a8d604abSBrian Somers   SHA1_Update(&Context, InitialSessionKey, LengthOfDesiredKey);
376a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad1, 40);
377a8d604abSBrian Somers   SHA1_Update(&Context, CurrentSessionKey, LengthOfDesiredKey);
378a8d604abSBrian Somers   SHA1_Update(&Context, SHA1_Pad2, 40);
379a8d604abSBrian Somers   SHA1_Final(Digest, &Context);
380a8d604abSBrian Somers 
381a8d604abSBrian Somers   memcpy(CurrentSessionKey, Digest, LengthOfDesiredKey);
382a8d604abSBrian Somers }
3839b996792SBrian Somers #endif
384a8d604abSBrian Somers 
3850f8e0938SBrian Somers /* passwordHash 16-bytes MD4 hashed password
3860f8e0938SBrian Somers    challenge    8-bytes peer CHAP challenge
3870f8e0938SBrian Somers    since passwordHash is in a 24-byte buffer, response is written in there */
3880f8e0938SBrian Somers void
mschap_NT(char * passwordHash,char * challenge)3895e315498SBrian Somers mschap_NT(char *passwordHash, char *challenge)
3900f8e0938SBrian Somers {
3910f8e0938SBrian Somers     u_char response[24];
3920f8e0938SBrian Somers 
3930f8e0938SBrian Somers     ChallengeResponse(challenge, passwordHash, response);
39475240ed1SBrian Somers     memcpy(passwordHash, response, 24);
3955e315498SBrian Somers     passwordHash[24] = 1;		/* NT-style response */
3965e315498SBrian Somers }
3975e315498SBrian Somers 
3985e315498SBrian Somers void
mschap_LANMan(char * digest,char * challenge,char * secret)3995e315498SBrian Somers mschap_LANMan(char *digest, char *challenge, char *secret)
4005e315498SBrian Somers {
4015e315498SBrian Somers   static u_char salt[] = "KGS!@#$%";	/* RASAPI32.dll */
4025e315498SBrian Somers   char SECRET[14], *ptr, *end;
4035e315498SBrian Somers   u_char hash[16];
4045e315498SBrian Somers 
4055e315498SBrian Somers   end = SECRET + sizeof SECRET;
4065e315498SBrian Somers   for (ptr = SECRET; *secret && ptr < end; ptr++, secret++)
4075e315498SBrian Somers     *ptr = toupper(*secret);
4085e315498SBrian Somers   if (ptr < end)
4095e315498SBrian Somers     memset(ptr, '\0', end - ptr);
4105e315498SBrian Somers 
4115e315498SBrian Somers   DesEncrypt(salt, SECRET, hash);
4125e315498SBrian Somers   DesEncrypt(salt, SECRET + 7, hash + 8);
4135e315498SBrian Somers 
4145e315498SBrian Somers   ChallengeResponse(challenge, hash, digest);
4150f8e0938SBrian Somers }
416