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