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