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