1 /* $OpenBSD: chap_ms.c,v 1.2 2011/05/27 12:01:02 reyk Exp $ */ 2 /* $vantronix: chap_ms.c,v 1.7 2010/06/02 12:22:58 reyk Exp $ */ 3 4 /* 5 * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> 6 * Copyright (c) 1997 - 2001 Brian Somers <brian@Awfulhak.org> 7 * Copyright (c) 1997 Gabor Kincses <gabor@acm.org> 8 * Copyright (c) 1995 Eric Rosenquist 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/cdefs.h> 36 37 #include <ctype.h> 38 #include <string.h> 39 #include <stdio.h> 40 41 #include <openssl/evp.h> 42 #include <openssl/des.h> 43 #include <openssl/md4.h> 44 #include <openssl/md5.h> 45 #include <openssl/sha.h> 46 47 #include "chap_ms.h" 48 49 /* 50 * Documentation & specifications: 51 * 52 * MS-CHAP (CHAP80) RFC2433 53 * MS-CHAP-V2 (CHAP81) RFC2759 54 * MPPE key management RFC3079 55 * 56 * Security analysis: 57 * Schneier/Mudge/Wagner, "MS-CHAP-v2", Oct 99 58 * "It is unclear to us why this protocol is so complicated." 59 */ 60 61 static u_int8_t sha1_pad1[40] = { 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 66 }; 67 68 static u_int8_t sha1_pad2[40] = { 69 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 70 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 71 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 72 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 73 }; 74 75 u_int8_t get7bits(u_int8_t *, int); 76 void mschap_des_addparity(u_int8_t *, u_int8_t *); 77 void mschap_des_encrypt(u_int8_t *, u_int8_t *, u_int8_t *); 78 void mschap_challenge_response(u_int8_t *, u_int8_t *, u_int8_t *); 79 80 u_int8_t 81 get7bits(u_int8_t *in, int start) 82 { 83 u_int word; 84 85 word = (u_int)in[start / 8] << 8; 86 word |= (u_int)in[start / 8 + 1]; 87 word >>= 15 - (start % 8 + 7); 88 89 return (word & 0xfe); 90 } 91 92 /* IN 56 bit DES key missing parity bits 93 OUT 64 bit DES key with parity bits added */ 94 void 95 mschap_des_addparity(u_int8_t *key, u_int8_t *des_key) 96 { 97 des_key[0] = get7bits(key, 0); 98 des_key[1] = get7bits(key, 7); 99 des_key[2] = get7bits(key, 14); 100 des_key[3] = get7bits(key, 21); 101 des_key[4] = get7bits(key, 28); 102 des_key[5] = get7bits(key, 35); 103 des_key[6] = get7bits(key, 42); 104 des_key[7] = get7bits(key, 49); 105 106 DES_set_odd_parity((des_cblock *)des_key); 107 } 108 109 void 110 mschap_des_encrypt(u_int8_t *clear, u_int8_t *key, u_int8_t *cipher) 111 { 112 des_cblock des_key; 113 des_key_schedule key_schedule; 114 115 mschap_des_addparity(key, des_key); 116 117 DES_set_key(&des_key, &key_schedule); 118 DES_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, 119 &key_schedule, 1); 120 } 121 122 void 123 mschap_challenge_response(u_int8_t *challenge, u_int8_t *pwhash, 124 u_int8_t *response) 125 { 126 u_int8_t padpwhash[21]; 127 128 bzero(&padpwhash, sizeof(padpwhash)); 129 memcpy(padpwhash, pwhash, MSCHAP_HASH_SZ); 130 131 mschap_des_encrypt(challenge, padpwhash + 0, response + 0); 132 mschap_des_encrypt(challenge, padpwhash + 7, response + 8); 133 mschap_des_encrypt(challenge, padpwhash + 14, response + 16); 134 } 135 136 void 137 mschap_ntpassword_hash(u_int8_t *in, int inlen, u_int8_t *hash) 138 { 139 EVP_MD_CTX ctx; 140 u_int mdlen; 141 142 EVP_DigestInit(&ctx, EVP_md4()); 143 EVP_DigestUpdate(&ctx, in, inlen); 144 EVP_DigestFinal(&ctx, hash, &mdlen); 145 } 146 147 void 148 mschap_challenge_hash(u_int8_t *peer_challenge, u_int8_t *auth_challenge, 149 u_int8_t *username, int usernamelen, u_int8_t *challenge) 150 { 151 EVP_MD_CTX ctx; 152 u_int8_t md[SHA_DIGEST_LENGTH]; 153 u_int mdlen; 154 u_int8_t *name; 155 156 if ((name = strrchr(username, '\\')) == NULL) 157 name = username; 158 else 159 name++; 160 161 EVP_DigestInit(&ctx, EVP_sha1()); 162 EVP_DigestUpdate(&ctx, peer_challenge, MSCHAPV2_CHALLENGE_SZ); 163 EVP_DigestUpdate(&ctx, auth_challenge, MSCHAPV2_CHALLENGE_SZ); 164 EVP_DigestUpdate(&ctx, name, strlen(name)); 165 EVP_DigestFinal(&ctx, md, &mdlen); 166 167 memcpy(challenge, md, MSCHAP_CHALLENGE_SZ); 168 } 169 170 void 171 mschap_nt_response(u_int8_t *auth_challenge, u_int8_t *peer_challenge, 172 u_int8_t *username, int usernamelen, u_int8_t *password, int passwordlen, 173 u_int8_t *response) 174 { 175 u_int8_t challenge[MSCHAP_CHALLENGE_SZ]; 176 u_int8_t password_hash[MSCHAP_HASH_SZ]; 177 178 mschap_challenge_hash(peer_challenge, auth_challenge, 179 username, usernamelen, challenge); 180 181 mschap_ntpassword_hash(password, passwordlen, password_hash); 182 mschap_challenge_response(challenge, password_hash, response); 183 } 184 185 void 186 mschap_auth_response(u_int8_t *password, int passwordlen, 187 u_int8_t *ntresponse, u_int8_t *auth_challenge, u_int8_t *peer_challenge, 188 u_int8_t *username, int usernamelen, u_int8_t *auth_response) 189 { 190 EVP_MD_CTX ctx; 191 u_int8_t password_hash[MSCHAP_HASH_SZ]; 192 u_int8_t password_hash2[MSCHAP_HASH_SZ]; 193 u_int8_t challenge[MSCHAP_CHALLENGE_SZ]; 194 u_int8_t md[SHA_DIGEST_LENGTH], *ptr; 195 u_int mdlen; 196 int i; 197 const u_int8_t hex[] = "0123456789ABCDEF"; 198 static u_int8_t magic1[39] = { 199 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 200 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 201 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 202 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 203 }; 204 static u_int8_t magic2[41] = { 205 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 206 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 207 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 208 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 209 0x6E 210 }; 211 212 mschap_ntpassword_hash(password, passwordlen, password_hash); 213 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2); 214 215 EVP_DigestInit(&ctx, EVP_sha1()); 216 EVP_DigestUpdate(&ctx, password_hash2, sizeof(password_hash2)); 217 EVP_DigestUpdate(&ctx, ntresponse, 24); 218 EVP_DigestUpdate(&ctx, magic1, 39); 219 EVP_DigestFinal(&ctx, md, &mdlen); 220 221 mschap_challenge_hash(peer_challenge, auth_challenge, 222 username, usernamelen, challenge); 223 224 EVP_DigestInit(&ctx, EVP_sha1()); 225 EVP_DigestUpdate(&ctx, md, sizeof(md)); 226 EVP_DigestUpdate(&ctx, challenge, sizeof(challenge)); 227 EVP_DigestUpdate(&ctx, magic2, 41); 228 EVP_DigestFinal(&ctx, md, &mdlen); 229 230 /* 231 * Encode the value of 'Digest' as "S=" followed by 232 * 40 ASCII hexadecimal digits and return it in 233 * AuthenticatorResponse. 234 * For example, 235 * "S=0123456789ABCDEF0123456789ABCDEF01234567" 236 */ 237 ptr = auth_response; 238 *ptr++ = 'S'; 239 *ptr++ = '='; 240 for (i = 0; i < SHA_DIGEST_LENGTH; i++) { 241 *ptr++ = hex[md[i] >> 4]; 242 *ptr++ = hex[md[i] & 0x0f]; 243 } 244 } 245 246 void 247 mschap_masterkey(u_int8_t *password_hash2, u_int8_t *ntresponse, 248 u_int8_t *masterkey) 249 { 250 u_int8_t md[SHA_DIGEST_LENGTH]; 251 u_int mdlen; 252 EVP_MD_CTX ctx; 253 static u_int8_t magic1[27] = { 254 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 255 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 256 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 257 }; 258 259 EVP_DigestInit(&ctx, EVP_sha1()); 260 EVP_DigestUpdate(&ctx, password_hash2, MSCHAP_HASH_SZ); 261 EVP_DigestUpdate(&ctx, ntresponse, 24); 262 EVP_DigestUpdate(&ctx, magic1, 27); 263 EVP_DigestFinal(&ctx, md, &mdlen); 264 265 memcpy(masterkey, md, 16); 266 } 267 268 void 269 mschap_asymetric_startkey(u_int8_t *masterkey, u_int8_t *sessionkey, 270 int sessionkeylen, int issend, int isserver) 271 { 272 EVP_MD_CTX ctx; 273 u_int8_t md[SHA_DIGEST_LENGTH]; 274 u_int mdlen; 275 u_int8_t *s; 276 static u_int8_t magic2[84] = { 277 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 278 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 279 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 280 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 281 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 282 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 283 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 284 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 285 0x6b, 0x65, 0x79, 0x2e 286 }; 287 static u_int8_t magic3[84] = { 288 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 289 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 290 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 291 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 292 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 293 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 294 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 295 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 296 0x6b, 0x65, 0x79, 0x2e 297 }; 298 299 if (issend) 300 s = isserver ? magic3 : magic2; 301 else 302 s = isserver ? magic2 : magic3; 303 304 EVP_DigestInit(&ctx, EVP_sha1()); 305 EVP_DigestUpdate(&ctx, masterkey, 16); 306 EVP_DigestUpdate(&ctx, sha1_pad1, 40); 307 EVP_DigestUpdate(&ctx, s, 84); 308 EVP_DigestUpdate(&ctx, sha1_pad2, 40); 309 EVP_DigestFinal(&ctx, md, &mdlen); 310 311 memcpy(sessionkey, md, sessionkeylen); 312 } 313 314 void 315 mschap_msk(u_int8_t *password, int passwordlen, 316 u_int8_t *ntresponse, u_int8_t *msk) 317 { 318 u_int8_t password_hash[MSCHAP_HASH_SZ]; 319 u_int8_t password_hash2[MSCHAP_HASH_SZ]; 320 u_int8_t masterkey[MSCHAP_MASTERKEY_SZ]; 321 u_int8_t sendkey[MSCHAP_MASTERKEY_SZ]; 322 u_int8_t recvkey[MSCHAP_MASTERKEY_SZ]; 323 324 mschap_ntpassword_hash(password, passwordlen, password_hash); 325 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2); 326 327 mschap_masterkey(password_hash2, ntresponse, masterkey); 328 mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1); 329 mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1); 330 331 /* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */ 332 bzero(msk, MSCHAP_MSK_SZ); 333 memcpy(msk, &recvkey, sizeof(recvkey)); 334 memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey)); 335 } 336 337 void 338 mschap_newkey(u_int8_t *startkey, u_int8_t *sessionkey, 339 long sessionkeylen, u_int8_t *key) 340 { 341 EVP_MD_CTX ctx; 342 u_int8_t md[SHA_DIGEST_LENGTH]; 343 u_int mdlen; 344 345 EVP_DigestInit(&ctx, EVP_sha1()); 346 EVP_DigestUpdate(&ctx, startkey, sessionkeylen); 347 EVP_DigestUpdate(&ctx, sha1_pad1, sizeof(sha1_pad1)); 348 EVP_DigestUpdate(&ctx, sessionkey, sessionkeylen); 349 EVP_DigestUpdate(&ctx, sha1_pad2, sizeof(sha1_pad2)); 350 EVP_DigestFinal(&ctx, md, &mdlen); 351 352 memcpy(key, md, sessionkeylen); 353 } 354 355 void 356 mschap_nt(u_int8_t *password_hash, u_int8_t *challenge) 357 { 358 u_int8_t response[24]; 359 360 mschap_challenge_response(challenge, password_hash, response); 361 memcpy(password_hash, response, sizeof(response)); 362 password_hash[24] = 1; /* NT-style response */ 363 } 364 365 void 366 mschap_lanman(u_int8_t *digest, u_int8_t *challenge, u_int8_t *secret) 367 { 368 static u_int8_t salt[] = "KGS!@#$%"; /* RASAPI32.dll */ 369 u_int8_t SECRET[14], *ptr, *end; 370 u_int8_t hash[MSCHAP_HASH_SZ]; 371 372 end = SECRET + sizeof(SECRET); 373 for (ptr = SECRET; *secret && ptr < end; ptr++, secret++) 374 *ptr = toupper(*secret); 375 if (ptr < end) 376 memset(ptr, '\0', end - ptr); 377 378 mschap_des_encrypt(salt, SECRET, hash); 379 mschap_des_encrypt(salt, SECRET + 7, hash + 8); 380 381 mschap_challenge_response(challenge, hash, digest); 382 } 383 384 void 385 mschap_radiuskey(u_int8_t *plain, const u_int8_t *crypted, 386 const u_int8_t *authenticator, const u_int8_t *secret) 387 { 388 EVP_MD_CTX ctx; 389 u_int8_t b[MD5_DIGEST_LENGTH], p[32]; 390 u_int i, mdlen; 391 392 EVP_DigestInit(&ctx, EVP_md5()); 393 EVP_DigestUpdate(&ctx, secret, strlen(secret)); 394 EVP_DigestUpdate(&ctx, authenticator, 16); 395 EVP_DigestUpdate(&ctx, crypted, 2); 396 EVP_DigestFinal(&ctx, b, &mdlen); 397 398 for (i = 0; i < mdlen; i++) { 399 p[i] = b[i] ^ crypted[i+2]; 400 } 401 402 EVP_DigestInit(&ctx, EVP_md5()); 403 EVP_DigestUpdate(&ctx, secret, strlen(secret)); 404 EVP_DigestUpdate(&ctx, crypted + 2, mdlen); 405 EVP_DigestFinal(&ctx, b, &mdlen); 406 407 for (i = 0; i < mdlen; i++) { 408 p[i+16] = b[i] ^ crypted[i+18]; 409 } 410 411 memcpy(plain, p+1, 16); 412 } 413