ReactOS 0.4.16-dev-819-g75c0dc0
mppe.c
Go to the documentation of this file.
1/*
2 * mppe.c - interface MPPE to the PPP code.
3 *
4 * By Frank Cusack <fcusack@fcusack.com>.
5 * Copyright (c) 2002,2003,2004 Google, Inc.
6 * All rights reserved.
7 *
8 * License:
9 * Permission to use, copy, modify, and distribute this software and its
10 * documentation is hereby granted, provided that the above copyright
11 * notice appears in all copies. This software is provided without any
12 * warranty, express or implied.
13 *
14 * Changelog:
15 * 08/12/05 - Matt Domsch <Matt_Domsch@dell.com>
16 * Only need extra skb padding on transmit, not receive.
17 * 06/18/04 - Matt Domsch <Matt_Domsch@dell.com>, Oleg Makarenko <mole@quadra.ru>
18 * Use Linux kernel 2.6 arc4 and sha1 routines rather than
19 * providing our own.
20 * 2/15/04 - TS: added #include <version.h> and testing for Kernel
21 * version before using
22 * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are
23 * deprecated in 2.6
24 */
25
26#include "netif/ppp/ppp_opts.h"
27#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */
28
29#include <string.h>
30
31#include "lwip/err.h"
32
33#include "netif/ppp/ppp_impl.h"
34#include "netif/ppp/ccp.h"
35#include "netif/ppp/mppe.h"
36#include "netif/ppp/pppdebug.h"
37#include "netif/ppp/pppcrypt.h"
38
39#define SHA1_SIGNATURE_SIZE 20
40
41/* ppp_mppe_state.bits definitions */
42#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */
43#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */
44#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */
45#define MPPE_BIT_D 0x10 /* This is an encrypted frame */
46
47#define MPPE_BIT_FLUSHED MPPE_BIT_A
48#define MPPE_BIT_ENCRYPTED MPPE_BIT_D
49
50#define MPPE_BITS(p) ((p)[0] & 0xf0)
51#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1])
52#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */
53
54#define MPPE_OVHD 2 /* MPPE overhead/packet */
55#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */
56
57/*
58 * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3.
59 * Well, not what's written there, but rather what they meant.
60 */
61static void mppe_rekey(ppp_mppe_state * state, int initial_key)
62{
63 lwip_sha1_context sha1_ctx;
64 u8_t sha1_digest[SHA1_SIGNATURE_SIZE];
65
66 /*
67 * Key Derivation, from RFC 3078, RFC 3079.
68 * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
69 */
70 lwip_sha1_init(&sha1_ctx);
71 lwip_sha1_starts(&sha1_ctx);
72 lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen);
73 lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE);
74 lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen);
75 lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE);
76 lwip_sha1_finish(&sha1_ctx, sha1_digest);
77 lwip_sha1_free(&sha1_ctx);
78 MEMCPY(state->session_key, sha1_digest, state->keylen);
79
80 if (!initial_key) {
81 lwip_arc4_init(&state->arc4);
82 lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen);
83 lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen);
84 lwip_arc4_free(&state->arc4);
85 }
86 if (state->keylen == 8) {
87 /* See RFC 3078 */
88 state->session_key[0] = 0xd1;
89 state->session_key[1] = 0x26;
90 state->session_key[2] = 0x9e;
91 }
92 lwip_arc4_init(&state->arc4);
93 lwip_arc4_setup(&state->arc4, state->session_key, state->keylen);
94}
95
96/*
97 * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we
98 * don't have to keep multiple copies of keys.
99 */
100void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) {
101 LWIP_UNUSED_ARG(pcb);
102 MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN);
103}
104
105/*
106 * Initialize (de)compressor state.
107 */
108void
109mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options)
110{
111#if PPP_DEBUG
112 const u8_t *debugstr = (const u8_t*)"mppe_comp_init";
113 if (&pcb->mppe_decomp == state) {
114 debugstr = (const u8_t*)"mppe_decomp_init";
115 }
116#endif /* PPP_DEBUG */
117
118 /* Save keys. */
119 MEMCPY(state->session_key, state->master_key, sizeof(state->master_key));
120
121 if (options & MPPE_OPT_128)
122 state->keylen = 16;
123 else if (options & MPPE_OPT_40)
124 state->keylen = 8;
125 else {
126 PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr,
127 pcb->netif->num));
128 lcp_close(pcb, "MPPE required but peer negotiation failed");
129 return;
130 }
131 if (options & MPPE_OPT_STATEFUL)
132 state->stateful = 1;
133
134 /* Generate the initial session key. */
135 mppe_rekey(state, 1);
136
137#if PPP_DEBUG
138 {
139 int i;
140 char mkey[sizeof(state->master_key) * 2 + 1];
141 char skey[sizeof(state->session_key) * 2 + 1];
142
143 PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n",
144 debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40,
145 (state->stateful) ? "stateful" : "stateless"));
146
147 for (i = 0; i < (int)sizeof(state->master_key); i++)
148 sprintf(mkey + i * 2, "%02x", state->master_key[i]);
149 for (i = 0; i < (int)sizeof(state->session_key); i++)
150 sprintf(skey + i * 2, "%02x", state->session_key[i]);
151 PPPDEBUG(LOG_DEBUG,
152 ("%s[%d]: keys: master: %s initial session: %s\n",
153 debugstr, pcb->netif->num, mkey, skey));
154 }
155#endif /* PPP_DEBUG */
156
157 /*
158 * Initialize the coherency count. The initial value is not specified
159 * in RFC 3078, but we can make a reasonable assumption that it will
160 * start at 0. Setting it to the max here makes the comp/decomp code
161 * do the right thing (determined through experiment).
162 */
163 state->ccount = MPPE_CCOUNT_SPACE - 1;
164
165 /*
166 * Note that even though we have initialized the key table, we don't
167 * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1.
168 */
169 state->bits = MPPE_BIT_ENCRYPTED;
170}
171
172/*
173 * We received a CCP Reset-Request (actually, we are sending a Reset-Ack),
174 * tell the compressor to rekey. Note that we MUST NOT rekey for
175 * every CCP Reset-Request; we only rekey on the next xmit packet.
176 * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost.
177 * So, rekeying for every CCP Reset-Request is broken as the peer will not
178 * know how many times we've rekeyed. (If we rekey and THEN get another
179 * CCP Reset-Request, we must rekey again.)
180 */
181void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state)
182{
183 LWIP_UNUSED_ARG(pcb);
184 state->bits |= MPPE_BIT_FLUSHED;
185}
186
187/*
188 * Compress (encrypt) a packet.
189 * It's strange to call this a compressor, since the output is always
190 * MPPE_OVHD + 2 bytes larger than the input.
191 */
192err_t
193mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol)
194{
195 struct pbuf *n, *np;
196 u8_t *pl;
197 err_t err;
198
199 LWIP_UNUSED_ARG(pcb);
200
201 /* TCP stack requires that we don't change the packet payload, therefore we copy
202 * the whole packet before encryption.
203 */
204 np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_RAM);
205 if (!np) {
206 return ERR_MEM;
207 }
208
209 /* Hide MPPE header + protocol */
210 pbuf_remove_header(np, MPPE_OVHD + sizeof(protocol));
211
212 if ((err = pbuf_copy(np, *pb)) != ERR_OK) {
213 pbuf_free(np);
214 return err;
215 }
216
217 /* Reveal MPPE header + protocol */
218 pbuf_add_header(np, MPPE_OVHD + sizeof(protocol));
219
220 *pb = np;
221 pl = (u8_t*)np->payload;
222
223 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
224 PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount));
225 /* FIXME: use PUT* macros */
226 pl[0] = state->ccount>>8;
227 pl[1] = state->ccount;
228
229 if (!state->stateful || /* stateless mode */
230 ((state->ccount & 0xff) == 0xff) || /* "flag" packet */
231 (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */
232 /* We must rekey */
233 if (state->stateful) {
234 PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num));
235 }
236 mppe_rekey(state, 0);
237 state->bits |= MPPE_BIT_FLUSHED;
238 }
239 pl[0] |= state->bits;
240 state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */
241 pl += MPPE_OVHD;
242
243 /* Add protocol */
244 /* FIXME: add PFC support */
245 pl[0] = protocol >> 8;
246 pl[1] = protocol;
247
248 /* Hide MPPE header */
249 pbuf_remove_header(np, MPPE_OVHD);
250
251 /* Encrypt packet */
252 for (n = np; n != NULL; n = n->next) {
253 lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len);
254 if (n->tot_len == n->len) {
255 break;
256 }
257 }
258
259 /* Reveal MPPE header */
260 pbuf_add_header(np, MPPE_OVHD);
261
262 return ERR_OK;
263}
264
265/*
266 * We received a CCP Reset-Ack. Just ignore it.
267 */
268void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state)
269{
270 LWIP_UNUSED_ARG(pcb);
272 return;
273}
274
275/*
276 * Decompress (decrypt) an MPPE packet.
277 */
278err_t
279mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb)
280{
281 struct pbuf *n0 = *pb, *n;
282 u8_t *pl;
283 u16_t ccount;
284 u8_t flushed;
285
286 /* MPPE Header */
287 if (n0->len < MPPE_OVHD) {
288 PPPDEBUG(LOG_DEBUG,
289 ("mppe_decompress[%d]: short pkt (%d)\n",
290 pcb->netif->num, n0->len));
291 state->sanity_errors += 100;
292 goto sanity_error;
293 }
294
295 pl = (u8_t*)n0->payload;
296 flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED;
297 ccount = MPPE_CCOUNT(pl);
298 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n",
299 pcb->netif->num, ccount));
300
301 /* sanity checks -- terminate with extreme prejudice */
302 if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) {
303 PPPDEBUG(LOG_DEBUG,
304 ("mppe_decompress[%d]: ENCRYPTED bit not set!\n",
305 pcb->netif->num));
306 state->sanity_errors += 100;
307 goto sanity_error;
308 }
309 if (!state->stateful && !flushed) {
310 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in "
311 "stateless mode!\n", pcb->netif->num));
312 state->sanity_errors += 100;
313 goto sanity_error;
314 }
315 if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
316 PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on "
317 "flag packet!\n", pcb->netif->num));
318 state->sanity_errors += 100;
319 goto sanity_error;
320 }
321
322 /*
323 * Check the coherency count.
324 */
325
326 if (!state->stateful) {
327 /* Discard late packet */
328 if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) {
329 state->sanity_errors++;
330 goto sanity_error;
331 }
332
333 /* RFC 3078, sec 8.1. Rekey for every packet. */
334 while (state->ccount != ccount) {
335 mppe_rekey(state, 0);
336 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
337 }
338 } else {
339 /* RFC 3078, sec 8.2. */
340 if (!state->discard) {
341 /* normal state */
342 state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
343 if (ccount != state->ccount) {
344 /*
345 * (ccount > state->ccount)
346 * Packet loss detected, enter the discard state.
347 * Signal the peer to rekey (by sending a CCP Reset-Request).
348 */
349 state->discard = 1;
350 ccp_resetrequest(pcb);
351 return ERR_BUF;
352 }
353 } else {
354 /* discard state */
355 if (!flushed) {
356 /* ccp.c will be silent (no additional CCP Reset-Requests). */
357 return ERR_BUF;
358 } else {
359 /* Rekey for every missed "flag" packet. */
360 while ((ccount & ~0xff) !=
361 (state->ccount & ~0xff)) {
362 mppe_rekey(state, 0);
363 state->ccount =
364 (state->ccount +
365 256) % MPPE_CCOUNT_SPACE;
366 }
367
368 /* reset */
369 state->discard = 0;
370 state->ccount = ccount;
371 /*
372 * Another problem with RFC 3078 here. It implies that the
373 * peer need not send a Reset-Ack packet. But RFC 1962
374 * requires it. Hopefully, M$ does send a Reset-Ack; even
375 * though it isn't required for MPPE synchronization, it is
376 * required to reset CCP state.
377 */
378 }
379 }
380 if (flushed)
381 mppe_rekey(state, 0);
382 }
383
384 /* Hide MPPE header */
385 pbuf_remove_header(n0, MPPE_OVHD);
386
387 /* Decrypt the packet. */
388 for (n = n0; n != NULL; n = n->next) {
389 lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len);
390 if (n->tot_len == n->len) {
391 break;
392 }
393 }
394
395 /* good packet credit */
396 state->sanity_errors >>= 1;
397
398 return ERR_OK;
399
400sanity_error:
401 if (state->sanity_errors >= SANITY_MAX) {
402 /*
403 * Take LCP down if the peer is sending too many bogons.
404 * We don't want to do this for a single or just a few
405 * instances since it could just be due to packet corruption.
406 */
407 lcp_close(pcb, "Too many MPPE errors");
408 }
409 return ERR_BUF;
410}
411
412#endif /* PPP_SUPPORT && MPPE_SUPPORT */
static int state
Definition: maze.c:121
#define NULL
Definition: types.h:112
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define ERR_MEM
Definition: fontsub.h:52
GLdouble n
Definition: glext.h:7729
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
s8_t err_t
Definition: err.h:96
@ ERR_BUF
Definition: err.h:59
@ ERR_OK
Definition: err.h:55
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:959
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_RAW
Definition: pbuf.h:111
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
#define sprintf(buf, format,...)
Definition: sprintf.c:55
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
#define err(...)
struct define * next
Definition: compiler.c:65
Definition: copy.c:22
Definition: pbuf.h:186
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
#define LOG_DEBUG
Definition: syslog.h:52