Line 0
Link Here
|
|
|
1 |
/* |
2 |
* ppp_mppe_compress.c - interface MPPE to the PPP code. |
3 |
* This version is for use with Linux kernel 2.2.19+, 2.4.18+ and 2.6.2+. |
4 |
* |
5 |
* By Frank Cusack <frank@google.com>. |
6 |
* Copyright (c) 2002,2003,2004 Google, Inc. |
7 |
* All rights reserved. |
8 |
* |
9 |
* Permission to use, copy, modify, and distribute this software and its |
10 |
* documentation is hereby granted, provided that the above copyright |
11 |
* notice appears in all copies. This software is provided without any |
12 |
* warranty, express or implied. |
13 |
* |
14 |
* Changelog: |
15 |
* 2/15/04 - TS: added #include <version.h> and testing for Kernel |
16 |
* version before using |
17 |
* MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are |
18 |
* deprecated in 2.6 |
19 |
*/ |
20 |
|
21 |
#include <linux/module.h> |
22 |
#include <linux/kernel.h> |
23 |
#include <linux/version.h> |
24 |
#include <linux/init.h> |
25 |
#include <linux/types.h> |
26 |
#include <linux/slab.h> |
27 |
#include <linux/string.h> |
28 |
|
29 |
#include <linux/ppp_defs.h> |
30 |
#include <linux/ppp-comp.h> |
31 |
#include "ppp-comp-local.h" |
32 |
|
33 |
#include "arcfour.h" |
34 |
#include "sha1.h" |
35 |
|
36 |
/* |
37 |
* State for an MPPE (de)compressor. |
38 |
*/ |
39 |
typedef struct ppp_mppe_state { |
40 |
unsigned char master_key[MPPE_MAX_KEY_LEN]; |
41 |
unsigned char session_key[MPPE_MAX_KEY_LEN]; |
42 |
arcfour_context arcfour_context; /* encryption state */ |
43 |
unsigned keylen; /* key length in bytes */ |
44 |
/* NB: 128-bit == 16, 40-bit == 8! */ |
45 |
/* If we want to support 56-bit, */ |
46 |
/* the unit has to change to bits */ |
47 |
unsigned char bits; /* MPPE control bits */ |
48 |
unsigned ccount; /* 12-bit coherency count (seqno) */ |
49 |
unsigned stateful; /* stateful mode flag */ |
50 |
int discard; /* stateful mode packet loss flag */ |
51 |
int sanity_errors; /* take down LCP if too many */ |
52 |
int unit; |
53 |
int debug; |
54 |
struct compstat stats; |
55 |
} ppp_mppe_state; |
56 |
|
57 |
/* ppp_mppe_state.bits definitions */ |
58 |
#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ |
59 |
#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ |
60 |
#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ |
61 |
#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ |
62 |
|
63 |
#define MPPE_BIT_FLUSHED MPPE_BIT_A |
64 |
#define MPPE_BIT_ENCRYPTED MPPE_BIT_D |
65 |
|
66 |
#define MPPE_BITS(p) ((p)[4] & 0xf0) |
67 |
#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) |
68 |
#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ |
69 |
|
70 |
#define MPPE_OVHD 2 /* MPPE overhead/packet */ |
71 |
#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ |
72 |
|
73 |
static void GetNewKeyFromSHA __P((unsigned char *StartKey, |
74 |
unsigned char *SessionKey, |
75 |
unsigned SessionKeyLength, |
76 |
unsigned char *InterimKey)); |
77 |
static void mppe_rekey __P((ppp_mppe_state *state, int)); |
78 |
static void *mppe_alloc __P((unsigned char *options, int optlen)); |
79 |
static void mppe_free __P((void *state)); |
80 |
static int mppe_init __P((void *state, unsigned char *options, |
81 |
int optlen, int unit, int debug, const char *)); |
82 |
static int mppe_comp_init __P((void *state, unsigned char *options, |
83 |
int optlen, |
84 |
int unit, int hdrlen, int debug)); |
85 |
static int mppe_decomp_init __P((void *state, unsigned char *options, |
86 |
int optlen, int unit, |
87 |
int hdrlen, int mru, int debug)); |
88 |
static int mppe_compress __P((void *state, unsigned char *ibuf, |
89 |
unsigned char *obuf, |
90 |
int isize, int osize)); |
91 |
static void mppe_incomp __P((void *state, unsigned char *ibuf, int icnt)); |
92 |
static int mppe_decompress __P((void *state, unsigned char *ibuf, |
93 |
int isize, unsigned char *obuf,int osize)); |
94 |
static void mppe_comp_reset __P((void *state)); |
95 |
static void mppe_decomp_reset __P((void *state)); |
96 |
static void mppe_comp_stats __P((void *state, struct compstat *stats)); |
97 |
|
98 |
|
99 |
/* |
100 |
* Key Derivation, from RFC 3078, RFC 3079. |
101 |
* Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. |
102 |
*/ |
103 |
static void |
104 |
GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey, |
105 |
unsigned SessionKeyLength, unsigned char *InterimKey) |
106 |
{ |
107 |
SHA1_CTX Context; |
108 |
unsigned char Digest[SHA1_SIGNATURE_SIZE]; |
109 |
|
110 |
unsigned char SHApad1[40] = |
111 |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
112 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
113 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
114 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
115 |
unsigned char SHApad2[40] = |
116 |
{ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, |
117 |
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, |
118 |
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, |
119 |
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; |
120 |
|
121 |
/* assert(SessionKeyLength <= SHA1_SIGNATURE_SIZE); */ |
122 |
|
123 |
SHA1_Init(&Context); |
124 |
SHA1_Update(&Context, MasterKey, SessionKeyLength); |
125 |
SHA1_Update(&Context, SHApad1, sizeof(SHApad1)); |
126 |
SHA1_Update(&Context, SessionKey, SessionKeyLength); |
127 |
SHA1_Update(&Context, SHApad2, sizeof(SHApad2)); |
128 |
SHA1_Final(Digest, &Context); |
129 |
|
130 |
memcpy(InterimKey, Digest, SessionKeyLength); |
131 |
} |
132 |
|
133 |
/* |
134 |
* Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. |
135 |
* Well, not what's written there, but rather what they meant. |
136 |
*/ |
137 |
static void |
138 |
mppe_rekey(ppp_mppe_state *state, int initial_key) |
139 |
{ |
140 |
unsigned char InterimKey[MPPE_MAX_KEY_LEN]; |
141 |
|
142 |
GetNewKeyFromSHA(state->master_key, state->session_key, |
143 |
state->keylen, InterimKey); |
144 |
if (!initial_key) { |
145 |
arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen); |
146 |
arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen, |
147 |
state->session_key); |
148 |
} else { |
149 |
memcpy(state->session_key, InterimKey, state->keylen); |
150 |
} |
151 |
if (state->keylen == 8) { |
152 |
/* See RFC 3078 */ |
153 |
state->session_key[0] = 0xd1; |
154 |
state->session_key[1] = 0x26; |
155 |
state->session_key[2] = 0x9e; |
156 |
} |
157 |
arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen); |
158 |
} |
159 |
|
160 |
|
161 |
/* |
162 |
* Allocate space for a (de)compressor. |
163 |
*/ |
164 |
static void * |
165 |
mppe_alloc(unsigned char *options, int optlen) |
166 |
{ |
167 |
ppp_mppe_state *state; |
168 |
|
169 |
if (optlen != CILEN_MPPE + sizeof(state->master_key) |
170 |
|| options[0] != CI_MPPE |
171 |
|| options[1] != CILEN_MPPE) |
172 |
return NULL; |
173 |
|
174 |
state = (ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); |
175 |
if (state == NULL) |
176 |
return NULL; |
177 |
|
178 |
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) |
179 |
try_module_get(THIS_MODULE); |
180 |
#else |
181 |
MOD_INC_USE_COUNT; |
182 |
#endif |
183 |
memset(state, 0, sizeof(*state)); |
184 |
|
185 |
/* Save keys. */ |
186 |
memcpy(state->master_key, &options[CILEN_MPPE], sizeof(state->master_key)); |
187 |
memcpy(state->session_key, state->master_key, sizeof(state->master_key)); |
188 |
/* |
189 |
* We defer initial key generation until mppe_init(), as mppe_alloc() |
190 |
* is called frequently during negotiation. |
191 |
*/ |
192 |
|
193 |
return (void *) state; |
194 |
} |
195 |
|
196 |
/* |
197 |
* Deallocate space for a (de)compressor. |
198 |
*/ |
199 |
static void |
200 |
mppe_free(void *arg) |
201 |
{ |
202 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
203 |
|
204 |
if (state) { |
205 |
kfree(state); |
206 |
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) |
207 |
module_put(THIS_MODULE); |
208 |
#else |
209 |
MOD_DEC_USE_COUNT; |
210 |
#endif |
211 |
} |
212 |
} |
213 |
|
214 |
|
215 |
/* |
216 |
* Initialize (de)compressor state. |
217 |
*/ |
218 |
static int |
219 |
mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, |
220 |
const char *debugstr) |
221 |
{ |
222 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
223 |
unsigned char mppe_opts; |
224 |
|
225 |
if (optlen != CILEN_MPPE |
226 |
|| options[0] != CI_MPPE |
227 |
|| options[1] != CILEN_MPPE) |
228 |
return 0; |
229 |
|
230 |
MPPE_CI_TO_OPTS(&options[2], mppe_opts); |
231 |
if (mppe_opts & MPPE_OPT_128) |
232 |
state->keylen = 16; |
233 |
else if (mppe_opts & MPPE_OPT_40) |
234 |
state->keylen = 8; |
235 |
else { |
236 |
printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, unit); |
237 |
return 0; |
238 |
} |
239 |
if (mppe_opts & MPPE_OPT_STATEFUL) |
240 |
state->stateful = 1; |
241 |
|
242 |
/* Generate the initial session key. */ |
243 |
mppe_rekey(state, 1); |
244 |
|
245 |
if (debug) { |
246 |
int i; |
247 |
char mkey[sizeof(state->master_key) * 2 + 1]; |
248 |
char skey[sizeof(state->session_key) * 2 + 1]; |
249 |
|
250 |
printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr, |
251 |
unit, (state->keylen == 16)? 128: 40, |
252 |
(state->stateful)? "stateful": "stateless"); |
253 |
|
254 |
for (i = 0; i < sizeof(state->master_key); i++) |
255 |
sprintf(mkey + i * 2, "%.2x", state->master_key[i]); |
256 |
for (i = 0; i < sizeof(state->session_key); i++) |
257 |
sprintf(skey + i * 2, "%.2x", state->session_key[i]); |
258 |
printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n", |
259 |
debugstr, unit, mkey, skey); |
260 |
} |
261 |
|
262 |
/* |
263 |
* Initialize the coherency count. The initial value is not specified |
264 |
* in RFC 3078, but we can make a reasonable assumption that it will |
265 |
* start at 0. Setting it to the max here makes the comp/decomp code |
266 |
* do the right thing (determined through experiment). |
267 |
*/ |
268 |
state->ccount = MPPE_CCOUNT_SPACE - 1; |
269 |
|
270 |
/* |
271 |
* Note that even though we have initialized the key table, we don't |
272 |
* set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. |
273 |
*/ |
274 |
state->bits = MPPE_BIT_ENCRYPTED; |
275 |
|
276 |
state->unit = unit; |
277 |
state->debug = debug; |
278 |
|
279 |
return 1; |
280 |
} |
281 |
|
282 |
|
283 |
|
284 |
static int |
285 |
mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit, |
286 |
int hdrlen, int debug) |
287 |
{ |
288 |
/* ARGSUSED */ |
289 |
return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init"); |
290 |
} |
291 |
|
292 |
/* |
293 |
* We received a CCP Reset-Request (actually, we are sending a Reset-Ack), |
294 |
* tell the compressor to rekey. Note that we MUST NOT rekey for |
295 |
* every CCP Reset-Request; we only rekey on the next xmit packet. |
296 |
* We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. |
297 |
* So, rekeying for every CCP Reset-Request is broken as the peer will not |
298 |
* know how many times we've rekeyed. (If we rekey and THEN get another |
299 |
* CCP Reset-Request, we must rekey again.) |
300 |
*/ |
301 |
static void |
302 |
mppe_comp_reset(void *arg) |
303 |
{ |
304 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
305 |
|
306 |
state->bits |= MPPE_BIT_FLUSHED; |
307 |
} |
308 |
|
309 |
/* |
310 |
* Compress (encrypt) a packet. |
311 |
* It's strange to call this a compressor, since the output is always |
312 |
* MPPE_OVHD + 2 bytes larger than the input. |
313 |
*/ |
314 |
int |
315 |
mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, |
316 |
int isize, int osize) |
317 |
{ |
318 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
319 |
int proto; |
320 |
|
321 |
/* |
322 |
* Check that the protocol is in the range we handle. |
323 |
*/ |
324 |
proto = PPP_PROTOCOL(ibuf); |
325 |
if (proto < 0x0021 || proto > 0x00fa) |
326 |
return 0; |
327 |
|
328 |
/* Make sure we have enough room to generate an encrypted packet. */ |
329 |
if (osize < isize + MPPE_OVHD + 2) { |
330 |
/* Drop the packet if we should encrypt it, but can't. */ |
331 |
printk(KERN_DEBUG "mppe_compress[%d]: osize too small! " |
332 |
"(have: %d need: %d)\n", state->unit, |
333 |
osize, osize + MPPE_OVHD + 2); |
334 |
return -1; |
335 |
} |
336 |
|
337 |
osize = isize + MPPE_OVHD + 2; |
338 |
|
339 |
/* |
340 |
* Copy over the PPP header and set control bits. |
341 |
*/ |
342 |
obuf[0] = PPP_ADDRESS(ibuf); |
343 |
obuf[1] = PPP_CONTROL(ibuf); |
344 |
obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */ |
345 |
obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */ |
346 |
obuf += PPP_HDRLEN; |
347 |
|
348 |
state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; |
349 |
if (state->debug >= 7) |
350 |
printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit, |
351 |
state->ccount); |
352 |
obuf[0] = state->ccount >> 8; |
353 |
obuf[1] = state->ccount & 0xff; |
354 |
|
355 |
if (!state->stateful || /* stateless mode */ |
356 |
((state->ccount & 0xff) == 0xff) || /* "flag" packet */ |
357 |
(state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ |
358 |
/* We must rekey */ |
359 |
if (state->debug && state->stateful) |
360 |
printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", state->unit); |
361 |
mppe_rekey(state, 0); |
362 |
state->bits |= MPPE_BIT_FLUSHED; |
363 |
} |
364 |
obuf[0] |= state->bits; |
365 |
state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ |
366 |
|
367 |
obuf += MPPE_OVHD; |
368 |
ibuf += 2; /* skip to proto field */ |
369 |
isize -= 2; |
370 |
|
371 |
/* Encrypt packet */ |
372 |
arcfour_encrypt(&state->arcfour_context, ibuf, isize, obuf); |
373 |
|
374 |
state->stats.unc_bytes += isize; |
375 |
state->stats.unc_packets++; |
376 |
state->stats.comp_bytes += osize; |
377 |
state->stats.comp_packets++; |
378 |
|
379 |
return osize; |
380 |
} |
381 |
|
382 |
/* |
383 |
* Since every frame grows by MPPE_OVHD + 2 bytes, this is always going |
384 |
* to look bad ... and the longer the link is up the worse it will get. |
385 |
*/ |
386 |
static void |
387 |
mppe_comp_stats(void *arg, struct compstat *stats) |
388 |
{ |
389 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
390 |
|
391 |
*stats = state->stats; |
392 |
} |
393 |
|
394 |
|
395 |
static int |
396 |
mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit, |
397 |
int hdrlen, int mru, int debug) |
398 |
{ |
399 |
/* ARGSUSED */ |
400 |
return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init"); |
401 |
} |
402 |
|
403 |
/* |
404 |
* We received a CCP Reset-Ack. Just ignore it. |
405 |
*/ |
406 |
static void |
407 |
mppe_decomp_reset(void *arg) |
408 |
{ |
409 |
/* ARGSUSED */ |
410 |
return; |
411 |
} |
412 |
|
413 |
/* |
414 |
* Decompress (decrypt) an MPPE packet. |
415 |
*/ |
416 |
int |
417 |
mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, |
418 |
int osize) |
419 |
{ |
420 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
421 |
unsigned ccount; |
422 |
int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; |
423 |
int sanity = 0; |
424 |
|
425 |
if (isize <= PPP_HDRLEN + MPPE_OVHD) { |
426 |
if (state->debug) |
427 |
printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n", |
428 |
state->unit, isize); |
429 |
return DECOMP_ERROR; |
430 |
} |
431 |
|
432 |
/* |
433 |
* Make sure we have enough room to decrypt the packet. |
434 |
* Note that for our test we only subtract 1 byte whereas in |
435 |
* mppe_compress() we added 2 bytes (+MPPE_OVHD); |
436 |
* this is to account for possible PFC. |
437 |
*/ |
438 |
if (osize < isize - MPPE_OVHD - 1) { |
439 |
printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " |
440 |
"(have: %d need: %d)\n", state->unit, |
441 |
osize, isize - MPPE_OVHD - 1); |
442 |
return DECOMP_ERROR; |
443 |
} |
444 |
osize = isize - MPPE_OVHD - 2; /* assume no PFC */ |
445 |
|
446 |
ccount = MPPE_CCOUNT(ibuf); |
447 |
if (state->debug >= 7) |
448 |
printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", state->unit, |
449 |
ccount); |
450 |
|
451 |
/* sanity checks -- terminate with extreme prejudice */ |
452 |
if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { |
453 |
printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n", |
454 |
state->unit); |
455 |
state->sanity_errors += 100; |
456 |
sanity = 1; |
457 |
} |
458 |
if (!state->stateful && !flushed) { |
459 |
printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " |
460 |
"stateless mode!\n", state->unit); |
461 |
state->sanity_errors += 100; |
462 |
sanity = 1; |
463 |
} |
464 |
if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { |
465 |
printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " |
466 |
"flag packet!\n", state->unit); |
467 |
state->sanity_errors += 100; |
468 |
sanity = 1; |
469 |
} |
470 |
|
471 |
if (sanity) { |
472 |
if (state->sanity_errors < SANITY_MAX) |
473 |
return DECOMP_ERROR; |
474 |
else |
475 |
/* |
476 |
* Take LCP down if the peer is sending too many bogons. |
477 |
* We don't want to do this for a single or just a few |
478 |
* instances since it could just be due to packet corruption. |
479 |
*/ |
480 |
return DECOMP_FATALERROR; |
481 |
} |
482 |
|
483 |
/* |
484 |
* Check the coherency count. |
485 |
*/ |
486 |
|
487 |
if (!state->stateful) { |
488 |
/* RFC 3078, sec 8.1. Rekey for every packet. */ |
489 |
while (state->ccount != ccount) { |
490 |
mppe_rekey(state, 0); |
491 |
state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; |
492 |
} |
493 |
} else { |
494 |
/* RFC 3078, sec 8.2. */ |
495 |
if (!state->discard) { |
496 |
/* normal state */ |
497 |
state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; |
498 |
if (ccount != state->ccount) { |
499 |
/* |
500 |
* (ccount > state->ccount) |
501 |
* Packet loss detected, enter the discard state. |
502 |
* Signal the peer to rekey (by sending a CCP Reset-Request). |
503 |
*/ |
504 |
state->discard = 1; |
505 |
return DECOMP_ERROR; |
506 |
} |
507 |
} else { |
508 |
/* discard state */ |
509 |
if (!flushed) { |
510 |
/* ccp.c will be silent (no additional CCP Reset-Requests). */ |
511 |
return DECOMP_ERROR; |
512 |
} else { |
513 |
/* Rekey for every missed "flag" packet. */ |
514 |
while ((ccount & ~0xff) != (state->ccount & ~0xff)) { |
515 |
mppe_rekey(state, 0); |
516 |
state->ccount = (state->ccount + 256) % MPPE_CCOUNT_SPACE; |
517 |
} |
518 |
|
519 |
/* reset */ |
520 |
state->discard = 0; |
521 |
state->ccount = ccount; |
522 |
/* |
523 |
* Another problem with RFC 3078 here. It implies that the |
524 |
* peer need not send a Reset-Ack packet. But RFC 1962 |
525 |
* requires it. Hopefully, M$ does send a Reset-Ack; even |
526 |
* though it isn't required for MPPE synchronization, it is |
527 |
* required to reset CCP state. |
528 |
*/ |
529 |
} |
530 |
} |
531 |
if (flushed) |
532 |
mppe_rekey(state, 0); |
533 |
} |
534 |
|
535 |
/* |
536 |
* Fill in the first part of the PPP header. The protocol field |
537 |
* comes from the decrypted data. |
538 |
*/ |
539 |
obuf[0] = PPP_ADDRESS(ibuf); /* +1 */ |
540 |
obuf[1] = PPP_CONTROL(ibuf); /* +1 */ |
541 |
obuf += 2; |
542 |
ibuf += PPP_HDRLEN + MPPE_OVHD; |
543 |
isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */ |
544 |
/* net osize: isize-4 */ |
545 |
|
546 |
/* |
547 |
* Decrypt the first byte in order to check if it is |
548 |
* a compressed or uncompressed protocol field. |
549 |
*/ |
550 |
arcfour_decrypt(&state->arcfour_context, ibuf, 1, obuf); |
551 |
|
552 |
/* |
553 |
* Do PFC decompression. |
554 |
* This would be nicer if we were given the actual sk_buff |
555 |
* instead of a char *. |
556 |
*/ |
557 |
if ((obuf[0] & 0x01) != 0) { |
558 |
obuf[1] = obuf[0]; |
559 |
obuf[0] = 0; |
560 |
obuf++; |
561 |
osize++; |
562 |
} |
563 |
|
564 |
/* And finally, decrypt the rest of the packet. */ |
565 |
arcfour_decrypt(&state->arcfour_context, ibuf + 1, isize - 1, obuf + 1); |
566 |
|
567 |
state->stats.unc_bytes += osize; |
568 |
state->stats.unc_packets++; |
569 |
state->stats.comp_bytes += isize; |
570 |
state->stats.comp_packets++; |
571 |
|
572 |
/* good packet credit */ |
573 |
state->sanity_errors >>= 1; |
574 |
|
575 |
return osize; |
576 |
} |
577 |
|
578 |
/* |
579 |
* Incompressible data has arrived (this should never happen!). |
580 |
* We should probably drop the link if the protocol is in the range |
581 |
* of what should be encrypted. At the least, we should drop this |
582 |
* packet. (How to do this?) |
583 |
*/ |
584 |
static void |
585 |
mppe_incomp(void *arg, unsigned char *ibuf, int icnt) |
586 |
{ |
587 |
ppp_mppe_state *state = (ppp_mppe_state *) arg; |
588 |
|
589 |
if (state->debug && |
590 |
(PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) |
591 |
printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! " |
592 |
"(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf)); |
593 |
|
594 |
state->stats.inc_bytes += icnt; |
595 |
state->stats.inc_packets++; |
596 |
state->stats.unc_bytes += icnt; |
597 |
state->stats.unc_packets++; |
598 |
} |
599 |
|
600 |
/************************************************************* |
601 |
* Module interface table |
602 |
*************************************************************/ |
603 |
|
604 |
/* These are in ppp.c (2.2.x) or ppp_generic.c (2.4.x) */ |
605 |
extern int ppp_register_compressor (struct compressor *cp); |
606 |
extern void ppp_unregister_compressor (struct compressor *cp); |
607 |
|
608 |
/* |
609 |
* Procedures exported to if_ppp.c. |
610 |
*/ |
611 |
struct compressor ppp_mppe = { |
612 |
CI_MPPE, /* compress_proto */ |
613 |
mppe_alloc, /* comp_alloc */ |
614 |
mppe_free, /* comp_free */ |
615 |
mppe_comp_init, /* comp_init */ |
616 |
mppe_comp_reset, /* comp_reset */ |
617 |
mppe_compress, /* compress */ |
618 |
mppe_comp_stats, /* comp_stat */ |
619 |
mppe_alloc, /* decomp_alloc */ |
620 |
mppe_free, /* decomp_free */ |
621 |
mppe_decomp_init, /* decomp_init */ |
622 |
mppe_decomp_reset, /* decomp_reset */ |
623 |
mppe_decompress, /* decompress */ |
624 |
mppe_incomp, /* incomp */ |
625 |
mppe_comp_stats, /* decomp_stat */ |
626 |
}; |
627 |
|
628 |
/* 2.2 compatibility defines */ |
629 |
#ifndef __init |
630 |
#define __init |
631 |
#endif |
632 |
#ifndef __exit |
633 |
#define __exit |
634 |
#endif |
635 |
#ifndef MODULE_LICENSE |
636 |
#define MODULE_LICENSE(license) |
637 |
#endif |
638 |
|
639 |
int __init |
640 |
ppp_mppe_init(void) |
641 |
{ |
642 |
int answer = ppp_register_compressor(&ppp_mppe); |
643 |
|
644 |
if (answer == 0) |
645 |
printk(KERN_INFO "PPP MPPE Compression module registered\n"); |
646 |
return answer; |
647 |
} |
648 |
|
649 |
void __exit |
650 |
ppp_mppe_cleanup(void) |
651 |
{ |
652 |
ppp_unregister_compressor(&ppp_mppe); |
653 |
} |
654 |
|
655 |
module_init(ppp_mppe_init); |
656 |
module_exit(ppp_mppe_cleanup); |
657 |
MODULE_LICENSE("BSD without advertisement clause"); |