xref: /freebsd/usr.sbin/ppp/mppe.c (revision 17d6c636720d00f77e5d098daf4c278f89d84f7b)
1 /*-
2  * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #include <sys/types.h>
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <termios.h>
35 #ifdef __FreeBSD__
36 #include <sha.h>
37 #else
38 #include <openssl/sha.h>
39 #endif
40 #include <openssl/rc4.h>
41 
42 #include "defs.h"
43 #include "mbuf.h"
44 #include "log.h"
45 #include "timer.h"
46 #include "fsm.h"
47 #include "lqr.h"
48 #include "hdlc.h"
49 #include "lcp.h"
50 #include "ccp.h"
51 #include "throughput.h"
52 #include "layer.h"
53 #include "link.h"
54 #include "chap_ms.h"
55 #include "proto.h"
56 #include "mppe.h"
57 #include "ua.h"
58 
59 /*
60  * Documentation:
61  *
62  * draft-ietf-pppext-mppe-04.txt
63  * draft-ietf-pppext-mppe-keys-02.txt
64  */
65 
66 #define	MPPE_OPT_STATELESS	0x1000000
67 #define	MPPE_OPT_COMPRESSED	0x01
68 #define	MPPE_OPT_40BIT		0x20
69 #define	MPPE_OPT_56BIT		0x80
70 #define	MPPE_OPT_128BIT		0x40
71 #define	MPPE_OPT_BITMASK	0xe0
72 #define	MPPE_OPT_MASK		(MPPE_OPT_STATELESS | MPPE_OPT_BITMASK)
73 
74 #define	MPPE_FLUSHED			0x8000
75 #define	MPPE_ENCRYPTED			0x1000
76 #define	MPPE_HEADER_BITMASK		0xf000
77 #define	MPPE_HEADER_FLAG		0x00ff
78 #define	MPPE_HEADER_FLAGMASK		0x00ff
79 #define	MPPE_HEADER_FLAGSHIFT		8
80 #define	MPPE_HEADER_STATEFUL_KEYCHANGES	16
81 
82 struct mppe_state {
83   unsigned	stateless : 1;
84   unsigned	flushnext : 1;
85   unsigned	flushrequired : 1;
86   int		cohnum;
87   int		keylen;			/* 8 or 16 bytes */
88   int 		keybits;		/* 40, 56 or 128 bits */
89   char		sesskey[MPPE_KEY_LEN];
90   char		mastkey[MPPE_KEY_LEN];
91   RC4_KEY	rc4key;
92 };
93 
94 int MPPE_MasterKeyValid = 0;
95 int MPPE_IsServer = 0;
96 char MPPE_MasterKey[MPPE_KEY_LEN];
97 
98 /*
99  * The peer has missed a packet.  Mark the next output frame to be FLUSHED
100  */
101 static int
102 MPPEResetOutput(void *v)
103 {
104   struct mppe_state *mop = (struct mppe_state *)v;
105 
106   if (mop->stateless)
107     log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n");
108   else {
109     log_Printf(LogCCP, "MPPE: Output channel reset\n");
110     mop->flushnext = 1;
111   }
112 
113   return 0;		/* Ask FSM not to ACK */
114 }
115 
116 static void
117 MPPEReduceSessionKey(struct mppe_state *mp)
118 {
119   switch(mp->keybits) {
120   case 40:
121     mp->sesskey[2] = 0x9e;
122     mp->sesskey[1] = 0x26;
123   case 56:
124     mp->sesskey[0] = 0xd1;
125   case 128:
126   }
127 }
128 
129 static void
130 MPPEKeyChange(struct mppe_state *mp)
131 {
132   char InterimKey[MPPE_KEY_LEN];
133   RC4_KEY RC4Key;
134 
135   GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey);
136   RC4_set_key(&RC4Key, mp->keylen, InterimKey);
137   RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey);
138 
139   MPPEReduceSessionKey(mp);
140 }
141 
142 static struct mbuf *
143 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto,
144            struct mbuf *mp)
145 {
146   struct mppe_state *mop = (struct mppe_state *)v;
147   struct mbuf *mo;
148   u_short nproto, prefix;
149   int dictinit, ilen, len;
150   char *rp;
151 
152   ilen = m_length(mp);
153   dictinit = 0;
154 
155   log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
156   if (*proto < 0x21 && *proto > 0xFA) {
157     log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
158     ccp->compout += ilen;
159     ccp->uncompout += ilen;
160     return mp;
161   }
162 
163   log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp);
164 
165   /* Get mbuf for prefixes */
166   mo = m_get(4, MB_CCPOUT);
167   mo->m_next = mp;
168 
169   rp = MBUF_CTOP(mo);
170   prefix = MPPE_ENCRYPTED | mop->cohnum;
171 
172   if (mop->stateless ||
173       (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
174     /* Change our key */
175     log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum);
176     MPPEKeyChange(mop);
177     dictinit = 1;
178   }
179 
180   if (mop->stateless || mop->flushnext) {
181     prefix |= MPPE_FLUSHED;
182     dictinit = 1;
183     mop->flushnext = 0;
184   }
185 
186   if (dictinit) {
187     /* Initialise our dictionary */
188     log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n",
189                mop->cohnum);
190     RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
191   }
192 
193   /* Set MPPE packet prefix */
194   ua_htons(&prefix, rp);
195 
196   /* Save encrypted protocol number */
197   nproto = htons(*proto);
198   RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2);
199 
200   /* Encrypt main packet */
201   rp = MBUF_CTOP(mp);
202   RC4(&mop->rc4key, ilen, rp, rp);
203 
204   mop->cohnum++;
205   mop->cohnum &= ~MPPE_HEADER_BITMASK;
206 
207   /* Set the protocol number */
208   *proto = ccp_Proto(ccp);
209   len = m_length(mo);
210   ccp->uncompout += ilen;
211   ccp->compout += len;
212 
213   log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n",
214              *proto, len);
215 
216   return mo;
217 }
218 
219 static void
220 MPPEResetInput(void *v)
221 {
222   log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
223 }
224 
225 static struct mbuf *
226 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp)
227 {
228   struct mppe_state *mip = (struct mppe_state *)v;
229   u_short prefix;
230   char *rp;
231   int dictinit, flushed, ilen, len, n;
232 
233   ilen = m_length(mp);
234   dictinit = 0;
235   ccp->compin += ilen;
236 
237   log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen);
238   log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp);
239 
240   mp = mbuf_Read(mp, &prefix, 2);
241   prefix = ntohs(prefix);
242   flushed = prefix & MPPE_FLUSHED;
243   prefix &= ~flushed;
244   if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) {
245     log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n",
246                (prefix & MPPE_HEADER_BITMASK) | flushed);
247     m_freem(mp);
248     return NULL;
249   }
250 
251   prefix &= ~MPPE_HEADER_BITMASK;
252 
253   if (!flushed && mip->stateless) {
254     log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set"
255                " in stateless mode\n");
256     flushed = MPPE_FLUSHED;
257     /* Should we really continue ? */
258   }
259 
260   if (mip->stateless) {
261     /* Change our key for each missed packet in stateless mode */
262     while (prefix != mip->cohnum) {
263       log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
264       MPPEKeyChange(mip);
265       /*
266        * mip->cohnum contains what we received last time in stateless
267        * mode.
268        */
269       mip->cohnum++;
270       mip->cohnum &= ~MPPE_HEADER_BITMASK;
271     }
272     dictinit = 1;
273   } else {
274     if (flushed) {
275       /*
276        * We can always process a flushed packet.
277        * Catch up on any outstanding key changes.
278        */
279       n = (prefix >> MPPE_HEADER_FLAGSHIFT) -
280           (mip->cohnum >> MPPE_HEADER_FLAGSHIFT);
281       if (n < 0)
282         n += MPPE_HEADER_STATEFUL_KEYCHANGES;
283       while (n--) {
284         log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n",
285                    prefix);
286         MPPEKeyChange(mip);
287       }
288       mip->flushrequired = 0;
289       mip->cohnum = prefix;
290       dictinit = 1;
291     }
292 
293     if (mip->flushrequired) {
294       /*
295        * Perhaps we should be lenient if
296        * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG
297        * The spec says that we shouldn't be though....
298        */
299       log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n");
300       fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
301                  MB_CCPOUT);
302       m_freem(mp);
303       return NULL;
304     }
305 
306     if (prefix != mip->cohnum) {
307       /*
308        * We're in stateful mode and didn't receive the expected
309        * packet.  Send a reset request, but don't tell the CCP layer
310        * about it as we don't expect to receive a Reset ACK !
311        * Guess what... M$ invented this !
312        */
313       log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n",
314                  prefix, mip->cohnum);
315       fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
316                  MB_CCPOUT);
317       mip->flushrequired = 1;
318       m_freem(mp);
319       return NULL;
320     }
321 
322     if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
323       log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
324       MPPEKeyChange(mip);
325       dictinit = 1;
326     } else if (flushed)
327       dictinit = 1;
328 
329     /*
330      * mip->cohnum contains what we expect to receive next time in stateful
331      * mode.
332      */
333     mip->cohnum++;
334     mip->cohnum &= ~MPPE_HEADER_BITMASK;
335   }
336 
337   if (dictinit) {
338     log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix);
339     RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
340   }
341 
342   mp = mbuf_Read(mp, proto, 2);
343   RC4(&mip->rc4key, 2, (char *)proto, (char *)proto);
344   *proto = ntohs(*proto);
345 
346   rp = MBUF_CTOP(mp);
347   len = m_length(mp);
348   RC4(&mip->rc4key, len, rp, rp);
349 
350   log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n",
351              *proto, len);
352   log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp);
353 
354   ccp->uncompin += len;
355 
356   return mp;
357 }
358 
359 static void
360 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
361 {
362 }
363 
364 static const char *
365 MPPEDispOpts(struct lcp_opt *o)
366 {
367   static char buf[70];
368   u_int32_t val;
369   char ch;
370   int len;
371 
372   ua_ntohl(o->data, &val);
373   snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val);
374   len = strlen(buf);
375   if (!(val & MPPE_OPT_BITMASK)) {
376     snprintf(buf + len, sizeof buf - len, "(0");
377     len++;
378   } else {
379     ch = '(';
380     if (val & MPPE_OPT_128BIT) {
381       snprintf(buf + len, sizeof buf - len, "%c128", ch);
382       len += strlen(buf + len);
383       ch = '/';
384     }
385     if (val & MPPE_OPT_56BIT) {
386       snprintf(buf + len, sizeof buf - len, "%c56", ch);
387       len += strlen(buf + len);
388       ch = '/';
389     }
390     if (val & MPPE_OPT_40BIT) {
391       snprintf(buf + len, sizeof buf - len, "%c40", ch);
392       len += strlen(buf + len);
393       ch = '/';
394     }
395   }
396 
397   snprintf(buf + len, sizeof buf - len, " bits, state%s",
398            (val & MPPE_OPT_STATELESS) ? "less" : "ful");
399   len += strlen(buf + len);
400 
401   if (val & MPPE_OPT_COMPRESSED) {
402     snprintf(buf + len, sizeof buf - len, ", compressed");
403     len += strlen(buf + len);
404   }
405 
406   snprintf(buf + len, sizeof buf - len, ")");
407 
408   return buf;
409 }
410 
411 static int
412 MPPEUsable(struct fsm *fp)
413 {
414   struct lcp *lcp;
415   int ok;
416 
417   lcp = &fp->link->lcp;
418   ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) ||
419        (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81);
420   if (!ok)
421     log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n");
422 
423   return ok;
424 }
425 
426 static int
427 MPPERequired(struct fsm *fp)
428 {
429   return fp->link->ccp.cfg.mppe.required;
430 }
431 
432 static u_int32_t
433 MPPE_ConfigVal(const struct ccp_config *cfg)
434 {
435   u_int32_t val;
436 
437   val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
438   switch(cfg->mppe.keybits) {
439   case 128:
440     val |= MPPE_OPT_128BIT;
441     break;
442   case 56:
443     val |= MPPE_OPT_56BIT;
444     break;
445   case 40:
446     val |= MPPE_OPT_40BIT;
447     break;
448   case 0:
449     val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
450     break;
451   }
452 
453   return val;
454 }
455 
456 /*
457  * What options should we use for our first configure request
458  */
459 static void
460 MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
461 {
462   u_int32_t mval;
463 
464   o->len = 6;
465 
466   if (!MPPE_MasterKeyValid) {
467     log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
468                " MPPE is available only with CHAP81 authentication\n");
469     ua_htonl(0x0, o->data);
470     return;
471   }
472 
473   mval = MPPE_ConfigVal(cfg);
474   ua_htonl(&mval, o->data);
475 }
476 
477 /*
478  * Our CCP request was NAK'd with the given options
479  */
480 static int
481 MPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
482 {
483   u_int32_t mval, peer;
484 
485   ua_ntohl(o->data, &peer);
486 
487   if (!MPPE_MasterKeyValid)
488     /* Treat their NAK as a REJ */
489     return MODE_NAK;
490 
491   mval = MPPE_ConfigVal(cfg);
492 
493   /*
494    * If we haven't been configured with a specific number of keybits, allow
495    * whatever the peer asks for.
496    */
497   if (!cfg->mppe.keybits) {
498     mval &= ~MPPE_OPT_BITMASK;
499     mval |= (peer & MPPE_OPT_BITMASK);
500     if (!(mval & MPPE_OPT_BITMASK))
501       mval |= MPPE_OPT_128BIT;
502   }
503 
504   /* Adjust our statelessness */
505   if (cfg->mppe.state == MPPE_ANYSTATE) {
506     mval &= ~MPPE_OPT_STATELESS;
507     mval |= (peer & MPPE_OPT_STATELESS);
508   }
509 
510   ua_htonl(&mval, o->data);
511 
512   return MODE_ACK;
513 }
514 
515 /*
516  * The peer has requested the given options
517  */
518 static int
519 MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
520 {
521   u_int32_t mval, peer;
522   int res = MODE_ACK;
523 
524   ua_ntohl(o->data, &peer);
525   if (!MPPE_MasterKeyValid) {
526     if (peer != 0) {
527       peer = 0;
528       ua_htonl(&peer, o->data);
529       return MODE_NAK;
530     } else
531       return MODE_ACK;
532   }
533 
534   mval = MPPE_ConfigVal(cfg);
535 
536   if (peer & ~MPPE_OPT_MASK)
537     /* He's asking for bits we don't know about */
538     res = MODE_NAK;
539 
540   if (peer & MPPE_OPT_STATELESS) {
541     if (cfg->mppe.state == MPPE_STATEFUL)
542       /* Peer can't have stateless */
543       res = MODE_NAK;
544     else
545       /* Peer wants stateless, that's ok */
546       mval |= MPPE_OPT_STATELESS;
547   } else {
548     if (cfg->mppe.state == MPPE_STATELESS)
549       /* Peer must have stateless */
550       res = MODE_NAK;
551     else
552       /* Peer doesn't want stateless, that's ok */
553       mval &= ~MPPE_OPT_STATELESS;
554   }
555 
556   /* If we've got a configured number of keybits - the peer must use that */
557   if (cfg->mppe.keybits) {
558     ua_htonl(&mval, o->data);
559     return peer == mval ? res : MODE_NAK;
560   }
561 
562   /* If a specific number of bits hasn't been requested, we'll need to NAK */
563   switch (peer & MPPE_OPT_BITMASK) {
564   case MPPE_OPT_128BIT:
565   case MPPE_OPT_56BIT:
566   case MPPE_OPT_40BIT:
567     break;
568   default:
569     res = MODE_NAK;
570   }
571 
572   /* Suggest the best number of bits */
573   mval &= ~MPPE_OPT_BITMASK;
574   if (peer & MPPE_OPT_128BIT)
575     mval |= MPPE_OPT_128BIT;
576   else if (peer & MPPE_OPT_56BIT)
577     mval |= MPPE_OPT_56BIT;
578   else if (peer & MPPE_OPT_40BIT)
579     mval |= MPPE_OPT_40BIT;
580   else
581     mval |= MPPE_OPT_128BIT;
582   ua_htonl(&mval, o->data);
583 
584   return res;
585 }
586 
587 static struct mppe_state *
588 MPPE_InitState(struct lcp_opt *o)
589 {
590   struct mppe_state *mp;
591   u_int32_t val;
592 
593   if ((mp = calloc(1, sizeof *mp)) != NULL) {
594     ua_ntohl(o->data, &val);
595 
596     switch (val & MPPE_OPT_BITMASK) {
597     case MPPE_OPT_128BIT:
598       mp->keylen = 16;
599       mp->keybits = 128;
600       break;
601     case MPPE_OPT_56BIT:
602       mp->keylen = 8;
603       mp->keybits = 56;
604       break;
605     case MPPE_OPT_40BIT:
606       mp->keylen = 8;
607       mp->keybits = 40;
608       break;
609     default:
610       log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val);
611       free(mp);
612       return NULL;
613     }
614 
615     mp->stateless = !!(val & MPPE_OPT_STATELESS);
616   }
617 
618   return mp;
619 }
620 
621 static void *
622 MPPEInitInput(struct lcp_opt *o)
623 {
624   struct mppe_state *mip;
625 
626   if (!MPPE_MasterKeyValid) {
627     log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
628     return NULL;
629   }
630 
631   if ((mip = MPPE_InitState(o)) == NULL) {
632     log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n");
633     return NULL;
634   }
635 
636   log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
637 
638   GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
639                        MPPE_IsServer);
640   GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
641 
642   MPPEReduceSessionKey(mip);
643 
644   log_Printf(LogCCP, "MPPE: Input channel initiated\n");
645 
646   if (!mip->stateless) {
647     /*
648      * We need to initialise our dictionary here as the first packet we
649      * receive is unlikely to have the FLUSHED bit set.
650      */
651     log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n",
652                mip->cohnum);
653     RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
654   } else {
655     /*
656      * We do the first key change here as the first packet is expected
657      * to have a sequence number of 0 and we'll therefore not expect
658      * to have to change the key at that point.
659      */
660     log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum);
661     MPPEKeyChange(mip);
662   }
663 
664   return mip;
665 }
666 
667 static void *
668 MPPEInitOutput(struct lcp_opt *o)
669 {
670   struct mppe_state *mop;
671 
672   if (!MPPE_MasterKeyValid) {
673     log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
674     return NULL;
675   }
676 
677   if ((mop = MPPE_InitState(o)) == NULL) {
678     log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n");
679     return NULL;
680   }
681 
682   log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
683 
684   GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
685                        MPPE_IsServer);
686   GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
687 
688   MPPEReduceSessionKey(mop);
689 
690   log_Printf(LogCCP, "MPPE: Output channel initiated\n");
691 
692   if (!mop->stateless) {
693     /*
694      * We need to initialise our dictionary now as the first packet we
695      * send won't have the FLUSHED bit set.
696      */
697     log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n",
698                mop->cohnum);
699     RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
700   }
701 
702   return mop;
703 }
704 
705 static void
706 MPPETermInput(void *v)
707 {
708   free(v);
709 }
710 
711 static void
712 MPPETermOutput(void *v)
713 {
714   free(v);
715 }
716 
717 const struct ccp_algorithm MPPEAlgorithm = {
718   TY_MPPE,
719   CCP_NEG_MPPE,
720   MPPEDispOpts,
721   MPPEUsable,
722   MPPERequired,
723   {
724     MPPESetOptsInput,
725     MPPEInitInput,
726     MPPETermInput,
727     MPPEResetInput,
728     MPPEInput,
729     MPPEDictSetup
730   },
731   {
732     2,
733     MPPEInitOptsOutput,
734     MPPESetOptsOutput,
735     MPPEInitOutput,
736     MPPETermOutput,
737     MPPEResetOutput,
738     MPPEOutput
739   },
740 };
741