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