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 --- |