1/* $OpenBSD: mppe.c,v 1.15 2019/02/27 04:52:19 denis Exp $ */ 2 3/*- 4 * Copyright (c) 2009 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/* $Id: mppe.c,v 1.15 2019/02/27 04:52:19 denis Exp $ */ 29/**@file 30 * 31 * The implementation of MPPE(Microsoft Point-To-Point Encryption Protocol) 32 */ 33/* 34 * To avoid the PPP packet out of sequence problem. 35 * It may avoid if it reconstruct the frame order in L2TP/IPsec. 36 */ 37#define WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING 1 38 39#include <sys/types.h> 40#include <sys/socket.h> 41#include <sys/time.h> 42#include <net/if_dl.h> 43#include <netinet/in.h> 44#include <endian.h> 45#include <stdlib.h> 46#include <stdio.h> 47#include <stdarg.h> 48#include <syslog.h> 49#include <string.h> 50#include <event.h> 51#ifdef WITH_OPENSSL 52#include <openssl/sha.h> 53#include <openssl/rc4.h> 54#endif 55 56#include "npppd.h" 57#include "debugutil.h" 58 59#ifdef MPPE_DEBUG 60#define MPPE_DBG(x) mppe_log x 61#define MPPE_ASSERT(x) \ 62 if (!(x)) { \ 63 fprintf(stderr, \ 64 "\nASSERT(%s) failed on %s() at %s:%d.\n" \ 65 , #x, __func__, __FILE__, __LINE__); \ 66 abort(); \ 67 } 68#else 69#define MPPE_DBG(x) 70#define MPPE_ASSERT(x) 71#endif 72 73#define SESS_KEY_LEN(len) (len < 16)? 8 : 16 74 75#define COHER_EQ(a, b) ((((a) - (b)) & 0xfff) == 0) 76#define COHER_LT(a, b) (((int16_t)(((a) - (b)) << 4)) < 0) 77#define COHER_GT(a, b) COHER_LT((b), (a)) 78#define COHER_NE(a, b) (!COHER_EQ((a), (b))) 79#define COHER_LE(a, b) (!COHER_GE((b), (a))) 80#define COHER_GE(a, b) (!COHER_LT((a), (b))) 81 82 83static const char *mppe_bits_to_string(uint32_t); 84static void mppe_log(mppe *, uint32_t, const char *, ...) __printflike(3,4); 85static int mppe_rc4_init(mppe *, mppe_rc4_t *, int); 86static int mppe_rc4_setkey(mppe *, mppe_rc4_t *); 87static int mppe_rc4_setoldkey(mppe *, mppe_rc4_t *, uint16_t); 88static void mppe_rc4_destroy(mppe *, mppe_rc4_t *); 89static void mppe_rc4_encrypt(mppe *, mppe_rc4_t *, int, u_char *, u_char *); 90static void *rc4_create_ctx(void); 91static int rc4_key(void *, int, u_char *); 92static void rc4(void *, int, u_char *, u_char *); 93static void GetNewKeyFromSHA(u_char *, u_char *, int, u_char *); 94 95/** 96 * initializing mppe context. 97 * - reading configuration. 98 */ 99void 100mppe_init(mppe *_this, npppd_ppp *ppp) 101{ 102 struct tunnconf *conf; 103 104 MPPE_ASSERT(ppp != NULL); 105 MPPE_ASSERT(_this != NULL); 106 107 memset(_this, 0, sizeof(mppe)); 108 109 _this->ppp = ppp; 110 111 _this->mode_auto = 1; 112 _this->mode_stateless = 0; 113 114 conf = ppp_get_tunnconf(ppp); 115 _this->enabled = conf->mppe_yesno; 116 if (_this->enabled == 0) 117 goto mppe_config_done; 118 119 _this->required = conf->mppe_required; 120 121 if (conf->mppe_keystate == (NPPPD_MPPE_STATEFUL|NPPPD_MPPE_STATELESS)) { 122 /* no need to change from default. */ 123 } else if (conf->mppe_keystate == NPPPD_MPPE_STATELESS) { 124 _this->mode_auto = 0; 125 _this->mode_stateless = 1; 126 } else if (conf->mppe_keystate == NPPPD_MPPE_STATEFUL) { 127 _this->mode_auto = 0; 128 _this->mode_stateless = 0; 129 } 130 131 _this->keylenbits = 0; 132 if ((conf->mppe_keylen & NPPPD_MPPE_40BIT) != 0) 133 _this->keylenbits |= CCP_MPPE_NT_40bit; 134 if ((conf->mppe_keylen & NPPPD_MPPE_56BIT) != 0) 135 _this->keylenbits |= CCP_MPPE_NT_56bit; 136 if ((conf->mppe_keylen & NPPPD_MPPE_128BIT) != 0) 137 _this->keylenbits |= CCP_MPPE_NT_128bit; 138 139mppe_config_done: 140 /* nothing */; 141} 142 143void 144mppe_fini(mppe *_this) 145{ 146 mppe_rc4_destroy(_this, &_this->send); 147 mppe_rc4_destroy(_this, &_this->recv); 148} 149 150static void 151mppe_reduce_key(mppe_rc4_t *_this) 152{ 153 switch (_this->keybits) { 154 case 40: 155 _this->session_key[1] = 0x26; 156 _this->session_key[2] = 0x9e; 157 case 56: 158 _this->session_key[0] = 0xd1; 159 } 160} 161 162static void 163mppe_key_change(mppe *_mppe, mppe_rc4_t *_this) 164{ 165 u_char interim[16]; 166 void *keychg; 167 168 keychg = rc4_create_ctx(); 169 170 GetNewKeyFromSHA(_this->master_key, _this->session_key, 171 _this->keylen, interim); 172 173 rc4_key(keychg, _this->keylen, interim); 174 rc4(keychg, _this->keylen, interim, _this->session_key); 175 mppe_reduce_key(_this); 176 177 if (_this->old_session_keys) { 178 int idx = _this->coher_cnt % MPPE_NOLDKEY; 179 memcpy(_this->old_session_keys[idx], 180 _this->session_key, MPPE_KEYLEN); 181 } 182 183 free(keychg); 184} 185 186/** 187 * starting mppe protocol. 188 */ 189void 190mppe_start(mppe *_this) 191{ 192 char buf[256]; 193 194 strlcpy(buf, mppe_bits_to_string(_this->ppp->ccp.mppe_o_bits), 195 sizeof(buf)); 196 197 mppe_log(_this, LOG_INFO, "logtype=Opened our=%s peer=%s", buf, 198 mppe_bits_to_string(_this->ppp->ccp.mppe_p_bits)); 199 200 _this->ppp->mppe_started = 1; 201 202 _this->send.stateless = 203 ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_STATELESS) != 0)? 1 : 0; 204 205 if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_40bit) != 0) { 206 _this->send.keylen = 8; 207 _this->send.keybits = 40; 208 } else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_56bit) != 0) { 209 _this->send.keylen = 8; 210 _this->send.keybits = 56; 211 } else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_128bit) != 0) { 212 _this->send.keylen = 16; 213 _this->send.keybits = 128; 214 } 215 216 _this->recv.stateless = 217 ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_STATELESS) != 0)? 1 : 0; 218 if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_40bit) != 0) { 219 _this->recv.keylen = 8; 220 _this->recv.keybits = 40; 221 } else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_56bit) != 0) { 222 _this->recv.keylen = 8; 223 _this->recv.keybits = 56; 224 } else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_128bit) != 0) { 225 _this->recv.keylen = 16; 226 _this->recv.keybits = 128; 227 } 228 229 if (_this->send.keybits > 0) { 230 mppe_rc4_init(_this, &_this->send, 0); 231 GetNewKeyFromSHA(_this->send.master_key, _this->send.master_key, 232 _this->send.keylen, _this->send.session_key); 233 mppe_reduce_key(&_this->send); 234 mppe_rc4_setkey(_this, &_this->send); 235 } 236 if (_this->recv.keybits > 0) { 237 mppe_rc4_init(_this, &_this->recv, _this->recv.stateless); 238 GetNewKeyFromSHA(_this->recv.master_key, _this->recv.master_key, 239 _this->recv.keylen, _this->recv.session_key); 240 mppe_reduce_key(&_this->recv); 241 mppe_rc4_setkey(_this, &_this->recv); 242 } 243} 244 245/** 246 * creating the mppe bits. In case of first proposal, it specifies the 247 * peer_bits as 0 value. If it specifies the peer_bits, it returns the 248 * value as peer's proposal. 249 */ 250uint32_t 251mppe_create_our_bits(mppe *_this, uint32_t peer_bits) 252{ 253 uint32_t our_bits; 254 255 /* default proposal */ 256 our_bits = _this->keylenbits; 257 if (peer_bits != 0 && (peer_bits & our_bits) != 0) { 258 if ((peer_bits & CCP_MPPE_NT_128bit) != 0) 259 our_bits = CCP_MPPE_NT_128bit; 260 else if ((peer_bits & CCP_MPPE_NT_56bit) != 0) 261 our_bits = CCP_MPPE_NT_56bit; 262 else if ((peer_bits & CCP_MPPE_NT_40bit) != 0) 263 our_bits = CCP_MPPE_NT_40bit; 264 } 265 266 if (_this->mode_auto != 0) { 267 /* in case of auto_mode */ 268 if (peer_bits == 0) { 269 /* 270 * It proposes stateless mode in first time. Windows 9x has 271 * a bug that it is reverse to stateful and stateless in 272 * sending and receiving packets. 273 * Windows 9x is prior to negotiate in stateless mode, so 274 * it will avoid the Windows bug to be prior to negotiate 275 * in stateless mode. 276 * 277 * Even if this bug doesn't exists, the stateful mode is high 278 * cost from user's viewpoint when packets may loss more than a 279 * certain rate, so it is not good choice to use via Internet or 280 * wireless LAN. 281 */ 282 our_bits |= CCP_MPPE_STATELESS; 283 } else { 284 /* giving up */ 285 our_bits |= peer_bits & CCP_MPPE_STATELESS; 286 } 287 } else { 288 /* it doesn't give up in case of setting non-auto value. */ 289 if (_this->mode_stateless != 0) 290 our_bits |= CCP_MPPE_STATELESS; 291 } 292 if (peer_bits != 0 && our_bits != peer_bits) { 293 char obuf[128], pbuf[128]; 294 295 /* in case of failure, it puts a log. */ 296 strlcpy(obuf, mppe_bits_to_string(our_bits), sizeof(obuf)); 297 strlcpy(pbuf, mppe_bits_to_string(peer_bits), sizeof(pbuf)); 298 mppe_log(_this, LOG_INFO, 299 "mismatch our=%s peer=%s", obuf, pbuf); 300 } 301 302 return our_bits; 303} 304 305#define COHERENCY_CNT_MASK 0x0fff; 306 307/** 308 * receiving packets via MPPE. 309 * len must be 4 at least. 310 */ 311void 312mppe_input(mppe *_this, u_char *pktp, int len) 313{ 314 int pktloss, encrypt, flushed, m, n; 315 uint16_t coher_cnt; 316 u_char *pktp0, *opktp, *opktp0; 317 uint16_t proto; 318 int delayed = 0; 319 320 encrypt = 0; 321 flushed = 0; 322 323 MPPE_ASSERT(len >= 4); 324 325 pktp0 = pktp; 326 GETSHORT(coher_cnt, pktp); 327 328 flushed = (coher_cnt & 0x8000)? 1 : 0; 329 encrypt = (coher_cnt & 0x1000)? 1 : 0; 330 coher_cnt &= COHERENCY_CNT_MASK; 331 pktloss = 0; 332 333 MPPE_DBG((_this, DEBUG_LEVEL_2, "in coher_cnt=%03x/%03x %s%s", 334 _this->recv.coher_cnt, coher_cnt, (flushed)? "[flushed]" : "", 335 (encrypt)? "[encrypt]" : "")); 336 337 if (encrypt == 0) { 338 mppe_log(_this, LOG_WARNING, 339 "Received unexpected MPPE packet. (no encrypt)"); 340 return; 341 } 342 343 /* 344 * In L2TP/IPsec implementation, in case that the ppp frame sequence 345 * is not able to reconstruct and the ppp frame is out of sequence, it 346 * is unable to identify with many packets losing. If it does so, MPPE 347 * key is out of place. 348 * To avoid this problem, when it seems that more than 4096-256 packets 349 * drops, it assumes that the packet doesn't lose but the packet is out 350 * of sequence. 351 */ 352 { 353 int coher_cnt0; 354 355 coher_cnt0 = coher_cnt; 356 if (coher_cnt < _this->recv.coher_cnt) 357 coher_cnt0 += 0x1000; 358 if (coher_cnt0 - _this->recv.coher_cnt > 0x0f00) { 359 if (!_this->recv.stateless || 360 coher_cnt0 - _this->recv.coher_cnt 361 <= 0x1000 - MPPE_NOLDKEY) { 362 mppe_log(_this, LOG_INFO, 363 "Workaround the out-of-sequence PPP framing problem: " 364 "%d => %d", _this->recv.coher_cnt, coher_cnt); 365 return; 366 } 367 delayed = 1; 368 } 369 } 370 371 if (_this->recv.stateless != 0) { 372 if (!delayed) { 373 mppe_key_change(_this, &_this->recv); 374 while (_this->recv.coher_cnt != coher_cnt) { 375 _this->recv.coher_cnt++; 376 _this->recv.coher_cnt &= COHERENCY_CNT_MASK; 377 mppe_key_change(_this, &_this->recv); 378 pktloss++; 379 } 380 } 381 mppe_rc4_setoldkey(_this, &_this->recv, coher_cnt); 382 flushed = 1; 383 } else { 384 if (flushed) { 385 if (coher_cnt < _this->recv.coher_cnt) { 386 /* in case of carrying up. */ 387 coher_cnt += 0x1000; 388 } 389 pktloss += coher_cnt - _this->recv.coher_cnt; 390 m = _this->recv.coher_cnt / 256; 391 n = coher_cnt / 256; 392 while (m++ < n) 393 mppe_key_change(_this, &_this->recv); 394 395 coher_cnt &= COHERENCY_CNT_MASK; 396 _this->recv.coher_cnt = coher_cnt; 397 } else if (_this->recv.coher_cnt != coher_cnt) { 398 _this->recv.resetreq = 1; 399 400 opktp0 = ppp_packetbuf(_this->ppp, 401 PPP_PROTO_NCP | NCP_CCP); 402 opktp = opktp0; 403 404 PUTLONG(_this->ppp->ccp.mppe_p_bits, opktp); 405 406 ppp_output(_this->ppp, PPP_PROTO_NCP | NCP_CCP, 407 RESETREQ, _this->recv.resetreq, opktp0, 408 opktp - opktp0); 409 return; 410 } 411 if ((coher_cnt & 0xff) == 0xff) { 412 mppe_key_change(_this, &_this->recv); 413 flushed = 1; 414 } 415 if (flushed) { 416 mppe_rc4_setkey(_this, &_this->recv); 417 } 418 } 419 420 if (pktloss > 1000) { 421 /* 422 * In case of many packets losing or out of sequence. 423 * The latter is not able to communicate because the key is 424 * out of place soon. 425 * 426 */ 427 mppe_log(_this, LOG_WARNING, "%d packets loss", pktloss); 428 } 429 430 mppe_rc4_encrypt(_this, &_this->recv, len - 2, pktp, pktp); 431 432 if (!delayed) { 433 _this->recv.coher_cnt++; 434 _this->recv.coher_cnt &= COHERENCY_CNT_MASK; 435 } 436 437 if (pktp[0] & 1) 438 proto = pktp[0]; 439 else 440 proto = pktp[0] << 8 | pktp[1]; 441 /* 442 * According to RFC3078 section 3, 443 * MPPE only accept protocol number 0021-00FA. 444 * If decrypted protocol number is out of range, 445 * it indicates loss of coherency. 446 */ 447 if (!(proto & 1) || proto < 0x21 || proto > 0xfa) { 448 mppe_log(_this, LOG_INFO, "MPPE coherency is lost"); 449 return; /* drop frame */ 450 } 451 452 _this->ppp->recv_packet(_this->ppp, pktp, len - 2, 453 PPP_IO_FLAGS_MPPE_ENCRYPTED); 454} 455 456/** 457 * The call out function in case of receiving CCP Reset (key reset in case 458 * of MPPE). 459 */ 460void 461mppe_recv_ccp_reset(mppe *_this) 462{ 463 MPPE_DBG((_this, DEBUG_LEVEL_2, "%s() is called.", __func__)); 464 _this->send.resetreq = 1; 465} 466 467/** 468 * sending packet via MPPE. 469 */ 470void 471mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len) 472{ 473 int encrypt, flushed; 474 uint16_t coher_cnt; 475 u_char *outp, *outp0; 476 477 MPPE_ASSERT(proto == PPP_PROTO_IP); 478 479 flushed = 0; 480 encrypt = 1; 481 482 outp = ppp_packetbuf(_this->ppp, PPP_PROTO_MPPE); 483 outp0 = outp; 484 485 if (_this->send.stateless != 0) { 486 flushed = 1; 487 mppe_key_change(_this, &_this->send); 488 } else { 489 if ((_this->send.coher_cnt % 0x100) == 0xff) { 490 flushed = 1; 491 mppe_key_change(_this, &_this->send); 492 } else if (_this->send.resetreq != 0) { 493 flushed = 1; 494 _this->send.resetreq = 0; 495 } 496 } 497 498 if (flushed) { 499 mppe_rc4_setkey(_this, &_this->send); 500 } 501 502 MPPE_DBG((_this, DEBUG_LEVEL_2, "out coher_cnt=%03x %s%s", 503 _this->send.coher_cnt, (flushed)? "[flushed]" : "", 504 (encrypt)? "[encrypt]" : "")); 505 506 coher_cnt = _this->send.coher_cnt & COHERENCY_CNT_MASK; 507 if (flushed) 508 coher_cnt |= 0x8000; 509 if (encrypt) 510 coher_cnt |= 0x1000; 511 512 PUTSHORT(coher_cnt, outp); 513 proto = htons(proto); 514 mppe_rc4_encrypt(_this, &_this->send, 2, (u_char *)&proto, outp); 515 mppe_rc4_encrypt(_this, &_this->send, len, pktp, outp + 2); 516 517 ppp_output(_this->ppp, PPP_PROTO_MPPE, 0, 0, outp0, len + 4); 518 _this->send.coher_cnt++; 519 _this->send.coher_cnt &= COHERENCY_CNT_MASK; 520} 521 522static void 523mppe_log(mppe *_this, uint32_t prio, const char *fmt, ...) 524{ 525 char logbuf[BUFSIZ]; 526 va_list ap; 527 528 va_start(ap, fmt); 529 snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=mppe %s", 530 _this->ppp->id, fmt); 531 vlog_printf(prio, logbuf, ap); 532 va_end(ap); 533} 534 535static const char * 536mppe_bits_to_string(uint32_t bits) 537{ 538 static char buf[128]; 539 540 snprintf(buf, sizeof(buf), "%s%s%s%s%s%s" 541 , ((CCP_MPPC_ALONE & bits) != 0)? ",mppc" : "" 542 , ((CCP_MPPE_LM_40bit& bits) != 0)? ",40bit(LM)" : "" 543 , ((CCP_MPPE_NT_40bit& bits) != 0)? ",40bit" : "" 544 , ((CCP_MPPE_NT_128bit& bits) != 0)? ",128bit" : "" 545 , ((CCP_MPPE_NT_56bit& bits) != 0)? ",56bit" : "" 546 , ((CCP_MPPE_STATELESS& bits) != 0)? ",stateless" : ",stateful"); 547 548 if (buf[0] == '\0') 549 return ""; 550 551 return buf + 1; 552} 553 554/************************************************************************ 555 * implementations of authentication/cipher algorism. 556 ************************************************************************/ 557static u_char SHAPad1[] = { 558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 563}, SHAPad2[] = { 564 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 565 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 566 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 567 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 568 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 569}; 570#define ZeroMemory(dst, len) memset(dst, 0, len) 571#define MoveMemory(dst, src, len) memcpy(dst, src, len) 572 573#include <openssl/rc4.h> 574#include <openssl/sha.h> 575 576#define SHA_CTX SHA_CTX 577#define SHAInit SHA1_Init 578#define SHAUpdate SHA1_Update 579#define SHAFinal(ctx,digest) SHA1_Final(digest, ctx) 580 581/************************************************************************ 582 * implementations of OpenSSL version 583 ************************************************************************/ 584static void * 585rc4_create_ctx(void) 586{ 587 return malloc(sizeof(RC4_KEY)); 588} 589 590static int 591rc4_key(void *rc4ctx, int lkey, u_char *key) 592{ 593 594 RC4_set_key(rc4ctx, lkey, key); 595 596 return 0; 597} 598 599static void 600rc4(void *rc4ctx, int len, u_char *indata, u_char *outdata) 601{ 602 RC4(rc4ctx, len, indata, outdata); 603} 604 605static void 606GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength, 607 u_char *InterimKey) 608{ 609 u_char Digest[20]; 610 SHA_CTX Context; 611 612 ZeroMemory(Digest, 20); 613 614 SHAInit(&Context); 615 SHAUpdate(&Context, StartKey, SessionKeyLength); 616 SHAUpdate(&Context, SHAPad1, 40); 617 SHAUpdate(&Context, SessionKey, SessionKeyLength); 618 SHAUpdate(&Context, SHAPad2, 40); 619 SHAFinal(&Context, Digest); 620 621 MoveMemory(InterimKey, Digest, SessionKeyLength); 622} 623 624static int 625mppe_rc4_init(mppe *_mppe, mppe_rc4_t *_this, int has_oldkey) 626{ 627 if ((_this->rc4ctx = rc4_create_ctx()) == NULL) { 628 mppe_log(_mppe, LOG_ERR, "malloc() failed at %s: %m", 629 __func__); 630 return 1; 631 } 632 633 if (has_oldkey) 634 _this->old_session_keys = reallocarray(NULL, 635 MPPE_KEYLEN, MPPE_NOLDKEY); 636 else 637 _this->old_session_keys = NULL; 638 639 return 0; 640} 641 642static int 643mppe_rc4_setkey(mppe *_mppe, mppe_rc4_t *_this) 644{ 645 return rc4_key(_this->rc4ctx, _this->keylen, _this->session_key); 646} 647 648static int 649mppe_rc4_setoldkey(mppe *_mppe, mppe_rc4_t *_this, uint16_t coher_cnt) 650{ 651 return rc4_key(_this->rc4ctx, _this->keylen, 652 _this->old_session_keys[coher_cnt % MPPE_NOLDKEY]); 653} 654 655static void 656mppe_rc4_encrypt(mppe *_mppe, mppe_rc4_t *_this, int len, u_char *indata, u_char *outdata) 657{ 658 rc4(_this->rc4ctx, len, indata, outdata); 659} 660 661static void 662mppe_rc4_destroy(mppe *_mppe, mppe_rc4_t *_this) 663{ 664 free(_this->rc4ctx); 665 free(_this->old_session_keys); 666 _this->rc4ctx = NULL; 667} 668