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 #ifdef __FreeBSD__ 32 #include <netinet/in.h> 33 #endif 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <termios.h> 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 #include "ua.h" 57 58 /* 59 * Documentation: 60 * 61 * draft-ietf-pppext-mppe-04.txt 62 * draft-ietf-pppext-mppe-keys-02.txt 63 */ 64 65 #define MPPE_OPT_STATELESS 0x1000000 66 #define MPPE_OPT_COMPRESSED 0x01 67 #define MPPE_OPT_40BIT 0x20 68 #define MPPE_OPT_56BIT 0x80 69 #define MPPE_OPT_128BIT 0x40 70 #define MPPE_OPT_BITMASK 0xe0 71 #define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK) 72 73 #define MPPE_FLUSHED 0x8000 74 #define MPPE_ENCRYPTED 0x1000 75 #define MPPE_HEADER_BITMASK 0xf000 76 #define MPPE_HEADER_FLAG 0x00ff 77 #define MPPE_HEADER_FLAGMASK 0x00ff 78 #define MPPE_HEADER_FLAGSHIFT 8 79 #define MPPE_HEADER_STATEFUL_KEYCHANGES 16 80 81 struct mppe_state { 82 unsigned stateless : 1; 83 unsigned flushnext : 1; 84 unsigned flushrequired : 1; 85 int cohnum; 86 int keylen; /* 8 or 16 bytes */ 87 int keybits; /* 40, 56 or 128 bits */ 88 char sesskey[MPPE_KEY_LEN]; 89 char mastkey[MPPE_KEY_LEN]; 90 RC4_KEY rc4key; 91 }; 92 93 int MPPE_MasterKeyValid = 0; 94 int MPPE_IsServer = 0; 95 char MPPE_MasterKey[MPPE_KEY_LEN]; 96 97 /* 98 * The peer has missed a packet. Mark the next output frame to be FLUSHED 99 */ 100 static int 101 MPPEResetOutput(void *v) 102 { 103 struct mppe_state *mop = (struct mppe_state *)v; 104 105 if (mop->stateless) 106 log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n"); 107 else { 108 log_Printf(LogCCP, "MPPE: Output channel reset\n"); 109 mop->flushnext = 1; 110 } 111 112 return 0; /* Ask FSM not to ACK */ 113 } 114 115 static void 116 MPPEReduceSessionKey(struct mppe_state *mp) 117 { 118 switch(mp->keybits) { 119 case 40: 120 mp->sesskey[2] = 0x9e; 121 mp->sesskey[1] = 0x26; 122 case 56: 123 mp->sesskey[0] = 0xd1; 124 case 128: 125 break; 126 } 127 } 128 129 static void 130 MPPEKeyChange(struct mppe_state *mp) 131 { 132 char InterimKey[MPPE_KEY_LEN]; 133 RC4_KEY RC4Key; 134 135 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 136 RC4_set_key(&RC4Key, mp->keylen, InterimKey); 137 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 138 139 MPPEReduceSessionKey(mp); 140 } 141 142 static struct mbuf * 143 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 144 struct mbuf *mp) 145 { 146 struct mppe_state *mop = (struct mppe_state *)v; 147 struct mbuf *mo; 148 u_short nproto, prefix; 149 int dictinit, ilen, len; 150 char *rp; 151 152 ilen = m_length(mp); 153 dictinit = 0; 154 155 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 156 if (*proto < 0x21 && *proto > 0xFA) { 157 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 158 ccp->compout += ilen; 159 ccp->uncompout += ilen; 160 return mp; 161 } 162 163 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 164 165 /* Get mbuf for prefixes */ 166 mo = m_get(4, MB_CCPOUT); 167 mo->m_next = mp; 168 169 rp = MBUF_CTOP(mo); 170 prefix = MPPE_ENCRYPTED | mop->cohnum; 171 172 if (mop->stateless || 173 (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 174 /* Change our key */ 175 log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum); 176 MPPEKeyChange(mop); 177 dictinit = 1; 178 } 179 180 if (mop->stateless || mop->flushnext) { 181 prefix |= MPPE_FLUSHED; 182 dictinit = 1; 183 mop->flushnext = 0; 184 } 185 186 if (dictinit) { 187 /* Initialise our dictionary */ 188 log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n", 189 mop->cohnum); 190 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 191 } 192 193 /* Set MPPE packet prefix */ 194 ua_htons(&prefix, rp); 195 196 /* Save encrypted protocol number */ 197 nproto = htons(*proto); 198 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 199 200 /* Encrypt main packet */ 201 rp = MBUF_CTOP(mp); 202 RC4(&mop->rc4key, ilen, rp, rp); 203 204 mop->cohnum++; 205 mop->cohnum &= ~MPPE_HEADER_BITMASK; 206 207 /* Set the protocol number */ 208 *proto = ccp_Proto(ccp); 209 len = m_length(mo); 210 ccp->uncompout += ilen; 211 ccp->compout += len; 212 213 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 214 *proto, len); 215 216 return mo; 217 } 218 219 static void 220 MPPEResetInput(void *v) 221 { 222 log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n"); 223 } 224 225 static struct mbuf * 226 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 227 { 228 struct mppe_state *mip = (struct mppe_state *)v; 229 u_short prefix; 230 char *rp; 231 int dictinit, flushed, ilen, len, n; 232 233 ilen = m_length(mp); 234 dictinit = 0; 235 ccp->compin += ilen; 236 237 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 238 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 239 240 mp = mbuf_Read(mp, &prefix, 2); 241 prefix = ntohs(prefix); 242 flushed = prefix & MPPE_FLUSHED; 243 prefix &= ~flushed; 244 if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) { 245 log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n", 246 (prefix & MPPE_HEADER_BITMASK) | flushed); 247 m_freem(mp); 248 return NULL; 249 } 250 251 prefix &= ~MPPE_HEADER_BITMASK; 252 253 if (!flushed && mip->stateless) { 254 log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set" 255 " in stateless mode\n"); 256 flushed = MPPE_FLUSHED; 257 /* Should we really continue ? */ 258 } 259 260 if (mip->stateless) { 261 /* Change our key for each missed packet in stateless mode */ 262 while (prefix != mip->cohnum) { 263 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 264 MPPEKeyChange(mip); 265 /* 266 * mip->cohnum contains what we received last time in stateless 267 * mode. 268 */ 269 mip->cohnum++; 270 mip->cohnum &= ~MPPE_HEADER_BITMASK; 271 } 272 dictinit = 1; 273 } else { 274 if (flushed) { 275 /* 276 * We can always process a flushed packet. 277 * Catch up on any outstanding key changes. 278 */ 279 n = (prefix >> MPPE_HEADER_FLAGSHIFT) - 280 (mip->cohnum >> MPPE_HEADER_FLAGSHIFT); 281 if (n < 0) 282 n += MPPE_HEADER_STATEFUL_KEYCHANGES; 283 while (n--) { 284 log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n", 285 prefix); 286 MPPEKeyChange(mip); 287 } 288 mip->flushrequired = 0; 289 mip->cohnum = prefix; 290 dictinit = 1; 291 } 292 293 if (mip->flushrequired) { 294 /* 295 * Perhaps we should be lenient if 296 * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG 297 * The spec says that we shouldn't be though.... 298 */ 299 log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n"); 300 fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0, 301 MB_CCPOUT); 302 m_freem(mp); 303 return NULL; 304 } 305 306 if (prefix != mip->cohnum) { 307 /* 308 * We're in stateful mode and didn't receive the expected 309 * packet. Send a reset request, but don't tell the CCP layer 310 * about it as we don't expect to receive a Reset ACK ! 311 * Guess what... M$ invented this ! 312 */ 313 log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n", 314 prefix, mip->cohnum); 315 fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0, 316 MB_CCPOUT); 317 mip->flushrequired = 1; 318 m_freem(mp); 319 return NULL; 320 } 321 322 if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 323 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 324 MPPEKeyChange(mip); 325 dictinit = 1; 326 } else if (flushed) 327 dictinit = 1; 328 329 /* 330 * mip->cohnum contains what we expect to receive next time in stateful 331 * mode. 332 */ 333 mip->cohnum++; 334 mip->cohnum &= ~MPPE_HEADER_BITMASK; 335 } 336 337 if (dictinit) { 338 log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix); 339 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 340 } 341 342 mp = mbuf_Read(mp, proto, 2); 343 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 344 *proto = ntohs(*proto); 345 346 rp = MBUF_CTOP(mp); 347 len = m_length(mp); 348 RC4(&mip->rc4key, len, rp, rp); 349 350 log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n", 351 *proto, len); 352 log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp); 353 354 ccp->uncompin += len; 355 356 return mp; 357 } 358 359 static void 360 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 361 { 362 } 363 364 static const char * 365 MPPEDispOpts(struct fsm_opt *o) 366 { 367 static char buf[70]; 368 u_int32_t val; 369 char ch; 370 int len, n; 371 372 ua_ntohl(o->data, &val); 373 len = 0; 374 if ((n = snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val)) > 0) 375 len += n; 376 if (!(val & MPPE_OPT_BITMASK)) { 377 if ((n = snprintf(buf + len, sizeof buf - len, "(0")) > 0) 378 len += n; 379 } else { 380 ch = '('; 381 if (val & MPPE_OPT_128BIT) { 382 if ((n = snprintf(buf + len, sizeof buf - len, "%c128", ch)) > 0) 383 len += n; 384 ch = '/'; 385 } 386 if (val & MPPE_OPT_56BIT) { 387 if ((n = snprintf(buf + len, sizeof buf - len, "%c56", ch)) > 0) 388 len += n; 389 ch = '/'; 390 } 391 if (val & MPPE_OPT_40BIT) { 392 if ((n = snprintf(buf + len, sizeof buf - len, "%c40", ch)) > 0) 393 len += n; 394 ch = '/'; 395 } 396 } 397 398 if ((n = snprintf(buf + len, sizeof buf - len, " bits, state%s", 399 (val & MPPE_OPT_STATELESS) ? "less" : "ful")) > 0) 400 len += n; 401 402 if (val & MPPE_OPT_COMPRESSED) { 403 if ((n = snprintf(buf + len, sizeof buf - len, ", compressed")) > 0) 404 len += n; 405 } 406 407 snprintf(buf + len, sizeof buf - len, ")"); 408 409 return buf; 410 } 411 412 static int 413 MPPEUsable(struct fsm *fp) 414 { 415 struct lcp *lcp; 416 int ok; 417 418 lcp = &fp->link->lcp; 419 ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) || 420 (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81); 421 if (!ok) 422 log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n"); 423 424 return ok; 425 } 426 427 static int 428 MPPERequired(struct fsm *fp) 429 { 430 return fp->link->ccp.cfg.mppe.required; 431 } 432 433 static u_int32_t 434 MPPE_ConfigVal(const struct ccp_config *cfg) 435 { 436 u_int32_t val; 437 438 val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0; 439 switch(cfg->mppe.keybits) { 440 case 128: 441 val |= MPPE_OPT_128BIT; 442 break; 443 case 56: 444 val |= MPPE_OPT_56BIT; 445 break; 446 case 40: 447 val |= MPPE_OPT_40BIT; 448 break; 449 case 0: 450 val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT; 451 break; 452 } 453 454 return val; 455 } 456 457 /* 458 * What options should we use for our first configure request 459 */ 460 static void 461 MPPEInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg) 462 { 463 u_int32_t mval; 464 465 o->hdr.len = 6; 466 467 if (!MPPE_MasterKeyValid) { 468 log_Printf(LogCCP, "MPPE: MasterKey is invalid," 469 " MPPE is available only with CHAP81 authentication\n"); 470 ua_htonl(0x0, o->data); 471 return; 472 } 473 474 mval = MPPE_ConfigVal(cfg); 475 ua_htonl(&mval, o->data); 476 } 477 478 /* 479 * Our CCP request was NAK'd with the given options 480 */ 481 static int 482 MPPESetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg) 483 { 484 u_int32_t mval, peer; 485 486 ua_ntohl(o->data, &peer); 487 488 if (!MPPE_MasterKeyValid) 489 /* Treat their NAK as a REJ */ 490 return MODE_NAK; 491 492 mval = MPPE_ConfigVal(cfg); 493 494 /* 495 * If we haven't been configured with a specific number of keybits, allow 496 * whatever the peer asks for. 497 */ 498 if (!cfg->mppe.keybits) { 499 mval &= ~MPPE_OPT_BITMASK; 500 mval |= (peer & MPPE_OPT_BITMASK); 501 if (!(mval & MPPE_OPT_BITMASK)) 502 mval |= MPPE_OPT_128BIT; 503 } 504 505 /* Adjust our statelessness */ 506 if (cfg->mppe.state == MPPE_ANYSTATE) { 507 mval &= ~MPPE_OPT_STATELESS; 508 mval |= (peer & MPPE_OPT_STATELESS); 509 } 510 511 ua_htonl(&mval, o->data); 512 513 return MODE_ACK; 514 } 515 516 /* 517 * The peer has requested the given options 518 */ 519 static int 520 MPPESetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg) 521 { 522 u_int32_t mval, peer; 523 int res = MODE_ACK; 524 525 ua_ntohl(o->data, &peer); 526 if (!MPPE_MasterKeyValid) { 527 if (peer != 0) { 528 peer = 0; 529 ua_htonl(&peer, o->data); 530 return MODE_NAK; 531 } else 532 return MODE_ACK; 533 } 534 535 mval = MPPE_ConfigVal(cfg); 536 537 if (peer & ~MPPE_OPT_MASK) 538 /* He's asking for bits we don't know about */ 539 res = MODE_NAK; 540 541 if (peer & MPPE_OPT_STATELESS) { 542 if (cfg->mppe.state == MPPE_STATEFUL) 543 /* Peer can't have stateless */ 544 res = MODE_NAK; 545 else 546 /* Peer wants stateless, that's ok */ 547 mval |= MPPE_OPT_STATELESS; 548 } else { 549 if (cfg->mppe.state == MPPE_STATELESS) 550 /* Peer must have stateless */ 551 res = MODE_NAK; 552 else 553 /* Peer doesn't want stateless, that's ok */ 554 mval &= ~MPPE_OPT_STATELESS; 555 } 556 557 /* If we've got a configured number of keybits - the peer must use that */ 558 if (cfg->mppe.keybits) { 559 ua_htonl(&mval, o->data); 560 return peer == mval ? res : MODE_NAK; 561 } 562 563 /* If a specific number of bits hasn't been requested, we'll need to NAK */ 564 switch (peer & MPPE_OPT_BITMASK) { 565 case MPPE_OPT_128BIT: 566 case MPPE_OPT_56BIT: 567 case MPPE_OPT_40BIT: 568 break; 569 default: 570 res = MODE_NAK; 571 } 572 573 /* Suggest the best number of bits */ 574 mval &= ~MPPE_OPT_BITMASK; 575 if (peer & MPPE_OPT_128BIT) 576 mval |= MPPE_OPT_128BIT; 577 else if (peer & MPPE_OPT_56BIT) 578 mval |= MPPE_OPT_56BIT; 579 else if (peer & MPPE_OPT_40BIT) 580 mval |= MPPE_OPT_40BIT; 581 else 582 mval |= MPPE_OPT_128BIT; 583 ua_htonl(&mval, o->data); 584 585 return res; 586 } 587 588 static struct mppe_state * 589 MPPE_InitState(struct fsm_opt *o) 590 { 591 struct mppe_state *mp; 592 u_int32_t val; 593 594 if ((mp = calloc(1, sizeof *mp)) != NULL) { 595 ua_ntohl(o->data, &val); 596 597 switch (val & MPPE_OPT_BITMASK) { 598 case MPPE_OPT_128BIT: 599 mp->keylen = 16; 600 mp->keybits = 128; 601 break; 602 case MPPE_OPT_56BIT: 603 mp->keylen = 8; 604 mp->keybits = 56; 605 break; 606 case MPPE_OPT_40BIT: 607 mp->keylen = 8; 608 mp->keybits = 40; 609 break; 610 default: 611 log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val); 612 free(mp); 613 return NULL; 614 } 615 616 mp->stateless = !!(val & MPPE_OPT_STATELESS); 617 } 618 619 return mp; 620 } 621 622 static void * 623 MPPEInitInput(struct fsm_opt *o) 624 { 625 struct mppe_state *mip; 626 627 if (!MPPE_MasterKeyValid) { 628 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 629 return NULL; 630 } 631 632 if ((mip = MPPE_InitState(o)) == NULL) { 633 log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n"); 634 return NULL; 635 } 636 637 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 638 639 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 640 MPPE_IsServer); 641 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 642 643 MPPEReduceSessionKey(mip); 644 645 log_Printf(LogCCP, "MPPE: Input channel initiated\n"); 646 647 if (!mip->stateless) { 648 /* 649 * We need to initialise our dictionary here as the first packet we 650 * receive is unlikely to have the FLUSHED bit set. 651 */ 652 log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n", 653 mip->cohnum); 654 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 655 } else { 656 /* 657 * We do the first key change here as the first packet is expected 658 * to have a sequence number of 0 and we'll therefore not expect 659 * to have to change the key at that point. 660 */ 661 log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum); 662 MPPEKeyChange(mip); 663 } 664 665 return mip; 666 } 667 668 static void * 669 MPPEInitOutput(struct fsm_opt *o) 670 { 671 struct mppe_state *mop; 672 673 if (!MPPE_MasterKeyValid) { 674 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 675 return NULL; 676 } 677 678 if ((mop = MPPE_InitState(o)) == NULL) { 679 log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n"); 680 return NULL; 681 } 682 683 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 684 685 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 686 MPPE_IsServer); 687 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 688 689 MPPEReduceSessionKey(mop); 690 691 log_Printf(LogCCP, "MPPE: Output channel initiated\n"); 692 693 if (!mop->stateless) { 694 /* 695 * We need to initialise our dictionary now as the first packet we 696 * send won't have the FLUSHED bit set. 697 */ 698 log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n", 699 mop->cohnum); 700 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 701 } 702 703 return mop; 704 } 705 706 static void 707 MPPETermInput(void *v) 708 { 709 free(v); 710 } 711 712 static void 713 MPPETermOutput(void *v) 714 { 715 free(v); 716 } 717 718 const struct ccp_algorithm MPPEAlgorithm = { 719 TY_MPPE, 720 CCP_NEG_MPPE, 721 MPPEDispOpts, 722 MPPEUsable, 723 MPPERequired, 724 { 725 MPPESetOptsInput, 726 MPPEInitInput, 727 MPPETermInput, 728 MPPEResetInput, 729 MPPEInput, 730 MPPEDictSetup 731 }, 732 { 733 2, 734 MPPEInitOptsOutput, 735 MPPESetOptsOutput, 736 MPPEInitOutput, 737 MPPETermOutput, 738 MPPEResetOutput, 739 MPPEOutput 740 }, 741 }; 742