mppe.c revision 79165
167910Sbrian/*- 267910Sbrian * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org> 367910Sbrian * All rights reserved. 467910Sbrian * 567910Sbrian * Redistribution and use in source and binary forms, with or without 667910Sbrian * modification, are permitted provided that the following conditions 767910Sbrian * are met: 867910Sbrian * 1. Redistributions of source code must retain the above copyright 967910Sbrian * notice, this list of conditions and the following disclaimer. 1067910Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1167910Sbrian * notice, this list of conditions and the following disclaimer in the 1267910Sbrian * documentation and/or other materials provided with the distribution. 1367910Sbrian * 1467910Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1567910Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1667910Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1767910Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1867910Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1967910Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2067910Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2167910Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2267910Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2367910Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2467910Sbrian * SUCH DAMAGE. 2567910Sbrian * 2667910Sbrian * $FreeBSD: head/usr.sbin/ppp/mppe.c 79165 2001-07-03 22:20:19Z brian $ 2767910Sbrian */ 2867910Sbrian 2967910Sbrian#include <sys/types.h> 3067910Sbrian 3167910Sbrian#include <stdio.h> 3267910Sbrian#include <stdlib.h> 3378411Sbrian#include <string.h> 3467910Sbrian#include <termios.h> 3568344Sbrian#ifdef __FreeBSD__ 3667910Sbrian#include <sha.h> 3768344Sbrian#else 3868344Sbrian#include <openssl/sha.h> 3968344Sbrian#endif 4067910Sbrian#include <openssl/rc4.h> 4167910Sbrian 4267910Sbrian#include "defs.h" 4367910Sbrian#include "mbuf.h" 4467910Sbrian#include "log.h" 4567910Sbrian#include "timer.h" 4667910Sbrian#include "fsm.h" 4767910Sbrian#include "lqr.h" 4867910Sbrian#include "hdlc.h" 4967910Sbrian#include "lcp.h" 5067910Sbrian#include "ccp.h" 5172025Sbrian#include "throughput.h" 5272025Sbrian#include "layer.h" 5372025Sbrian#include "link.h" 5467910Sbrian#include "chap_ms.h" 5572025Sbrian#include "proto.h" 5667910Sbrian#include "mppe.h" 5767910Sbrian 5867910Sbrian/* 5967910Sbrian * Documentation: 6067910Sbrian * 6167910Sbrian * draft-ietf-pppext-mppe-04.txt 6267910Sbrian * draft-ietf-pppext-mppe-keys-02.txt 6367910Sbrian */ 6467910Sbrian 6578411Sbrian#define MPPE_OPT_STATELESS 0x1000000 6678411Sbrian#define MPPE_OPT_COMPRESSED 0x01 6778411Sbrian#define MPPE_OPT_40BIT 0x20 6878411Sbrian#define MPPE_OPT_56BIT 0x80 6978411Sbrian#define MPPE_OPT_128BIT 0x40 7078411Sbrian#define MPPE_OPT_BITMASK 0xe0 7178411Sbrian#define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK) 7278411Sbrian 7378411Sbrian#define MPPE_FLUSHED 0x8000 7478411Sbrian#define MPPE_ENCRYPTED 0x1000 7578411Sbrian#define MPPE_HEADER_BITMASK 0xf000 7678411Sbrian#define MPPE_HEADER_FLAG 0x00ff 7778411Sbrian#define MPPE_HEADER_FLAGMASK 0x00ff 7878411Sbrian#define MPPE_HEADER_FLAGSHIFT 8 7978411Sbrian 8067910Sbrianstruct mppe_state { 8178411Sbrian unsigned stateless : 1; 8278411Sbrian unsigned flushnext : 1; 8378411Sbrian unsigned flushrequired : 1; 8478411Sbrian int cohnum; 8578411Sbrian int keylen; /* 8 or 16 bytes */ 8678411Sbrian int keybits; /* 40, 56 or 128 bits */ 8778411Sbrian char sesskey[MPPE_KEY_LEN]; 8878411Sbrian char mastkey[MPPE_KEY_LEN]; 8978411Sbrian RC4_KEY rc4key; 9067910Sbrian}; 9167910Sbrian 9267910Sbrianint MPPE_MasterKeyValid = 0; 9368461Sbrianint MPPE_IsServer = 0; 9467910Sbrianchar MPPE_MasterKey[MPPE_KEY_LEN]; 9567910Sbrian 9678411Sbrian/* 9778411Sbrian * The peer has missed a packet. Mark the next output frame to be FLUSHED 9878411Sbrian */ 9978411Sbrianstatic int 10067910SbrianMPPEResetOutput(void *v) 10167910Sbrian{ 10278411Sbrian struct mppe_state *mop = (struct mppe_state *)v; 10378411Sbrian 10478411Sbrian if (mop->stateless) 10578411Sbrian log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n"); 10678411Sbrian else { 10778411Sbrian log_Printf(LogCCP, "MPPE: Output channel reset\n"); 10878411Sbrian mop->flushnext = 1; 10978411Sbrian } 11078411Sbrian 11178411Sbrian return 0; /* Ask FSM not to ACK */ 11267910Sbrian} 11367910Sbrian 11467912Sbrianstatic void 11567912SbrianMPPEReduceSessionKey(struct mppe_state *mp) 11667912Sbrian{ 11767910Sbrian switch(mp->keybits) { 11867910Sbrian case 40: 11967910Sbrian mp->sesskey[2] = 0x9e; 12067910Sbrian mp->sesskey[1] = 0x26; 12167910Sbrian case 56: 12267910Sbrian mp->sesskey[0] = 0xd1; 12367910Sbrian case 128: 12467910Sbrian } 12567910Sbrian} 12667910Sbrian 12767912Sbrianstatic void 12867912SbrianMPPEKeyChange(struct mppe_state *mp) 12967912Sbrian{ 13067910Sbrian char InterimKey[MPPE_KEY_LEN]; 13167910Sbrian RC4_KEY RC4Key; 13267910Sbrian 13367910Sbrian GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 13467910Sbrian RC4_set_key(&RC4Key, mp->keylen, InterimKey); 13567910Sbrian RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 13667910Sbrian 13767910Sbrian MPPEReduceSessionKey(mp); 13867910Sbrian} 13967910Sbrian 14067910Sbrianstatic struct mbuf * 14167910SbrianMPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 14267910Sbrian struct mbuf *mp) 14367910Sbrian{ 14467910Sbrian struct mppe_state *mop = (struct mppe_state *)v; 14567910Sbrian struct mbuf *mo; 14678411Sbrian u_short nproto, prefix; 14778411Sbrian int dictinit, ilen, len; 14867910Sbrian char *rp; 14967910Sbrian 15067910Sbrian ilen = m_length(mp); 15178411Sbrian dictinit = 0; 15267910Sbrian 15367910Sbrian log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 15467910Sbrian if (*proto < 0x21 && *proto > 0xFA) { 15567910Sbrian log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 15678411Sbrian ccp->compout += ilen; 15778411Sbrian ccp->uncompout += ilen; 15867910Sbrian return mp; 15967910Sbrian } 16067910Sbrian 16167910Sbrian log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 16267910Sbrian 16367910Sbrian /* Get mbuf for prefixes */ 16467910Sbrian mo = m_get(4, MB_CCPOUT); 16567910Sbrian mo->m_next = mp; 16667910Sbrian 16778411Sbrian rp = MBUF_CTOP(mo); 16878411Sbrian prefix = MPPE_ENCRYPTED | mop->cohnum; 16967910Sbrian 17078411Sbrian if (mop->stateless || 17178411Sbrian (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 17278411Sbrian /* Change our key */ 17378411Sbrian log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum); 17478411Sbrian MPPEKeyChange(mop); 17578411Sbrian dictinit = 1; 17678411Sbrian } 17778411Sbrian 17878411Sbrian if (mop->stateless || mop->flushnext) { 17978411Sbrian prefix |= MPPE_FLUSHED; 18078411Sbrian dictinit = 1; 18178411Sbrian mop->flushnext = 0; 18278411Sbrian } 18378411Sbrian 18478411Sbrian if (dictinit) { 18578411Sbrian /* Initialise our dictionary */ 18678411Sbrian log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n", 18778411Sbrian mop->cohnum); 18878411Sbrian RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 18978411Sbrian } 19078411Sbrian 19167910Sbrian /* Set MPPE packet prefix */ 19278411Sbrian *(u_short *)rp = htons(prefix); 19367910Sbrian 19467910Sbrian /* Save encrypted protocol number */ 19567910Sbrian nproto = htons(*proto); 19667910Sbrian RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 19767910Sbrian 19867910Sbrian /* Encrypt main packet */ 19967910Sbrian rp = MBUF_CTOP(mp); 20067910Sbrian RC4(&mop->rc4key, ilen, rp, rp); 20167910Sbrian 20278411Sbrian mop->cohnum++; 20378411Sbrian mop->cohnum &= ~MPPE_HEADER_BITMASK; 20467910Sbrian 20578411Sbrian /* Set the protocol number */ 20667910Sbrian *proto = ccp_Proto(ccp); 20778411Sbrian len = m_length(mo); 20878411Sbrian ccp->uncompout += ilen; 20978411Sbrian ccp->compout += len; 21067910Sbrian 21167912Sbrian log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 21278411Sbrian *proto, len); 21367910Sbrian 21467910Sbrian return mo; 21567910Sbrian} 21667910Sbrian 21767910Sbrianstatic void 21867910SbrianMPPEResetInput(void *v) 21967910Sbrian{ 22078411Sbrian log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n"); 22167910Sbrian} 22267910Sbrian 22367910Sbrianstatic struct mbuf * 22467910SbrianMPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 22567910Sbrian{ 22667910Sbrian struct mppe_state *mip = (struct mppe_state *)v; 22767910Sbrian u_short prefix; 22867910Sbrian char *rp; 22978411Sbrian int dictinit, flushed, ilen, len, n; 23067910Sbrian 23167910Sbrian ilen = m_length(mp); 23278411Sbrian dictinit = 0; 23378411Sbrian ccp->compin += ilen; 23467910Sbrian 23567910Sbrian log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 23667910Sbrian log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 23767910Sbrian 23867910Sbrian mp = mbuf_Read(mp, &prefix, 2); 23967910Sbrian prefix = ntohs(prefix); 24078411Sbrian flushed = prefix & MPPE_FLUSHED; 24178411Sbrian prefix &= ~flushed; 24278411Sbrian if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) { 24378411Sbrian log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n", 24478411Sbrian (prefix & MPPE_HEADER_BITMASK) | flushed); 24567910Sbrian m_freem(mp); 24667910Sbrian return NULL; 24767910Sbrian } 24867910Sbrian 24978411Sbrian prefix &= ~MPPE_HEADER_BITMASK; 25078411Sbrian 25178411Sbrian if (!flushed && mip->stateless) { 25278411Sbrian log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set" 25378411Sbrian " in stateless mode\n"); 25478411Sbrian flushed = MPPE_FLUSHED; 25578411Sbrian /* Should we really continue ? */ 25667910Sbrian } 25767910Sbrian 25878411Sbrian if (mip->stateless) { 25978411Sbrian /* Change our key for each missed packet in stateless mode */ 26078411Sbrian while (prefix != mip->cohnum) { 26178411Sbrian log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 26278411Sbrian MPPEKeyChange(mip); 26378411Sbrian /* 26478411Sbrian * mip->cohnum contains what we received last time in stateless 26578411Sbrian * mode. 26678411Sbrian */ 26778411Sbrian mip->cohnum++; 26878411Sbrian mip->cohnum &= ~MPPE_HEADER_BITMASK; 26978411Sbrian } 27078411Sbrian dictinit = 1; 27178411Sbrian } else { 27278411Sbrian if (flushed) { 27378411Sbrian /* 27478411Sbrian * We can always process a flushed packet. 27578411Sbrian * Catch up on any outstanding key changes. 27678411Sbrian */ 27778411Sbrian n = (prefix >> MPPE_HEADER_FLAGSHIFT) - 27878411Sbrian (mip->cohnum >> MPPE_HEADER_FLAGSHIFT); 27978411Sbrian while (n--) { 28078411Sbrian log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n", 28178411Sbrian prefix); 28278411Sbrian MPPEKeyChange(mip); 28378411Sbrian } 28478411Sbrian mip->flushrequired = 0; 28578411Sbrian mip->cohnum = prefix; 28678411Sbrian dictinit = 1; 28778411Sbrian } 28867910Sbrian 28978411Sbrian if (mip->flushrequired) { 29078411Sbrian /* 29178411Sbrian * Perhaps we should be lenient if 29278411Sbrian * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG 29378411Sbrian * The spec says that we shouldn't be though.... 29478411Sbrian */ 29578411Sbrian log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n"); 29678411Sbrian m_freem(mp); 29778411Sbrian return NULL; 29878411Sbrian } 29978411Sbrian 30078411Sbrian if (prefix != mip->cohnum) { 30178411Sbrian /* 30278411Sbrian * We're in stateful mode and didn't receive the expected 30378411Sbrian * packet. Send a reset request, but don't tell the CCP layer 30478411Sbrian * about it as we don't expect to receive a Reset ACK ! 30578411Sbrian * Guess what... M$ invented this ! 30678411Sbrian */ 30778411Sbrian log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n", 30878411Sbrian prefix, mip->cohnum); 30978411Sbrian fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0, 31078411Sbrian MB_CCPOUT); 31178411Sbrian mip->flushrequired = 1; 31278411Sbrian m_freem(mp); 31378411Sbrian return NULL; 31478411Sbrian } 31578411Sbrian 31678411Sbrian if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 31778411Sbrian log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 31878411Sbrian MPPEKeyChange(mip); 31978411Sbrian dictinit = 1; 32078411Sbrian } else if (flushed) 32178411Sbrian dictinit = 1; 32278411Sbrian 32378411Sbrian /* 32478411Sbrian * mip->cohnum contains what we expect to receive next time in stateful 32578411Sbrian * mode. 32678411Sbrian */ 32778411Sbrian mip->cohnum++; 32878411Sbrian mip->cohnum &= ~MPPE_HEADER_BITMASK; 32978411Sbrian } 33078411Sbrian 33178411Sbrian if (dictinit) { 33278411Sbrian log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix); 33378411Sbrian RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 33478411Sbrian } 33578411Sbrian 33667910Sbrian mp = mbuf_Read(mp, proto, 2); 33767910Sbrian RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 33867910Sbrian *proto = ntohs(*proto); 33967910Sbrian 34067910Sbrian rp = MBUF_CTOP(mp); 34178411Sbrian len = m_length(mp); 34278411Sbrian RC4(&mip->rc4key, len, rp, rp); 34367910Sbrian 34478411Sbrian log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n", 34578411Sbrian *proto, len); 34678411Sbrian log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp); 34767910Sbrian 34878411Sbrian ccp->uncompin += len; 34967910Sbrian 35067910Sbrian return mp; 35167910Sbrian} 35267910Sbrian 35367910Sbrianstatic void 35467910SbrianMPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 35567910Sbrian{ 35667910Sbrian} 35767910Sbrian 35867910Sbrianstatic const char * 35967910SbrianMPPEDispOpts(struct lcp_opt *o) 36067910Sbrian{ 36178411Sbrian static char buf[70]; 36278411Sbrian u_int32_t val = ntohl(*(u_int32_t *)o->data); 36378411Sbrian char ch; 36478411Sbrian int len; 36578411Sbrian 36678411Sbrian snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val); 36778411Sbrian len = strlen(buf); 36878411Sbrian if (!(val & MPPE_OPT_BITMASK)) { 36978411Sbrian snprintf(buf + len, sizeof buf - len, "(0"); 37078411Sbrian len++; 37178411Sbrian } else { 37278411Sbrian ch = '('; 37378411Sbrian if (val & MPPE_OPT_128BIT) { 37478411Sbrian snprintf(buf + len, sizeof buf - len, "%c128", ch); 37578411Sbrian len += strlen(buf + len); 37678411Sbrian ch = '/'; 37778411Sbrian } 37878411Sbrian if (val & MPPE_OPT_56BIT) { 37978411Sbrian snprintf(buf + len, sizeof buf - len, "%c56", ch); 38078411Sbrian len += strlen(buf + len); 38178411Sbrian ch = '/'; 38278411Sbrian } 38378411Sbrian if (val & MPPE_OPT_40BIT) { 38478411Sbrian snprintf(buf + len, sizeof buf - len, "%c40", ch); 38578411Sbrian len += strlen(buf + len); 38678411Sbrian ch = '/'; 38778411Sbrian } 38878411Sbrian } 38978411Sbrian 39078411Sbrian snprintf(buf + len, sizeof buf - len, " bits, state%s", 39178411Sbrian (val & MPPE_OPT_STATELESS) ? "less" : "full"); 39278411Sbrian len += strlen(buf + len); 39378411Sbrian 39478411Sbrian if (val & MPPE_OPT_COMPRESSED) { 39578411Sbrian snprintf(buf + len, sizeof buf - len, ", compressed"); 39678411Sbrian len += strlen(buf + len); 39778411Sbrian } 39878411Sbrian 39978411Sbrian snprintf(buf + len, sizeof buf - len, ")"); 40078411Sbrian 40167910Sbrian return buf; 40267910Sbrian} 40367910Sbrian 40472025Sbrianstatic int 40572025SbrianMPPEUsable(struct fsm *fp) 40672025Sbrian{ 40772025Sbrian struct lcp *lcp; 40872025Sbrian int ok; 40972025Sbrian 41072025Sbrian lcp = &fp->link->lcp; 41172025Sbrian ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) || 41272025Sbrian (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81); 41372025Sbrian if (!ok) 41472025Sbrian log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n"); 41572025Sbrian 41672025Sbrian return ok; 41772025Sbrian} 41872025Sbrian 41978411Sbrianstatic int 42078411SbrianMPPERequired(struct fsm *fp) 42178411Sbrian{ 42278411Sbrian return fp->link->ccp.cfg.mppe.required; 42378411Sbrian} 42478411Sbrian 42578411Sbrianstatic u_int32_t 42678411SbrianMPPE_ConfigVal(const struct ccp_config *cfg) 42778411Sbrian{ 42878411Sbrian u_int32_t val; 42978411Sbrian 43078411Sbrian val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0; 43178411Sbrian switch(cfg->mppe.keybits) { 43278411Sbrian case 128: 43378411Sbrian val |= MPPE_OPT_128BIT; 43478411Sbrian break; 43578411Sbrian case 56: 43678411Sbrian val |= MPPE_OPT_56BIT; 43778411Sbrian break; 43878411Sbrian case 40: 43978411Sbrian val |= MPPE_OPT_40BIT; 44078411Sbrian break; 44178411Sbrian case 0: 44278411Sbrian val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT; 44378411Sbrian break; 44478411Sbrian } 44578411Sbrian 44678411Sbrian return val; 44778411Sbrian} 44878411Sbrian 44978411Sbrian/* 45078411Sbrian * What options should we use for our first configure request 45178411Sbrian */ 45267910Sbrianstatic void 45367910SbrianMPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 45467910Sbrian{ 45578411Sbrian u_int32_t *p = (u_int32_t *)o->data; 45667910Sbrian 45767910Sbrian o->len = 6; 45867910Sbrian 45967910Sbrian if (!MPPE_MasterKeyValid) { 46070498Sbrian log_Printf(LogCCP, "MPPE: MasterKey is invalid," 46171971Sbrian " MPPE is available only with CHAP81 authentication\n"); 46278411Sbrian *p = htonl(0x0); 46367910Sbrian return; 46467910Sbrian } 46567910Sbrian 46678411Sbrian *p = htonl(MPPE_ConfigVal(cfg)); 46767910Sbrian} 46867910Sbrian 46978411Sbrian/* 47078411Sbrian * Our CCP request was NAK'd with the given options 47178411Sbrian */ 47267910Sbrianstatic int 47378411SbrianMPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 47467910Sbrian{ 47578411Sbrian u_int32_t *p = (u_int32_t *)o->data; 47678411Sbrian u_int32_t peer = ntohl(*p); 47778411Sbrian u_int32_t mval; 47867910Sbrian 47978411Sbrian if (!MPPE_MasterKeyValid) 48078411Sbrian /* Treat their NAK as a REJ */ 48178411Sbrian return MODE_NAK; 48267910Sbrian 48378411Sbrian mval = MPPE_ConfigVal(cfg); 48478411Sbrian 48578411Sbrian /* 48678411Sbrian * If we haven't been configured with a specific number of keybits, allow 48778411Sbrian * whatever the peer asks for. 48878411Sbrian */ 48978411Sbrian if (!cfg->mppe.keybits) { 49078411Sbrian mval &= ~MPPE_OPT_BITMASK; 49178411Sbrian mval |= (peer & MPPE_OPT_BITMASK); 49278411Sbrian if (!(mval & MPPE_OPT_BITMASK)) 49378411Sbrian mval |= MPPE_OPT_128BIT; 49467910Sbrian } 49567910Sbrian 49678411Sbrian /* Adjust our statelessness */ 49778411Sbrian if (cfg->mppe.state == MPPE_ANYSTATE) { 49878411Sbrian mval &= ~MPPE_OPT_STATELESS; 49978411Sbrian mval |= (peer & MPPE_OPT_STATELESS); 50078411Sbrian } 50167910Sbrian 50278411Sbrian *p = htonl(mval); 50378411Sbrian 50478411Sbrian return MODE_ACK; 50567910Sbrian} 50667910Sbrian 50778411Sbrian/* 50878411Sbrian * The peer has requested the given options 50978411Sbrian */ 51067910Sbrianstatic int 51167910SbrianMPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) 51267910Sbrian{ 51378411Sbrian u_int32_t *p = (u_int32_t *)(o->data); 51478411Sbrian u_int32_t peer = ntohl(*p); 51578411Sbrian u_int32_t mval; 51678411Sbrian int res = MODE_ACK; 51767910Sbrian 51867910Sbrian if (!MPPE_MasterKeyValid) { 51967910Sbrian if (*p != 0x0) { 52067910Sbrian *p = 0x0; 52167910Sbrian return MODE_NAK; 52278411Sbrian } else 52367910Sbrian return MODE_ACK; 52467910Sbrian } 52567910Sbrian 52678411Sbrian mval = MPPE_ConfigVal(cfg); 52778411Sbrian 52878411Sbrian if (peer & ~MPPE_OPT_MASK) 52978411Sbrian /* He's asking for bits we don't know about */ 53078411Sbrian res = MODE_NAK; 53178411Sbrian 53278411Sbrian if (peer & MPPE_OPT_STATELESS) { 53378411Sbrian if (cfg->mppe.state == MPPE_STATEFUL) 53478411Sbrian /* Peer can't have stateless */ 53578411Sbrian res = MODE_NAK; 53678411Sbrian else 53778411Sbrian /* Peer wants stateless, that's ok */ 53878411Sbrian mval |= MPPE_OPT_STATELESS; 53978411Sbrian } else { 54078411Sbrian if (cfg->mppe.state == MPPE_STATELESS) 54178411Sbrian /* Peer must have stateless */ 54278411Sbrian res = MODE_NAK; 54378411Sbrian else 54478411Sbrian /* Peer doesn't want stateless, that's ok */ 54578411Sbrian mval &= ~MPPE_OPT_STATELESS; 54667910Sbrian } 54767910Sbrian 54878411Sbrian /* If we've got a configured number of keybits - the peer must use that */ 54978411Sbrian if (cfg->mppe.keybits) { 55078411Sbrian *p = htonl(mval); 55178411Sbrian return peer == mval ? res : MODE_NAK; 55278411Sbrian } 55367910Sbrian 55478411Sbrian /* If a specific number of bits hasn't been requested, we'll need to NAK */ 55578411Sbrian switch (peer & MPPE_OPT_BITMASK) { 55678411Sbrian case MPPE_OPT_128BIT: 55778411Sbrian case MPPE_OPT_56BIT: 55878411Sbrian case MPPE_OPT_40BIT: 55978411Sbrian break; 56078411Sbrian default: 56178411Sbrian res = MODE_NAK; 56278411Sbrian } 56378411Sbrian 56478411Sbrian /* Suggest the best number of bits */ 56578411Sbrian mval &= ~MPPE_OPT_BITMASK; 56678411Sbrian if (peer & MPPE_OPT_128BIT) 56778411Sbrian mval |= MPPE_OPT_128BIT; 56878411Sbrian else if (peer & MPPE_OPT_56BIT) 56978411Sbrian mval |= MPPE_OPT_56BIT; 57078411Sbrian else if (peer & MPPE_OPT_40BIT) 57178411Sbrian mval |= MPPE_OPT_40BIT; 57278411Sbrian else 57378411Sbrian mval |= MPPE_OPT_128BIT; 57467910Sbrian *p = htonl(mval); 57567910Sbrian 57678411Sbrian return res; 57767910Sbrian} 57867910Sbrian 57978411Sbrianstatic struct mppe_state * 58078411SbrianMPPE_InitState(struct lcp_opt *o) 58178411Sbrian{ 58278411Sbrian struct mppe_state *mp; 58378411Sbrian u_int32_t val; 58478411Sbrian 58578411Sbrian if ((mp = calloc(1, sizeof *mp)) != NULL) { 58678411Sbrian val = ntohl(*(u_int32_t *)o->data); 58778411Sbrian 58878411Sbrian switch (val & MPPE_OPT_BITMASK) { 58978411Sbrian case MPPE_OPT_128BIT: 59078411Sbrian mp->keylen = 16; 59178411Sbrian mp->keybits = 128; 59278411Sbrian break; 59378411Sbrian case MPPE_OPT_56BIT: 59478411Sbrian mp->keylen = 8; 59578411Sbrian mp->keybits = 56; 59678411Sbrian break; 59778411Sbrian case MPPE_OPT_40BIT: 59878411Sbrian mp->keylen = 8; 59978411Sbrian mp->keybits = 40; 60078411Sbrian break; 60178411Sbrian default: 60278411Sbrian log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val); 60378411Sbrian free(mp); 60478411Sbrian return NULL; 60578411Sbrian } 60678411Sbrian 60778411Sbrian mp->stateless = !!(val & MPPE_OPT_STATELESS); 60878411Sbrian } 60978411Sbrian 61078411Sbrian return mp; 61178411Sbrian} 61278411Sbrian 61367910Sbrianstatic void * 61467910SbrianMPPEInitInput(struct lcp_opt *o) 61567910Sbrian{ 61667910Sbrian struct mppe_state *mip; 61767910Sbrian 61867910Sbrian if (!MPPE_MasterKeyValid) { 61971971Sbrian log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 62067910Sbrian return NULL; 62167910Sbrian } 62267910Sbrian 62378411Sbrian if ((mip = MPPE_InitState(o)) == NULL) { 62478411Sbrian log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n"); 62578411Sbrian return NULL; 62667910Sbrian } 62767910Sbrian 62867910Sbrian log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 62967910Sbrian 63068461Sbrian GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 63168461Sbrian MPPE_IsServer); 63267910Sbrian GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 63367910Sbrian 63467910Sbrian MPPEReduceSessionKey(mip); 63567910Sbrian 63678411Sbrian log_Printf(LogCCP, "MPPE: Input channel initiated\n"); 63767910Sbrian 63878411Sbrian if (!mip->stateless) { 63978411Sbrian /* 64078411Sbrian * We need to initialise our dictionary here as the first packet we 64178411Sbrian * receive is unlikely to have the FLUSHED bit set. 64278411Sbrian */ 64378411Sbrian log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n", 64478411Sbrian mip->cohnum); 64578411Sbrian RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 64678411Sbrian } else { 64778411Sbrian /* 64878411Sbrian * We do the first key change here as the first packet is expected 64978411Sbrian * to have a sequence number of 0 and we'll therefore not expect 65078411Sbrian * to have to change the key at that point. 65178411Sbrian */ 65278411Sbrian log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum); 65378411Sbrian MPPEKeyChange(mip); 65478411Sbrian } 65567910Sbrian 65667910Sbrian return mip; 65767910Sbrian} 65867910Sbrian 65967910Sbrianstatic void * 66067910SbrianMPPEInitOutput(struct lcp_opt *o) 66167910Sbrian{ 66267910Sbrian struct mppe_state *mop; 66367910Sbrian 66467910Sbrian if (!MPPE_MasterKeyValid) { 66571971Sbrian log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 66667910Sbrian return NULL; 66767910Sbrian } 66867910Sbrian 66978411Sbrian if ((mop = MPPE_InitState(o)) == NULL) { 67078411Sbrian log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n"); 67178411Sbrian return NULL; 67267910Sbrian } 67367910Sbrian 67467910Sbrian log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 67567910Sbrian 67668461Sbrian GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 67768461Sbrian MPPE_IsServer); 67867910Sbrian GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 67967910Sbrian 68067910Sbrian MPPEReduceSessionKey(mop); 68167910Sbrian 68278411Sbrian log_Printf(LogCCP, "MPPE: Output channel initiated\n"); 68367910Sbrian 68478411Sbrian if (!mop->stateless) { 68578411Sbrian /* 68678411Sbrian * We need to initialise our dictionary now as the first packet we 68778411Sbrian * send won't have the FLUSHED bit set. 68878411Sbrian */ 68978411Sbrian log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n", 69078411Sbrian mop->cohnum); 69178411Sbrian RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 69278411Sbrian } 69367910Sbrian 69467910Sbrian return mop; 69567910Sbrian} 69667910Sbrian 69767910Sbrianstatic void 69867910SbrianMPPETermInput(void *v) 69967910Sbrian{ 70067910Sbrian free(v); 70167910Sbrian} 70267910Sbrian 70367910Sbrianstatic void 70467910SbrianMPPETermOutput(void *v) 70567910Sbrian{ 70667910Sbrian free(v); 70767910Sbrian} 70867910Sbrian 70967910Sbrianconst struct ccp_algorithm MPPEAlgorithm = { 71067910Sbrian TY_MPPE, 71167910Sbrian CCP_NEG_MPPE, 71267910Sbrian MPPEDispOpts, 71372025Sbrian MPPEUsable, 71478411Sbrian MPPERequired, 71567910Sbrian { 71667910Sbrian MPPESetOptsInput, 71767910Sbrian MPPEInitInput, 71867910Sbrian MPPETermInput, 71967910Sbrian MPPEResetInput, 72067910Sbrian MPPEInput, 72167910Sbrian MPPEDictSetup 72267910Sbrian }, 72367910Sbrian { 72479165Sbrian 2, 72567910Sbrian MPPEInitOptsOutput, 72667910Sbrian MPPESetOptsOutput, 72767910Sbrian MPPEInitOutput, 72867910Sbrian MPPETermOutput, 72967910Sbrian MPPEResetOutput, 73067910Sbrian MPPEOutput 73167910Sbrian }, 73267910Sbrian}; 733