1 /* 2 * chap_ms.c - Microsoft MS-CHAP 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 23 #include <stdio.h> 24 #include <sys/types.h> 25 #include <sys/time.h> 26 #include <syslog.h> 27 #include <string.h> 28 29 #include "chap.h" 30 #include "chap_ms.h" 31 32 #include <des.h> 33 34 /* unused, for documentation only */ 35 /* only NTResp is filled in for FreeBSD */ 36 typedef struct { 37 u_char LANManResp[24]; 38 u_char NTResp[24]; 39 u_char UseNT; /* If 1, ignore the LANMan response field */ 40 } MS_ChapResponse; 41 42 static void DesEncrypt(u_char *, u_char *, u_char *); 43 static void MakeKey(u_char *, u_char *); 44 45 static void /* IN 8 octets IN 16 octets OUT 24 octets */ 46 ChallengeResponse(u_char* challenge, u_char* pwHash, u_char* response) 47 { 48 char ZPasswordHash[21]; 49 50 bzero(ZPasswordHash, sizeof(ZPasswordHash)); 51 bcopy(pwHash, ZPasswordHash, 16); 52 53 DesEncrypt(challenge, ZPasswordHash + 0, response + 0); 54 DesEncrypt(challenge, ZPasswordHash + 7, response + 8); 55 DesEncrypt(challenge, ZPasswordHash + 14, response + 16); 56 } 57 58 static void /* IN 8 octets IN 7 octest OUT 8 octets */ 59 DesEncrypt(u_char* clear, u_char* key, u_char* cipher) 60 { 61 des_cblock des_key; 62 des_key_schedule key_schedule; 63 64 MakeKey(key, des_key); 65 des_set_key(&des_key, key_schedule); 66 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); 67 } 68 69 static u_char Get7Bits(u_char* input, int startBit) 70 { 71 register unsigned int word; 72 73 word = (unsigned)input[startBit / 8] << 8; 74 word |= (unsigned)input[startBit / 8 + 1]; 75 76 word >>= 15 - (startBit % 8 + 7); 77 78 return word & 0xFE; 79 } 80 81 /* IN 56 bit DES key missing parity bits 82 OUT 64 bit DES key with parity bits added */ 83 static void MakeKey(u_char* key, u_char* des_key) 84 { 85 des_key[0] = Get7Bits(key, 0); 86 des_key[1] = Get7Bits(key, 7); 87 des_key[2] = Get7Bits(key, 14); 88 des_key[3] = Get7Bits(key, 21); 89 des_key[4] = Get7Bits(key, 28); 90 des_key[5] = Get7Bits(key, 35); 91 des_key[6] = Get7Bits(key, 42); 92 des_key[7] = Get7Bits(key, 49); 93 94 des_set_odd_parity((des_cblock *)des_key); 95 } 96 97 /* passwordHash 16-bytes MD4 hashed password 98 challenge 8-bytes peer CHAP challenge 99 since passwordHash is in a 24-byte buffer, response is written in there */ 100 void 101 ChapMS(char* passwordHash, char* challenge, int challenge_len) 102 { 103 u_char response[24]; 104 105 ChallengeResponse(challenge, passwordHash, response); 106 bcopy(response, passwordHash, 24); 107 passwordHash += 24; 108 *passwordHash = 1; 109 } 110