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