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 * 9 * Redistribution and use in source and binary forms are permitted 10 * provided that the above copyright notice and this paragraph are 11 * duplicated in all such forms and that any documentation, 12 * advertising materials, and other materials related to such 13 * distribution and use acknowledge that the software was developed 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$ 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 <string.h> 35 36 #include "chap_ms.h" 37 38 /* unused, for documentation only */ 39 /* only NTResp is filled in for FreeBSD */ 40 struct 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 46 static u_char Get7Bits(u_char *input, int startBit) 47 { 48 register unsigned int word; 49 50 word = (unsigned)input[startBit / 8] << 8; 51 word |= (unsigned)input[startBit / 8 + 1]; 52 53 word >>= 15 - (startBit % 8 + 7); 54 55 return word & 0xFE; 56 } 57 58 /* IN 56 bit DES key missing parity bits 59 OUT 64 bit DES key with parity bits added */ 60 static void MakeKey(u_char *key, u_char *des_key) 61 { 62 des_key[0] = Get7Bits(key, 0); 63 des_key[1] = Get7Bits(key, 7); 64 des_key[2] = Get7Bits(key, 14); 65 des_key[3] = Get7Bits(key, 21); 66 des_key[4] = Get7Bits(key, 28); 67 des_key[5] = Get7Bits(key, 35); 68 des_key[6] = Get7Bits(key, 42); 69 des_key[7] = Get7Bits(key, 49); 70 71 des_set_odd_parity((des_cblock *)des_key); 72 } 73 74 static void /* IN 8 octets IN 7 octest OUT 8 octets */ 75 DesEncrypt(u_char *clear, u_char *key, u_char *cipher) 76 { 77 des_cblock des_key; 78 des_key_schedule key_schedule; 79 80 MakeKey(key, des_key); 81 des_set_key(&des_key, key_schedule); 82 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); 83 } 84 85 static void /* IN 8 octets IN 16 octets OUT 24 octets */ 86 ChallengeResponse(u_char *challenge, u_char *pwHash, u_char *response) 87 { 88 char ZPasswordHash[21]; 89 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 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 */ 101 void 102 mschap_NT(char *passwordHash, char *challenge) 103 { 104 u_char response[24]; 105 106 ChallengeResponse(challenge, passwordHash, response); 107 memcpy(passwordHash, response, 24); 108 passwordHash[24] = 1; /* NT-style response */ 109 } 110 111 void 112 mschap_LANMan(char *digest, char *challenge, char *secret) 113 { 114 static u_char salt[] = "KGS!@#$%"; /* RASAPI32.dll */ 115 char SECRET[14], *ptr, *end; 116 u_char hash[16]; 117 118 end = SECRET + sizeof SECRET; 119 for (ptr = SECRET; *secret && ptr < end; ptr++, secret++) 120 *ptr = toupper(*secret); 121 if (ptr < end) 122 memset(ptr, '\0', end - ptr); 123 124 DesEncrypt(salt, SECRET, hash); 125 DesEncrypt(salt, SECRET + 7, hash + 8); 126 127 ChallengeResponse(challenge, hash, digest); 128 } 129