2 * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/usr.sbin/ppp/mppe.c,v 1.4.2.6 2002/09/01 02:12:29 brian Exp $
27 * $DragonFly: src/usr.sbin/ppp/mppe.c,v 1.2 2003/06/17 04:30:00 dillon Exp $
30 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
42 #include <openssl/rc4.h>
53 #include "throughput.h"
60 #include "descriptor.h"
66 #include "slcompress.h"
77 * draft-ietf-pppext-mppe-04.txt
78 * draft-ietf-pppext-mppe-keys-02.txt
81 #define MPPE_OPT_STATELESS 0x1000000
82 #define MPPE_OPT_COMPRESSED 0x01
83 #define MPPE_OPT_40BIT 0x20
84 #define MPPE_OPT_56BIT 0x80
85 #define MPPE_OPT_128BIT 0x40
86 #define MPPE_OPT_BITMASK 0xe0
87 #define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK)
89 #define MPPE_FLUSHED 0x8000
90 #define MPPE_ENCRYPTED 0x1000
91 #define MPPE_HEADER_BITMASK 0xf000
92 #define MPPE_HEADER_FLAG 0x00ff
93 #define MPPE_HEADER_FLAGMASK 0x00ff
94 #define MPPE_HEADER_FLAGSHIFT 8
95 #define MPPE_HEADER_STATEFUL_KEYCHANGES 16
98 unsigned stateless
: 1;
99 unsigned flushnext
: 1;
100 unsigned flushrequired
: 1;
102 int keylen
; /* 8 or 16 bytes */
103 int keybits
; /* 40, 56 or 128 bits */
104 char sesskey
[MPPE_KEY_LEN
];
105 char mastkey
[MPPE_KEY_LEN
];
109 int MPPE_MasterKeyValid
= 0;
110 int MPPE_IsServer
= 0;
111 char MPPE_MasterKey
[MPPE_KEY_LEN
];
114 * The peer has missed a packet. Mark the next output frame to be FLUSHED
117 MPPEResetOutput(void *v
)
119 struct mppe_state
*mop
= (struct mppe_state
*)v
;
122 log_Printf(LogCCP
, "MPPE: Unexpected output channel reset\n");
124 log_Printf(LogCCP
, "MPPE: Output channel reset\n");
128 return 0; /* Ask FSM not to ACK */
132 MPPEReduceSessionKey(struct mppe_state
*mp
)
134 switch(mp
->keybits
) {
136 mp
->sesskey
[2] = 0x9e;
137 mp
->sesskey
[1] = 0x26;
139 mp
->sesskey
[0] = 0xd1;
146 MPPEKeyChange(struct mppe_state
*mp
)
148 char InterimKey
[MPPE_KEY_LEN
];
151 GetNewKeyFromSHA(mp
->mastkey
, mp
->sesskey
, mp
->keylen
, InterimKey
);
152 RC4_set_key(&RC4Key
, mp
->keylen
, InterimKey
);
153 RC4(&RC4Key
, mp
->keylen
, InterimKey
, mp
->sesskey
);
155 MPPEReduceSessionKey(mp
);
159 MPPEOutput(void *v
, struct ccp
*ccp
, struct link
*l
, int pri
, u_short
*proto
,
162 struct mppe_state
*mop
= (struct mppe_state
*)v
;
164 u_short nproto
, prefix
;
165 int dictinit
, ilen
, len
;
171 log_Printf(LogDEBUG
, "MPPE: Output: Proto %02x (%d bytes)\n", *proto
, ilen
);
172 if (*proto
< 0x21 && *proto
> 0xFA) {
173 log_Printf(LogDEBUG
, "MPPE: Output: Not encrypting\n");
174 ccp
->compout
+= ilen
;
175 ccp
->uncompout
+= ilen
;
179 log_DumpBp(LogDEBUG
, "MPPE: Output: Encrypt packet:", mp
);
181 /* Get mbuf for prefixes */
182 mo
= m_get(4, MB_CCPOUT
);
186 prefix
= MPPE_ENCRYPTED
| mop
->cohnum
;
188 if (mop
->stateless
||
189 (mop
->cohnum
& MPPE_HEADER_FLAGMASK
) == MPPE_HEADER_FLAG
) {
191 log_Printf(LogDEBUG
, "MPPEOutput: Key changed [%d]\n", mop
->cohnum
);
196 if (mop
->stateless
|| mop
->flushnext
) {
197 prefix
|= MPPE_FLUSHED
;
203 /* Initialise our dictionary */
204 log_Printf(LogDEBUG
, "MPPEOutput: Dictionary initialised [%d]\n",
206 RC4_set_key(&mop
->rc4key
, mop
->keylen
, mop
->sesskey
);
209 /* Set MPPE packet prefix */
210 ua_htons(&prefix
, rp
);
212 /* Save encrypted protocol number */
213 nproto
= htons(*proto
);
214 RC4(&mop
->rc4key
, 2, (char *)&nproto
, rp
+ 2);
216 /* Encrypt main packet */
218 RC4(&mop
->rc4key
, ilen
, rp
, rp
);
221 mop
->cohnum
&= ~MPPE_HEADER_BITMASK
;
223 /* Set the protocol number */
224 *proto
= ccp_Proto(ccp
);
226 ccp
->uncompout
+= ilen
;
229 log_Printf(LogDEBUG
, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n",
236 MPPEResetInput(void *v
)
238 log_Printf(LogCCP
, "MPPE: Unexpected input channel ack\n");
242 MPPEInput(void *v
, struct ccp
*ccp
, u_short
*proto
, struct mbuf
*mp
)
244 struct mppe_state
*mip
= (struct mppe_state
*)v
;
247 int dictinit
, flushed
, ilen
, len
, n
;
253 log_Printf(LogDEBUG
, "MPPE: Input: Proto %02x (%d bytes)\n", *proto
, ilen
);
254 log_DumpBp(LogDEBUG
, "MPPE: Input: Packet:", mp
);
256 mp
= mbuf_Read(mp
, &prefix
, 2);
257 prefix
= ntohs(prefix
);
258 flushed
= prefix
& MPPE_FLUSHED
;
260 if ((prefix
& MPPE_HEADER_BITMASK
) != MPPE_ENCRYPTED
) {
261 log_Printf(LogERROR
, "MPPE: Input: Invalid packet (flags = 0x%x)\n",
262 (prefix
& MPPE_HEADER_BITMASK
) | flushed
);
267 prefix
&= ~MPPE_HEADER_BITMASK
;
269 if (!flushed
&& mip
->stateless
) {
270 log_Printf(LogCCP
, "MPPEInput: Packet without MPPE_FLUSHED set"
271 " in stateless mode\n");
272 flushed
= MPPE_FLUSHED
;
273 /* Should we really continue ? */
276 if (mip
->stateless
) {
277 /* Change our key for each missed packet in stateless mode */
278 while (prefix
!= mip
->cohnum
) {
279 log_Printf(LogDEBUG
, "MPPEInput: Key changed [%u]\n", prefix
);
282 * mip->cohnum contains what we received last time in stateless
286 mip
->cohnum
&= ~MPPE_HEADER_BITMASK
;
292 * We can always process a flushed packet.
293 * Catch up on any outstanding key changes.
295 n
= (prefix
>> MPPE_HEADER_FLAGSHIFT
) -
296 (mip
->cohnum
>> MPPE_HEADER_FLAGSHIFT
);
298 n
+= MPPE_HEADER_STATEFUL_KEYCHANGES
;
300 log_Printf(LogDEBUG
, "MPPEInput: Key changed during catchup [%u]\n",
304 mip
->flushrequired
= 0;
305 mip
->cohnum
= prefix
;
309 if (mip
->flushrequired
) {
311 * Perhaps we should be lenient if
312 * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG
313 * The spec says that we shouldn't be though....
315 log_Printf(LogDEBUG
, "MPPE: Not flushed - discarded\n");
316 fsm_Output(&ccp
->fsm
, CODE_RESETREQ
, ccp
->fsm
.reqid
++, NULL
, 0,
322 if (prefix
!= mip
->cohnum
) {
324 * We're in stateful mode and didn't receive the expected
325 * packet. Send a reset request, but don't tell the CCP layer
326 * about it as we don't expect to receive a Reset ACK !
327 * Guess what... M$ invented this !
329 log_Printf(LogCCP
, "MPPE: Input: Got seq %u, not %u\n",
330 prefix
, mip
->cohnum
);
331 fsm_Output(&ccp
->fsm
, CODE_RESETREQ
, ccp
->fsm
.reqid
++, NULL
, 0,
333 mip
->flushrequired
= 1;
338 if ((prefix
& MPPE_HEADER_FLAGMASK
) == MPPE_HEADER_FLAG
) {
339 log_Printf(LogDEBUG
, "MPPEInput: Key changed [%u]\n", prefix
);
346 * mip->cohnum contains what we expect to receive next time in stateful
350 mip
->cohnum
&= ~MPPE_HEADER_BITMASK
;
354 log_Printf(LogDEBUG
, "MPPEInput: Dictionary initialised [%u]\n", prefix
);
355 RC4_set_key(&mip
->rc4key
, mip
->keylen
, mip
->sesskey
);
358 mp
= mbuf_Read(mp
, proto
, 2);
359 RC4(&mip
->rc4key
, 2, (char *)proto
, (char *)proto
);
360 *proto
= ntohs(*proto
);
364 RC4(&mip
->rc4key
, len
, rp
, rp
);
366 log_Printf(LogDEBUG
, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n",
368 log_DumpBp(LogDEBUG
, "MPPEInput: Decrypted: Packet:", mp
);
370 ccp
->uncompin
+= len
;
376 MPPEDictSetup(void *v
, struct ccp
*ccp
, u_short proto
, struct mbuf
*mi
)
381 MPPEDispOpts(struct fsm_opt
*o
)
388 ua_ntohl(o
->data
, &val
);
390 if ((n
= snprintf(buf
, sizeof buf
, "value 0x%08x ", (unsigned)val
)) > 0)
392 if (!(val
& MPPE_OPT_BITMASK
)) {
393 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, "(0")) > 0)
397 if (val
& MPPE_OPT_128BIT
) {
398 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, "%c128", ch
)) > 0)
402 if (val
& MPPE_OPT_56BIT
) {
403 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, "%c56", ch
)) > 0)
407 if (val
& MPPE_OPT_40BIT
) {
408 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, "%c40", ch
)) > 0)
414 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, " bits, state%s",
415 (val
& MPPE_OPT_STATELESS
) ? "less" : "ful")) > 0)
418 if (val
& MPPE_OPT_COMPRESSED
) {
419 if ((n
= snprintf(buf
+ len
, sizeof buf
- len
, ", compressed")) > 0)
423 snprintf(buf
+ len
, sizeof buf
- len
, ")");
429 MPPEUsable(struct fsm
*fp
)
433 struct radius
*r
= &fp
->bundle
->radius
;
436 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
437 * use that instead of our configuration value.
440 ok
= r
->mppe
.sendkeylen
&& r
->mppe
.recvkeylen
;
442 log_Printf(LogCCP
, "MPPE: Not permitted by RADIUS server\n");
446 struct lcp
*lcp
= &fp
->link
->lcp
;
447 ok
= (lcp
->want_auth
== PROTO_CHAP
&& lcp
->want_authtype
== 0x81) ||
448 (lcp
->his_auth
== PROTO_CHAP
&& lcp
->his_authtype
== 0x81);
450 log_Printf(LogCCP
, "MPPE: Not usable without CHAP81\n");
457 MPPERequired(struct fsm
*fp
)
461 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
462 * use that instead of our configuration value.
464 if (*fp
->bundle
->radius
.cfg
.file
&& fp
->bundle
->radius
.mppe
.policy
)
465 return fp
->bundle
->radius
.mppe
.policy
== MPPE_POLICY_REQUIRED
? 1 : 0;
468 return fp
->link
->ccp
.cfg
.mppe
.required
;
472 MPPE_ConfigVal(struct bundle
*bundle
, const struct ccp_config
*cfg
)
476 val
= cfg
->mppe
.state
== MPPE_STATELESS
? MPPE_OPT_STATELESS
: 0;
479 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
480 * use that instead of our configuration value.
482 if (*bundle
->radius
.cfg
.file
&& bundle
->radius
.mppe
.types
) {
483 if (bundle
->radius
.mppe
.types
& MPPE_TYPE_40BIT
)
484 val
|= MPPE_OPT_40BIT
;
485 if (bundle
->radius
.mppe
.types
& MPPE_TYPE_128BIT
)
486 val
|= MPPE_OPT_128BIT
;
489 switch(cfg
->mppe
.keybits
) {
491 val
|= MPPE_OPT_128BIT
;
494 val
|= MPPE_OPT_56BIT
;
497 val
|= MPPE_OPT_40BIT
;
500 val
|= MPPE_OPT_128BIT
| MPPE_OPT_56BIT
| MPPE_OPT_40BIT
;
508 * What options should we use for our first configure request
511 MPPEInitOptsOutput(struct bundle
*bundle
, struct fsm_opt
*o
,
512 const struct ccp_config
*cfg
)
518 if (!MPPE_MasterKeyValid
) {
519 log_Printf(LogCCP
, "MPPE: MasterKey is invalid,"
520 " MPPE is available only with CHAP81 authentication\n");
521 ua_htonl(0x0, o
->data
);
526 mval
= MPPE_ConfigVal(bundle
, cfg
);
527 ua_htonl(&mval
, o
->data
);
531 * Our CCP request was NAK'd with the given options
534 MPPESetOptsOutput(struct bundle
*bundle
, struct fsm_opt
*o
,
535 const struct ccp_config
*cfg
)
537 u_int32_t mval
, peer
;
539 ua_ntohl(o
->data
, &peer
);
541 if (!MPPE_MasterKeyValid
)
542 /* Treat their NAK as a REJ */
545 mval
= MPPE_ConfigVal(bundle
, cfg
);
548 * If we haven't been configured with a specific number of keybits, allow
549 * whatever the peer asks for.
551 if (!cfg
->mppe
.keybits
) {
552 mval
&= ~MPPE_OPT_BITMASK
;
553 mval
|= (peer
& MPPE_OPT_BITMASK
);
554 if (!(mval
& MPPE_OPT_BITMASK
))
555 mval
|= MPPE_OPT_128BIT
;
558 /* Adjust our statelessness */
559 if (cfg
->mppe
.state
== MPPE_ANYSTATE
) {
560 mval
&= ~MPPE_OPT_STATELESS
;
561 mval
|= (peer
& MPPE_OPT_STATELESS
);
564 ua_htonl(&mval
, o
->data
);
570 * The peer has requested the given options
573 MPPESetOptsInput(struct bundle
*bundle
, struct fsm_opt
*o
,
574 const struct ccp_config
*cfg
)
576 u_int32_t mval
, peer
;
579 ua_ntohl(o
->data
, &peer
);
580 if (!MPPE_MasterKeyValid
) {
583 ua_htonl(&peer
, o
->data
);
589 mval
= MPPE_ConfigVal(bundle
, cfg
);
591 if (peer
& ~MPPE_OPT_MASK
)
592 /* He's asking for bits we don't know about */
595 if (peer
& MPPE_OPT_STATELESS
) {
596 if (cfg
->mppe
.state
== MPPE_STATEFUL
)
597 /* Peer can't have stateless */
600 /* Peer wants stateless, that's ok */
601 mval
|= MPPE_OPT_STATELESS
;
603 if (cfg
->mppe
.state
== MPPE_STATELESS
)
604 /* Peer must have stateless */
607 /* Peer doesn't want stateless, that's ok */
608 mval
&= ~MPPE_OPT_STATELESS
;
611 /* If we've got a configured number of keybits - the peer must use that */
612 if (cfg
->mppe
.keybits
) {
613 ua_htonl(&mval
, o
->data
);
614 return peer
== mval
? res
: MODE_NAK
;
617 /* If a specific number of bits hasn't been requested, we'll need to NAK */
618 switch (peer
& MPPE_OPT_BITMASK
) {
619 case MPPE_OPT_128BIT
:
627 /* Suggest the best number of bits */
628 mval
&= ~MPPE_OPT_BITMASK
;
629 if (peer
& MPPE_OPT_128BIT
)
630 mval
|= MPPE_OPT_128BIT
;
631 else if (peer
& MPPE_OPT_56BIT
)
632 mval
|= MPPE_OPT_56BIT
;
633 else if (peer
& MPPE_OPT_40BIT
)
634 mval
|= MPPE_OPT_40BIT
;
636 mval
|= MPPE_OPT_128BIT
;
637 ua_htonl(&mval
, o
->data
);
642 static struct mppe_state
*
643 MPPE_InitState(struct fsm_opt
*o
)
645 struct mppe_state
*mp
;
648 if ((mp
= calloc(1, sizeof *mp
)) != NULL
) {
649 ua_ntohl(o
->data
, &val
);
651 switch (val
& MPPE_OPT_BITMASK
) {
652 case MPPE_OPT_128BIT
:
665 log_Printf(LogWARN
, "Unexpected MPPE options 0x%08x\n", val
);
670 mp
->stateless
= !!(val
& MPPE_OPT_STATELESS
);
677 MPPEInitInput(struct bundle
*bundle
, struct fsm_opt
*o
)
679 struct mppe_state
*mip
;
681 if (!MPPE_MasterKeyValid
) {
682 log_Printf(LogWARN
, "MPPE: Cannot initialise without CHAP81\n");
686 if ((mip
= MPPE_InitState(o
)) == NULL
) {
687 log_Printf(LogWARN
, "MPPEInput: Cannot initialise - unexpected options\n");
691 log_Printf(LogDEBUG
, "MPPE: InitInput: %d-bits\n", mip
->keybits
);
694 if (*bundle
->radius
.cfg
.file
&& bundle
->radius
.mppe
.recvkey
) {
695 if (mip
->keylen
> bundle
->radius
.mppe
.recvkeylen
)
696 mip
->keylen
= bundle
->radius
.mppe
.recvkeylen
;
697 if (mip
->keylen
> sizeof mip
->mastkey
)
698 mip
->keylen
= sizeof mip
->mastkey
;
699 memcpy(mip
->mastkey
, bundle
->radius
.mppe
.recvkey
, mip
->keylen
);
702 GetAsymetricStartKey(MPPE_MasterKey
, mip
->mastkey
, mip
->keylen
, 0,
705 GetNewKeyFromSHA(mip
->mastkey
, mip
->mastkey
, mip
->keylen
, mip
->sesskey
);
707 MPPEReduceSessionKey(mip
);
709 log_Printf(LogCCP
, "MPPE: Input channel initiated\n");
711 if (!mip
->stateless
) {
713 * We need to initialise our dictionary here as the first packet we
714 * receive is unlikely to have the FLUSHED bit set.
716 log_Printf(LogDEBUG
, "MPPEInitInput: Dictionary initialised [%d]\n",
718 RC4_set_key(&mip
->rc4key
, mip
->keylen
, mip
->sesskey
);
721 * We do the first key change here as the first packet is expected
722 * to have a sequence number of 0 and we'll therefore not expect
723 * to have to change the key at that point.
725 log_Printf(LogDEBUG
, "MPPEInitInput: Key changed [%d]\n", mip
->cohnum
);
733 MPPEInitOutput(struct bundle
*bundle
, struct fsm_opt
*o
)
735 struct mppe_state
*mop
;
737 if (!MPPE_MasterKeyValid
) {
738 log_Printf(LogWARN
, "MPPE: Cannot initialise without CHAP81\n");
742 if ((mop
= MPPE_InitState(o
)) == NULL
) {
743 log_Printf(LogWARN
, "MPPEOutput: Cannot initialise - unexpected options\n");
747 log_Printf(LogDEBUG
, "MPPE: InitOutput: %d-bits\n", mop
->keybits
);
750 if (*bundle
->radius
.cfg
.file
&& bundle
->radius
.mppe
.sendkey
) {
751 if (mop
->keylen
> bundle
->radius
.mppe
.sendkeylen
)
752 mop
->keylen
= bundle
->radius
.mppe
.sendkeylen
;
753 if (mop
->keylen
> sizeof mop
->mastkey
)
754 mop
->keylen
= sizeof mop
->mastkey
;
755 memcpy(mop
->mastkey
, bundle
->radius
.mppe
.sendkey
, mop
->keylen
);
758 GetAsymetricStartKey(MPPE_MasterKey
, mop
->mastkey
, mop
->keylen
, 1,
761 GetNewKeyFromSHA(mop
->mastkey
, mop
->mastkey
, mop
->keylen
, mop
->sesskey
);
763 MPPEReduceSessionKey(mop
);
765 log_Printf(LogCCP
, "MPPE: Output channel initiated\n");
767 if (!mop
->stateless
) {
769 * We need to initialise our dictionary now as the first packet we
770 * send won't have the FLUSHED bit set.
772 log_Printf(LogDEBUG
, "MPPEInitOutput: Dictionary initialised [%d]\n",
774 RC4_set_key(&mop
->rc4key
, mop
->keylen
, mop
->sesskey
);
781 MPPETermInput(void *v
)
787 MPPETermOutput(void *v
)
792 const struct ccp_algorithm MPPEAlgorithm
= {