1195972f6Sopenharmony_ci/* 2195972f6Sopenharmony_ci * mppe.c - interface MPPE to the PPP code. 3195972f6Sopenharmony_ci * 4195972f6Sopenharmony_ci * By Frank Cusack <fcusack@fcusack.com>. 5195972f6Sopenharmony_ci * Copyright (c) 2002,2003,2004 Google, Inc. 6195972f6Sopenharmony_ci * All rights reserved. 7195972f6Sopenharmony_ci * 8195972f6Sopenharmony_ci * License: 9195972f6Sopenharmony_ci * Permission to use, copy, modify, and distribute this software and its 10195972f6Sopenharmony_ci * documentation is hereby granted, provided that the above copyright 11195972f6Sopenharmony_ci * notice appears in all copies. This software is provided without any 12195972f6Sopenharmony_ci * warranty, express or implied. 13195972f6Sopenharmony_ci * 14195972f6Sopenharmony_ci * Changelog: 15195972f6Sopenharmony_ci * 08/12/05 - Matt Domsch <Matt_Domsch@dell.com> 16195972f6Sopenharmony_ci * Only need extra skb padding on transmit, not receive. 17195972f6Sopenharmony_ci * 06/18/04 - Matt Domsch <Matt_Domsch@dell.com>, Oleg Makarenko <mole@quadra.ru> 18195972f6Sopenharmony_ci * Use Linux kernel 2.6 arc4 and sha1 routines rather than 19195972f6Sopenharmony_ci * providing our own. 20195972f6Sopenharmony_ci * 2/15/04 - TS: added #include <version.h> and testing for Kernel 21195972f6Sopenharmony_ci * version before using 22195972f6Sopenharmony_ci * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are 23195972f6Sopenharmony_ci * deprecated in 2.6 24195972f6Sopenharmony_ci */ 25195972f6Sopenharmony_ci 26195972f6Sopenharmony_ci#include "netif/ppp/ppp_opts.h" 27195972f6Sopenharmony_ci#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ 28195972f6Sopenharmony_ci 29195972f6Sopenharmony_ci#include <string.h> 30195972f6Sopenharmony_ci 31195972f6Sopenharmony_ci#include "lwip/err.h" 32195972f6Sopenharmony_ci 33195972f6Sopenharmony_ci#include "netif/ppp/ppp_impl.h" 34195972f6Sopenharmony_ci#include "netif/ppp/ccp.h" 35195972f6Sopenharmony_ci#include "netif/ppp/mppe.h" 36195972f6Sopenharmony_ci#include "netif/ppp/pppdebug.h" 37195972f6Sopenharmony_ci#include "netif/ppp/pppcrypt.h" 38195972f6Sopenharmony_ci 39195972f6Sopenharmony_ci#define SHA1_SIGNATURE_SIZE 20 40195972f6Sopenharmony_ci 41195972f6Sopenharmony_ci/* ppp_mppe_state.bits definitions */ 42195972f6Sopenharmony_ci#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ 43195972f6Sopenharmony_ci#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ 44195972f6Sopenharmony_ci#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ 45195972f6Sopenharmony_ci#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ 46195972f6Sopenharmony_ci 47195972f6Sopenharmony_ci#define MPPE_BIT_FLUSHED MPPE_BIT_A 48195972f6Sopenharmony_ci#define MPPE_BIT_ENCRYPTED MPPE_BIT_D 49195972f6Sopenharmony_ci 50195972f6Sopenharmony_ci#define MPPE_BITS(p) ((p)[0] & 0xf0) 51195972f6Sopenharmony_ci#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) 52195972f6Sopenharmony_ci#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ 53195972f6Sopenharmony_ci 54195972f6Sopenharmony_ci#define MPPE_OVHD 2 /* MPPE overhead/packet */ 55195972f6Sopenharmony_ci#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ 56195972f6Sopenharmony_ci 57195972f6Sopenharmony_ci/* 58195972f6Sopenharmony_ci * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. 59195972f6Sopenharmony_ci * Well, not what's written there, but rather what they meant. 60195972f6Sopenharmony_ci */ 61195972f6Sopenharmony_cistatic void mppe_rekey(ppp_mppe_state * state, int initial_key) 62195972f6Sopenharmony_ci{ 63195972f6Sopenharmony_ci lwip_sha1_context sha1_ctx; 64195972f6Sopenharmony_ci u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; 65195972f6Sopenharmony_ci 66195972f6Sopenharmony_ci /* 67195972f6Sopenharmony_ci * Key Derivation, from RFC 3078, RFC 3079. 68195972f6Sopenharmony_ci * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. 69195972f6Sopenharmony_ci */ 70195972f6Sopenharmony_ci lwip_sha1_init(&sha1_ctx); 71195972f6Sopenharmony_ci lwip_sha1_starts(&sha1_ctx); 72195972f6Sopenharmony_ci lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen); 73195972f6Sopenharmony_ci lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); 74195972f6Sopenharmony_ci lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen); 75195972f6Sopenharmony_ci lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); 76195972f6Sopenharmony_ci lwip_sha1_finish(&sha1_ctx, sha1_digest); 77195972f6Sopenharmony_ci lwip_sha1_free(&sha1_ctx); 78195972f6Sopenharmony_ci MEMCPY(state->session_key, sha1_digest, state->keylen); 79195972f6Sopenharmony_ci 80195972f6Sopenharmony_ci if (!initial_key) { 81195972f6Sopenharmony_ci lwip_arc4_init(&state->arc4); 82195972f6Sopenharmony_ci lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen); 83195972f6Sopenharmony_ci lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen); 84195972f6Sopenharmony_ci lwip_arc4_free(&state->arc4); 85195972f6Sopenharmony_ci } 86195972f6Sopenharmony_ci if (state->keylen == 8) { 87195972f6Sopenharmony_ci /* See RFC 3078 */ 88195972f6Sopenharmony_ci state->session_key[0] = 0xd1; 89195972f6Sopenharmony_ci state->session_key[1] = 0x26; 90195972f6Sopenharmony_ci state->session_key[2] = 0x9e; 91195972f6Sopenharmony_ci } 92195972f6Sopenharmony_ci lwip_arc4_init(&state->arc4); 93195972f6Sopenharmony_ci lwip_arc4_setup(&state->arc4, state->session_key, state->keylen); 94195972f6Sopenharmony_ci} 95195972f6Sopenharmony_ci 96195972f6Sopenharmony_ci/* 97195972f6Sopenharmony_ci * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we 98195972f6Sopenharmony_ci * don't have to keep multiple copies of keys. 99195972f6Sopenharmony_ci */ 100195972f6Sopenharmony_civoid mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { 101195972f6Sopenharmony_ci LWIP_UNUSED_ARG(pcb); 102195972f6Sopenharmony_ci MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); 103195972f6Sopenharmony_ci} 104195972f6Sopenharmony_ci 105195972f6Sopenharmony_ci/* 106195972f6Sopenharmony_ci * Initialize (de)compressor state. 107195972f6Sopenharmony_ci */ 108195972f6Sopenharmony_civoid 109195972f6Sopenharmony_cimppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) 110195972f6Sopenharmony_ci{ 111195972f6Sopenharmony_ci#if PPP_DEBUG 112195972f6Sopenharmony_ci const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; 113195972f6Sopenharmony_ci if (&pcb->mppe_decomp == state) { 114195972f6Sopenharmony_ci debugstr = (const u8_t*)"mppe_decomp_init"; 115195972f6Sopenharmony_ci } 116195972f6Sopenharmony_ci#endif /* PPP_DEBUG */ 117195972f6Sopenharmony_ci 118195972f6Sopenharmony_ci /* Save keys. */ 119195972f6Sopenharmony_ci MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); 120195972f6Sopenharmony_ci 121195972f6Sopenharmony_ci if (options & MPPE_OPT_128) 122195972f6Sopenharmony_ci state->keylen = 16; 123195972f6Sopenharmony_ci else if (options & MPPE_OPT_40) 124195972f6Sopenharmony_ci state->keylen = 8; 125195972f6Sopenharmony_ci else { 126195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, 127195972f6Sopenharmony_ci pcb->netif->num)); 128195972f6Sopenharmony_ci lcp_close(pcb, "MPPE required but peer negotiation failed"); 129195972f6Sopenharmony_ci return; 130195972f6Sopenharmony_ci } 131195972f6Sopenharmony_ci if (options & MPPE_OPT_STATEFUL) 132195972f6Sopenharmony_ci state->stateful = 1; 133195972f6Sopenharmony_ci 134195972f6Sopenharmony_ci /* Generate the initial session key. */ 135195972f6Sopenharmony_ci mppe_rekey(state, 1); 136195972f6Sopenharmony_ci 137195972f6Sopenharmony_ci#if PPP_DEBUG 138195972f6Sopenharmony_ci { 139195972f6Sopenharmony_ci int i; 140195972f6Sopenharmony_ci char mkey[sizeof(state->master_key) * 2 + 1]; 141195972f6Sopenharmony_ci char skey[sizeof(state->session_key) * 2 + 1]; 142195972f6Sopenharmony_ci 143195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", 144195972f6Sopenharmony_ci debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, 145195972f6Sopenharmony_ci (state->stateful) ? "stateful" : "stateless")); 146195972f6Sopenharmony_ci 147195972f6Sopenharmony_ci for (i = 0; i < (int)sizeof(state->master_key); i++) 148195972f6Sopenharmony_ci sprintf(mkey + i * 2, "%02x", state->master_key[i]); 149195972f6Sopenharmony_ci for (i = 0; i < (int)sizeof(state->session_key); i++) 150195972f6Sopenharmony_ci sprintf(skey + i * 2, "%02x", state->session_key[i]); 151195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, 152195972f6Sopenharmony_ci ("%s[%d]: keys: master: %s initial session: %s\n", 153195972f6Sopenharmony_ci debugstr, pcb->netif->num, mkey, skey)); 154195972f6Sopenharmony_ci } 155195972f6Sopenharmony_ci#endif /* PPP_DEBUG */ 156195972f6Sopenharmony_ci 157195972f6Sopenharmony_ci /* 158195972f6Sopenharmony_ci * Initialize the coherency count. The initial value is not specified 159195972f6Sopenharmony_ci * in RFC 3078, but we can make a reasonable assumption that it will 160195972f6Sopenharmony_ci * start at 0. Setting it to the max here makes the comp/decomp code 161195972f6Sopenharmony_ci * do the right thing (determined through experiment). 162195972f6Sopenharmony_ci */ 163195972f6Sopenharmony_ci state->ccount = MPPE_CCOUNT_SPACE - 1; 164195972f6Sopenharmony_ci 165195972f6Sopenharmony_ci /* 166195972f6Sopenharmony_ci * Note that even though we have initialized the key table, we don't 167195972f6Sopenharmony_ci * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. 168195972f6Sopenharmony_ci */ 169195972f6Sopenharmony_ci state->bits = MPPE_BIT_ENCRYPTED; 170195972f6Sopenharmony_ci} 171195972f6Sopenharmony_ci 172195972f6Sopenharmony_ci/* 173195972f6Sopenharmony_ci * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), 174195972f6Sopenharmony_ci * tell the compressor to rekey. Note that we MUST NOT rekey for 175195972f6Sopenharmony_ci * every CCP Reset-Request; we only rekey on the next xmit packet. 176195972f6Sopenharmony_ci * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. 177195972f6Sopenharmony_ci * So, rekeying for every CCP Reset-Request is broken as the peer will not 178195972f6Sopenharmony_ci * know how many times we've rekeyed. (If we rekey and THEN get another 179195972f6Sopenharmony_ci * CCP Reset-Request, we must rekey again.) 180195972f6Sopenharmony_ci */ 181195972f6Sopenharmony_civoid mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) 182195972f6Sopenharmony_ci{ 183195972f6Sopenharmony_ci LWIP_UNUSED_ARG(pcb); 184195972f6Sopenharmony_ci state->bits |= MPPE_BIT_FLUSHED; 185195972f6Sopenharmony_ci} 186195972f6Sopenharmony_ci 187195972f6Sopenharmony_ci/* 188195972f6Sopenharmony_ci * Compress (encrypt) a packet. 189195972f6Sopenharmony_ci * It's strange to call this a compressor, since the output is always 190195972f6Sopenharmony_ci * MPPE_OVHD + 2 bytes larger than the input. 191195972f6Sopenharmony_ci */ 192195972f6Sopenharmony_cierr_t 193195972f6Sopenharmony_cimppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) 194195972f6Sopenharmony_ci{ 195195972f6Sopenharmony_ci struct pbuf *n, *np; 196195972f6Sopenharmony_ci u8_t *pl; 197195972f6Sopenharmony_ci err_t err; 198195972f6Sopenharmony_ci 199195972f6Sopenharmony_ci LWIP_UNUSED_ARG(pcb); 200195972f6Sopenharmony_ci 201195972f6Sopenharmony_ci /* TCP stack requires that we don't change the packet payload, therefore we copy 202195972f6Sopenharmony_ci * the whole packet before encryption. 203195972f6Sopenharmony_ci */ 204195972f6Sopenharmony_ci np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_RAM); 205195972f6Sopenharmony_ci if (!np) { 206195972f6Sopenharmony_ci return ERR_MEM; 207195972f6Sopenharmony_ci } 208195972f6Sopenharmony_ci 209195972f6Sopenharmony_ci /* Hide MPPE header + protocol */ 210195972f6Sopenharmony_ci pbuf_remove_header(np, MPPE_OVHD + sizeof(protocol)); 211195972f6Sopenharmony_ci 212195972f6Sopenharmony_ci if ((err = pbuf_copy(np, *pb)) != ERR_OK) { 213195972f6Sopenharmony_ci pbuf_free(np); 214195972f6Sopenharmony_ci return err; 215195972f6Sopenharmony_ci } 216195972f6Sopenharmony_ci 217195972f6Sopenharmony_ci /* Reveal MPPE header + protocol */ 218195972f6Sopenharmony_ci pbuf_add_header(np, MPPE_OVHD + sizeof(protocol)); 219195972f6Sopenharmony_ci 220195972f6Sopenharmony_ci *pb = np; 221195972f6Sopenharmony_ci pl = (u8_t*)np->payload; 222195972f6Sopenharmony_ci 223195972f6Sopenharmony_ci state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 224195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); 225195972f6Sopenharmony_ci /* FIXME: use PUT* macros */ 226195972f6Sopenharmony_ci pl[0] = state->ccount>>8; 227195972f6Sopenharmony_ci pl[1] = state->ccount; 228195972f6Sopenharmony_ci 229195972f6Sopenharmony_ci if (!state->stateful || /* stateless mode */ 230195972f6Sopenharmony_ci ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ 231195972f6Sopenharmony_ci (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ 232195972f6Sopenharmony_ci /* We must rekey */ 233195972f6Sopenharmony_ci if (state->stateful) { 234195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); 235195972f6Sopenharmony_ci } 236195972f6Sopenharmony_ci mppe_rekey(state, 0); 237195972f6Sopenharmony_ci state->bits |= MPPE_BIT_FLUSHED; 238195972f6Sopenharmony_ci } 239195972f6Sopenharmony_ci pl[0] |= state->bits; 240195972f6Sopenharmony_ci state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ 241195972f6Sopenharmony_ci pl += MPPE_OVHD; 242195972f6Sopenharmony_ci 243195972f6Sopenharmony_ci /* Add protocol */ 244195972f6Sopenharmony_ci /* FIXME: add PFC support */ 245195972f6Sopenharmony_ci pl[0] = protocol >> 8; 246195972f6Sopenharmony_ci pl[1] = protocol; 247195972f6Sopenharmony_ci 248195972f6Sopenharmony_ci /* Hide MPPE header */ 249195972f6Sopenharmony_ci pbuf_remove_header(np, MPPE_OVHD); 250195972f6Sopenharmony_ci 251195972f6Sopenharmony_ci /* Encrypt packet */ 252195972f6Sopenharmony_ci for (n = np; n != NULL; n = n->next) { 253195972f6Sopenharmony_ci lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); 254195972f6Sopenharmony_ci if (n->tot_len == n->len) { 255195972f6Sopenharmony_ci break; 256195972f6Sopenharmony_ci } 257195972f6Sopenharmony_ci } 258195972f6Sopenharmony_ci 259195972f6Sopenharmony_ci /* Reveal MPPE header */ 260195972f6Sopenharmony_ci pbuf_add_header(np, MPPE_OVHD); 261195972f6Sopenharmony_ci 262195972f6Sopenharmony_ci return ERR_OK; 263195972f6Sopenharmony_ci} 264195972f6Sopenharmony_ci 265195972f6Sopenharmony_ci/* 266195972f6Sopenharmony_ci * We received a CCP Reset-Ack. Just ignore it. 267195972f6Sopenharmony_ci */ 268195972f6Sopenharmony_civoid mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) 269195972f6Sopenharmony_ci{ 270195972f6Sopenharmony_ci LWIP_UNUSED_ARG(pcb); 271195972f6Sopenharmony_ci LWIP_UNUSED_ARG(state); 272195972f6Sopenharmony_ci return; 273195972f6Sopenharmony_ci} 274195972f6Sopenharmony_ci 275195972f6Sopenharmony_ci/* 276195972f6Sopenharmony_ci * Decompress (decrypt) an MPPE packet. 277195972f6Sopenharmony_ci */ 278195972f6Sopenharmony_cierr_t 279195972f6Sopenharmony_cimppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) 280195972f6Sopenharmony_ci{ 281195972f6Sopenharmony_ci struct pbuf *n0 = *pb, *n; 282195972f6Sopenharmony_ci u8_t *pl; 283195972f6Sopenharmony_ci u16_t ccount; 284195972f6Sopenharmony_ci u8_t flushed; 285195972f6Sopenharmony_ci 286195972f6Sopenharmony_ci /* MPPE Header */ 287195972f6Sopenharmony_ci if (n0->len < MPPE_OVHD) { 288195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, 289195972f6Sopenharmony_ci ("mppe_decompress[%d]: short pkt (%d)\n", 290195972f6Sopenharmony_ci pcb->netif->num, n0->len)); 291195972f6Sopenharmony_ci state->sanity_errors += 100; 292195972f6Sopenharmony_ci goto sanity_error; 293195972f6Sopenharmony_ci } 294195972f6Sopenharmony_ci 295195972f6Sopenharmony_ci pl = (u8_t*)n0->payload; 296195972f6Sopenharmony_ci flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; 297195972f6Sopenharmony_ci ccount = MPPE_CCOUNT(pl); 298195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", 299195972f6Sopenharmony_ci pcb->netif->num, ccount)); 300195972f6Sopenharmony_ci 301195972f6Sopenharmony_ci /* sanity checks -- terminate with extreme prejudice */ 302195972f6Sopenharmony_ci if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { 303195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, 304195972f6Sopenharmony_ci ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", 305195972f6Sopenharmony_ci pcb->netif->num)); 306195972f6Sopenharmony_ci state->sanity_errors += 100; 307195972f6Sopenharmony_ci goto sanity_error; 308195972f6Sopenharmony_ci } 309195972f6Sopenharmony_ci if (!state->stateful && !flushed) { 310195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " 311195972f6Sopenharmony_ci "stateless mode!\n", pcb->netif->num)); 312195972f6Sopenharmony_ci state->sanity_errors += 100; 313195972f6Sopenharmony_ci goto sanity_error; 314195972f6Sopenharmony_ci } 315195972f6Sopenharmony_ci if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { 316195972f6Sopenharmony_ci PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " 317195972f6Sopenharmony_ci "flag packet!\n", pcb->netif->num)); 318195972f6Sopenharmony_ci state->sanity_errors += 100; 319195972f6Sopenharmony_ci goto sanity_error; 320195972f6Sopenharmony_ci } 321195972f6Sopenharmony_ci 322195972f6Sopenharmony_ci /* 323195972f6Sopenharmony_ci * Check the coherency count. 324195972f6Sopenharmony_ci */ 325195972f6Sopenharmony_ci 326195972f6Sopenharmony_ci if (!state->stateful) { 327195972f6Sopenharmony_ci /* Discard late packet */ 328195972f6Sopenharmony_ci if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { 329195972f6Sopenharmony_ci state->sanity_errors++; 330195972f6Sopenharmony_ci goto sanity_error; 331195972f6Sopenharmony_ci } 332195972f6Sopenharmony_ci 333195972f6Sopenharmony_ci /* RFC 3078, sec 8.1. Rekey for every packet. */ 334195972f6Sopenharmony_ci while (state->ccount != ccount) { 335195972f6Sopenharmony_ci mppe_rekey(state, 0); 336195972f6Sopenharmony_ci state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 337195972f6Sopenharmony_ci } 338195972f6Sopenharmony_ci } else { 339195972f6Sopenharmony_ci /* RFC 3078, sec 8.2. */ 340195972f6Sopenharmony_ci if (!state->discard) { 341195972f6Sopenharmony_ci /* normal state */ 342195972f6Sopenharmony_ci state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 343195972f6Sopenharmony_ci if (ccount != state->ccount) { 344195972f6Sopenharmony_ci /* 345195972f6Sopenharmony_ci * (ccount > state->ccount) 346195972f6Sopenharmony_ci * Packet loss detected, enter the discard state. 347195972f6Sopenharmony_ci * Signal the peer to rekey (by sending a CCP Reset-Request). 348195972f6Sopenharmony_ci */ 349195972f6Sopenharmony_ci state->discard = 1; 350195972f6Sopenharmony_ci ccp_resetrequest(pcb); 351195972f6Sopenharmony_ci return ERR_BUF; 352195972f6Sopenharmony_ci } 353195972f6Sopenharmony_ci } else { 354195972f6Sopenharmony_ci /* discard state */ 355195972f6Sopenharmony_ci if (!flushed) { 356195972f6Sopenharmony_ci /* ccp.c will be silent (no additional CCP Reset-Requests). */ 357195972f6Sopenharmony_ci return ERR_BUF; 358195972f6Sopenharmony_ci } else { 359195972f6Sopenharmony_ci /* Rekey for every missed "flag" packet. */ 360195972f6Sopenharmony_ci while ((ccount & ~0xff) != 361195972f6Sopenharmony_ci (state->ccount & ~0xff)) { 362195972f6Sopenharmony_ci mppe_rekey(state, 0); 363195972f6Sopenharmony_ci state->ccount = 364195972f6Sopenharmony_ci (state->ccount + 365195972f6Sopenharmony_ci 256) % MPPE_CCOUNT_SPACE; 366195972f6Sopenharmony_ci } 367195972f6Sopenharmony_ci 368195972f6Sopenharmony_ci /* reset */ 369195972f6Sopenharmony_ci state->discard = 0; 370195972f6Sopenharmony_ci state->ccount = ccount; 371195972f6Sopenharmony_ci /* 372195972f6Sopenharmony_ci * Another problem with RFC 3078 here. It implies that the 373195972f6Sopenharmony_ci * peer need not send a Reset-Ack packet. But RFC 1962 374195972f6Sopenharmony_ci * requires it. Hopefully, M$ does send a Reset-Ack; even 375195972f6Sopenharmony_ci * though it isn't required for MPPE synchronization, it is 376195972f6Sopenharmony_ci * required to reset CCP state. 377195972f6Sopenharmony_ci */ 378195972f6Sopenharmony_ci } 379195972f6Sopenharmony_ci } 380195972f6Sopenharmony_ci if (flushed) 381195972f6Sopenharmony_ci mppe_rekey(state, 0); 382195972f6Sopenharmony_ci } 383195972f6Sopenharmony_ci 384195972f6Sopenharmony_ci /* Hide MPPE header */ 385195972f6Sopenharmony_ci pbuf_remove_header(n0, MPPE_OVHD); 386195972f6Sopenharmony_ci 387195972f6Sopenharmony_ci /* Decrypt the packet. */ 388195972f6Sopenharmony_ci for (n = n0; n != NULL; n = n->next) { 389195972f6Sopenharmony_ci lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); 390195972f6Sopenharmony_ci if (n->tot_len == n->len) { 391195972f6Sopenharmony_ci break; 392195972f6Sopenharmony_ci } 393195972f6Sopenharmony_ci } 394195972f6Sopenharmony_ci 395195972f6Sopenharmony_ci /* good packet credit */ 396195972f6Sopenharmony_ci state->sanity_errors >>= 1; 397195972f6Sopenharmony_ci 398195972f6Sopenharmony_ci return ERR_OK; 399195972f6Sopenharmony_ci 400195972f6Sopenharmony_cisanity_error: 401195972f6Sopenharmony_ci if (state->sanity_errors >= SANITY_MAX) { 402195972f6Sopenharmony_ci /* 403195972f6Sopenharmony_ci * Take LCP down if the peer is sending too many bogons. 404195972f6Sopenharmony_ci * We don't want to do this for a single or just a few 405195972f6Sopenharmony_ci * instances since it could just be due to packet corruption. 406195972f6Sopenharmony_ci */ 407195972f6Sopenharmony_ci lcp_close(pcb, "Too many MPPE errors"); 408195972f6Sopenharmony_ci } 409195972f6Sopenharmony_ci return ERR_BUF; 410195972f6Sopenharmony_ci} 411195972f6Sopenharmony_ci 412195972f6Sopenharmony_ci#endif /* PPP_SUPPORT && MPPE_SUPPORT */ 413