OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [ppp_mppe.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *  ==FILEVERSION 9906180==
3
 *
4
 * ppp_mppe.c - MPPE "compressor/decompressor" module.
5
 *
6
 * Copyright (c) 1994 Árpád Magosányi <mag@bunuel.tii.matav.hu>
7
 * All rights reserved.
8
 * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com>
9
 *
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. The Australian National University
14
 * makes no representations about the suitability of this software for
15
 * any purpose.
16
 *
17
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
18
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
19
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
20
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
21
 * OF SUCH DAMAGE.
22
 *
23
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
26
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
27
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
28
 * OR MODIFICATIONS.
29
 *
30
 * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp
31
 */
32
 
33
#include <linux/module.h>
34
#include <linux/version.h>
35
#include <linux/kernel.h>
36
#include <linux/sched.h>
37
#include <linux/types.h>
38
#include <linux/fcntl.h>
39
#include <linux/interrupt.h>
40
#include <linux/ptrace.h>
41
#include <linux/ioport.h>
42
#include <linux/in.h>
43
#include <linux/malloc.h>
44
 
45
#undef VERSION
46
/* a nice define to generate linux version numbers */
47
#define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
48
 
49
#if LINUX_VERSION_CODE >= VERSION(2,1,4)
50
#include <linux/vmalloc.h>
51
#endif
52
#include <linux/errno.h>
53
#include <linux/sched.h>        /* to get the struct task_struct */
54
#include <linux/string.h>       /* used in new tty drivers */
55
#include <linux/signal.h>       /* used in new tty drivers */
56
 
57
#include <asm/system.h>
58
 
59
#include <linux/netdevice.h>
60
#include <linux/skbuff.h>
61
#include <linux/inet.h>
62
#include <linux/ioctl.h>
63
 
64
#include <linux/ppp_defs.h>
65
#include <linux/ppp-comp.h>
66
#include "rc4.h"
67
#include "rc4_enc.c"
68
#include "sha1dgst.c"
69
#include "mppe.h"
70
 
71
/*
72
 * State for a mppe "(de)compressor".
73
 */
74
struct ppp_mppe_state {
75
    unsigned int        ccount; /*coherency count */
76
    RC4_KEY             RC4_send_key; /* chap-ms-v2 dictates 2 keys */
77
    RC4_KEY             RC4_recv_key;
78
    unsigned char       session_send_key[16];
79
    unsigned char       session_recv_key[16];
80
    unsigned char       master_send_key[16];
81
    unsigned char       master_recv_key[16];
82
    int                 keylen;
83
    int                 stateless;
84
    int                 decomp_error;
85
    unsigned int        bits;
86
    int                 unit;
87
    int                 debug;
88
    int                 mru;
89
    struct compstat     stats;
90
};
91
 
92
#define MPPE_CCOUNT_FROM_PACKET(ibuf)   ((((ibuf)[4] & 0x0f) << 8) + (ibuf)[5])
93
#define MPPE_BITS(ibuf)         ((ibuf)[4] & 0xf0 )
94
#define MPPE_CTRLHI(state)      ((((state)->ccount & 0xf00)>>8)|((state)->bits))
95
#define MPPE_CTRLLO(state)      ((state)->ccount & 0xff)
96
 
97
#define MPPE_OVHD               4
98
 
99
/* Procedures from the MPPE draft */
100
static void
101
mppe_synchronize_key(struct ppp_mppe_state *state)
102
{
103
    /* get new keys and flag our state as such */
104
    RC4_set_key(&(state->RC4_send_key),state->keylen,state->session_send_key);
105
    RC4_set_key(&(state->RC4_recv_key),state->keylen,state->session_recv_key);
106
 
107
    state->bits=MPPE_BIT_FLUSHED|MPPE_BIT_ENCRYPTED;
108
}
109
 
110
 
111
static void
112
mppe_initialize_key(struct ppp_mppe_state *state)
113
{
114
    /* generate new session keys */
115
    GetNewKeyFromSHA(state->master_send_key, state->master_send_key,
116
        state->keylen, state->session_send_key);
117
    GetNewKeyFromSHA(state->master_recv_key, state->master_recv_key,
118
        state->keylen, state->session_recv_key);
119
 
120
    if(state->keylen == 8) {
121
        /* cripple them from 64bit->40bit */
122
        state->session_send_key[0]=state->session_recv_key[0] = MPPE_40_SALT0;
123
        state->session_send_key[1]=state->session_recv_key[1] = MPPE_40_SALT1;
124
        state->session_send_key[2]=state->session_recv_key[2] = MPPE_40_SALT2;
125
    }
126
 
127
    mppe_synchronize_key(state);
128
}
129
 
130
 
131
static void
132
mppe_change_key(struct ppp_mppe_state *state)
133
{
134
    unsigned char InterimSendKey[16];
135
    unsigned char InterimRecvKey[16];
136
 
137
    /* get temp keys */
138
    GetNewKeyFromSHA(state->master_send_key, state->session_send_key,
139
        state->keylen, InterimSendKey);
140
    GetNewKeyFromSHA(state->master_recv_key, state->session_recv_key,
141
        state->keylen, InterimRecvKey);
142
 
143
    /* build RC4 keys from the temp keys */
144
    RC4_set_key(&(state->RC4_send_key), state->keylen, InterimSendKey);
145
    RC4_set_key(&(state->RC4_recv_key), state->keylen, InterimRecvKey);
146
 
147
    /* make new session keys */
148
    RC4(&(state->RC4_send_key), state->keylen, InterimSendKey,
149
        state->session_send_key);
150
    RC4(&(state->RC4_recv_key), state->keylen, InterimRecvKey,
151
        state->session_recv_key);
152
 
153
    if(state->keylen == 8)
154
    {
155
        /* cripple them from 64->40 bits*/
156
        state->session_send_key[0]=state->session_recv_key[0] = MPPE_40_SALT0;
157
        state->session_send_key[1]=state->session_recv_key[1] = MPPE_40_SALT1;
158
        state->session_send_key[2]=state->session_recv_key[2] = MPPE_40_SALT2;
159
    }
160
 
161
    /* make the final rc4 keys */
162
    RC4_set_key(&(state->RC4_send_key), state->keylen, state->session_send_key);
163
    RC4_set_key(&(state->RC4_recv_key), state->keylen, state->session_recv_key);
164
 
165
    state->bits=MPPE_BIT_ENCRYPTED;
166
}
167
 
168
 
169
#ifdef DEBUG
170
/* Utility procedures to print a buffer in hex/ascii */
171
static void
172
ppp_print_hex (register __u8 *out, const __u8 *in, int count)
173
{
174
        register __u8 next_ch;
175
        static char hex[] = "0123456789ABCDEF";
176
 
177
        while (count-- > 0) {
178
                next_ch = *in++;
179
                *out++ = hex[(next_ch >> 4) & 0x0F];
180
                *out++ = hex[next_ch & 0x0F];
181
                ++out;
182
        }
183
}
184
 
185
 
186
static void
187
ppp_print_char (register __u8 *out, const __u8 *in, int count)
188
{
189
        register __u8 next_ch;
190
 
191
        while (count-- > 0) {
192
                next_ch = *in++;
193
 
194
                if (next_ch < 0x20 || next_ch > 0x7e)
195
                        *out++ = '.';
196
                else {
197
                        *out++ = next_ch;
198
                        if (next_ch == '%')   /* printk/syslogd has a bug !! */
199
                                *out++ = '%';
200
                }
201
        }
202
        *out = '\0';
203
}
204
 
205
 
206
static void
207
ppp_print_buffer (const __u8 *name, const __u8 *buf, int count)
208
{
209
        __u8 line[44];
210
 
211
        if (name != (__u8 *) NULL)
212
                printk (KERN_DEBUG "ppp: %s, count = %d\n", name, count);
213
 
214
        while (count > 8) {
215
                memset (line, 32, 44);
216
                ppp_print_hex (line, buf, 8);
217
                ppp_print_char (&line[8 * 3], buf, 8);
218
                printk (KERN_DEBUG "%s\n", line);
219
                count -= 8;
220
                buf += 8;
221
        }
222
 
223
        if (count > 0) {
224
                memset (line, 32, 44);
225
                ppp_print_hex (line, buf, count);
226
                ppp_print_char (&line[8 * 3], buf, count);
227
                printk (KERN_DEBUG "%s\n", line);
228
        }
229
}
230
#endif
231
 
232
/* our 'compressor' proper */
233
static void     *mppe_comp_alloc __P((unsigned char *, int));
234
static void     mppe_comp_free __P((void *));
235
static int      mppe_comp_init __P((void *, unsigned char *,
236
                                        int, int, int, int));
237
static int      mppe_decomp_init __P((void *, unsigned char *,
238
                                        int, int, int, int, int));
239
static int      mppe_compress __P((void *, unsigned char *,
240
                                        unsigned char *, int, int));
241
static void     mppe_incomp __P((void *, unsigned char *, int));
242
static int      mppe_decompress __P((void *, unsigned char *,
243
                                        int, unsigned char *, int));
244
static void     mppe_comp_reset __P((void *));
245
static void     mppe_comp_stats __P((void *, struct compstat *));
246
 
247
 
248
/* cleanup the compressor */
249
static void
250
mppe_comp_free(void *arg)
251
{
252
    struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
253
 
254
    if (state) {
255
            kfree(state);
256
            MOD_DEC_USE_COUNT;
257
    }
258
}
259
 
260
 
261
/* allocate space for a compressor.  */
262
static void *
263
mppe_comp_alloc(unsigned char *options, int opt_len)
264
{
265
    struct ppp_mppe_state *state;
266
 
267
    if (((2*8)+3 != opt_len && (2*16)+3 != opt_len) /* 2 keys + 3 */
268
       || options[0] != CI_MPPE || options[1] != CILEN_MPPE) {
269
            printk(KERN_DEBUG "compress rejected: opt_len=%u,o[0]=%x,o[1]=%x\n",
270
                opt_len,options[0],options[1]);
271
            return NULL;
272
    }
273
 
274
    state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL);
275
    if (state == NULL)
276
        return NULL;
277
 
278
    MOD_INC_USE_COUNT;
279
 
280
    memset (state, 0, sizeof (struct ppp_mppe_state));
281
 
282
    /* write the data in options to the right places */
283
    memcpy(&state->stateless,options+2,1);
284
 
285
    state->keylen = (opt_len-3)/2;
286
    memcpy(state->master_send_key,options+3,state->keylen);
287
    memcpy(state->master_recv_key,options+3+state->keylen,state->keylen);
288
 
289
    mppe_initialize_key(state);
290
 
291
    return (void *) state;
292
}
293
 
294
 
295
static int
296
mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit,
297
                int hdrlen, int debug)
298
{
299
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
300
 
301
    if (options[0] != CI_MPPE || options[1] != CILEN_MPPE) {
302
        printk(KERN_DEBUG "compress rejected: opt_len=%u,o[0]=%x,o[1]=%x\n",
303
            opt_len,options[0],options[1]);
304
        return 0;
305
    }
306
 
307
    state->ccount = 0;
308
    state->unit  = unit;
309
    state->debug = debug;
310
 
311
    /* 19 is the min (2*keylen) + 3 */
312
    if(opt_len >= 19) {
313
        memcpy(&state->stateless,options+2,1);
314
 
315
        state->keylen = (opt_len-3)/2;
316
        memcpy(state->master_send_key,options+3,state->keylen);
317
        memcpy(state->master_recv_key,options+3+state->keylen,state->keylen);
318
 
319
        mppe_initialize_key(state);
320
    }
321
 
322
    return 1;
323
}
324
 
325
 
326
static int
327
mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit,
328
                int hdrlen, int mru, int debug)
329
{
330
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
331
 
332
    if (options[0] != CI_MPPE || options[1] != CILEN_MPPE) {
333
        printk(KERN_DEBUG"options are bad: %x %x\n",options[0],options[1]);
334
        return 0;
335
    }
336
 
337
    state->ccount = 0;
338
    state->unit  = unit;
339
    state->debug = debug;
340
    state->mru = mru;
341
 
342
    /* 19 is the min (2*keylen)+3 */
343
    if(opt_len >= 19) {
344
        memcpy(&state->stateless,options+2,1);
345
 
346
        state->keylen = (opt_len-3)/2;
347
        memcpy(state->master_send_key,options+3,state->keylen);
348
        memcpy(state->master_recv_key,options+3+state->keylen,state->keylen);
349
 
350
        mppe_initialize_key(state);
351
    }
352
 
353
    return 1;
354
}
355
 
356
 
357
static void
358
mppe_comp_reset(void *arg)
359
{
360
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
361
 
362
    printk(KERN_DEBUG "mppe_comp_reset\n");
363
 
364
    (state->stats).in_count = 0;
365
    (state->stats).bytes_out = 0;
366
    (state->stats).ratio = 0;
367
 
368
    mppe_synchronize_key(state);
369
}
370
 
371
 
372
static void
373
mppe_update_count(struct ppp_mppe_state *state)
374
{
375
    if(!state->stateless)
376
    {
377
        if ( 0xff == (state->ccount&0xff)){
378
            /* time to change keys */
379
            if ( 0xfff == (state->ccount&0xfff)){
380
                state->ccount = 0;
381
            } else {
382
                (state->ccount)++;
383
            }
384
            mppe_change_key(state);
385
        } else {
386
            state->ccount++;
387
        }
388
    } else {
389
        if ( 0xFFF == (state->ccount & 0xFFF)) {
390
            state->ccount = 0;
391
        } else {
392
            (state->ccount)++;
393
        }
394
        mppe_change_key(state);
395
    }
396
}
397
 
398
 
399
/* the big nasty */
400
int
401
mppe_compress(void *arg, unsigned char *rptr, unsigned char *obuf,
402
                int isize, int osize)
403
{
404
    struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
405
    int proto, olen;
406
    unsigned char *wptr;
407
 
408
#ifdef DEBUG
409
    ppp_print_buffer("mppe_encrypt",rptr,isize);
410
#endif
411
 
412
    if(osize < isize+MPPE_OVHD) {
413
        printk(KERN_DEBUG "Not enough space to encrypt packet: %d<%d+%d!\n",
414
                isize, osize, MPPE_OVHD);
415
        return 0;
416
    }
417
 
418
    /* Check that the protocol is in the range we handle. */
419
    proto = PPP_PROTOCOL(rptr);
420
    if (proto < 0x0021 || proto > 0x00FA )
421
        return 0;
422
 
423
    wptr = obuf;
424
 
425
    /* Copy over the PPP header and store the 2-byte sequence number. */
426
    wptr[0] = PPP_ADDRESS(rptr);
427
    wptr[1] = PPP_CONTROL(rptr);
428
    wptr[2] = PPP_MPPE >>8;
429
    wptr[3] = PPP_MPPE;
430
    wptr += PPP_HDRLEN;
431
    wptr[0] = MPPE_CTRLHI(state);
432
    wptr[1] = MPPE_CTRLLO(state);
433
    wptr += 2;
434
 
435
    state->bits=MPPE_BIT_ENCRYPTED;
436
    mppe_update_count(state);
437
 
438
    /* read from rptr, write to wptr adjust for PPP_HDRLEN */
439
    RC4(&(state->RC4_send_key),isize-2,rptr+2,wptr);
440
    olen=isize+MPPE_OVHD;
441
 
442
    (state->stats).comp_bytes += isize;
443
    (state->stats).comp_packets++;
444
 
445
#ifdef DEBUG
446
    ppp_print_buffer("mppe_encrypt out",obuf,olen);
447
#endif
448
 
449
    return olen;
450
}
451
 
452
 
453
static void
454
mppe_comp_stats(void *arg, struct compstat *stats)
455
{
456
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
457
 
458
    /* since we don't REALLY compress at all, this should be OK */
459
    (state->stats).in_count = (state->stats).unc_bytes;
460
    (state->stats).bytes_out = (state->stats).comp_bytes;
461
 
462
    /* this _SHOULD_ always be 1 */
463
    (state->stats).ratio = (state->stats).in_count/(state->stats).bytes_out;
464
 
465
    *stats = state->stats;
466
 
467
}
468
 
469
 
470
/* the other big nasty */
471
int
472
mppe_decompress(void *arg, unsigned char *ibuf, int isize,
473
                unsigned char *obuf, int osize)
474
{
475
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
476
    int seq;
477
 
478
    if (isize <= PPP_HDRLEN + MPPE_OVHD) {
479
        if (state->debug) {
480
            printk(KERN_DEBUG "mppe_decompress%d: short packet (len=%d)\n",
481
                state->unit, isize);
482
        }
483
 
484
        return DECOMP_ERROR;
485
    }
486
 
487
    /* Check the sequence number. */
488
    seq = MPPE_CCOUNT_FROM_PACKET(ibuf);
489
 
490
    if(!state->stateless && (MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED)) {
491
        state->decomp_error = 0;
492
        state->ccount = seq;
493
    }
494
 
495
    if(state->decomp_error) {
496
        return DECOMP_ERROR;
497
    }
498
 
499
    if (seq != state->ccount) {
500
        if (state->debug) {
501
            printk(KERN_DEBUG "mppe_decompress%d: bad seq # %d, expected %d\n",
502
                   state->unit, seq, state->ccount);
503
        }
504
 
505
        while(state->ccount != seq) {
506
            mppe_update_count(state);
507
        }
508
 
509
        mppe_update_count(state);
510
 
511
        return DECOMP_ERROR;
512
    }
513
 
514
    /*
515
     * Fill in the first part of the PPP header.  The protocol field
516
     * comes from the decompressed data.
517
     */
518
    obuf[0] = PPP_ADDRESS(ibuf);
519
    obuf[1] = PPP_CONTROL(ibuf);
520
    obuf += 2;
521
 
522
    if(!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
523
        printk(KERN_DEBUG"ERROR: not an encrypted packet");
524
        mppe_synchronize_key(state);
525
        return DECOMP_ERROR;
526
    } else {
527
        if(!state->stateless && (MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED))
528
            mppe_synchronize_key(state);
529
        mppe_update_count(state);
530
 
531
        /* decrypt - adjust for PPP_HDRLEN + MPPE_OVHD - mru should be OK */
532
        RC4(&(state->RC4_recv_key),isize-6,ibuf+6,obuf);
533
 
534
        (state->stats).unc_bytes += (isize-MPPE_OVHD);
535
        (state->stats).unc_packets ++;
536
 
537
        return isize-MPPE_OVHD;
538
    }
539
}
540
 
541
 
542
/* Incompressible data has arrived - add it to the history.  */
543
static void
544
mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
545
{
546
    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
547
 
548
    (state->stats).inc_bytes += icnt;
549
    (state->stats).inc_packets++;
550
}
551
 
552
 
553
/*************************************************************
554
 * Module interface table
555
 *************************************************************/
556
 
557
/* These are in ppp.c */
558
extern int  ppp_register_compressor   (struct compressor *cp);
559
extern void ppp_unregister_compressor (struct compressor *cp);
560
 
561
/*
562
 * Procedures exported to if_ppp.c.
563
 */
564
struct compressor ppp_mppe = {
565
    CI_MPPE,                    /* compress_proto */
566
    mppe_comp_alloc,            /* comp_alloc */
567
    mppe_comp_free,             /* comp_free */
568
    mppe_comp_init,             /* comp_init */
569
    mppe_comp_reset,            /* comp_reset */
570
    mppe_compress,              /* compress */
571
    mppe_comp_stats,            /* comp_stat */
572
    mppe_comp_alloc,            /* decomp_alloc */
573
    mppe_comp_free,             /* decomp_free */
574
    mppe_decomp_init,           /* decomp_init */
575
    mppe_comp_reset,            /* decomp_reset */
576
    mppe_decompress,            /* decompress */
577
    mppe_incomp,                /* incomp */
578
    mppe_comp_stats,            /* decomp_stat */
579
};
580
 
581
 
582
#ifdef MODULE
583
/*************************************************************
584
 * Module support routines
585
 *************************************************************/
586
 
587
int
588
init_module(void)
589
{
590
    int answer = ppp_register_compressor(&ppp_mppe);
591
    if (answer == 0) {
592
        printk(KERN_INFO "PPP MPPE compression module registered\n");
593
    }
594
    return answer;
595
}
596
 
597
 
598
void
599
cleanup_module(void)
600
{
601
    if (MOD_IN_USE) {
602
        printk (KERN_INFO "MPPE module busy, remove delayed\n");
603
    } else {
604
        ppp_unregister_compressor (&ppp_mppe);
605
        printk(KERN_INFO "PPP MPPE compression module unregistered\n");
606
    }
607
}
608
#endif /* MODULE */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.