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