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 "throughput.h" 51 #include "layer.h" 52 #include "link.h" 53 #include "chap_ms.h" 54 #include "proto.h" 55 #include "mppe.h" 56 57 /* 58 * Documentation: 59 * 60 * draft-ietf-pppext-mppe-04.txt 61 * draft-ietf-pppext-mppe-keys-02.txt 62 */ 63 64 struct mppe_state { 65 int cohnum; 66 int keylen; /* 8 or 16 bytes */ 67 int keybits; /* 40, 56 or 128 bits */ 68 char sesskey[MPPE_KEY_LEN]; 69 char mastkey[MPPE_KEY_LEN]; 70 RC4_KEY rc4key; 71 }; 72 73 int MPPE_MasterKeyValid = 0; 74 int MPPE_IsServer = 0; 75 char MPPE_MasterKey[MPPE_KEY_LEN]; 76 77 static void 78 MPPEResetOutput(void *v) 79 { 80 log_Printf(LogCCP, "MPPE: Output channel reset\n"); 81 } 82 83 static void 84 MPPEReduceSessionKey(struct mppe_state *mp) 85 { 86 switch(mp->keybits) { 87 case 40: 88 mp->sesskey[2] = 0x9e; 89 mp->sesskey[1] = 0x26; 90 case 56: 91 mp->sesskey[0] = 0xd1; 92 case 128: 93 } 94 } 95 96 static void 97 MPPEKeyChange(struct mppe_state *mp) 98 { 99 char InterimKey[MPPE_KEY_LEN]; 100 RC4_KEY RC4Key; 101 102 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 103 RC4_set_key(&RC4Key, mp->keylen, InterimKey); 104 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 105 106 MPPEReduceSessionKey(mp); 107 } 108 109 static struct mbuf * 110 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 111 struct mbuf *mp) 112 { 113 struct mppe_state *mop = (struct mppe_state *)v; 114 struct mbuf *mo; 115 u_short nproto; 116 int ilen; 117 char *rp; 118 119 log_Printf(LogCCP, "MPPE: Output\n"); 120 121 ilen = m_length(mp); 122 123 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 124 if (*proto < 0x21 && *proto > 0xFA) { 125 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 126 return mp; 127 } 128 129 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 130 131 /* Get mbuf for prefixes */ 132 mo = m_get(4, MB_CCPOUT); 133 mo->m_next = mp; 134 135 /* Init RC4 keys */ 136 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 137 138 /* Set MPPE packet prefix */ 139 rp = MBUF_CTOP(mo); 140 *(u_short *)rp = htons(0x9000 | mop->cohnum); 141 142 /* Save encrypted protocol number */ 143 nproto = htons(*proto); 144 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 145 146 /* Encrypt main packet */ 147 rp = MBUF_CTOP(mp); 148 RC4(&mop->rc4key, ilen, rp, rp); 149 150 /* Rotate keys */ 151 MPPEKeyChange(mop); 152 mop->cohnum ++; mop->cohnum &= 0xFFF; 153 154 /* Chage protocol number */ 155 *proto = ccp_Proto(ccp); 156 157 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 158 *proto, m_length(mo)); 159 160 return mo; 161 } 162 163 static void 164 MPPEResetInput(void *v) 165 { 166 log_Printf(LogCCP, "MPPE: Input channel reset\n"); 167 } 168 169 static struct mbuf * 170 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 171 { 172 struct mppe_state *mip = (struct mppe_state *)v; 173 u_short prefix; 174 char *rp; 175 int ilen; 176 177 log_Printf(LogCCP, "MPPE: Input\n"); 178 179 ilen = m_length(mp); 180 181 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 182 183 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 184 185 mp = mbuf_Read(mp, &prefix, 2); 186 prefix = ntohs(prefix); 187 if ((prefix & 0xF000) != 0x9000) { 188 log_Printf(LogERROR, "MPPE: Input: Invalid packet\n"); 189 m_freem(mp); 190 return NULL; 191 } 192 193 prefix &= 0xFFF; 194 while (prefix != mip->cohnum) { 195 MPPEKeyChange(mip); 196 mip->cohnum ++; mip->cohnum &= 0xFFF; 197 } 198 199 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 200 201 mp = mbuf_Read(mp, proto, 2); 202 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 203 *proto = ntohs(*proto); 204 205 rp = MBUF_CTOP(mp); 206 RC4(&mip->rc4key, m_length(mp), rp, rp); 207 208 log_Printf(LogDEBUG, "MPPE: Input: Decrypted: Proto %02x (%d bytes)\n", 209 *proto, m_length(mp)); 210 211 log_DumpBp(LogDEBUG, "MPPE: Input: Decrypted: Packet:", mp); 212 213 return mp; 214 } 215 216 static void 217 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 218 { 219 log_Printf(LogCCP, "MPPE: DictSetup\n"); 220 } 221 222 static const char * 223 MPPEDispOpts(struct lcp_opt *o) 224 { 225 static char buf[32]; 226 sprintf(buf, "value 0x%08x", (int)ntohl(*(u_int32_t *)(o->data))); 227 return buf; 228 } 229 230 static int 231 MPPEUsable(struct fsm *fp) 232 { 233 struct lcp *lcp; 234 int ok; 235 236 lcp = &fp->link->lcp; 237 ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) || 238 (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81); 239 if (!ok) 240 log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n"); 241 242 return ok; 243 } 244 245 static void 246 MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 247 { 248 u_long val; 249 250 o->len = 6; 251 252 log_Printf(LogCCP, "MPPE: InitOptsOutput\n"); 253 254 if (!MPPE_MasterKeyValid) { 255 log_Printf(LogCCP, "MPPE: MasterKey is invalid," 256 " MPPE is available only with CHAP81 authentication\n"); 257 *(u_int32_t *)o->data = htonl(0x0); 258 return; 259 } 260 261 val = 0x1000000; 262 switch(cfg->mppe.keybits) { 263 case 128: 264 val |= 0x40; break; 265 case 56: 266 val |= 0x80; break; 267 case 40: 268 val |= 0x20; break; 269 } 270 *(u_int32_t *)o->data = htonl(val); 271 } 272 273 static int 274 MPPESetOptsOutput(struct lcp_opt *o) 275 { 276 u_long *p = (u_long *)(o->data); 277 u_long val = ntohl(*p); 278 279 log_Printf(LogCCP, "MPPE: SetOptsOutput\n"); 280 281 if (!MPPE_MasterKeyValid) { 282 if (*p != 0x0) { 283 *p = 0x0; 284 return MODE_NAK; 285 } else { 286 return MODE_ACK; 287 } 288 } 289 290 if (val == 0x01000020 || 291 val == 0x01000040 || 292 val == 0x01000080) 293 return MODE_ACK; 294 295 return MODE_NAK; 296 } 297 298 static int 299 MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) 300 { 301 u_long *p = (u_long *)(o->data); 302 u_long val = ntohl(*p); 303 u_long mval; 304 305 log_Printf(LogCCP, "MPPE: SetOptsInput\n"); 306 307 if (!MPPE_MasterKeyValid) { 308 if (*p != 0x0) { 309 *p = 0x0; 310 return MODE_NAK; 311 } else { 312 return MODE_ACK; 313 } 314 } 315 316 mval = 0x01000000; 317 switch(cfg->mppe.keybits) { 318 case 128: 319 mval |= 0x40; break; 320 case 56: 321 mval |= 0x80; break; 322 case 40: 323 mval |= 0x20; break; 324 } 325 326 if (val == mval) 327 return MODE_ACK; 328 329 *p = htonl(mval); 330 331 return MODE_NAK; 332 } 333 334 static void * 335 MPPEInitInput(struct lcp_opt *o) 336 { 337 struct mppe_state *mip; 338 u_int32_t val = ntohl(*(unsigned long *)o->data); 339 340 log_Printf(LogCCP, "MPPE: InitInput\n"); 341 342 if (!MPPE_MasterKeyValid) { 343 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 344 return NULL; 345 } 346 347 mip = malloc(sizeof(*mip)); 348 memset(mip, 0, sizeof(*mip)); 349 350 if (val & 0x20) { /* 40-bits */ 351 mip->keylen = 8; 352 mip->keybits = 40; 353 } else if (val & 0x80) { /* 56-bits */ 354 mip->keylen = 8; 355 mip->keybits = 56; 356 } else { /* 128-bits */ 357 mip->keylen = 16; 358 mip->keybits = 128; 359 } 360 361 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 362 363 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 364 MPPE_IsServer); 365 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 366 367 MPPEReduceSessionKey(mip); 368 369 MPPEKeyChange(mip); 370 371 mip->cohnum = 0; 372 373 return mip; 374 } 375 376 static void * 377 MPPEInitOutput(struct lcp_opt *o) 378 { 379 struct mppe_state *mop; 380 u_int32_t val = ntohl(*(unsigned long *)o->data); 381 382 log_Printf(LogCCP, "MPPE: InitOutput\n"); 383 384 if (!MPPE_MasterKeyValid) { 385 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 386 return NULL; 387 } 388 389 mop = malloc(sizeof(*mop)); 390 memset(mop, 0, sizeof(*mop)); 391 392 if (val & 0x20) { /* 40-bits */ 393 mop->keylen = 8; 394 mop->keybits = 40; 395 } else if (val & 0x80) { /* 56-bits */ 396 mop->keylen = 8; 397 mop->keybits = 56; 398 } else { /* 128-bits */ 399 mop->keylen = 16; 400 mop->keybits = 128; 401 } 402 403 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 404 405 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 406 MPPE_IsServer); 407 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 408 409 MPPEReduceSessionKey(mop); 410 411 MPPEKeyChange(mop); 412 413 mop->cohnum = 0; 414 415 return mop; 416 } 417 418 static void 419 MPPETermInput(void *v) 420 { 421 log_Printf(LogCCP, "MPPE: TermInput\n"); 422 free(v); 423 } 424 425 static void 426 MPPETermOutput(void *v) 427 { 428 log_Printf(LogCCP, "MPPE: TermOutput\n"); 429 free(v); 430 } 431 432 const struct ccp_algorithm MPPEAlgorithm = { 433 TY_MPPE, 434 CCP_NEG_MPPE, 435 MPPEDispOpts, 436 MPPEUsable, 437 { 438 MPPESetOptsInput, 439 MPPEInitInput, 440 MPPETermInput, 441 MPPEResetInput, 442 MPPEInput, 443 MPPEDictSetup 444 }, 445 { 446 MPPEInitOptsOutput, 447 MPPESetOptsOutput, 448 MPPEInitOutput, 449 MPPETermOutput, 450 MPPEResetOutput, 451 MPPEOutput 452 }, 453 }; 454