Deleted Added
full compact
chap_ms.c (58040) chap_ms.c (67910)
1/*
2 * chap_ms.c - Microsoft MS-CHAP (NT only) compatible implementation.
3 *
4 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
5 * http://www.strataware.com/
6 *
7 * All rights reserved.
8 *

--- 5 unchanged lines hidden (view full) ---

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 *
1/*
2 * chap_ms.c - Microsoft MS-CHAP (NT only) compatible implementation.
3 *
4 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
5 * http://www.strataware.com/
6 *
7 * All rights reserved.
8 *

--- 5 unchanged lines hidden (view full) ---

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 * $FreeBSD: head/usr.sbin/ppp/chap_ms.c 58040 2000-03-14 01:47:11Z brian $
22 * $FreeBSD: head/usr.sbin/ppp/chap_ms.c 67910 2000-10-30 00:15:04Z brian $
23 *
24 */
25
26#include <sys/types.h>
27
28#include <ctype.h>
29#ifdef __FreeBSD__
30#include <openssl/des.h>
31#else
32#include <des.h>
33#endif
23 *
24 */
25
26#include <sys/types.h>
27
28#include <ctype.h>
29#ifdef __FreeBSD__
30#include <openssl/des.h>
31#else
32#include <des.h>
33#endif
34#include <sha.h>
35#include <md4.h>
34#include <string.h>
35
36#include "chap_ms.h"
37
36#include <string.h>
37
38#include "chap_ms.h"
39
40/*
41 * Documentation & specifications:
42 *
43 * MS-CHAP (CHAP80) rfc2433
44 * MS-CHAP-V2 (CHAP81) rfc2759
45 * MPPE key management draft-ietf-pppext-mppe-keys-02.txt
46 */
47
48static char SHA1_Pad1[40] =
49 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
53
54static char SHA1_Pad2[40] =
55 {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
56 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
57 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
58 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
59
38/* unused, for documentation only */
39/* only NTResp is filled in for FreeBSD */
40struct MS_ChapResponse {
41 u_char LANManResp[24];
42 u_char NTResp[24];
43 u_char UseNT; /* If 1, ignore the LANMan response field */
44};
45

--- 44 unchanged lines hidden (view full) ---

90 memset(ZPasswordHash, '\0', sizeof ZPasswordHash);
91 memcpy(ZPasswordHash, pwHash, 16);
92
93 DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
94 DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
95 DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
96}
97
60/* unused, for documentation only */
61/* only NTResp is filled in for FreeBSD */
62struct MS_ChapResponse {
63 u_char LANManResp[24];
64 u_char NTResp[24];
65 u_char UseNT; /* If 1, ignore the LANMan response field */
66};
67

--- 44 unchanged lines hidden (view full) ---

112 memset(ZPasswordHash, '\0', sizeof ZPasswordHash);
113 memcpy(ZPasswordHash, pwHash, 16);
114
115 DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
116 DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
117 DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
118}
119
120void
121NtPasswordHash(char *key, int keylen, char *hash) {
122 MD4_CTX MD4context;
123
124 MD4Init(&MD4context);
125 MD4Update(&MD4context, key, keylen);
126 MD4Final(hash, &MD4context);
127}
128
129void
130HashNtPasswordHash(char *hash, char *hashhash) {
131 MD4_CTX MD4context;
132
133 MD4Init(&MD4context);
134 MD4Update(&MD4context, hash, 16);
135 MD4Final(hashhash, &MD4context);
136}
137
138void
139ChallengeHash(char *PeerChallenge, char *AuthenticatorChallenge, char *UserName, int UserNameLen, char *Challenge) {
140 SHA_CTX Context;
141 char Digest[SHA_DIGEST_LENGTH];
142 char *Name;
143
144 Name = strrchr(UserName, '\\');
145 if(NULL == Name)
146 Name = UserName;
147 else
148 Name++;
149
150 SHA1_Init(&Context);
151
152 SHA1_Update(&Context, PeerChallenge, 16);
153 SHA1_Update(&Context, AuthenticatorChallenge, 16);
154 SHA1_Update(&Context, UserName, UserNameLen);
155
156 SHA1_Final(Digest, &Context);
157 memcpy(Challenge, Digest, 8);
158}
159
160void
161GenerateNTResponse(char *AuthenticatorChallenge, char *PeerChallenge, char *UserName, int UserNameLen, char *Password, int PasswordLen, char *Response) {
162 char Challenge[8];
163 char PasswordHash[16];
164
165 ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, UserNameLen,
166 Challenge);
167 NtPasswordHash(Password, PasswordLen, PasswordHash);
168 ChallengeResponse(Challenge, PasswordHash, Response);
169}
170
171void
172GenerateAuthenticatorResponse(char *Password, int PasswordLen, char *NTResponse, char *PeerChallenge, char *AuthenticatorChallenge, char *UserName, int UserNameLen, char *AuthenticatorResponse) {
173 SHA_CTX Context;
174 char PasswordHash[16];
175 char PasswordHashHash[16];
176 char Challenge[8];
177 u_char Digest[SHA_DIGEST_LENGTH];
178 int i;
179
180 /*
181 * "Magic" constants used in response generation
182 */
183 char Magic1[39] =
184 {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
185 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
186 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
187 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
188
189
190 char Magic2[41] =
191 {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
192 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
193 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
194 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
195 0x6E};
196 /*
197 * Hash the password with MD4
198 */
199 NtPasswordHash(Password, PasswordLen, PasswordHash);
200 /*
201 * Now hash the hash
202 */
203 HashNtPasswordHash(PasswordHash, PasswordHashHash);
204
205 SHA1_Init(&Context);
206 SHA1_Update(&Context, PasswordHashHash, 16);
207 SHA1_Update(&Context, NTResponse, 24);
208 SHA1_Update(&Context, Magic1, 39);
209 SHA1_Final(Digest, &Context);
210 ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, UserNameLen,
211 Challenge);
212 SHA1_Init(&Context);
213 SHA1_Update(&Context, Digest, 20);
214 SHA1_Update(&Context, Challenge, 8);
215 SHA1_Update(&Context, Magic2, 41);
216
217 /*
218 * Encode the value of 'Digest' as "S=" followed by
219 * 40 ASCII hexadecimal digits and return it in
220 * AuthenticatorResponse.
221 * For example,
222 * "S=0123456789ABCDEF0123456789ABCDEF01234567"
223 */
224 AuthenticatorResponse[0] = 'S';
225 AuthenticatorResponse[1] = '=';
226 SHA1_End(&Context, AuthenticatorResponse + 2);
227 for (i=2; i<42; i++)
228 AuthenticatorResponse[i] = toupper(AuthenticatorResponse[i]);
229
230}
231
232void
233GetMasterKey(char *PasswordHashHash, char *NTResponse, char *MasterKey) {
234 char Digest[SHA_DIGEST_LENGTH];
235 SHA_CTX Context;
236 static char Magic1[27] =
237 {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
238 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
239 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79};
240
241 SHA1_Init(&Context);
242 SHA1_Update(&Context, PasswordHashHash, 16);
243 SHA1_Update(&Context, NTResponse, 24);
244 SHA1_Update(&Context, Magic1, 27);
245 SHA1_Final(Digest, &Context);
246 memcpy(MasterKey, Digest, 16);
247}
248
249void
250GetAsymetricStartKey(char *MasterKey, char *SessionKey, int SessionKeyLength, int IsSend, int IsServer) {
251 char Digest[SHA_DIGEST_LENGTH];
252 SHA_CTX Context;
253 char *s;
254
255 static char Magic2[84] =
256 {0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
257 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
258 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
259 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
260 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
261 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
262 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
263 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
264 0x6b, 0x65, 0x79, 0x2e};
265
266 static char Magic3[84] =
267 {0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
268 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
269 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
270 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
271 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
272 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
273 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
274 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
275 0x6b, 0x65, 0x79, 0x2e};
276
277 if (IsSend) {
278 if (IsServer) {
279 s = Magic3;
280 } else {
281 s = Magic2;
282 }
283 } else {
284 if (IsServer) {
285 s = Magic2;
286 } else {
287 s = Magic3;
288 }
289 }
290
291 SHA1_Init(&Context);
292 SHA1_Update(&Context, MasterKey, 16);
293 SHA1_Update(&Context, SHA1_Pad1, 40);
294 SHA1_Update(&Context, s, 84);
295 SHA1_Update(&Context, SHA1_Pad2, 40);
296 SHA1_Final(Digest, &Context);
297
298 memcpy(SessionKey, Digest, SessionKeyLength);
299}
300
301void
302GetNewKeyFromSHA(char *StartKey, char *SessionKey, long SessionKeyLength, char *InterimKey) {
303 SHA_CTX Context;
304 char Digest[SHA_DIGEST_LENGTH];
305
306 SHA1_Init(&Context);
307 SHA1_Update(&Context, StartKey, SessionKeyLength);
308 SHA1_Update(&Context, SHA1_Pad1, 40);
309 SHA1_Update(&Context, SessionKey, SessionKeyLength);
310 SHA1_Update(&Context, SHA1_Pad2, 40);
311 SHA1_Final(Digest, &Context);
312
313 memcpy(InterimKey, Digest, SessionKeyLength);
314}
315
316void
317Get_Key(char *InitialSessionKey, char *CurrentSessionKey, int LengthOfDesiredKey) {
318 SHA_CTX Context;
319 char Digest[SHA_DIGEST_LENGTH];
320
321 SHA1_Init(&Context);
322 SHA1_Update(&Context, InitialSessionKey, LengthOfDesiredKey);
323 SHA1_Update(&Context, SHA1_Pad1, 40);
324 SHA1_Update(&Context, CurrentSessionKey, LengthOfDesiredKey);
325 SHA1_Update(&Context, SHA1_Pad2, 40);
326 SHA1_Final(Digest, &Context);
327
328 memcpy(CurrentSessionKey, Digest, LengthOfDesiredKey);
329}
330
98/* passwordHash 16-bytes MD4 hashed password
99 challenge 8-bytes peer CHAP challenge
100 since passwordHash is in a 24-byte buffer, response is written in there */
101void
102mschap_NT(char *passwordHash, char *challenge)
103{
104 u_char response[24];
105

--- 23 unchanged lines hidden ---
331/* passwordHash 16-bytes MD4 hashed password
332 challenge 8-bytes peer CHAP challenge
333 since passwordHash is in a 24-byte buffer, response is written in there */
334void
335mschap_NT(char *passwordHash, char *challenge)
336{
337 u_char response[24];
338

--- 23 unchanged lines hidden ---