1 /*- 2 * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/types.h> 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <termios.h> 34 #ifdef __FreeBSD__ 35 #include <sha.h> 36 #else 37 #include <openssl/sha.h> 38 #endif 39 #include <openssl/rc4.h> 40 41 #include "defs.h" 42 #include "mbuf.h" 43 #include "log.h" 44 #include "timer.h" 45 #include "fsm.h" 46 #include "lqr.h" 47 #include "hdlc.h" 48 #include "lcp.h" 49 #include "ccp.h" 50 #include "chap_ms.h" 51 #include "mppe.h" 52 53 /* 54 * Documentation: 55 * 56 * draft-ietf-pppext-mppe-04.txt 57 * draft-ietf-pppext-mppe-keys-02.txt 58 */ 59 60 struct mppe_state { 61 int cohnum; 62 int keylen; /* 8 or 16 bytes */ 63 int keybits; /* 40, 56 or 128 bits */ 64 char sesskey[MPPE_KEY_LEN]; 65 char mastkey[MPPE_KEY_LEN]; 66 RC4_KEY rc4key; 67 }; 68 69 int MPPE_MasterKeyValid = 0; 70 int MPPE_IsServer = 0; 71 char MPPE_MasterKey[MPPE_KEY_LEN]; 72 73 static void 74 MPPEResetOutput(void *v) 75 { 76 log_Printf(LogCCP, "MPPE: Output channel reset\n"); 77 } 78 79 static void 80 MPPEReduceSessionKey(struct mppe_state *mp) 81 { 82 switch(mp->keybits) { 83 case 40: 84 mp->sesskey[2] = 0x9e; 85 mp->sesskey[1] = 0x26; 86 case 56: 87 mp->sesskey[0] = 0xd1; 88 case 128: 89 } 90 } 91 92 static void 93 MPPEKeyChange(struct mppe_state *mp) 94 { 95 char InterimKey[MPPE_KEY_LEN]; 96 RC4_KEY RC4Key; 97 98 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 99 RC4_set_key(&RC4Key, mp->keylen, InterimKey); 100 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 101 102 MPPEReduceSessionKey(mp); 103 } 104 105 static struct mbuf * 106 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 107 struct mbuf *mp) 108 { 109 struct mppe_state *mop = (struct mppe_state *)v; 110 struct mbuf *mo; 111 u_short nproto; 112 int ilen; 113 char *rp; 114 115 log_Printf(LogCCP, "MPPE: Output\n"); 116 117 ilen = m_length(mp); 118 119 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 120 if (*proto < 0x21 && *proto > 0xFA) { 121 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 122 return mp; 123 } 124 125 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 126 127 /* Get mbuf for prefixes */ 128 mo = m_get(4, MB_CCPOUT); 129 mo->m_next = mp; 130 131 /* Init RC4 keys */ 132 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 133 134 /* Set MPPE packet prefix */ 135 rp = MBUF_CTOP(mo); 136 *(u_short *)rp = htons(0x9000 | mop->cohnum); 137 138 /* Save encrypted protocol number */ 139 nproto = htons(*proto); 140 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 141 142 /* Encrypt main packet */ 143 rp = MBUF_CTOP(mp); 144 RC4(&mop->rc4key, ilen, rp, rp); 145 146 /* Rotate keys */ 147 MPPEKeyChange(mop); 148 mop->cohnum ++; mop->cohnum &= 0xFFF; 149 150 /* Chage protocol number */ 151 *proto = ccp_Proto(ccp); 152 153 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 154 *proto, m_length(mo)); 155 156 return mo; 157 } 158 159 static void 160 MPPEResetInput(void *v) 161 { 162 log_Printf(LogCCP, "MPPE: Input channel reset\n"); 163 } 164 165 static struct mbuf * 166 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 167 { 168 struct mppe_state *mip = (struct mppe_state *)v; 169 u_short prefix; 170 char *rp; 171 int ilen; 172 173 log_Printf(LogCCP, "MPPE: Input\n"); 174 175 ilen = m_length(mp); 176 177 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 178 179 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 180 181 mp = mbuf_Read(mp, &prefix, 2); 182 prefix = ntohs(prefix); 183 if ((prefix & 0xF000) != 0x9000) { 184 log_Printf(LogERROR, "MPPE: Input: Invalid packet\n"); 185 m_freem(mp); 186 return NULL; 187 } 188 189 prefix &= 0xFFF; 190 while (prefix != mip->cohnum) { 191 MPPEKeyChange(mip); 192 mip->cohnum ++; mip->cohnum &= 0xFFF; 193 } 194 195 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 196 197 mp = mbuf_Read(mp, proto, 2); 198 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 199 *proto = ntohs(*proto); 200 201 rp = MBUF_CTOP(mp); 202 RC4(&mip->rc4key, m_length(mp), rp, rp); 203 204 log_Printf(LogDEBUG, "MPPE: Input: Decrypted: Proto %02x (%d bytes)\n", 205 *proto, m_length(mp)); 206 207 log_DumpBp(LogDEBUG, "MPPE: Input: Decrypted: Packet:", mp); 208 209 return mp; 210 } 211 212 static void 213 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 214 { 215 log_Printf(LogCCP, "MPPE: DictSetup\n"); 216 } 217 218 static const char * 219 MPPEDispOpts(struct lcp_opt *o) 220 { 221 static char buf[32]; 222 sprintf(buf, "value 0x%08x", (int)ntohl(*(u_int32_t *)(o->data))); 223 return buf; 224 } 225 226 static void 227 MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 228 { 229 u_long val; 230 231 o->len = 6; 232 233 log_Printf(LogCCP, "MPPE: InitOptsOutput\n"); 234 235 if (!MPPE_MasterKeyValid) { 236 log_Printf(LogWARN, "MPPE: MasterKey is invalid," 237 " MPPE is capable only with CHAP81 authentication\n"); 238 *(u_int32_t *)o->data = htonl(0x0); 239 return; 240 } 241 242 val = 0x1000000; 243 switch(cfg->mppe.keybits) { 244 case 128: 245 val |= 0x40; break; 246 case 56: 247 val |= 0x80; break; 248 case 40: 249 val |= 0x20; break; 250 } 251 *(u_int32_t *)o->data = htonl(val); 252 } 253 254 static int 255 MPPESetOptsOutput(struct lcp_opt *o) 256 { 257 u_long *p = (u_long *)(o->data); 258 u_long val = ntohl(*p); 259 260 log_Printf(LogCCP, "MPPE: SetOptsOutput\n"); 261 262 if (!MPPE_MasterKeyValid) { 263 if (*p != 0x0) { 264 *p = 0x0; 265 return MODE_NAK; 266 } else { 267 return MODE_ACK; 268 } 269 } 270 271 if (val == 0x01000020 || 272 val == 0x01000040 || 273 val == 0x01000080) 274 return MODE_ACK; 275 276 return MODE_NAK; 277 } 278 279 static int 280 MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) 281 { 282 u_long *p = (u_long *)(o->data); 283 u_long val = ntohl(*p); 284 u_long mval; 285 286 log_Printf(LogCCP, "MPPE: SetOptsInput\n"); 287 288 if (!MPPE_MasterKeyValid) { 289 if (*p != 0x0) { 290 *p = 0x0; 291 return MODE_NAK; 292 } else { 293 return MODE_ACK; 294 } 295 } 296 297 mval = 0x01000000; 298 switch(cfg->mppe.keybits) { 299 case 128: 300 mval |= 0x40; break; 301 case 56: 302 mval |= 0x80; break; 303 case 40: 304 mval |= 0x20; break; 305 } 306 307 if (val == mval) 308 return MODE_ACK; 309 310 *p = htonl(mval); 311 312 return MODE_NAK; 313 } 314 315 static void * 316 MPPEInitInput(struct lcp_opt *o) 317 { 318 struct mppe_state *mip; 319 u_int32_t val = ntohl(*(unsigned long *)o->data); 320 321 log_Printf(LogCCP, "MPPE: InitInput\n"); 322 323 if (!MPPE_MasterKeyValid) { 324 log_Printf(LogERROR, "MPPE: InitInput: MasterKey is invalid!!!!\n"); 325 return NULL; 326 } 327 328 mip = malloc(sizeof(*mip)); 329 memset(mip, 0, sizeof(*mip)); 330 331 if (val & 0x20) { /* 40-bits */ 332 mip->keylen = 8; 333 mip->keybits = 40; 334 } else if (val & 0x80) { /* 56-bits */ 335 mip->keylen = 8; 336 mip->keybits = 56; 337 } else { /* 128-bits */ 338 mip->keylen = 16; 339 mip->keybits = 128; 340 } 341 342 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 343 344 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 345 MPPE_IsServer); 346 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 347 348 MPPEReduceSessionKey(mip); 349 350 MPPEKeyChange(mip); 351 352 mip->cohnum = 0; 353 354 return mip; 355 } 356 357 static void * 358 MPPEInitOutput(struct lcp_opt *o) 359 { 360 struct mppe_state *mop; 361 u_int32_t val = ntohl(*(unsigned long *)o->data); 362 363 log_Printf(LogCCP, "MPPE: InitOutput\n"); 364 365 if (!MPPE_MasterKeyValid) { 366 log_Printf(LogERROR, "MPPE: InitOutput: MasterKey is invalid!!!!\n"); 367 return NULL; 368 } 369 370 mop = malloc(sizeof(*mop)); 371 memset(mop, 0, sizeof(*mop)); 372 373 if (val & 0x20) { /* 40-bits */ 374 mop->keylen = 8; 375 mop->keybits = 40; 376 } else if (val & 0x80) { /* 56-bits */ 377 mop->keylen = 8; 378 mop->keybits = 56; 379 } else { /* 128-bits */ 380 mop->keylen = 16; 381 mop->keybits = 128; 382 } 383 384 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 385 386 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 387 MPPE_IsServer); 388 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 389 390 MPPEReduceSessionKey(mop); 391 392 MPPEKeyChange(mop); 393 394 mop->cohnum = 0; 395 396 return mop; 397 } 398 399 static void 400 MPPETermInput(void *v) 401 { 402 log_Printf(LogCCP, "MPPE: TermInput\n"); 403 free(v); 404 } 405 406 static void 407 MPPETermOutput(void *v) 408 { 409 log_Printf(LogCCP, "MPPE: TermOutput\n"); 410 free(v); 411 } 412 413 const struct ccp_algorithm MPPEAlgorithm = { 414 TY_MPPE, 415 CCP_NEG_MPPE, 416 MPPEDispOpts, 417 { 418 MPPESetOptsInput, 419 MPPEInitInput, 420 MPPETermInput, 421 MPPEResetInput, 422 MPPEInput, 423 MPPEDictSetup 424 }, 425 { 426 MPPEInitOptsOutput, 427 MPPESetOptsOutput, 428 MPPEInitOutput, 429 MPPETermOutput, 430 MPPEResetOutput, 431 MPPEOutput 432 }, 433 }; 434