mppe.c revision 68344
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: head/usr.sbin/ppp/mppe.c 68344 2000-11-05 03:25:09Z brian $ 27 */ 28 29#include <sys/types.h> 30 31#include <stdio.h> 32#include <stdlib.h> 33#include <termios.h> 34#ifdef __FreeBSD__ 35#include <sha.h> 36#else 37#include <openssl/sha.h> 38#endif 39#include <openssl/rc4.h> 40 41#include "defs.h" 42#include "mbuf.h" 43#include "log.h" 44#include "timer.h" 45#include "fsm.h" 46#include "lqr.h" 47#include "hdlc.h" 48#include "lcp.h" 49#include "ccp.h" 50#include "chap_ms.h" 51#include "mppe.h" 52 53/* 54 * Documentation: 55 * 56 * draft-ietf-pppext-mppe-04.txt 57 * draft-ietf-pppext-mppe-keys-02.txt 58 */ 59 60struct mppe_state { 61 int cohnum; 62 int keylen; /* 8 or 16 bytes */ 63 int keybits; /* 40, 56 or 128 bits */ 64 char sesskey[MPPE_KEY_LEN]; 65 char mastkey[MPPE_KEY_LEN]; 66 RC4_KEY rc4key; 67}; 68 69int MPPE_MasterKeyValid = 0; 70char MPPE_MasterKey[MPPE_KEY_LEN]; 71 72static void 73MPPEResetOutput(void *v) 74{ 75 log_Printf(LogCCP, "MPPE: Output channel reset\n"); 76} 77 78static void 79MPPEReduceSessionKey(struct mppe_state *mp) 80{ 81 switch(mp->keybits) { 82 case 40: 83 mp->sesskey[2] = 0x9e; 84 mp->sesskey[1] = 0x26; 85 case 56: 86 mp->sesskey[0] = 0xd1; 87 case 128: 88 } 89} 90 91static void 92MPPEKeyChange(struct mppe_state *mp) 93{ 94 char InterimKey[MPPE_KEY_LEN]; 95 RC4_KEY RC4Key; 96 97 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 98 RC4_set_key(&RC4Key, mp->keylen, InterimKey); 99 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 100 101 MPPEReduceSessionKey(mp); 102} 103 104static struct mbuf * 105MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 106 struct mbuf *mp) 107{ 108 struct mppe_state *mop = (struct mppe_state *)v; 109 struct mbuf *mo; 110 u_short nproto; 111 int ilen; 112 char *rp; 113 114 log_Printf(LogCCP, "MPPE: Output\n"); 115 116 ilen = m_length(mp); 117 118 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 119 if (*proto < 0x21 && *proto > 0xFA) { 120 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 121 return mp; 122 } 123 124 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 125 126 /* Get mbuf for prefixes */ 127 mo = m_get(4, MB_CCPOUT); 128 mo->m_next = mp; 129 130 /* Init RC4 keys */ 131 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 132 133 /* Set MPPE packet prefix */ 134 rp = MBUF_CTOP(mo); 135 *(u_short *)rp = htons(0x9000 | mop->cohnum); 136 137 /* Save encrypted protocol number */ 138 nproto = htons(*proto); 139 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 140 141 /* Encrypt main packet */ 142 rp = MBUF_CTOP(mp); 143 RC4(&mop->rc4key, ilen, rp, rp); 144 145 /* Rotate keys */ 146 MPPEKeyChange(mop); 147 mop->cohnum ++; mop->cohnum &= 0xFFF; 148 149 /* Chage protocol number */ 150 *proto = ccp_Proto(ccp); 151 152 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 153 *proto, m_length(mo)); 154 155 return mo; 156} 157 158static void 159MPPEResetInput(void *v) 160{ 161 log_Printf(LogCCP, "MPPE: Input channel reset\n"); 162} 163 164static struct mbuf * 165MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 166{ 167 struct mppe_state *mip = (struct mppe_state *)v; 168 u_short prefix; 169 char *rp; 170 int ilen; 171 172 log_Printf(LogCCP, "MPPE: Input\n"); 173 174 ilen = m_length(mp); 175 176 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 177 178 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 179 180 mp = mbuf_Read(mp, &prefix, 2); 181 prefix = ntohs(prefix); 182 if ((prefix & 0xF000) != 0x9000) { 183 log_Printf(LogERROR, "MPPE: Input: Invalid packet\n"); 184 m_freem(mp); 185 return NULL; 186 } 187 188 prefix &= 0xFFF; 189 while (prefix != mip->cohnum) { 190 MPPEKeyChange(mip); 191 mip->cohnum ++; mip->cohnum &= 0xFFF; 192 } 193 194 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 195 196 mp = mbuf_Read(mp, proto, 2); 197 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 198 *proto = ntohs(*proto); 199 200 rp = MBUF_CTOP(mp); 201 RC4(&mip->rc4key, m_length(mp), rp, rp); 202 203 log_Printf(LogDEBUG, "MPPE: Input: Decrypted: Proto %02x (%d bytes)\n", 204 *proto, m_length(mp)); 205 206 log_DumpBp(LogDEBUG, "MPPE: Input: Decrypted: Packet:", mp); 207 208 return mp; 209} 210 211static void 212MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 213{ 214 log_Printf(LogCCP, "MPPE: DictSetup\n"); 215} 216 217static const char * 218MPPEDispOpts(struct lcp_opt *o) 219{ 220 static char buf[32]; 221 sprintf(buf, "value 0x%08x", (int)ntohl(*(u_int32_t *)(o->data))); 222 return buf; 223} 224 225static void 226MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 227{ 228 u_long val; 229 230 o->len = 6; 231 232 log_Printf(LogCCP, "MPPE: InitOptsOutput\n"); 233 234 if (!MPPE_MasterKeyValid) { 235 log_Printf(LogWARN, "MPPE: MasterKey is invalid," 236 " MPPE is capable only with CHAP81 authentication\n"); 237 *(u_int32_t *)o->data = htonl(0x0); 238 return; 239 } 240 241 val = 0x1000000; 242 switch(cfg->mppe.keybits) { 243 case 128: 244 val |= 0x40; break; 245 case 56: 246 val |= 0x80; break; 247 case 40: 248 val |= 0x20; break; 249 } 250 *(u_int32_t *)o->data = htonl(val); 251} 252 253static int 254MPPESetOptsOutput(struct lcp_opt *o) 255{ 256 u_long *p = (u_long *)(o->data); 257 u_long val = ntohl(*p); 258 259 log_Printf(LogCCP, "MPPE: SetOptsOutput\n"); 260 261 if (!MPPE_MasterKeyValid) { 262 if (*p != 0x0) { 263 *p = 0x0; 264 return MODE_NAK; 265 } else { 266 return MODE_ACK; 267 } 268 } 269 270 if (val == 0x01000020 || 271 val == 0x01000040 || 272 val == 0x01000080) 273 return MODE_ACK; 274 275 return MODE_NAK; 276} 277 278static int 279MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) 280{ 281 u_long *p = (u_long *)(o->data); 282 u_long val = ntohl(*p); 283 u_long mval; 284 285 log_Printf(LogCCP, "MPPE: SetOptsInput\n"); 286 287 if (!MPPE_MasterKeyValid) { 288 if (*p != 0x0) { 289 *p = 0x0; 290 return MODE_NAK; 291 } else { 292 return MODE_ACK; 293 } 294 } 295 296 mval = 0x01000000; 297 switch(cfg->mppe.keybits) { 298 case 128: 299 mval |= 0x40; break; 300 case 56: 301 mval |= 0x80; break; 302 case 40: 303 mval |= 0x20; break; 304 } 305 306 if (val == mval) 307 return MODE_ACK; 308 309 *p = htonl(mval); 310 311 return MODE_NAK; 312} 313 314static void * 315MPPEInitInput(struct lcp_opt *o) 316{ 317 struct mppe_state *mip; 318 u_int32_t val = ntohl(*(unsigned long *)o->data); 319 320 log_Printf(LogCCP, "MPPE: InitInput\n"); 321 322 if (!MPPE_MasterKeyValid) { 323 log_Printf(LogERROR, "MPPE: InitInput: MasterKey is invalid!!!!\n"); 324 return NULL; 325 } 326 327 mip = malloc(sizeof(*mip)); 328 memset(mip, 0, sizeof(*mip)); 329 330 if (val & 0x20) { /* 40-bits */ 331 mip->keylen = 8; 332 mip->keybits = 40; 333 } else if (val & 0x80) { /* 56-bits */ 334 mip->keylen = 8; 335 mip->keybits = 56; 336 } else { /* 128-bits */ 337 mip->keylen = 16; 338 mip->keybits = 128; 339 } 340 341 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 342 343 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 0); 344 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 345 346 MPPEReduceSessionKey(mip); 347 348 MPPEKeyChange(mip); 349 350 mip->cohnum = 0; 351 352 return mip; 353} 354 355static void * 356MPPEInitOutput(struct lcp_opt *o) 357{ 358 struct mppe_state *mop; 359 u_int32_t val = ntohl(*(unsigned long *)o->data); 360 361 log_Printf(LogCCP, "MPPE: InitOutput\n"); 362 363 if (!MPPE_MasterKeyValid) { 364 log_Printf(LogERROR, "MPPE: InitOutput: MasterKey is invalid!!!!\n"); 365 return NULL; 366 } 367 368 mop = malloc(sizeof(*mop)); 369 memset(mop, 0, sizeof(*mop)); 370 371 if (val & 0x20) { /* 40-bits */ 372 mop->keylen = 8; 373 mop->keybits = 40; 374 } else if (val & 0x80) { /* 56-bits */ 375 mop->keylen = 8; 376 mop->keybits = 56; 377 } else { /* 128-bits */ 378 mop->keylen = 16; 379 mop->keybits = 128; 380 } 381 382 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 383 384 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 0); 385 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 386 387 MPPEReduceSessionKey(mop); 388 389 MPPEKeyChange(mop); 390 391 mop->cohnum = 0; 392 393 return mop; 394} 395 396static void 397MPPETermInput(void *v) 398{ 399 log_Printf(LogCCP, "MPPE: TermInput\n"); 400 free(v); 401} 402 403static void 404MPPETermOutput(void *v) 405{ 406 log_Printf(LogCCP, "MPPE: TermOutput\n"); 407 free(v); 408} 409 410const struct ccp_algorithm MPPEAlgorithm = { 411 TY_MPPE, 412 CCP_NEG_MPPE, 413 MPPEDispOpts, 414 { 415 MPPESetOptsInput, 416 MPPEInitInput, 417 MPPETermInput, 418 MPPEResetInput, 419 MPPEInput, 420 MPPEDictSetup 421 }, 422 { 423 MPPEInitOptsOutput, 424 MPPESetOptsOutput, 425 MPPEInitOutput, 426 MPPETermOutput, 427 MPPEResetOutput, 428 MPPEOutput 429 }, 430}; 431