| 1 | MPPE/MPPC kernel module for Linux |
| 2 | |
| 3 | Microsoft Point-to-Point Encryption / Compression support |
| 4 | |
| 5 | http://www.polbox.com/h/hs001/linux-2.4.29-mppe-mppc-1.3.patch.gz |
| 6 | |
| 7 | --- a/Documentation/Configure.help |
| 8 | +++ b/Documentation/Configure.help |
| 9 | @@ -9986,6 +9986,28 @@ CONFIG_PPP_BSDCOMP |
| 10 | module; it is called bsd_comp.o and will show up in the directory |
| 11 | modules once you have said "make modules". If unsure, say N. |
| 12 | |
| 13 | +Microsoft PPP compression/encryption (MPPC/MPPE) |
| 14 | +CONFIG_PPP_MPPE_MPPC |
| 15 | + Support for the Microsoft Point-To-Point Compression (RFC2118) and |
| 16 | + Microsoft Point-To-Point Encryption (RFC3078). These protocols are |
| 17 | + supported by Microsoft Windows and wide range of "hardware" access |
| 18 | + servers. MPPE is common protocol in Virtual Private Networks. According |
| 19 | + to RFC3078, MPPE supports 40, 56 and 128-bit key lengths. Depending on |
| 20 | + PPP daemon configuration on both ends of the link, following scenarios |
| 21 | + are possible: |
| 22 | + - only compression (MPPC) is used, |
| 23 | + - only encryption (MPPE) is used, |
| 24 | + - compression and encryption (MPPC+MPPE) are used. |
| 25 | + |
| 26 | + Please note that Hi/Fn (http://www.hifn.com) holds patent on MPPC so |
| 27 | + you should check if this patent is valid in your country in order to |
| 28 | + avoid legal problems. |
| 29 | + |
| 30 | + For more information please visit http://free.polbox.pl/h/hs001 |
| 31 | + |
| 32 | + To compile this driver as a module, choose M here. The module will |
| 33 | + be called ppp_mppe_mppc.o. |
| 34 | + |
| 35 | PPP over Ethernet |
| 36 | CONFIG_PPPOE |
| 37 | Support for PPP over Ethernet. |
| 38 | --- a/crypto/Config.in |
| 39 | +++ b/crypto/Config.in |
| 40 | @@ -11,7 +11,9 @@ if [ "$CONFIG_INET_AH" = "y" -o \ |
| 41 | "$CONFIG_INET6_AH" = "y" -o \ |
| 42 | "$CONFIG_INET6_AH" = "m" -o \ |
| 43 | "$CONFIG_INET6_ESP" = "y" -o \ |
| 44 | - "$CONFIG_INET6_ESP" = "m" ]; then |
| 45 | + "$CONFIG_INET6_ESP" = "m" -o \ |
| 46 | + "$CONFIG_PPP_MPPE_MPPC" = "y" -o \ |
| 47 | + "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then |
| 48 | define_bool CONFIG_CRYPTO y |
| 49 | else |
| 50 | bool 'Cryptographic API' CONFIG_CRYPTO |
| 51 | @@ -51,11 +53,24 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then |
| 52 | "$CONFIG_INET6_AH" = "y" -o \ |
| 53 | "$CONFIG_INET6_AH" = "m" -o \ |
| 54 | "$CONFIG_INET6_ESP" = "y" -o \ |
| 55 | - "$CONFIG_INET6_ESP" = "m" ]; then |
| 56 | - define_bool CONFIG_CRYPTO_SHA1 y |
| 57 | - else |
| 58 | - tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1 |
| 59 | + "$CONFIG_INET6_ESP" = "m" -o \ |
| 60 | + "$CONFIG_PPP_MPPE_MPPC" = "y" -o \ |
| 61 | + "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then |
| 62 | + if [ "$CONFIG_INET_AH" = "y" -o \ |
| 63 | + "$CONFIG_INET_ESP" = "y" -o \ |
| 64 | + "$CONFIG_INET6_AH" = "y" -o \ |
| 65 | + "$CONFIG_INET6_ESP" = "y" -o \ |
| 66 | + "$CONFIG_PPP_MPPE_MPPC" = "y" ]; then |
| 67 | + define_tristate CONFIG_CRYPTO_SHA1 y |
| 68 | + else |
| 69 | + if [ "$CONFIG_CRYPTO_SHA1" != "y" -a \ |
| 70 | + "$CONFIG_CRYPTO_SHA1" != "m" ]; then |
| 71 | + define_tristate CONFIG_CRYPTO_SHA1 m |
| 72 | + fi |
| 73 | + fi |
| 74 | fi |
| 75 | + tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1 |
| 76 | + |
| 77 | tristate ' SHA256 digest algorithm' CONFIG_CRYPTO_SHA256 |
| 78 | tristate ' SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512 |
| 79 | tristate ' Whirlpool digest algorithms' CONFIG_CRYPTO_WP512 |
| 80 | @@ -76,7 +91,20 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then |
| 81 | tristate ' TEA and XTEA cipher algorithms' CONFIG_CRYPTO_TEA |
| 82 | tristate ' Khazad cipher algorithm' CONFIG_CRYPTO_KHAZAD |
| 83 | tristate ' Anubis cipher algorithm' CONFIG_CRYPTO_ANUBIS |
| 84 | + |
| 85 | + if [ "$CONFIG_PPP_MPPE_MPPC" = "y" -o \ |
| 86 | + "$CONFIG_PPP_MPPE_MPPC" = "m" ]; then |
| 87 | + if [ "$CONFIG_PPP_MPPE_MPPC" = "y" ]; then |
| 88 | + define_tristate CONFIG_CRYPTO_ARC4 y |
| 89 | + else |
| 90 | + if [ "$CONFIG_CRYPTO_ARC4" != "y" -a \ |
| 91 | + "$CONFIG_CRYPTO_ARC4" != "m" ]; then |
| 92 | + define_tristate CONFIG_CRYPTO_ARC4 m |
| 93 | + fi |
| 94 | + fi |
| 95 | + fi |
| 96 | tristate ' ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4 |
| 97 | + |
| 98 | if [ "$CONFIG_INET_IPCOMP" = "y" -o \ |
| 99 | "$CONFIG_INET_IPCOMP" = "m" -o \ |
| 100 | "$CONFIG_INET6_IPCOMP" = "y" -o \ |
| 101 | --- a/drivers/net/Config.in |
| 102 | +++ b/drivers/net/Config.in |
| 103 | @@ -336,6 +336,7 @@ if [ ! "$CONFIG_PPP" = "n" ]; then |
| 104 | dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP |
| 105 | dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP |
| 106 | dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP |
| 107 | + dep_tristate ' Microsoft PPP compression/encryption (MPPC/MPPE)' CONFIG_PPP_MPPE_MPPC $CONFIG_PPP |
| 108 | if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then |
| 109 | dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP |
| 110 | fi |
| 111 | --- a/drivers/net/Makefile |
| 112 | +++ b/drivers/net/Makefile |
| 113 | @@ -166,6 +166,7 @@ obj-$(CONFIG_PPP_ASYNC) += ppp_async.o |
| 114 | obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o |
| 115 | obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o |
| 116 | obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o |
| 117 | +obj-$(CONFIG_PPP_MPPE_MPPC) += ppp_mppe_mppc.o |
| 118 | obj-$(CONFIG_PPPOE) += pppox.o pppoe.o |
| 119 | |
| 120 | obj-$(CONFIG_SLIP) += slip.o |
| 121 | --- a/drivers/net/ppp_generic.c |
| 122 | +++ b/drivers/net/ppp_generic.c |
| 123 | @@ -19,7 +19,7 @@ |
| 124 | * PPP driver, written by Michael Callahan and Al Longyear, and |
| 125 | * subsequently hacked by Paul Mackerras. |
| 126 | * |
| 127 | - * ==FILEVERSION 20020217== |
| 128 | + * ==FILEVERSION 20040509== |
| 129 | */ |
| 130 | |
| 131 | #include <linux/config.h> |
| 132 | @@ -102,6 +102,7 @@ struct ppp { |
| 133 | spinlock_t rlock; /* lock for receive side 58 */ |
| 134 | spinlock_t wlock; /* lock for transmit side 5c */ |
| 135 | int mru; /* max receive unit 60 */ |
| 136 | + int mru_alloc; /* MAX(1500,MRU) for dev_alloc_skb() */ |
| 137 | unsigned int flags; /* control bits 64 */ |
| 138 | unsigned int xstate; /* transmit state bits 68 */ |
| 139 | unsigned int rstate; /* receive state bits 6c */ |
| 140 | @@ -552,7 +553,9 @@ static int ppp_ioctl(struct inode *inode |
| 141 | case PPPIOCSMRU: |
| 142 | if (get_user(val, (int *) arg)) |
| 143 | break; |
| 144 | - ppp->mru = val; |
| 145 | + ppp->mru_alloc = ppp->mru = val; |
| 146 | + if (ppp->mru_alloc < PPP_MRU) |
| 147 | + ppp->mru_alloc = PPP_MRU; /* increase for broken peers */ |
| 148 | err = 0; |
| 149 | break; |
| 150 | |
| 151 | @@ -1025,14 +1028,37 @@ ppp_send_frame(struct ppp *ppp, struct s |
| 152 | case PPP_CCP: |
| 153 | /* peek at outbound CCP frames */ |
| 154 | ppp_ccp_peek(ppp, skb, 0); |
| 155 | + /* |
| 156 | + * When LZS or MPPE/MPPC has been negotiated we don't send |
| 157 | + * CCP_RESETACK after receiving CCP_RESETREQ; in fact pppd |
| 158 | + * sends such a packet but we silently discard it here |
| 159 | + */ |
| 160 | + if (CCP_CODE(skb->data+2) == CCP_RESETACK |
| 161 | + && (ppp->xcomp->compress_proto == CI_MPPE |
| 162 | + || ppp->xcomp->compress_proto == CI_LZS)) { |
| 163 | + --ppp->stats.tx_packets; |
| 164 | + ppp->stats.tx_bytes -= skb->len - 2; |
| 165 | + kfree_skb(skb); |
| 166 | + return; |
| 167 | + } |
| 168 | break; |
| 169 | } |
| 170 | |
| 171 | /* try to do packet compression */ |
| 172 | if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 |
| 173 | && proto != PPP_LCP && proto != PPP_CCP) { |
| 174 | - new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, |
| 175 | - GFP_ATOMIC); |
| 176 | + int comp_ovhd = 0; |
| 177 | + /* |
| 178 | + * because of possible data expansion when MPPC or LZS |
| 179 | + * is used, allocate compressor's buffer 12.5% bigger |
| 180 | + * than MTU |
| 181 | + */ |
| 182 | + if (ppp->xcomp->compress_proto == CI_MPPE) |
| 183 | + comp_ovhd = ((ppp->dev->mtu * 9) / 8) + 1 + MPPE_OVHD; |
| 184 | + else if (ppp->xcomp->compress_proto == CI_LZS) |
| 185 | + comp_ovhd = ((ppp->dev->mtu * 9) / 8) + 1 + LZS_OVHD; |
| 186 | + new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len |
| 187 | + + comp_ovhd, GFP_ATOMIC); |
| 188 | if (new_skb == 0) { |
| 189 | printk(KERN_ERR "PPP: no memory (comp pkt)\n"); |
| 190 | goto drop; |
| 191 | @@ -1050,9 +1076,21 @@ ppp_send_frame(struct ppp *ppp, struct s |
| 192 | skb = new_skb; |
| 193 | skb_put(skb, len); |
| 194 | skb_pull(skb, 2); /* pull off A/C bytes */ |
| 195 | - } else { |
| 196 | + } else if (len == 0) { |
| 197 | /* didn't compress, or CCP not up yet */ |
| 198 | kfree_skb(new_skb); |
| 199 | + } else { |
| 200 | + /* |
| 201 | + * (len < 0) |
| 202 | + * MPPE requires that we do not send unencrypted |
| 203 | + * frames. The compressor will return -1 if we |
| 204 | + * should drop the frame. We cannot simply test |
| 205 | + * the compress_proto because MPPE and MPPC share |
| 206 | + * the same number. |
| 207 | + */ |
| 208 | + printk(KERN_ERR "ppp: compressor dropped pkt\n"); |
| 209 | + kfree_skb(new_skb); |
| 210 | + goto drop; |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | @@ -1540,14 +1578,15 @@ ppp_decompress_frame(struct ppp *ppp, st |
| 215 | int len; |
| 216 | |
| 217 | if (proto == PPP_COMP) { |
| 218 | - ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN); |
| 219 | + ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN); |
| 220 | if (ns == 0) { |
| 221 | printk(KERN_ERR "ppp_decompress_frame: no memory\n"); |
| 222 | goto err; |
| 223 | } |
| 224 | /* the decompressor still expects the A/C bytes in the hdr */ |
| 225 | len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2, |
| 226 | - skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN); |
| 227 | + skb->len + 2, ns->data, |
| 228 | + ppp->mru_alloc + PPP_HDRLEN); |
| 229 | if (len < 0) { |
| 230 | /* Pass the compressed frame to pppd as an |
| 231 | error indication. */ |
| 232 | @@ -1573,7 +1612,14 @@ ppp_decompress_frame(struct ppp *ppp, st |
| 233 | return skb; |
| 234 | |
| 235 | err: |
| 236 | - ppp->rstate |= SC_DC_ERROR; |
| 237 | + if (ppp->rcomp->compress_proto != CI_MPPE |
| 238 | + && ppp->rcomp->compress_proto != CI_LZS) { |
| 239 | + /* |
| 240 | + * If decompression protocol isn't MPPE/MPPC or LZS, we set |
| 241 | + * SC_DC_ERROR flag and wait for CCP_RESETACK |
| 242 | + */ |
| 243 | + ppp->rstate |= SC_DC_ERROR; |
| 244 | + } |
| 245 | ppp_receive_error(ppp); |
| 246 | return skb; |
| 247 | } |
| 248 | @@ -2253,6 +2299,7 @@ ppp_create_interface(int unit, int *retp |
| 249 | /* Initialize the new ppp unit */ |
| 250 | ppp->file.index = unit; |
| 251 | ppp->mru = PPP_MRU; |
| 252 | + ppp->mru_alloc = PPP_MRU; |
| 253 | init_ppp_file(&ppp->file, INTERFACE); |
| 254 | ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */ |
| 255 | for (i = 0; i < NUM_NP; ++i) |
| 256 | --- /dev/null |
| 257 | +++ b/drivers/net/ppp_mppe_mppc.c |
| 258 | @@ -0,0 +1,1312 @@ |
| 259 | +/* |
| 260 | + * ppp_mppe_mppc.c - MPPC/MPPE "compressor/decompressor" module. |
| 261 | + * |
| 262 | + * Copyright (c) 1994 Árpád Magosányi <mag@bunuel.tii.matav.hu> |
| 263 | + * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com> |
| 264 | + * Copyright (c) 2002-2005 Jan Dubiec <jdx@slackware.pl> |
| 265 | + * |
| 266 | + * Permission to use, copy, modify, and distribute this software and its |
| 267 | + * documentation is hereby granted, provided that the above copyright |
| 268 | + * notice appears in all copies. This software is provided without any |
| 269 | + * warranty, express or implied. |
| 270 | + * |
| 271 | + * The code is based on MPPE kernel module written by Árpád Magosányi and |
| 272 | + * Tim Hockin which can be found on http://planetmirror.com/pub/mppe/. |
| 273 | + * I have added MPPC and 56 bit session keys support in MPPE. |
| 274 | + * |
| 275 | + * WARNING! Although this is open source code, its usage in some countries |
| 276 | + * (in particular in the USA) may violate Stac Inc. patent for MPPC. |
| 277 | + * |
| 278 | + * ==FILEVERSION 20050202== |
| 279 | + * |
| 280 | + */ |
| 281 | + |
| 282 | +#include <linux/init.h> |
| 283 | +#include <linux/module.h> |
| 284 | +#include <linux/mm.h> |
| 285 | +#include <linux/slab.h> |
| 286 | +#include <asm/scatterlist.h> |
| 287 | +#include <linux/vmalloc.h> |
| 288 | +#include <linux/crypto.h> |
| 289 | + |
| 290 | +#include <linux/ppp_defs.h> |
| 291 | +#include <linux/ppp-comp.h> |
| 292 | + |
| 293 | +/* |
| 294 | + * In 2.4.x kernels macro offset_in_page() is not defined in linux/mm.h so |
| 295 | + * we define it here; PAGE_MASK is defined in asm/page.h which is included |
| 296 | + * by linux/mm.h. |
| 297 | + */ |
| 298 | +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) |
| 299 | + |
| 300 | +/* |
| 301 | + * State for a mppc/mppe "(de)compressor". |
| 302 | + */ |
| 303 | +struct ppp_mppe_state { |
| 304 | + struct crypto_tfm *arc4_tfm; |
| 305 | + struct crypto_tfm *sha1_tfm; |
| 306 | + u8 *sha1_digest; |
| 307 | + u8 master_key[MPPE_MAX_KEY_LEN]; |
| 308 | + u8 session_key[MPPE_MAX_KEY_LEN]; |
| 309 | + u8 mppc; /* do we use compression (MPPC)? */ |
| 310 | + u8 mppe; /* do we use encryption (MPPE)? */ |
| 311 | + u8 keylen; /* key length in bytes */ |
| 312 | + u8 bitkeylen; /* key length in bits */ |
| 313 | + u16 ccount; /* coherency counter */ |
| 314 | + u16 bits; /* MPPC/MPPE control bits */ |
| 315 | + u8 stateless; /* do we use stateless mode? */ |
| 316 | + u8 nextflushed; /* set A bit in the next outgoing packet; |
| 317 | + used only by compressor*/ |
| 318 | + u8 flushexpected; /* drop packets until A bit is received; |
| 319 | + used only by decompressor*/ |
| 320 | + u8 *hist; /* MPPC history */ |
| 321 | + u16 *hash; /* Hash table; used only by compressor */ |
| 322 | + u16 histptr; /* history "cursor" */ |
| 323 | + int unit; |
| 324 | + int debug; |
| 325 | + int mru; |
| 326 | + struct compstat stats; |
| 327 | +}; |
| 328 | + |
| 329 | +#define MPPE_HIST_LEN 8192 /* MPPC history size */ |
| 330 | +#define MPPE_MAX_CCOUNT 0x0FFF /* max. coherency counter value */ |
| 331 | + |
| 332 | +#define MPPE_BIT_FLUSHED 0x80 /* bit A */ |
| 333 | +#define MPPE_BIT_RESET 0x40 /* bit B */ |
| 334 | +#define MPPE_BIT_COMP 0x20 /* bit C */ |
| 335 | +#define MPPE_BIT_ENCRYPTED 0x10 /* bit D */ |
| 336 | + |
| 337 | +#define MPPE_SALT0 0xD1 /* values used in MPPE key derivation */ |
| 338 | +#define MPPE_SALT1 0x26 /* according to RFC3079 */ |
| 339 | +#define MPPE_SALT2 0x9E |
| 340 | + |
| 341 | +#define MPPE_CCOUNT(x) ((((x)[4] & 0x0f) << 8) + (x)[5]) |
| 342 | +#define MPPE_BITS(x) ((x)[4] & 0xf0) |
| 343 | +#define MPPE_CTRLHI(x) ((((x)->ccount & 0xf00)>>8)|((x)->bits)) |
| 344 | +#define MPPE_CTRLLO(x) ((x)->ccount & 0xff) |
| 345 | + |
| 346 | +/* |
| 347 | + * Kernel Crypto API needs its arguments to be in kmalloc'd memory, not in the |
| 348 | + * module static data area. That means sha_pad needs to be kmalloc'd. It is done |
| 349 | + * in mppe_module_init(). This has been pointed out on 30th July 2004 by Oleg |
| 350 | + * Makarenko on pptpclient-devel mailing list. |
| 351 | + */ |
| 352 | +#define SHA1_PAD_SIZE 40 |
| 353 | +struct sha_pad { |
| 354 | + unsigned char sha_pad1[SHA1_PAD_SIZE]; |
| 355 | + unsigned char sha_pad2[SHA1_PAD_SIZE]; |
| 356 | +}; |
| 357 | +static struct sha_pad *sha_pad; |
| 358 | + |
| 359 | +static inline void |
| 360 | +setup_sg(struct scatterlist *sg, const void *address, unsigned int length) |
| 361 | +{ |
| 362 | + sg[0].page = virt_to_page(address); |
| 363 | + sg[0].offset = offset_in_page(address); |
| 364 | + sg[0].length = length; |
| 365 | +} |
| 366 | + |
| 367 | +static inline void |
| 368 | +arc4_setkey(struct ppp_mppe_state *state, const unsigned char *key, |
| 369 | + const unsigned int keylen) |
| 370 | +{ |
| 371 | + crypto_cipher_setkey(state->arc4_tfm, key, keylen); |
| 372 | +} |
| 373 | + |
| 374 | +static inline void |
| 375 | +arc4_encrypt(struct ppp_mppe_state *state, const unsigned char *in, |
| 376 | + const unsigned int len, unsigned char *out) |
| 377 | +{ |
| 378 | + struct scatterlist sgin[4], sgout[4]; |
| 379 | + |
| 380 | + setup_sg(sgin, in, len); |
| 381 | + setup_sg(sgout, out, len); |
| 382 | + crypto_cipher_encrypt(state->arc4_tfm, sgout, sgin, len); |
| 383 | +} |
| 384 | + |
| 385 | +#define arc4_decrypt arc4_encrypt |
| 386 | + |
| 387 | +/* |
| 388 | + * Key Derivation, from RFC 3078, RFC 3079. |
| 389 | + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. |
| 390 | + */ |
| 391 | +static void |
| 392 | +get_new_key_from_sha(struct ppp_mppe_state *state, unsigned char *interim_key) |
| 393 | +{ |
| 394 | + struct scatterlist sg[4]; |
| 395 | + |
| 396 | + setup_sg(&sg[0], state->master_key, state->keylen); |
| 397 | + setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); |
| 398 | + setup_sg(&sg[2], state->session_key, state->keylen); |
| 399 | + setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); |
| 400 | + |
| 401 | + crypto_digest_digest (state->sha1_tfm, sg, 4, state->sha1_digest); |
| 402 | + |
| 403 | + memcpy(interim_key, state->sha1_digest, state->keylen); |
| 404 | +} |
| 405 | + |
| 406 | +static void |
| 407 | +mppe_change_key(struct ppp_mppe_state *state, int initialize) |
| 408 | +{ |
| 409 | + unsigned char interim_key[MPPE_MAX_KEY_LEN]; |
| 410 | + |
| 411 | + get_new_key_from_sha(state, interim_key); |
| 412 | + if (initialize) { |
| 413 | + memcpy(state->session_key, interim_key, state->keylen); |
| 414 | + } else { |
| 415 | + arc4_setkey(state, interim_key, state->keylen); |
| 416 | + arc4_encrypt(state, interim_key, state->keylen, state->session_key); |
| 417 | + } |
| 418 | + if (state->keylen == 8) { |
| 419 | + if (state->bitkeylen == 40) { |
| 420 | + state->session_key[0] = MPPE_SALT0; |
| 421 | + state->session_key[1] = MPPE_SALT1; |
| 422 | + state->session_key[2] = MPPE_SALT2; |
| 423 | + } else { |
| 424 | + state->session_key[0] = MPPE_SALT0; |
| 425 | + } |
| 426 | + } |
| 427 | + arc4_setkey(state, state->session_key, state->keylen); |
| 428 | +} |
| 429 | + |
| 430 | +/* increase 12-bit coherency counter */ |
| 431 | +static inline void |
| 432 | +mppe_increase_ccount(struct ppp_mppe_state *state) |
| 433 | +{ |
| 434 | + state->ccount = (state->ccount + 1) & MPPE_MAX_CCOUNT; |
| 435 | + if (state->mppe) { |
| 436 | + if (state->stateless) { |
| 437 | + mppe_change_key(state, 0); |
| 438 | + state->nextflushed = 1; |
| 439 | + } else { |
| 440 | + if ((state->ccount & 0xff) == 0xff) { |
| 441 | + mppe_change_key(state, 0); |
| 442 | + } |
| 443 | + } |
| 444 | + } |
| 445 | +} |
| 446 | + |
| 447 | +/* allocate space for a MPPE/MPPC (de)compressor. */ |
| 448 | +/* comp != 0 -> init compressor */ |
| 449 | +/* comp = 0 -> init decompressor */ |
| 450 | +static void * |
| 451 | +mppe_alloc(unsigned char *options, int opt_len, int comp) |
| 452 | +{ |
| 453 | + struct ppp_mppe_state *state; |
| 454 | + unsigned int digestsize; |
| 455 | + u8* fname; |
| 456 | + |
| 457 | + fname = comp ? "mppe_comp_alloc" : "mppe_decomp_alloc"; |
| 458 | + |
| 459 | + /* |
| 460 | + * Hack warning - additionally to the standard MPPC/MPPE configuration |
| 461 | + * options, pppd passes to the (de)copressor 8 or 16 byte session key. |
| 462 | + * Therefore options[1] contains MPPC/MPPE configuration option length |
| 463 | + * (CILEN_MPPE = 6), but the real options length, depending on the key |
| 464 | + * length, is 6+8 or 6+16. |
| 465 | + */ |
| 466 | + if (opt_len < CILEN_MPPE) { |
| 467 | + printk(KERN_WARNING "%s: wrong options length: %u\n", fname, opt_len); |
| 468 | + return NULL; |
| 469 | + } |
| 470 | + |
| 471 | + if (options[0] != CI_MPPE || options[1] != CILEN_MPPE || |
| 472 | + (options[2] & ~MPPE_STATELESS) != 0 || |
| 473 | + options[3] != 0 || options[4] != 0 || |
| 474 | + (options[5] & ~(MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) != 0 || |
| 475 | + (options[5] & (MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) == 0) { |
| 476 | + printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, " |
| 477 | + "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, options[0], |
| 478 | + options[1], options[2], options[3], options[4], options[5]); |
| 479 | + return NULL; |
| 480 | + } |
| 481 | + |
| 482 | + state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL); |
| 483 | + if (state == NULL) { |
| 484 | + printk(KERN_ERR "%s: cannot allocate space for %scompressor\n", fname, |
| 485 | + comp ? "" : "de"); |
| 486 | + return NULL; |
| 487 | + } |
| 488 | + memset(state, 0, sizeof(struct ppp_mppe_state)); |
| 489 | + |
| 490 | + state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */ |
| 491 | + state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT | |
| 492 | + MPPE_40BIT); /* Do we use MPPE? */ |
| 493 | + |
| 494 | + if (state->mppc) { |
| 495 | + /* allocate MPPC history */ |
| 496 | + state->hist = (u8*)vmalloc(2*MPPE_HIST_LEN*sizeof(u8)); |
| 497 | + if (state->hist == NULL) { |
| 498 | + kfree(state); |
| 499 | + printk(KERN_ERR "%s: cannot allocate space for MPPC history\n", |
| 500 | + fname); |
| 501 | + return NULL; |
| 502 | + } |
| 503 | + |
| 504 | + /* allocate hashtable for MPPC compressor */ |
| 505 | + if (comp) { |
| 506 | + state->hash = (u16*)vmalloc(MPPE_HIST_LEN*sizeof(u16)); |
| 507 | + if (state->hash == NULL) { |
| 508 | + vfree(state->hist); |
| 509 | + kfree(state); |
| 510 | + printk(KERN_ERR "%s: cannot allocate space for MPPC history\n", |
| 511 | + fname); |
| 512 | + return NULL; |
| 513 | + } |
| 514 | + } |
| 515 | + } |
| 516 | + |
| 517 | + if (state->mppe) { /* specific for MPPE */ |
| 518 | + /* Load ARC4 algorithm */ |
| 519 | + state->arc4_tfm = crypto_alloc_tfm("arc4", 0); |
| 520 | + if (state->arc4_tfm == NULL) { |
| 521 | + if (state->mppc) { |
| 522 | + vfree(state->hash); |
| 523 | + if (comp) |
| 524 | + vfree(state->hist); |
| 525 | + } |
| 526 | + kfree(state); |
| 527 | + printk(KERN_ERR "%s: cannot load ARC4 module\n", fname); |
| 528 | + return NULL; |
| 529 | + } |
| 530 | + |
| 531 | + /* Load SHA1 algorithm */ |
| 532 | + state->sha1_tfm = crypto_alloc_tfm("sha1", 0); |
| 533 | + if (state->sha1_tfm == NULL) { |
| 534 | + crypto_free_tfm(state->arc4_tfm); |
| 535 | + if (state->mppc) { |
| 536 | + vfree(state->hash); |
| 537 | + if (comp) |
| 538 | + vfree(state->hist); |
| 539 | + } |
| 540 | + kfree(state); |
| 541 | + printk(KERN_ERR "%s: cannot load SHA1 module\n", fname); |
| 542 | + return NULL; |
| 543 | + } |
| 544 | + |
| 545 | + digestsize = crypto_tfm_alg_digestsize(state->sha1_tfm); |
| 546 | + if (digestsize < MPPE_MAX_KEY_LEN) { |
| 547 | + crypto_free_tfm(state->sha1_tfm); |
| 548 | + crypto_free_tfm(state->arc4_tfm); |
| 549 | + if (state->mppc) { |
| 550 | + vfree(state->hash); |
| 551 | + if (comp) |
| 552 | + vfree(state->hist); |
| 553 | + } |
| 554 | + kfree(state); |
| 555 | + printk(KERN_ERR "%s: CryptoAPI SHA1 digest size too small\n", fname); |
| 556 | + } |
| 557 | + |
| 558 | + state->sha1_digest = kmalloc(digestsize, GFP_KERNEL); |
| 559 | + if (!state->sha1_digest) { |
| 560 | + crypto_free_tfm(state->sha1_tfm); |
| 561 | + crypto_free_tfm(state->arc4_tfm); |
| 562 | + if (state->mppc) { |
| 563 | + vfree(state->hash); |
| 564 | + if (comp) |
| 565 | + vfree(state->hist); |
| 566 | + } |
| 567 | + kfree(state); |
| 568 | + printk(KERN_ERR "%s: cannot allocate space for SHA1 digest\n", fname); |
| 569 | + } |
| 570 | + |
| 571 | + memcpy(state->master_key, options+CILEN_MPPE, MPPE_MAX_KEY_LEN); |
| 572 | + memcpy(state->session_key, state->master_key, MPPE_MAX_KEY_LEN); |
| 573 | + /* initial key generation is done in mppe_init() */ |
| 574 | + } |
| 575 | + |
| 576 | + MOD_INC_USE_COUNT; |
| 577 | + |
| 578 | + return (void *) state; |
| 579 | +} |
| 580 | + |
| 581 | +static void * |
| 582 | +mppe_comp_alloc(unsigned char *options, int opt_len) |
| 583 | +{ |
| 584 | + return mppe_alloc(options, opt_len, 1); |
| 585 | +} |
| 586 | + |
| 587 | +static void * |
| 588 | +mppe_decomp_alloc(unsigned char *options, int opt_len) |
| 589 | +{ |
| 590 | + return mppe_alloc(options, opt_len, 0); |
| 591 | +} |
| 592 | + |
| 593 | +/* cleanup the (de)compressor */ |
| 594 | +static void |
| 595 | +mppe_comp_free(void *arg) |
| 596 | +{ |
| 597 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
| 598 | + |
| 599 | + if (state != NULL) { |
| 600 | + if (state->mppe) { |
| 601 | + if (state->sha1_tfm != NULL) |
| 602 | + crypto_free_tfm(state->sha1_tfm); |
| 603 | + if (state->arc4_tfm != NULL) |
| 604 | + crypto_free_tfm(state->arc4_tfm); |
| 605 | + } |
| 606 | + if (state->hist != NULL) |
| 607 | + vfree(state->hist); |
| 608 | + if (state->hash != NULL) |
| 609 | + vfree(state->hash); |
| 610 | + kfree(state); |
| 611 | + } |
| 612 | + |
| 613 | + MOD_DEC_USE_COUNT; |
| 614 | +} |
| 615 | + |
| 616 | +/* init MPPC/MPPE (de)compresor */ |
| 617 | +/* comp != 0 -> init compressor */ |
| 618 | +/* comp = 0 -> init decompressor */ |
| 619 | +static int |
| 620 | +mppe_init(void *arg, unsigned char *options, int opt_len, int unit, |
| 621 | + int hdrlen, int mru, int debug, int comp) |
| 622 | +{ |
| 623 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
| 624 | + u8* fname; |
| 625 | + |
| 626 | + fname = comp ? "mppe_comp_init" : "mppe_decomp_init"; |
| 627 | + |
| 628 | + if (opt_len < CILEN_MPPE) { |
| 629 | + if (debug) |
| 630 | + printk(KERN_WARNING "%s: wrong options length: %u\n", |
| 631 | + fname, opt_len); |
| 632 | + return 0; |
| 633 | + } |
| 634 | + |
| 635 | + if (options[0] != CI_MPPE || options[1] != CILEN_MPPE || |
| 636 | + (options[2] & ~MPPE_STATELESS) != 0 || |
| 637 | + options[3] != 0 || options[4] != 0 || |
| 638 | + (options[5] & ~(MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) != 0 || |
| 639 | + (options[5] & (MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) == 0) { |
| 640 | + if (debug) |
| 641 | + printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, " |
| 642 | + "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, |
| 643 | + options[0], options[1], options[2], options[3], options[4], |
| 644 | + options[5]); |
| 645 | + return 0; |
| 646 | + } |
| 647 | + |
| 648 | + if ((options[5] & ~MPPE_MPPC) != MPPE_128BIT && |
| 649 | + (options[5] & ~MPPE_MPPC) != MPPE_56BIT && |
| 650 | + (options[5] & ~MPPE_MPPC) != MPPE_40BIT && |
| 651 | + (options[5] & MPPE_MPPC) != MPPE_MPPC) { |
| 652 | + if (debug) |
| 653 | + printk(KERN_WARNING "%s: don't know what to do: o[5]=%02x\n", |
| 654 | + fname, options[5]); |
| 655 | + return 0; |
| 656 | + } |
| 657 | + |
| 658 | + state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */ |
| 659 | + state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT | |
| 660 | + MPPE_40BIT); /* Do we use MPPE? */ |
| 661 | + state->stateless = options[2] & MPPE_STATELESS; /* Do we use stateless mode? */ |
| 662 | + |
| 663 | + switch (state->mppe) { |
| 664 | + case MPPE_40BIT: /* 40 bit key */ |
| 665 | + state->keylen = 8; |
| 666 | + state->bitkeylen = 40; |
| 667 | + break; |
| 668 | + case MPPE_56BIT: /* 56 bit key */ |
| 669 | + state->keylen = 8; |
| 670 | + state->bitkeylen = 56; |
| 671 | + break; |
| 672 | + case MPPE_128BIT: /* 128 bit key */ |
| 673 | + state->keylen = 16; |
| 674 | + state->bitkeylen = 128; |
| 675 | + break; |
| 676 | + default: |
| 677 | + state->keylen = 0; |
| 678 | + state->bitkeylen = 0; |
| 679 | + } |
| 680 | + |
| 681 | + state->ccount = MPPE_MAX_CCOUNT; |
| 682 | + state->bits = 0; |
| 683 | + state->unit = unit; |
| 684 | + state->debug = debug; |
| 685 | + state->histptr = MPPE_HIST_LEN; |
| 686 | + if (state->mppc) { /* reset history if MPPC was negotiated */ |
| 687 | + memset(state->hist, 0, 2*MPPE_HIST_LEN*sizeof(u8)); |
| 688 | + } |
| 689 | + |
| 690 | + if (state->mppe) { /* generate initial session keys */ |
| 691 | + mppe_change_key(state, 1); |
| 692 | + } |
| 693 | + |
| 694 | + if (comp) { /* specific for compressor */ |
| 695 | + state->nextflushed = 1; |
| 696 | + } else { /* specific for decompressor */ |
| 697 | + state->mru = mru; |
| 698 | + state->flushexpected = 1; |
| 699 | + } |
| 700 | + |
| 701 | + return 1; |
| 702 | +} |
| 703 | + |
| 704 | +static int |
| 705 | +mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit, |
| 706 | + int hdrlen, int debug) |
| 707 | +{ |
| 708 | + return mppe_init(arg, options, opt_len, unit, hdrlen, 0, debug, 1); |
| 709 | +} |
| 710 | + |
| 711 | + |
| 712 | +static int |
| 713 | +mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit, |
| 714 | + int hdrlen, int mru, int debug) |
| 715 | +{ |
| 716 | + return mppe_init(arg, options, opt_len, unit, hdrlen, mru, debug, 0); |
| 717 | +} |
| 718 | + |
| 719 | +static void |
| 720 | +mppe_comp_reset(void *arg) |
| 721 | +{ |
| 722 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; |
| 723 | + |
| 724 | + if (state->debug) |
| 725 | + printk(KERN_DEBUG "%s%d: resetting MPPC/MPPE compressor\n", |
| 726 | + __FUNCTION__, state->unit); |
| 727 | + |
| 728 | + state->nextflushed = 1; |
| 729 | + if (state->mppe) |
| 730 | + arc4_setkey(state, state->session_key, state->keylen); |
| 731 | +} |
| 732 | + |
| 733 | +static void |
| 734 | +mppe_decomp_reset(void *arg) |
| 735 | +{ |
| 736 | + /* When MPPC/MPPE is in use, we shouldn't receive any CCP Reset-Ack. |
| 737 | + But when we receive such a packet, we just ignore it. */ |
| 738 | + return; |
| 739 | +} |
| 740 | + |
| 741 | +static void |
| 742 | +mppe_stats(void *arg, struct compstat *stats) |
| 743 | +{ |
| 744 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; |
| 745 | + |
| 746 | + *stats = state->stats; |
| 747 | +} |
| 748 | + |
| 749 | +/***************************/ |
| 750 | +/**** Compression stuff ****/ |
| 751 | +/***************************/ |
| 752 | +/* inserts 1 to 8 bits into the output buffer */ |
| 753 | +static inline void putbits8(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) |
| 754 | +{ |
| 755 | + buf += *i; |
| 756 | + if (*l >= n) { |
| 757 | + *l = (*l) - n; |
| 758 | + val <<= *l; |
| 759 | + *buf = *buf | (val & 0xff); |
| 760 | + if (*l == 0) { |
| 761 | + *l = 8; |
| 762 | + (*i)++; |
| 763 | + *(++buf) = 0; |
| 764 | + } |
| 765 | + } else { |
| 766 | + (*i)++; |
| 767 | + *l = 8 - n + (*l); |
| 768 | + val <<= *l; |
| 769 | + *buf = *buf | ((val >> 8) & 0xff); |
| 770 | + *(++buf) = val & 0xff; |
| 771 | + } |
| 772 | +} |
| 773 | + |
| 774 | +/* inserts 9 to 16 bits into the output buffer */ |
| 775 | +static inline void putbits16(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) |
| 776 | +{ |
| 777 | + buf += *i; |
| 778 | + if (*l >= n - 8) { |
| 779 | + (*i)++; |
| 780 | + *l = 8 - n + (*l); |
| 781 | + val <<= *l; |
| 782 | + *buf = *buf | ((val >> 8) & 0xff); |
| 783 | + *(++buf) = val & 0xff; |
| 784 | + if (*l == 0) { |
| 785 | + *l = 8; |
| 786 | + (*i)++; |
| 787 | + *(++buf) = 0; |
| 788 | + } |
| 789 | + } else { |
| 790 | + (*i)++; (*i)++; |
| 791 | + *l = 16 - n + (*l); |
| 792 | + val <<= *l; |
| 793 | + *buf = *buf | ((val >> 16) & 0xff); |
| 794 | + *(++buf) = (val >> 8) & 0xff; |
| 795 | + *(++buf) = val & 0xff; |
| 796 | + } |
| 797 | +} |
| 798 | + |
| 799 | +/* inserts 17 to 24 bits into the output buffer */ |
| 800 | +static inline void putbits24(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) |
| 801 | +{ |
| 802 | + buf += *i; |
| 803 | + if (*l >= n - 16) { |
| 804 | + (*i)++; (*i)++; |
| 805 | + *l = 16 - n + (*l); |
| 806 | + val <<= *l; |
| 807 | + *buf = *buf | ((val >> 16) & 0xff); |
| 808 | + *(++buf) = (val >> 8) & 0xff; |
| 809 | + *(++buf) = val & 0xff; |
| 810 | + if (*l == 0) { |
| 811 | + *l = 8; |
| 812 | + (*i)++; |
| 813 | + *(++buf) = 0; |
| 814 | + } |
| 815 | + } else { |
| 816 | + (*i)++; (*i)++; (*i)++; |
| 817 | + *l = 24 - n + (*l); |
| 818 | + val <<= *l; |
| 819 | + *buf = *buf | ((val >> 24) & 0xff); |
| 820 | + *(++buf) = (val >> 16) & 0xff; |
| 821 | + *(++buf) = (val >> 8) & 0xff; |
| 822 | + *(++buf) = val & 0xff; |
| 823 | + } |
| 824 | +} |
| 825 | + |
| 826 | +static int |
| 827 | +mppc_compress(struct ppp_mppe_state *state, unsigned char *ibuf, |
| 828 | + unsigned char *obuf, int isize, int osize) |
| 829 | +{ |
| 830 | + u32 olen, off, len, idx, i, l; |
| 831 | + u8 *hist, *sbuf, *p, *q, *r, *s; |
| 832 | + |
| 833 | + /* |
| 834 | + At this point, to avoid possible buffer overflow caused by packet |
| 835 | + expansion during/after compression, we should make sure that |
| 836 | + osize >= (((isize*9)/8)+1)+2, but we don't do that because in |
| 837 | + ppp_generic.c we simply allocate bigger obuf. |
| 838 | + |
| 839 | + Maximum MPPC packet expansion is 12.5%. This is the worst case when |
| 840 | + all octets in the input buffer are >= 0x80 and we cannot find any |
| 841 | + repeated tokens. Additionally we have to reserve 2 bytes for MPPE/MPPC |
| 842 | + status bits and coherency counter. |
| 843 | + */ |
| 844 | + |
| 845 | + hist = state->hist + MPPE_HIST_LEN; |
| 846 | + /* check if there is enough room at the end of the history */ |
| 847 | + if (state->histptr + isize >= 2*MPPE_HIST_LEN) { |
| 848 | + state->bits |= MPPE_BIT_RESET; |
| 849 | + state->histptr = MPPE_HIST_LEN; |
| 850 | + memcpy(state->hist, hist, MPPE_HIST_LEN); |
| 851 | + } |
| 852 | + /* add packet to the history; isize must be <= MPPE_HIST_LEN */ |
| 853 | + sbuf = state->hist + state->histptr; |
| 854 | + memcpy(sbuf, ibuf, isize); |
| 855 | + state->histptr += isize; |
| 856 | + |
| 857 | + /* compress data */ |
| 858 | + r = sbuf + isize; |
| 859 | + *obuf = olen = i = 0; |
| 860 | + l = 8; |
| 861 | + while (i < isize - 2) { |
| 862 | + s = q = sbuf + i; |
| 863 | + idx = ((40543*((((s[0]<<4)^s[1])<<4)^s[2]))>>4) & 0x1fff; |
| 864 | + p = hist + state->hash[idx]; |
| 865 | + state->hash[idx] = (u16) (s - hist); |
| 866 | + off = s - p; |
| 867 | + if (off > MPPE_HIST_LEN - 1 || off < 1 || *p++ != *s++ || *p++ != *s++ || |
| 868 | + *p++ != *s++) { |
| 869 | + /* no match found; encode literal byte */ |
| 870 | + if (ibuf[i] < 0x80) { /* literal byte < 0x80 */ |
| 871 | + putbits8(obuf, (u32) ibuf[i], 8, &olen, &l); |
| 872 | + } else { /* literal byte >= 0x80 */ |
| 873 | + putbits16(obuf, (u32) (0x100|(ibuf[i]&0x7f)), 9, &olen, &l); |
| 874 | + } |
| 875 | + ++i; |
| 876 | + continue; |
| 877 | + } |
| 878 | + if (r - q >= 64) { |
| 879 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 880 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 881 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 882 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 883 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 884 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 885 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 886 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 887 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 888 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 889 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 890 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 891 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 892 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 893 | + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || |
| 894 | + *p++ != *s++; |
| 895 | + if (s - q == 64) { |
| 896 | + p--; s--; |
| 897 | + while((*p++ == *s++) && (s < r) && (p < q)); |
| 898 | + } |
| 899 | + } else { |
| 900 | + while((*p++ == *s++) && (s < r) && (p < q)); |
| 901 | + } |
| 902 | + len = s - q - 1; |
| 903 | + i += len; |
| 904 | + |
| 905 | + /* at least 3 character match found; code data */ |
| 906 | + /* encode offset */ |
| 907 | + if (off < 64) { /* 10-bit offset; 0 <= offset < 64 */ |
| 908 | + putbits16(obuf, 0x3c0|off, 10, &olen, &l); |
| 909 | + } else if (off < 320) { /* 12-bit offset; 64 <= offset < 320 */ |
| 910 | + putbits16(obuf, 0xe00|(off-64), 12, &olen, &l); |
| 911 | + } else if (off < 8192) { /* 16-bit offset; 320 <= offset < 8192 */ |
| 912 | + putbits16(obuf, 0xc000|(off-320), 16, &olen, &l); |
| 913 | + } else { |
| 914 | + /* This shouldn't happen; we return 0 what means "packet expands", |
| 915 | + and we send packet uncompressed. */ |
| 916 | + if (state->debug) |
| 917 | + printk(KERN_DEBUG "%s%d: wrong offset value: %d\n", |
| 918 | + __FUNCTION__, state->unit, off); |
| 919 | + return 0; |
| 920 | + } |
| 921 | + /* encode length of match */ |
| 922 | + if (len < 4) { /* length = 3 */ |
| 923 | + putbits8(obuf, 0, 1, &olen, &l); |
| 924 | + } else if (len < 8) { /* 4 <= length < 8 */ |
| 925 | + putbits8(obuf, 0x08|(len&0x03), 4, &olen, &l); |
| 926 | + } else if (len < 16) { /* 8 <= length < 16 */ |
| 927 | + putbits8(obuf, 0x30|(len&0x07), 6, &olen, &l); |
| 928 | + } else if (len < 32) { /* 16 <= length < 32 */ |
| 929 | + putbits8(obuf, 0xe0|(len&0x0f), 8, &olen, &l); |
| 930 | + } else if (len < 64) { /* 32 <= length < 64 */ |
| 931 | + putbits16(obuf, 0x3c0|(len&0x1f), 10, &olen, &l); |
| 932 | + } else if (len < 128) { /* 64 <= length < 128 */ |
| 933 | + putbits16(obuf, 0xf80|(len&0x3f), 12, &olen, &l); |
| 934 | + } else if (len < 256) { /* 128 <= length < 256 */ |
| 935 | + putbits16(obuf, 0x3f00|(len&0x7f), 14, &olen, &l); |
| 936 | + } else if (len < 512) { /* 256 <= length < 512 */ |
| 937 | + putbits16(obuf, 0xfe00|(len&0xff), 16, &olen, &l); |
| 938 | + } else if (len < 1024) { /* 512 <= length < 1024 */ |
| 939 | + putbits24(obuf, 0x3fc00|(len&0x1ff), 18, &olen, &l); |
| 940 | + } else if (len < 2048) { /* 1024 <= length < 2048 */ |
| 941 | + putbits24(obuf, 0xff800|(len&0x3ff), 20, &olen, &l); |
| 942 | + } else if (len < 4096) { /* 2048 <= length < 4096 */ |
| 943 | + putbits24(obuf, 0x3ff000|(len&0x7ff), 22, &olen, &l); |
| 944 | + } else if (len < 8192) { /* 4096 <= length < 8192 */ |
| 945 | + putbits24(obuf, 0xffe000|(len&0xfff), 24, &olen, &l); |
| 946 | + } else { |
| 947 | + /* This shouldn't happen; we return 0 what means "packet expands", |
| 948 | + and send packet uncompressed. */ |
| 949 | + if (state->debug) |
| 950 | + printk(KERN_DEBUG "%s%d: wrong length of match value: %d\n", |
| 951 | + __FUNCTION__, state->unit, len); |
| 952 | + return 0; |
| 953 | + } |
| 954 | + } |
| 955 | + |
| 956 | + /* Add remaining octets to the output */ |
| 957 | + while(isize - i > 0) { |
| 958 | + if (ibuf[i] < 0x80) { /* literal byte < 0x80 */ |
| 959 | + putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l); |
| 960 | + } else { /* literal byte >= 0x80 */ |
| 961 | + putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l); |
| 962 | + } |
| 963 | + } |
| 964 | + /* Reset unused bits of the last output octet */ |
| 965 | + if ((l != 0) && (l != 8)) { |
| 966 | + putbits8(obuf, 0, l, &olen, &l); |
| 967 | + } |
| 968 | + |
| 969 | + return (int) olen; |
| 970 | +} |
| 971 | + |
| 972 | +int |
| 973 | +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, |
| 974 | + int isize, int osize) |
| 975 | +{ |
| 976 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
| 977 | + int proto, olen, complen, off; |
| 978 | + unsigned char *wptr; |
| 979 | + |
| 980 | + /* Check that the protocol is in the range we handle. */ |
| 981 | + proto = PPP_PROTOCOL(ibuf); |
| 982 | + if (proto < 0x0021 || proto > 0x00fa) |
| 983 | + return 0; |
| 984 | + |
| 985 | + wptr = obuf; |
| 986 | + /* Copy over the PPP header */ |
| 987 | + wptr[0] = PPP_ADDRESS(ibuf); |
| 988 | + wptr[1] = PPP_CONTROL(ibuf); |
| 989 | + wptr[2] = PPP_COMP >> 8; |
| 990 | + wptr[3] = PPP_COMP; |
| 991 | + wptr += PPP_HDRLEN + (MPPE_OVHD / 2); /* Leave two octets for MPPE/MPPC bits */ |
| 992 | + |
| 993 | + /* |
| 994 | + * In ver. 0.99 protocol field was compressed. Deflate and BSD compress |
| 995 | + * do PFC before actual compression, RCF2118 and RFC3078 are not precise |
| 996 | + * on this topic so I decided to do PFC. Unfortunately this change caused |
| 997 | + * incompatibility with older/other MPPE/MPPC modules. I have received |
| 998 | + * a lot of complaints from unexperienced users so I have decided to revert |
| 999 | + * to previous state, i.e. the protocol field is sent uncompressed now. |
| 1000 | + * Although this may be changed in the future. |
| 1001 | + * |
| 1002 | + * Receiving side (mppe_decompress()) still accepts packets with compressed |
| 1003 | + * and uncompressed protocol field so you shouldn't get "Unsupported protocol |
| 1004 | + * 0x2145 received" messages anymore. |
| 1005 | + */ |
| 1006 | + //off = (proto > 0xff) ? 2 : 3; /* PFC - skip first protocol byte if 0 */ |
| 1007 | + off = 2; |
| 1008 | + |
| 1009 | + ibuf += off; |
| 1010 | + |
| 1011 | + mppe_increase_ccount(state); |
| 1012 | + |
| 1013 | + if (state->nextflushed) { |
| 1014 | + state->bits |= MPPE_BIT_FLUSHED; |
| 1015 | + state->nextflushed = 0; |
| 1016 | + if (state->mppe && !state->stateless) { |
| 1017 | + /* |
| 1018 | + * If this is the flag packet, the key has been already changed in |
| 1019 | + * mppe_increase_ccount() so we dont't do it once again. |
| 1020 | + */ |
| 1021 | + if ((state->ccount & 0xff) != 0xff) { |
| 1022 | + arc4_setkey(state, state->session_key, state->keylen); |
| 1023 | + } |
| 1024 | + } |
| 1025 | + if (state->mppc) { /* reset history */ |
| 1026 | + state->bits |= MPPE_BIT_RESET; |
| 1027 | + state->histptr = MPPE_HIST_LEN; |
| 1028 | + memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8)); |
| 1029 | + } |
| 1030 | + } |
| 1031 | + |
| 1032 | + if (state->mppc && !state->mppe) { /* Do only compression */ |
| 1033 | + complen = mppc_compress(state, ibuf, wptr, isize - off, |
| 1034 | + osize - PPP_HDRLEN - (MPPE_OVHD / 2)); |
| 1035 | + /* |
| 1036 | + * TODO: Implement an heuristics to handle packet expansion in a smart |
| 1037 | + * way. Now, when a packet expands, we send it as uncompressed and |
| 1038 | + * when next packet is sent we have to reset compressor's history. |
| 1039 | + * Maybe it would be better to send such packet as compressed in order |
| 1040 | + * to keep history's continuity. |
| 1041 | + */ |
| 1042 | + if ((complen > isize) || (complen > osize - PPP_HDRLEN) || |
| 1043 | + (complen == 0)) { |
| 1044 | + /* packet expands */ |
| 1045 | + state->nextflushed = 1; |
| 1046 | + memcpy(wptr, ibuf, isize - off); |
| 1047 | + olen = isize - (off - 2) + MPPE_OVHD; |
| 1048 | + (state->stats).inc_bytes += olen; |
| 1049 | + (state->stats).inc_packets++; |
| 1050 | + } else { |
| 1051 | + state->bits |= MPPE_BIT_COMP; |
| 1052 | + olen = complen + PPP_HDRLEN + (MPPE_OVHD / 2); |
| 1053 | + (state->stats).comp_bytes += olen; |
| 1054 | + (state->stats).comp_packets++; |
| 1055 | + } |
| 1056 | + } else { /* Do encryption with or without compression */ |
| 1057 | + state->bits |= MPPE_BIT_ENCRYPTED; |
| 1058 | + if (!state->mppc && state->mppe) { /* Do only encryption */ |
| 1059 | + /* read from ibuf, write to wptr, adjust for PPP_HDRLEN */ |
| 1060 | + arc4_encrypt(state, ibuf, isize - off, wptr); |
| 1061 | + olen = isize - (off - 2) + MPPE_OVHD; |
| 1062 | + (state->stats).inc_bytes += olen; |
| 1063 | + (state->stats).inc_packets++; |
| 1064 | + } else { /* Do compression and then encryption - RFC3078 */ |
| 1065 | + complen = mppc_compress(state, ibuf, wptr, isize - off, |
| 1066 | + osize - PPP_HDRLEN - (MPPE_OVHD / 2)); |
| 1067 | + /* |
| 1068 | + * TODO: Implement an heuristics to handle packet expansion in a smart |
| 1069 | + * way. Now, when a packet expands, we send it as uncompressed and |
| 1070 | + * when next packet is sent we have to reset compressor's history. |
| 1071 | + * Maybe it would be good to send such packet as compressed in order |
| 1072 | + * to keep history's continuity. |
| 1073 | + */ |
| 1074 | + if ((complen > isize) || (complen > osize - PPP_HDRLEN) || |
| 1075 | + (complen == 0)) { |
| 1076 | + /* packet expands */ |
| 1077 | + state->nextflushed = 1; |
| 1078 | + arc4_encrypt(state, ibuf, isize - off, wptr); |
| 1079 | + olen = isize - (off - 2) + MPPE_OVHD; |
| 1080 | + (state->stats).inc_bytes += olen; |
| 1081 | + (state->stats).inc_packets++; |
| 1082 | + } else { |
| 1083 | + state->bits |= MPPE_BIT_COMP; |
| 1084 | + /* Hack warning !!! RC4 implementation which we use does |
| 1085 | + encryption "in place" - it means that input and output |
| 1086 | + buffers can be *the same* memory area. Therefore we don't |
| 1087 | + need to use a temporary buffer. But be careful - other |
| 1088 | + implementations don't have to be so nice. |
| 1089 | + I used to use ibuf as temporary buffer here, but it led |
| 1090 | + packet sniffers into error. Thanks to Wilfried Weissmann |
| 1091 | + for pointing that. */ |
| 1092 | + arc4_encrypt(state, wptr, complen, wptr); |
| 1093 | + olen = complen + PPP_HDRLEN + (MPPE_OVHD / 2); |
| 1094 | + (state->stats).comp_bytes += olen; |
| 1095 | + (state->stats).comp_packets++; |
| 1096 | + } |
| 1097 | + } |
| 1098 | + } |
| 1099 | + |
| 1100 | + /* write status bits and coherency counter into the output buffer */ |
| 1101 | + wptr = obuf + PPP_HDRLEN; |
| 1102 | + wptr[0] = MPPE_CTRLHI(state); |
| 1103 | + wptr[1] = MPPE_CTRLLO(state); |
| 1104 | + |
| 1105 | + state->bits = 0; |
| 1106 | + |
| 1107 | + (state->stats).unc_bytes += isize; |
| 1108 | + (state->stats).unc_packets++; |
| 1109 | + |
| 1110 | + return olen; |
| 1111 | +} |
| 1112 | + |
| 1113 | +/***************************/ |
| 1114 | +/*** Decompression stuff ***/ |
| 1115 | +/***************************/ |
| 1116 | +static inline u32 getbits(const u8 *buf, const u32 n, u32 *i, u32 *l) |
| 1117 | +{ |
| 1118 | + static const u32 m[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; |
| 1119 | + u32 res, ol; |
| 1120 | + |
| 1121 | + ol = *l; |
| 1122 | + if (*l >= n) { |
| 1123 | + *l = (*l) - n; |
| 1124 | + res = (buf[*i] & m[ol]) >> (*l); |
| 1125 | + if (*l == 0) { |
| 1126 | + *l = 8; |
| 1127 | + (*i)++; |
| 1128 | + } |
| 1129 | + } else { |
| 1130 | + *l = 8 - n + (*l); |
| 1131 | + res = (buf[(*i)++] & m[ol]) << 8; |
| 1132 | + res = (res | buf[*i]) >> (*l); |
| 1133 | + } |
| 1134 | + |
| 1135 | + return res; |
| 1136 | +} |
| 1137 | + |
| 1138 | +static inline u32 getbyte(const u8 *buf, const u32 i, const u32 l) |
| 1139 | +{ |
| 1140 | + if (l == 8) { |
| 1141 | + return buf[i]; |
| 1142 | + } else { |
| 1143 | + return (((buf[i] << 8) | buf[i+1]) >> l) & 0xff; |
| 1144 | + } |
| 1145 | +} |
| 1146 | + |
| 1147 | +static inline void lamecopy(u8 *dst, u8 *src, u32 len) |
| 1148 | +{ |
| 1149 | + while (len--) |
| 1150 | + *dst++ = *src++; |
| 1151 | +} |
| 1152 | + |
| 1153 | +static int |
| 1154 | +mppc_decompress(struct ppp_mppe_state *state, unsigned char *ibuf, |
| 1155 | + unsigned char *obuf, int isize, int osize) |
| 1156 | +{ |
| 1157 | + u32 olen, off, len, bits, val, sig, i, l; |
| 1158 | + u8 *history, *s; |
| 1159 | + |
| 1160 | + history = state->hist + state->histptr; |
| 1161 | + olen = len = i = 0; |
| 1162 | + l = 8; |
| 1163 | + bits = isize * 8; |
| 1164 | + while (bits >= 8) { |
| 1165 | + val = getbyte(ibuf, i++, l); |
| 1166 | + if (val < 0x80) { /* literal byte < 0x80 */ |
| 1167 | + if (state->histptr < 2*MPPE_HIST_LEN) { |
| 1168 | + /* copy uncompressed byte to the history */ |
| 1169 | + (state->hist)[(state->histptr)++] = (u8) val; |
| 1170 | + } else { |
| 1171 | + /* buffer overflow; drop packet */ |
| 1172 | + if (state->debug) |
| 1173 | + printk(KERN_ERR "%s%d: trying to write outside history " |
| 1174 | + "buffer\n", __FUNCTION__, state->unit); |
| 1175 | + return DECOMP_ERROR; |
| 1176 | + } |
| 1177 | + olen++; |
| 1178 | + bits -= 8; |
| 1179 | + continue; |
| 1180 | + } |
| 1181 | + |
| 1182 | + sig = val & 0xc0; |
| 1183 | + if (sig == 0x80) { /* literal byte >= 0x80 */ |
| 1184 | + if (state->histptr < 2*MPPE_HIST_LEN) { |
| 1185 | + /* copy uncompressed byte to the history */ |
| 1186 | + (state->hist)[(state->histptr)++] = |
| 1187 | + (u8) (0x80|((val&0x3f)<<1)|getbits(ibuf, 1 , &i ,&l)); |
| 1188 | + } else { |
| 1189 | + /* buffer overflow; drop packet */ |
| 1190 | + if (state->debug) |
| 1191 | + printk(KERN_ERR "%s%d: trying to write outside history " |
| 1192 | + "buffer\n", __FUNCTION__, state->unit); |
| 1193 | + return DECOMP_ERROR; |
| 1194 | + } |
| 1195 | + olen++; |
| 1196 | + bits -= 9; |
| 1197 | + continue; |
| 1198 | + } |
| 1199 | + |
| 1200 | + /* Not a literal byte so it must be an (offset,length) pair */ |
| 1201 | + /* decode offset */ |
| 1202 | + sig = val & 0xf0; |
| 1203 | + if (sig == 0xf0) { /* 10-bit offset; 0 <= offset < 64 */ |
| 1204 | + off = (((val&0x0f)<<2)|getbits(ibuf, 2 , &i ,&l)); |
| 1205 | + bits -= 10; |
| 1206 | + } else { |
| 1207 | + if (sig == 0xe0) { /* 12-bit offset; 64 <= offset < 320 */ |
| 1208 | + off = ((((val&0x0f)<<4)|getbits(ibuf, 4 , &i ,&l))+64); |
| 1209 | + bits -= 12; |
| 1210 | + } else { |
| 1211 | + if ((sig&0xe0) == 0xc0) {/* 16-bit offset; 320 <= offset < 8192 */ |
| 1212 | + off = ((((val&0x1f)<<8)|getbyte(ibuf, i++, l))+320); |
| 1213 | + bits -= 16; |
| 1214 | + if (off > MPPE_HIST_LEN - 1) { |
| 1215 | + if (state->debug) |
| 1216 | + printk(KERN_DEBUG "%s%d: too big offset value: %d\n", |
| 1217 | + __FUNCTION__, state->unit, off); |
| 1218 | + return DECOMP_ERROR; |
| 1219 | + } |
| 1220 | + } else { /* this shouldn't happen */ |
| 1221 | + if (state->debug) |
| 1222 | + printk(KERN_DEBUG "%s%d: cannot decode offset value\n", |
| 1223 | + __FUNCTION__, state->unit); |
| 1224 | + return DECOMP_ERROR; |
| 1225 | + } |
| 1226 | + } |
| 1227 | + } |
| 1228 | + /* decode length of match */ |
| 1229 | + val = getbyte(ibuf, i, l); |
| 1230 | + if ((val & 0x80) == 0x00) { /* len = 3 */ |
| 1231 | + len = 3; |
| 1232 | + bits--; |
| 1233 | + getbits(ibuf, 1 , &i ,&l); |
| 1234 | + } else if ((val & 0xc0) == 0x80) { /* 4 <= len < 8 */ |
| 1235 | + len = 0x04 | ((val>>4) & 0x03); |
| 1236 | + bits -= 4; |
| 1237 | + getbits(ibuf, 4 , &i ,&l); |
| 1238 | + } else if ((val & 0xe0) == 0xc0) { /* 8 <= len < 16 */ |
| 1239 | + len = 0x08 | ((val>>2) & 0x07); |
| 1240 | + bits -= 6; |
| 1241 | + getbits(ibuf, 6 , &i ,&l); |
| 1242 | + } else if ((val & 0xf0) == 0xe0) { /* 16 <= len < 32 */ |
| 1243 | + len = 0x10 | (val & 0x0f); |
| 1244 | + bits -= 8; |
| 1245 | + i++; |
| 1246 | + } else { |
| 1247 | + bits -= 8; |
| 1248 | + val = (val << 8) | getbyte(ibuf, ++i, l); |
| 1249 | + if ((val & 0xf800) == 0xf000) { /* 32 <= len < 64 */ |
| 1250 | + len = 0x0020 | ((val >> 6) & 0x001f); |
| 1251 | + bits -= 2; |
| 1252 | + getbits(ibuf, 2 , &i ,&l); |
| 1253 | + } else if ((val & 0xfc00) == 0xf800) { /* 64 <= len < 128 */ |
| 1254 | + len = 0x0040 | ((val >> 4) & 0x003f); |
| 1255 | + bits -= 4; |
| 1256 | + getbits(ibuf, 4 , &i ,&l); |
| 1257 | + } else if ((val & 0xfe00) == 0xfc00) { /* 128 <= len < 256 */ |
| 1258 | + len = 0x0080 | ((val >> 2) & 0x007f); |
| 1259 | + bits -= 6; |
| 1260 | + getbits(ibuf, 6 , &i ,&l); |
| 1261 | + } else if ((val & 0xff00) == 0xfe00) { /* 256 <= len < 512 */ |
| 1262 | + len = 0x0100 | (val & 0x00ff); |
| 1263 | + bits -= 8; |
| 1264 | + i++; |
| 1265 | + } else { |
| 1266 | + bits -= 8; |
| 1267 | + val = (val << 8) | getbyte(ibuf, ++i, l); |
| 1268 | + if ((val & 0xff8000) == 0xff0000) { /* 512 <= len < 1024 */ |
| 1269 | + len = 0x000200 | ((val >> 6) & 0x0001ff); |
| 1270 | + bits -= 2; |
| 1271 | + getbits(ibuf, 2 , &i ,&l); |
| 1272 | + } else if ((val & 0xffc000) == 0xff8000) {/* 1024 <= len < 2048 */ |
| 1273 | + len = 0x000400 | ((val >> 4) & 0x0003ff); |
| 1274 | + bits -= 4; |
| 1275 | + getbits(ibuf, 4 , &i ,&l); |
| 1276 | + } else if ((val & 0xffe000) == 0xffc000) {/* 2048 <= len < 4096 */ |
| 1277 | + len = 0x000800 | ((val >> 2) & 0x0007ff); |
| 1278 | + bits -= 6; |
| 1279 | + getbits(ibuf, 6 , &i ,&l); |
| 1280 | + } else if ((val & 0xfff000) == 0xffe000) {/* 4096 <= len < 8192 */ |
| 1281 | + len = 0x001000 | (val & 0x000fff); |
| 1282 | + bits -= 8; |
| 1283 | + i++; |
| 1284 | + } else { /* this shouldn't happen */ |
| 1285 | + if (state->debug) |
| 1286 | + printk(KERN_DEBUG "%s%d: wrong length code: 0x%X\n", |
| 1287 | + __FUNCTION__, state->unit, val); |
| 1288 | + return DECOMP_ERROR; |
| 1289 | + } |
| 1290 | + } |
| 1291 | + } |
| 1292 | + s = state->hist + state->histptr; |
| 1293 | + state->histptr += len; |
| 1294 | + olen += len; |
| 1295 | + if (state->histptr < 2*MPPE_HIST_LEN) { |
| 1296 | + /* copy uncompressed bytes to the history */ |
| 1297 | + |
| 1298 | + /* In some cases len may be greater than off. It means that memory |
| 1299 | + * areas pointed by s and s-off overlap. I had used memmove() here |
| 1300 | + * because I thought that it acts as libc's version. Unfortunately, |
| 1301 | + * I was wrong. :-) I got strange errors sometimes. Wilfried suggested |
| 1302 | + * using of byte by byte copying here and strange errors disappeared. |
| 1303 | + */ |
| 1304 | + lamecopy(s, s - off, len); |
| 1305 | + } else { |
| 1306 | + /* buffer overflow; drop packet */ |
| 1307 | + if (state->debug) |
| 1308 | + printk(KERN_ERR "%s%d: trying to write outside history " |
| 1309 | + "buffer\n", __FUNCTION__, state->unit); |
| 1310 | + return DECOMP_ERROR; |
| 1311 | + } |
| 1312 | + } |
| 1313 | + |
| 1314 | + /* Do PFC decompression */ |
| 1315 | + len = olen; |
| 1316 | + if ((history[0] & 0x01) != 0) { |
| 1317 | + obuf[0] = 0; |
| 1318 | + obuf++; |
| 1319 | + len++; |
| 1320 | + } |
| 1321 | + |
| 1322 | + if (len <= osize) { |
| 1323 | + /* copy uncompressed packet to the output buffer */ |
| 1324 | + memcpy(obuf, history, olen); |
| 1325 | + } else { |
| 1326 | + /* buffer overflow; drop packet */ |
| 1327 | + if (state->debug) |
| 1328 | + printk(KERN_ERR "%s%d: too big uncompressed packet: %d\n", |
| 1329 | + __FUNCTION__, state->unit, len + (PPP_HDRLEN / 2)); |
| 1330 | + return DECOMP_ERROR; |
| 1331 | + } |
| 1332 | + |
| 1333 | + return (int) len; |
| 1334 | +} |
| 1335 | + |
| 1336 | +int |
| 1337 | +mppe_decompress(void *arg, unsigned char *ibuf, int isize, |
| 1338 | + unsigned char *obuf, int osize) |
| 1339 | +{ |
| 1340 | + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; |
| 1341 | + int seq, bits, uncomplen; |
| 1342 | + |
| 1343 | + if (isize <= PPP_HDRLEN + MPPE_OVHD) { |
| 1344 | + if (state->debug) { |
| 1345 | + printk(KERN_DEBUG "%s%d: short packet (len=%d)\n", __FUNCTION__, |
| 1346 | + state->unit, isize); |
| 1347 | + } |
| 1348 | + return DECOMP_ERROR; |
| 1349 | + } |
| 1350 | + |
| 1351 | + /* Get coherency counter and control bits from input buffer */ |
| 1352 | + seq = MPPE_CCOUNT(ibuf); |
| 1353 | + bits = MPPE_BITS(ibuf); |
| 1354 | + |
| 1355 | + if (state->stateless) { |
| 1356 | + /* RFC 3078, sec 8.1. */ |
| 1357 | + mppe_increase_ccount(state); |
| 1358 | + if ((seq != state->ccount) && state->debug) |
| 1359 | + printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n", |
| 1360 | + __FUNCTION__, state->unit, seq, state->ccount); |
| 1361 | + while (seq != state->ccount) |
| 1362 | + mppe_increase_ccount(state); |
| 1363 | + } else { |
| 1364 | + /* RFC 3078, sec 8.2. */ |
| 1365 | + if (state->flushexpected) { /* discard state */ |
| 1366 | + if ((bits & MPPE_BIT_FLUSHED)) { /* we received expected FLUSH bit */ |
| 1367 | + while (seq != state->ccount) |
| 1368 | + mppe_increase_ccount(state); |
| 1369 | + state->flushexpected = 0; |
| 1370 | + } else /* drop packet*/ |
| 1371 | + return DECOMP_ERROR; |
| 1372 | + } else { /* normal state */ |
| 1373 | + mppe_increase_ccount(state); |
| 1374 | + if (seq != state->ccount) { |
| 1375 | + /* Packet loss detected, enter the discard state. */ |
| 1376 | + if (state->debug) |
| 1377 | + printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n", |
| 1378 | + __FUNCTION__, state->unit, seq, state->ccount); |
| 1379 | + state->flushexpected = 1; |
| 1380 | + return DECOMP_ERROR; |
| 1381 | + } |
| 1382 | + } |
| 1383 | + if (state->mppe && (bits & MPPE_BIT_FLUSHED)) { |
| 1384 | + arc4_setkey(state, state->session_key, state->keylen); |
| 1385 | + } |
| 1386 | + } |
| 1387 | + |
| 1388 | + if (state->mppc && (bits & (MPPE_BIT_FLUSHED | MPPE_BIT_RESET))) { |
| 1389 | + state->histptr = MPPE_HIST_LEN; |
| 1390 | + if ((bits & MPPE_BIT_FLUSHED)) { |
| 1391 | + memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8)); |
| 1392 | + } else |
| 1393 | + if ((bits & MPPE_BIT_RESET)) { |
| 1394 | + memcpy(state->hist, state->hist + MPPE_HIST_LEN, MPPE_HIST_LEN); |
| 1395 | + } |
| 1396 | + } |
| 1397 | + |
| 1398 | + /* Fill in the first part of the PPP header. The protocol field |
| 1399 | + comes from the decompressed data. */ |
| 1400 | + obuf[0] = PPP_ADDRESS(ibuf); |
| 1401 | + obuf[1] = PPP_CONTROL(ibuf); |
| 1402 | + obuf += PPP_HDRLEN / 2; |
| 1403 | + |
| 1404 | + if (state->mppe) { /* process encrypted packet */ |
| 1405 | + if ((bits & MPPE_BIT_ENCRYPTED)) { |
| 1406 | + /* OK, packet encrypted, so decrypt it */ |
| 1407 | + if (state->mppc && (bits & MPPE_BIT_COMP)) { |
| 1408 | + /* Hack warning !!! RC4 implementation which we use does |
| 1409 | + decryption "in place" - it means that input and output |
| 1410 | + buffers can be *the same* memory area. Therefore we don't |
| 1411 | + need to use a temporary buffer. But be careful - other |
| 1412 | + implementations don't have to be so nice. */ |
| 1413 | + arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), isize - |
| 1414 | + PPP_HDRLEN - (MPPE_OVHD / 2), ibuf + PPP_HDRLEN + |
| 1415 | + (MPPE_OVHD / 2)); |
| 1416 | + uncomplen = mppc_decompress(state, ibuf + PPP_HDRLEN + |
| 1417 | + (MPPE_OVHD / 2), obuf, isize - |
| 1418 | + PPP_HDRLEN - (MPPE_OVHD / 2), |
| 1419 | + osize - (PPP_HDRLEN / 2)); |
| 1420 | + if (uncomplen == DECOMP_ERROR) { |
| 1421 | + state->flushexpected = 1; |
| 1422 | + return DECOMP_ERROR; |
| 1423 | + } |
| 1424 | + uncomplen += PPP_HDRLEN / 2; |
| 1425 | + (state->stats).comp_bytes += isize; |
| 1426 | + (state->stats).comp_packets++; |
| 1427 | + } else { |
| 1428 | + uncomplen = isize - MPPE_OVHD; |
| 1429 | + /* Decrypt the first byte in order to check if it is |
| 1430 | + compressed or uncompressed protocol field */ |
| 1431 | + arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), 1, obuf); |
| 1432 | + /* Do PFC decompression */ |
| 1433 | + if ((obuf[0] & 0x01) != 0) { |
| 1434 | + obuf[1] = obuf[0]; |
| 1435 | + obuf[0] = 0; |
| 1436 | + obuf++; |
| 1437 | + uncomplen++; |
| 1438 | + } |
| 1439 | + /* And finally, decrypt the rest of the frame. */ |
| 1440 | + arc4_decrypt(state, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2) + 1, |
| 1441 | + isize - PPP_HDRLEN - (MPPE_OVHD / 2) - 1, obuf + 1); |
| 1442 | + (state->stats).inc_bytes += isize; |
| 1443 | + (state->stats).inc_packets++; |
| 1444 | + } |
| 1445 | + } else { /* this shouldn't happen */ |
| 1446 | + if (state->debug) |
| 1447 | + printk(KERN_ERR "%s%d: encryption negotiated but not an " |
| 1448 | + "encrypted packet received\n", __FUNCTION__, state->unit); |
| 1449 | + mppe_change_key(state, 0); |
| 1450 | + state->flushexpected = 1; |
| 1451 | + return DECOMP_ERROR; |
| 1452 | + } |
| 1453 | + } else { |
| 1454 | + if (state->mppc) { /* no MPPE, only MPPC */ |
| 1455 | + if ((bits & MPPE_BIT_COMP)) { |
| 1456 | + uncomplen = mppc_decompress(state, ibuf + PPP_HDRLEN + |
| 1457 | + (MPPE_OVHD / 2), obuf, isize - |
| 1458 | + PPP_HDRLEN - (MPPE_OVHD / 2), |
| 1459 | + osize - (PPP_HDRLEN / 2)); |
| 1460 | + if (uncomplen == DECOMP_ERROR) { |
| 1461 | + state->flushexpected = 1; |
| 1462 | + return DECOMP_ERROR; |
| 1463 | + } |
| 1464 | + uncomplen += PPP_HDRLEN / 2; |
| 1465 | + (state->stats).comp_bytes += isize; |
| 1466 | + (state->stats).comp_packets++; |
| 1467 | + } else { |
| 1468 | + memcpy(obuf, ibuf + PPP_HDRLEN + (MPPE_OVHD / 2), isize - |
| 1469 | + PPP_HDRLEN - (MPPE_OVHD / 2)); |
| 1470 | + uncomplen = isize - MPPE_OVHD; |
| 1471 | + (state->stats).inc_bytes += isize; |
| 1472 | + (state->stats).inc_packets++; |
| 1473 | + } |
| 1474 | + } else { /* this shouldn't happen */ |
| 1475 | + if (state->debug) |
| 1476 | + printk(KERN_ERR "%s%d: error - not an MPPC or MPPE frame " |
| 1477 | + "received\n", __FUNCTION__, state->unit); |
| 1478 | + state->flushexpected = 1; |
| 1479 | + return DECOMP_ERROR; |
| 1480 | + } |
| 1481 | + } |
| 1482 | + |
| 1483 | + (state->stats).unc_bytes += uncomplen; |
| 1484 | + (state->stats).unc_packets++; |
| 1485 | + |
| 1486 | + return uncomplen; |
| 1487 | +} |
| 1488 | + |
| 1489 | + |
| 1490 | +/************************************************************ |
| 1491 | + * Module interface table |
| 1492 | + ************************************************************/ |
| 1493 | + |
| 1494 | +/* These are in ppp_generic.c */ |
| 1495 | +extern int ppp_register_compressor (struct compressor *cp); |
| 1496 | +extern void ppp_unregister_compressor (struct compressor *cp); |
| 1497 | + |
| 1498 | +/* |
| 1499 | + * Functions exported to ppp_generic.c. |
| 1500 | + * |
| 1501 | + * In case of MPPC/MPPE there is no need to process incompressible data |
| 1502 | + * because such a data is sent in MPPC/MPPE frame. Therefore the (*incomp) |
| 1503 | + * callback function isn't needed. |
| 1504 | + */ |
| 1505 | +struct compressor ppp_mppe = { |
| 1506 | + CI_MPPE, /* compress_proto */ |
| 1507 | + mppe_comp_alloc, /* comp_alloc */ |
| 1508 | + mppe_comp_free, /* comp_free */ |
| 1509 | + mppe_comp_init, /* comp_init */ |
| 1510 | + mppe_comp_reset, /* comp_reset */ |
| 1511 | + mppe_compress, /* compress */ |
| 1512 | + mppe_stats, /* comp_stat */ |
| 1513 | + mppe_decomp_alloc, /* decomp_alloc */ |
| 1514 | + mppe_comp_free, /* decomp_free */ |
| 1515 | + mppe_decomp_init, /* decomp_init */ |
| 1516 | + mppe_decomp_reset, /* decomp_reset */ |
| 1517 | + mppe_decompress, /* decompress */ |
| 1518 | + NULL, /* incomp */ |
| 1519 | + mppe_stats, /* decomp_stat */ |
| 1520 | +}; |
| 1521 | + |
| 1522 | +/************************************************************ |
| 1523 | + * Module support routines |
| 1524 | + ************************************************************/ |
| 1525 | + |
| 1526 | +int __init mppe_module_init(void) |
| 1527 | +{ |
| 1528 | + int answer; |
| 1529 | + |
| 1530 | + /* When the module is compiled into kernel, it is initialized before |
| 1531 | + * CryptoAPI. Therefore the code below reports that there is no crypto |
| 1532 | + * stuff in the kernel. Marlon de Boer who has pointed out the problem, |
| 1533 | + * has sent also a message to CryptoAPI developers, so maybe in the future |
| 1534 | + * the code will be uncommented. |
| 1535 | + * |
| 1536 | + if (!(crypto_alg_available("arc4", 0) && crypto_alg_available("sha1", 0))) { |
| 1537 | + printk(KERN_ERR "Kernel doesn't provide ARC4 and/or SHA1 algorithms " |
| 1538 | + "required by MPPE/MPPC. Check CryptoAPI configuration.\n"); |
| 1539 | + return -ENODEV; |
| 1540 | + } |
| 1541 | + */ |
| 1542 | + |
| 1543 | + /* Allocate space for SHAPad1, SHAPad2 and ... */ |
| 1544 | + sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); |
| 1545 | + if (sha_pad == NULL) |
| 1546 | + return -ENOMEM; |
| 1547 | + /* ... initialize them */ |
| 1548 | + memset(sha_pad->sha_pad1, 0x00, sizeof(sha_pad->sha_pad1)); |
| 1549 | + memset(sha_pad->sha_pad2, 0xf2, sizeof(sha_pad->sha_pad2)); |
| 1550 | + |
| 1551 | + answer = ppp_register_compressor(&ppp_mppe); |
| 1552 | + if (answer == 0) { |
| 1553 | + printk(KERN_INFO "MPPE/MPPC encryption/compression module registered\n"); |
| 1554 | + } |
| 1555 | + return answer; |
| 1556 | +} |
| 1557 | + |
| 1558 | +void __exit mppe_module_cleanup(void) |
| 1559 | +{ |
| 1560 | + kfree(sha_pad); |
| 1561 | + ppp_unregister_compressor(&ppp_mppe); |
| 1562 | + printk(KERN_INFO "MPPE/MPPC encryption/compression module unregistered\n"); |
| 1563 | +} |
| 1564 | + |
| 1565 | +module_init(mppe_module_init); |
| 1566 | +module_exit(mppe_module_cleanup); |
| 1567 | + |
| 1568 | +MODULE_AUTHOR("Jan Dubiec <jdx@slackware.pl>"); |
| 1569 | +MODULE_DESCRIPTION("MPPE/MPPC encryption/compression module for Linux"); |
| 1570 | +MODULE_LICENSE("Dual BSD/GPL"); |
| 1571 | --- a/include/linux/ppp-comp.h |
| 1572 | +++ b/include/linux/ppp-comp.h |
| 1573 | @@ -28,7 +28,7 @@ |
| 1574 | */ |
| 1575 | |
| 1576 | /* |
| 1577 | - * ==FILEVERSION 980319== |
| 1578 | + * ==FILEVERSION 20040509== |
| 1579 | * |
| 1580 | * NOTE TO MAINTAINERS: |
| 1581 | * If you modify this file at all, please set the above date. |
| 1582 | @@ -78,7 +78,7 @@ struct compressor { |
| 1583 | |
| 1584 | /* Compress a packet */ |
| 1585 | int (*compress) (void *state, unsigned char *rptr, |
| 1586 | - unsigned char *obuf, int isize, int osize); |
| 1587 | + unsigned char *obuf, int isize, int osize); |
| 1588 | |
| 1589 | /* Return compression statistics */ |
| 1590 | void (*comp_stat) (void *state, struct compstat *stats); |
| 1591 | @@ -99,7 +99,7 @@ struct compressor { |
| 1592 | |
| 1593 | /* Decompress a packet. */ |
| 1594 | int (*decompress) (void *state, unsigned char *ibuf, int isize, |
| 1595 | - unsigned char *obuf, int osize); |
| 1596 | + unsigned char *obuf, int osize); |
| 1597 | |
| 1598 | /* Update state for an incompressible packet received */ |
| 1599 | void (*incomp) (void *state, unsigned char *ibuf, int icnt); |
| 1600 | @@ -187,6 +187,42 @@ struct compressor { |
| 1601 | #define DEFLATE_CHK_SEQUENCE 0 |
| 1602 | |
| 1603 | /* |
| 1604 | + * Definitions for MPPE/MPPC. |
| 1605 | + */ |
| 1606 | + |
| 1607 | +#define CI_MPPE 18 /* config option for MPPE */ |
| 1608 | +#define CILEN_MPPE 6 /* length of config option */ |
| 1609 | + |
| 1610 | +#define MPPE_OVHD 4 /* MPPE overhead */ |
| 1611 | +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ |
| 1612 | + |
| 1613 | +#define MPPE_STATELESS 0x01 /* configuration bit H */ |
| 1614 | +#define MPPE_40BIT 0x20 /* configuration bit L */ |
| 1615 | +#define MPPE_56BIT 0x80 /* configuration bit M */ |
| 1616 | +#define MPPE_128BIT 0x40 /* configuration bit S */ |
| 1617 | +#define MPPE_MPPC 0x01 /* configuration bit C */ |
| 1618 | + |
| 1619 | +/* |
| 1620 | + * Definitions for Stac LZS. |
| 1621 | + */ |
| 1622 | + |
| 1623 | +#define CI_LZS 17 /* config option for Stac LZS */ |
| 1624 | +#define CILEN_LZS 5 /* length of config option */ |
| 1625 | + |
| 1626 | +#define LZS_OVHD 4 /* max. LZS overhead */ |
| 1627 | +#define LZS_HIST_LEN 2048 /* LZS history size */ |
| 1628 | +#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */ |
| 1629 | + |
| 1630 | +#define LZS_MODE_NONE 0 |
| 1631 | +#define LZS_MODE_LCB 1 |
| 1632 | +#define LZS_MODE_CRC 2 |
| 1633 | +#define LZS_MODE_SEQ 3 |
| 1634 | +#define LZS_MODE_EXT 4 |
| 1635 | + |
| 1636 | +#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */ |
| 1637 | +#define LZS_EXT_BIT_COMP 0x20 /* bit C */ |
| 1638 | + |
| 1639 | +/* |
| 1640 | * Definitions for other, as yet unsupported, compression methods. |
| 1641 | */ |
| 1642 | |
| 1643 | |