Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
mppe.c
00001 /* 00002 * mppe.c - interface MPPE to the PPP code. 00003 * 00004 * By Frank Cusack <fcusack@fcusack.com>. 00005 * Copyright (c) 2002,2003,2004 Google, Inc. 00006 * All rights reserved. 00007 * 00008 * License: 00009 * Permission to use, copy, modify, and distribute this software and its 00010 * documentation is hereby granted, provided that the above copyright 00011 * notice appears in all copies. This software is provided without any 00012 * warranty, express or implied. 00013 * 00014 * Changelog: 00015 * 08/12/05 - Matt Domsch <Matt_Domsch@dell.com> 00016 * Only need extra skb padding on transmit, not receive. 00017 * 06/18/04 - Matt Domsch <Matt_Domsch@dell.com>, Oleg Makarenko <mole@quadra.ru> 00018 * Use Linux kernel 2.6 arc4 and sha1 routines rather than 00019 * providing our own. 00020 * 2/15/04 - TS: added #include <version.h> and testing for Kernel 00021 * version before using 00022 * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are 00023 * deprecated in 2.6 00024 */ 00025 00026 #include "ppp_opts.h" 00027 #if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in ppp_opts.h */ 00028 00029 #include <string.h> 00030 00031 #include "ppp_impl.h" 00032 #include "ccp.h" 00033 #include "mppe.h" 00034 #include "pppdebug.h" 00035 #include "pppcrypt.h" 00036 00037 #define SHA1_SIGNATURE_SIZE 20 00038 00039 /* ppp_mppe_state.bits definitions */ 00040 #define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ 00041 #define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ 00042 #define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ 00043 #define MPPE_BIT_D 0x10 /* This is an encrypted frame */ 00044 00045 #define MPPE_BIT_FLUSHED MPPE_BIT_A 00046 #define MPPE_BIT_ENCRYPTED MPPE_BIT_D 00047 00048 #define MPPE_BITS(p) ((p)[0] & 0xf0) 00049 #define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) 00050 #define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ 00051 00052 #define MPPE_OVHD 2 /* MPPE overhead/packet */ 00053 #define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ 00054 00055 /* 00056 * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. 00057 * Well, not what's written there, but rather what they meant. 00058 */ 00059 static void mppe_rekey(ppp_mppe_state * state, int initial_key) 00060 { 00061 ppp_sha1_context sha1_ctx; 00062 u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; 00063 00064 /* 00065 * Key Derivation, from RFC 3078, RFC 3079. 00066 * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. 00067 */ 00068 ppp_sha1_init(&sha1_ctx); 00069 ppp_sha1_starts(&sha1_ctx); 00070 ppp_sha1_update(&sha1_ctx, state->master_key, state->keylen); 00071 ppp_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); 00072 ppp_sha1_update(&sha1_ctx, state->session_key, state->keylen); 00073 ppp_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); 00074 ppp_sha1_finish(&sha1_ctx, sha1_digest); 00075 ppp_sha1_free(&sha1_ctx); 00076 MEMCPY(state->session_key, sha1_digest, state->keylen); 00077 00078 if (!initial_key) { 00079 ARC4_init(&state->arc4); 00080 ARC4_setup(&state->arc4, sha1_digest, state->keylen); 00081 ARC4_crypt(&state->arc4, state->session_key, state->keylen); 00082 ARC4_free(&state->arc4); 00083 } 00084 if (state->keylen == 8) { 00085 /* See RFC 3078 */ 00086 state->session_key[0] = 0xd1; 00087 state->session_key[1] = 0x26; 00088 state->session_key[2] = 0x9e; 00089 } 00090 ARC4_init(&state->arc4); 00091 ARC4_setup(&state->arc4, state->session_key, state->keylen); 00092 } 00093 00094 /* 00095 * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we 00096 * don't have to keep multiple copies of keys. 00097 */ 00098 void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { 00099 PPP_UNUSED_ARG(pcb); 00100 MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); 00101 } 00102 00103 /* 00104 * Initialize (de)compressor state. 00105 */ 00106 void 00107 mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) 00108 { 00109 #if PPP_DEBUG 00110 const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; 00111 if (&pcb->mppe_decomp == state) { 00112 debugstr = (const u8_t*)"mppe_decomp_init"; 00113 } 00114 #endif /* PPP_DEBUG */ 00115 00116 /* Save keys. */ 00117 MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); 00118 00119 if (options & MPPE_OPT_128) 00120 state->keylen = 16; 00121 else if (options & MPPE_OPT_40) 00122 state->keylen = 8; 00123 else { 00124 PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, 00125 pcb->netif->num)); 00126 lcp_close(pcb, "MPPE required but peer negotiation failed"); 00127 return; 00128 } 00129 if (options & MPPE_OPT_STATEFUL) 00130 state->stateful = 1; 00131 00132 /* Generate the initial session key. */ 00133 mppe_rekey(state, 1); 00134 00135 #if PPP_DEBUG 00136 { 00137 int i; 00138 char mkey[sizeof(state->master_key) * 2 + 1]; 00139 char skey[sizeof(state->session_key) * 2 + 1]; 00140 00141 PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", 00142 debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, 00143 (state->stateful) ? "stateful" : "stateless")); 00144 00145 for (i = 0; i < (int)sizeof(state->master_key); i++) 00146 sprintf(mkey + i * 2, "%02x", state->master_key[i]); 00147 for (i = 0; i < (int)sizeof(state->session_key); i++) 00148 sprintf(skey + i * 2, "%02x", state->session_key[i]); 00149 PPPDEBUG(LOG_DEBUG, 00150 ("%s[%d]: keys: master: %s initial session: %s\n", 00151 debugstr, pcb->netif->num, mkey, skey)); 00152 } 00153 #endif /* PPP_DEBUG */ 00154 00155 /* 00156 * Initialize the coherency count. The initial value is not specified 00157 * in RFC 3078, but we can make a reasonable assumption that it will 00158 * start at 0. Setting it to the max here makes the comp/decomp code 00159 * do the right thing (determined through experiment). 00160 */ 00161 state->ccount = MPPE_CCOUNT_SPACE - 1; 00162 00163 /* 00164 * Note that even though we have initialized the key table, we don't 00165 * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. 00166 */ 00167 state->bits = MPPE_BIT_ENCRYPTED; 00168 } 00169 00170 /* 00171 * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), 00172 * tell the compressor to rekey. Note that we MUST NOT rekey for 00173 * every CCP Reset-Request; we only rekey on the next xmit packet. 00174 * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. 00175 * So, rekeying for every CCP Reset-Request is broken as the peer will not 00176 * know how many times we've rekeyed. (If we rekey and THEN get another 00177 * CCP Reset-Request, we must rekey again.) 00178 */ 00179 void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) 00180 { 00181 PPP_UNUSED_ARG(pcb); 00182 state->bits |= MPPE_BIT_FLUSHED; 00183 } 00184 00185 /* 00186 * Compress (encrypt) a packet. 00187 * It's strange to call this a compressor, since the output is always 00188 * MPPE_OVHD + 2 bytes larger than the input. 00189 */ 00190 err_t 00191 mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) 00192 { 00193 struct pbuf *n, *np; 00194 u8_t *pl; 00195 err_t err; 00196 00197 PPP_UNUSED_ARG(pcb); 00198 00199 /* TCP stack requires that we don't change the packet payload, therefore we copy 00200 * the whole packet before encryption. 00201 */ 00202 np = ppp_memory_buffer_allocate(pcb->netif->memory_manager, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PPP_BUF_HEAP); 00203 if (!np) { 00204 return ERR_MEM; 00205 } 00206 00207 /* Hide MPPE header + protocol */ 00208 pbuf_remove_header(np, MPPE_OVHD + sizeof(protocol)); 00209 00210 if ((err = pbuf_copy(np, *pb)) != ERR_OK) { 00211 ppp_memory_buffer_free(np); 00212 return err; 00213 } 00214 00215 /* Reveal MPPE header + protocol */ 00216 pbuf_add_header(np, MPPE_OVHD + sizeof(protocol)); 00217 00218 *pb = np; 00219 pl = (u8_t*)np->payload; 00220 00221 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 00222 PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); 00223 /* FIXME: use PUT* macros */ 00224 pl[0] = state->ccount>>8; 00225 pl[1] = state->ccount; 00226 00227 if (!state->stateful || /* stateless mode */ 00228 ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ 00229 (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ 00230 /* We must rekey */ 00231 if (state->stateful) { 00232 PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); 00233 } 00234 mppe_rekey(state, 0); 00235 state->bits |= MPPE_BIT_FLUSHED; 00236 } 00237 pl[0] |= state->bits; 00238 state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ 00239 pl += MPPE_OVHD; 00240 00241 /* Add protocol */ 00242 /* FIXME: add PFC support */ 00243 pl[0] = protocol >> 8; 00244 pl[1] = protocol; 00245 00246 /* Hide MPPE header */ 00247 pbuf_remove_header(np, MPPE_OVHD); 00248 00249 /* Encrypt packet */ 00250 for (n = np; n != NULL; n = n->next) { 00251 ARC4_crypt(&state->arc4, (u8_t*)n->payload, n->len); 00252 if (n->tot_len == n->len) { 00253 break; 00254 } 00255 } 00256 00257 /* Reveal MPPE header */ 00258 pbuf_add_header(np, MPPE_OVHD); 00259 00260 return ERR_OK; 00261 } 00262 00263 /* 00264 * We received a CCP Reset-Ack. Just ignore it. 00265 */ 00266 void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) 00267 { 00268 PPP_UNUSED_ARG(pcb); 00269 PPP_UNUSED_ARG(state); 00270 return; 00271 } 00272 00273 /* 00274 * Decompress (decrypt) an MPPE packet. 00275 */ 00276 err_t 00277 mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) 00278 { 00279 struct pbuf *n0 = *pb, *n; 00280 u8_t *pl; 00281 u16_t ccount; 00282 u8_t flushed; 00283 00284 /* MPPE Header */ 00285 if (n0->len < MPPE_OVHD) { 00286 PPPDEBUG(LOG_DEBUG, 00287 ("mppe_decompress[%d]: short pkt (%d)\n", 00288 pcb->netif->num, n0->len)); 00289 state->sanity_errors += 100; 00290 goto sanity_error; 00291 } 00292 00293 pl = (u8_t*)n0->payload; 00294 flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; 00295 ccount = MPPE_CCOUNT(pl); 00296 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", 00297 pcb->netif->num, ccount)); 00298 00299 /* sanity checks -- terminate with extreme prejudice */ 00300 if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { 00301 PPPDEBUG(LOG_DEBUG, 00302 ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", 00303 pcb->netif->num)); 00304 state->sanity_errors += 100; 00305 goto sanity_error; 00306 } 00307 if (!state->stateful && !flushed) { 00308 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " 00309 "stateless mode!\n", pcb->netif->num)); 00310 state->sanity_errors += 100; 00311 goto sanity_error; 00312 } 00313 if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { 00314 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " 00315 "flag packet!\n", pcb->netif->num)); 00316 state->sanity_errors += 100; 00317 goto sanity_error; 00318 } 00319 00320 /* 00321 * Check the coherency count. 00322 */ 00323 00324 if (!state->stateful) { 00325 /* Discard late packet */ 00326 if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { 00327 state->sanity_errors++; 00328 goto sanity_error; 00329 } 00330 00331 /* RFC 3078, sec 8.1. Rekey for every packet. */ 00332 while (state->ccount != ccount) { 00333 mppe_rekey(state, 0); 00334 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 00335 } 00336 } else { 00337 /* RFC 3078, sec 8.2. */ 00338 if (!state->discard) { 00339 /* normal state */ 00340 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; 00341 if (ccount != state->ccount) { 00342 /* 00343 * (ccount > state->ccount) 00344 * Packet loss detected, enter the discard state. 00345 * Signal the peer to rekey (by sending a CCP Reset-Request). 00346 */ 00347 state->discard = 1; 00348 ccp_resetrequest(pcb); 00349 return ERR_BUF; 00350 } 00351 } else { 00352 /* discard state */ 00353 if (!flushed) { 00354 /* ccp.c will be silent (no additional CCP Reset-Requests). */ 00355 return ERR_BUF; 00356 } else { 00357 /* Rekey for every missed "flag" packet. */ 00358 while ((ccount & ~0xff) != 00359 (state->ccount & ~0xff)) { 00360 mppe_rekey(state, 0); 00361 state->ccount = 00362 (state->ccount + 00363 256) % MPPE_CCOUNT_SPACE; 00364 } 00365 00366 /* reset */ 00367 state->discard = 0; 00368 state->ccount = ccount; 00369 /* 00370 * Another problem with RFC 3078 here. It implies that the 00371 * peer need not send a Reset-Ack packet. But RFC 1962 00372 * requires it. Hopefully, M$ does send a Reset-Ack; even 00373 * though it isn't required for MPPE synchronization, it is 00374 * required to reset CCP state. 00375 */ 00376 } 00377 } 00378 if (flushed) 00379 mppe_rekey(state, 0); 00380 } 00381 00382 /* Hide MPPE header */ 00383 pbuf_remove_header(n0, MPPE_OVHD); 00384 00385 /* Decrypt the packet. */ 00386 for (n = n0; n != NULL; n = n->next) { 00387 ARC4_crypt(&state->arc4, (u8_t*)n->payload, n->len); 00388 if (n->tot_len == n->len) { 00389 break; 00390 } 00391 } 00392 00393 /* good packet credit */ 00394 state->sanity_errors >>= 1; 00395 00396 return ERR_OK; 00397 00398 sanity_error: 00399 if (state->sanity_errors >= SANITY_MAX) { 00400 /* 00401 * Take LCP down if the peer is sending too many bogons. 00402 * We don't want to do this for a single or just a few 00403 * instances since it could just be due to packet corruption. 00404 */ 00405 lcp_close(pcb, "Too many MPPE errors"); 00406 } 00407 return ERR_BUF; 00408 } 00409 00410 #endif /* PPP_SUPPORT && MPPE_SUPPORT */
Generated on Tue Jul 12 2022 13:54:35 by
1.7.2