Bug Summary

File:src/usr.sbin/npppd/npppd/mppe.c
Warning:line 382, column 3
Value stored to 'flushed' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mppe.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/npppd/npppd/../common -I /usr/src/usr.sbin/npppd/npppd -I /usr/src/usr.sbin/npppd/npppd/../pptp -I /usr/src/usr.sbin/npppd/npppd/../l2tp -I /usr/src/usr.sbin/npppd/npppd/../pppoe -D USE_NPPPD_PPTP -D USE_NPPPD_L2TP -D USE_NPPPD_PPPOE -D __COPYRIGHT(x)= -D __RCSID(x)= -D NPPPD_MAX_IFACE=8 -D NPPPD_MAX_POOL=8 -D USE_NPPPD_MPPE -D USE_NPPPD_PIPEX -D USE_NPPPD_RADIUS -D USE_SA_COOKIE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/npppd/npppd/mppe.c
1/* $OpenBSD: mppe.c,v 1.15 2019/02/27 04:52:19 denis Exp $ */
2
3/*-
4 * Copyright (c) 2009 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/* $Id: mppe.c,v 1.15 2019/02/27 04:52:19 denis Exp $ */
29/**@file
30 *
31 * The implementation of MPPE(Microsoft Point-To-Point Encryption Protocol)
32 */
33/*
34 * To avoid the PPP packet out of sequence problem.
35 * It may avoid if it reconstruct the frame order in L2TP/IPsec.
36 */
37#define WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING1 1
38
39#include <sys/types.h>
40#include <sys/socket.h>
41#include <sys/time.h>
42#include <net/if_dl.h>
43#include <netinet/in.h>
44#include <endian.h>
45#include <stdlib.h>
46#include <stdio.h>
47#include <stdarg.h>
48#include <syslog.h>
49#include <string.h>
50#include <event.h>
51#ifdef WITH_OPENSSL
52#include <openssl/sha.h>
53#include <openssl/rc4.h>
54#endif
55
56#include "npppd.h"
57#include "debugutil.h"
58
59#ifdef MPPE_DEBUG
60#define MPPE_DBG(x) mppe_log x
61#define MPPE_ASSERT(x) \
62 if (!(x)) { \
63 fprintf(stderr(&__sF[2]), \
64 "\nASSERT(%s) failed on %s() at %s:%d.\n" \
65 , #x, __func__, __FILE__"/usr/src/usr.sbin/npppd/npppd/mppe.c", __LINE__65); \
66 abort(); \
67 }
68#else
69#define MPPE_DBG(x)
70#define MPPE_ASSERT(x)
71#endif
72
73#define SESS_KEY_LEN(len)(len < 16)? 8 : 16 (len < 16)? 8 : 16
74
75#define COHER_EQ(a, b)((((a) - (b)) & 0xfff) == 0) ((((a) - (b)) & 0xfff) == 0)
76#define COHER_LT(a, b)(((int16_t)(((a) - (b)) << 4)) < 0) (((int16_t)(((a) - (b)) << 4)) < 0)
77#define COHER_GT(a, b)(((int16_t)((((b)) - ((a))) << 4)) < 0) COHER_LT((b), (a))(((int16_t)((((b)) - ((a))) << 4)) < 0)
78#define COHER_NE(a, b)(!(((((a)) - ((b))) & 0xfff) == 0)) (!COHER_EQ((a), (b))(((((a)) - ((b))) & 0xfff) == 0))
79#define COHER_LE(a, b)(!(!(((int16_t)(((((b))) - (((a)))) << 4)) < 0))) (!COHER_GE((b), (a))(!(((int16_t)(((((b))) - (((a)))) << 4)) < 0)))
80#define COHER_GE(a, b)(!(((int16_t)((((a)) - ((b))) << 4)) < 0)) (!COHER_LT((a), (b))(((int16_t)((((a)) - ((b))) << 4)) < 0))
81
82
83static const char *mppe_bits_to_string(uint32_t);
84static void mppe_log(mppe *, uint32_t, const char *, ...) __printflike(3,4)__attribute__((__format__ (__printf__, 3, 4)));
85static int mppe_rc4_init(mppe *, mppe_rc4_t *, int);
86static int mppe_rc4_setkey(mppe *, mppe_rc4_t *);
87static int mppe_rc4_setoldkey(mppe *, mppe_rc4_t *, uint16_t);
88static void mppe_rc4_destroy(mppe *, mppe_rc4_t *);
89static void mppe_rc4_encrypt(mppe *, mppe_rc4_t *, int, u_char *, u_char *);
90static void *rc4_create_ctx(void);
91static int rc4_key(void *, int, u_char *);
92static void rc4(void *, int, u_char *, u_char *);
93static void GetNewKeyFromSHA(u_char *, u_char *, int, u_char *);
94
95/**
96 * initializing mppe context.
97 * - reading configuration.
98 */
99void
100mppe_init(mppe *_this, npppd_ppp *ppp)
101{
102 struct tunnconf *conf;
103
104 MPPE_ASSERT(ppp != NULL);
105 MPPE_ASSERT(_this != NULL);
106
107 memset(_this, 0, sizeof(mppe));
108
109 _this->ppp = ppp;
110
111 _this->mode_auto = 1;
112 _this->mode_stateless = 0;
113
114 conf = ppp_get_tunnconf(ppp);
115 _this->enabled = conf->mppe_yesno;
116 if (_this->enabled == 0)
117 goto mppe_config_done;
118
119 _this->required = conf->mppe_required;
120
121 if (conf->mppe_keystate == (NPPPD_MPPE_STATEFUL0x0001|NPPPD_MPPE_STATELESS0x0002)) {
122 /* no need to change from default. */
123 } else if (conf->mppe_keystate == NPPPD_MPPE_STATELESS0x0002) {
124 _this->mode_auto = 0;
125 _this->mode_stateless = 1;
126 } else if (conf->mppe_keystate == NPPPD_MPPE_STATEFUL0x0001) {
127 _this->mode_auto = 0;
128 _this->mode_stateless = 0;
129 }
130
131 _this->keylenbits = 0;
132 if ((conf->mppe_keylen & NPPPD_MPPE_40BIT0x0001) != 0)
133 _this->keylenbits |= CCP_MPPE_NT_40bit0x00000020;
134 if ((conf->mppe_keylen & NPPPD_MPPE_56BIT0x0002) != 0)
135 _this->keylenbits |= CCP_MPPE_NT_56bit0x00000080;
136 if ((conf->mppe_keylen & NPPPD_MPPE_128BIT0x0004) != 0)
137 _this->keylenbits |= CCP_MPPE_NT_128bit0x00000040;
138
139mppe_config_done:
140 /* nothing */;
141}
142
143void
144mppe_fini(mppe *_this)
145{
146 mppe_rc4_destroy(_this, &_this->send);
147 mppe_rc4_destroy(_this, &_this->recv);
148}
149
150static void
151mppe_reduce_key(mppe_rc4_t *_this)
152{
153 switch (_this->keybits) {
154 case 40:
155 _this->session_key[1] = 0x26;
156 _this->session_key[2] = 0x9e;
157 case 56:
158 _this->session_key[0] = 0xd1;
159 }
160}
161
162static void
163mppe_key_change(mppe *_mppe, mppe_rc4_t *_this)
164{
165 u_char interim[16];
166 void *keychg;
167
168 keychg = rc4_create_ctx();
169
170 GetNewKeyFromSHA(_this->master_key, _this->session_key,
171 _this->keylen, interim);
172
173 rc4_key(keychg, _this->keylen, interim);
174 rc4(keychg, _this->keylen, interim, _this->session_key);
175 mppe_reduce_key(_this);
176
177 if (_this->old_session_keys) {
178 int idx = _this->coher_cnt % MPPE_NOLDKEY64;
179 memcpy(_this->old_session_keys[idx],
180 _this->session_key, MPPE_KEYLEN16);
181 }
182
183 free(keychg);
184}
185
186/**
187 * starting mppe protocol.
188 */
189void
190mppe_start(mppe *_this)
191{
192 char buf[256];
193
194 strlcpy(buf, mppe_bits_to_string(_this->ppp->ccp.mppe_o_bits),
195 sizeof(buf));
196
197 mppe_log(_this, LOG_INFO6, "logtype=Opened our=%s peer=%s", buf,
198 mppe_bits_to_string(_this->ppp->ccp.mppe_p_bits));
199
200 _this->ppp->mppe_started = 1;
201
202 _this->send.stateless =
203 ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_STATELESS0x01000000) != 0)? 1 : 0;
204
205 if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_40bit0x00000020) != 0) {
206 _this->send.keylen = 8;
207 _this->send.keybits = 40;
208 } else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_56bit0x00000080) != 0) {
209 _this->send.keylen = 8;
210 _this->send.keybits = 56;
211 } else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_128bit0x00000040) != 0) {
212 _this->send.keylen = 16;
213 _this->send.keybits = 128;
214 }
215
216 _this->recv.stateless =
217 ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_STATELESS0x01000000) != 0)? 1 : 0;
218 if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_40bit0x00000020) != 0) {
219 _this->recv.keylen = 8;
220 _this->recv.keybits = 40;
221 } else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_56bit0x00000080) != 0) {
222 _this->recv.keylen = 8;
223 _this->recv.keybits = 56;
224 } else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_128bit0x00000040) != 0) {
225 _this->recv.keylen = 16;
226 _this->recv.keybits = 128;
227 }
228
229 if (_this->send.keybits > 0) {
230 mppe_rc4_init(_this, &_this->send, 0);
231 GetNewKeyFromSHA(_this->send.master_key, _this->send.master_key,
232 _this->send.keylen, _this->send.session_key);
233 mppe_reduce_key(&_this->send);
234 mppe_rc4_setkey(_this, &_this->send);
235 }
236 if (_this->recv.keybits > 0) {
237 mppe_rc4_init(_this, &_this->recv, _this->recv.stateless);
238 GetNewKeyFromSHA(_this->recv.master_key, _this->recv.master_key,
239 _this->recv.keylen, _this->recv.session_key);
240 mppe_reduce_key(&_this->recv);
241 mppe_rc4_setkey(_this, &_this->recv);
242 }
243}
244
245/**
246 * creating the mppe bits. In case of first proposal, it specifies the
247 * peer_bits as 0 value. If it specifies the peer_bits, it returns the
248 * value as peer's proposal.
249 */
250uint32_t
251mppe_create_our_bits(mppe *_this, uint32_t peer_bits)
252{
253 uint32_t our_bits;
254
255 /* default proposal */
256 our_bits = _this->keylenbits;
257 if (peer_bits != 0 && (peer_bits & our_bits) != 0) {
258 if ((peer_bits & CCP_MPPE_NT_128bit0x00000040) != 0)
259 our_bits = CCP_MPPE_NT_128bit0x00000040;
260 else if ((peer_bits & CCP_MPPE_NT_56bit0x00000080) != 0)
261 our_bits = CCP_MPPE_NT_56bit0x00000080;
262 else if ((peer_bits & CCP_MPPE_NT_40bit0x00000020) != 0)
263 our_bits = CCP_MPPE_NT_40bit0x00000020;
264 }
265
266 if (_this->mode_auto != 0) {
267 /* in case of auto_mode */
268 if (peer_bits == 0) {
269 /*
270 * It proposes stateless mode in first time. Windows 9x has
271 * a bug that it is reverse to stateful and stateless in
272 * sending and receiving packets.
273 * Windows 9x is prior to negotiate in stateless mode, so
274 * it will avoid the Windows bug to be prior to negotiate
275 * in stateless mode.
276 *
277 * Even if this bug doesn't exists, the stateful mode is high
278 * cost from user's viewpoint when packets may loss more than a
279 * certain rate, so it is not good choice to use via Internet or
280 * wireless LAN.
281 */
282 our_bits |= CCP_MPPE_STATELESS0x01000000;
283 } else {
284 /* giving up */
285 our_bits |= peer_bits & CCP_MPPE_STATELESS0x01000000;
286 }
287 } else {
288 /* it doesn't give up in case of setting non-auto value. */
289 if (_this->mode_stateless != 0)
290 our_bits |= CCP_MPPE_STATELESS0x01000000;
291 }
292 if (peer_bits != 0 && our_bits != peer_bits) {
293 char obuf[128], pbuf[128];
294
295 /* in case of failure, it puts a log. */
296 strlcpy(obuf, mppe_bits_to_string(our_bits), sizeof(obuf));
297 strlcpy(pbuf, mppe_bits_to_string(peer_bits), sizeof(pbuf));
298 mppe_log(_this, LOG_INFO6,
299 "mismatch our=%s peer=%s", obuf, pbuf);
300 }
301
302 return our_bits;
303}
304
305#define COHERENCY_CNT_MASK0x0fff; 0x0fff;
306
307/**
308 * receiving packets via MPPE.
309 * len must be 4 at least.
310 */
311void
312mppe_input(mppe *_this, u_char *pktp, int len)
313{
314 int pktloss, encrypt, flushed, m, n;
315 uint16_t coher_cnt;
316 u_char *pktp0, *opktp, *opktp0;
317 uint16_t proto;
318 int delayed = 0;
319
320 encrypt = 0;
321 flushed = 0;
322
323 MPPE_ASSERT(len >= 4);
324
325 pktp0 = pktp;
326 GETSHORT(coher_cnt, pktp){ (coher_cnt) = *(pktp)++ << 8; (coher_cnt) |= *(pktp)++
; }
;
327
328 flushed = (coher_cnt & 0x8000)? 1 : 0;
329 encrypt = (coher_cnt & 0x1000)? 1 : 0;
330 coher_cnt &= COHERENCY_CNT_MASK0x0fff;;
331 pktloss = 0;
332
333 MPPE_DBG((_this, DEBUG_LEVEL_2, "in coher_cnt=%03x/%03x %s%s",
334 _this->recv.coher_cnt, coher_cnt, (flushed)? "[flushed]" : "",
335 (encrypt)? "[encrypt]" : ""));
336
337 if (encrypt == 0) {
338 mppe_log(_this, LOG_WARNING4,
339 "Received unexpected MPPE packet. (no encrypt)");
340 return;
341 }
342
343 /*
344 * In L2TP/IPsec implementation, in case that the ppp frame sequence
345 * is not able to reconstruct and the ppp frame is out of sequence, it
346 * is unable to identify with many packets losing. If it does so, MPPE
347 * key is out of place.
348 * To avoid this problem, when it seems that more than 4096-256 packets
349 * drops, it assumes that the packet doesn't lose but the packet is out
350 * of sequence.
351 */
352 {
353 int coher_cnt0;
354
355 coher_cnt0 = coher_cnt;
356 if (coher_cnt < _this->recv.coher_cnt)
357 coher_cnt0 += 0x1000;
358 if (coher_cnt0 - _this->recv.coher_cnt > 0x0f00) {
359 if (!_this->recv.stateless ||
360 coher_cnt0 - _this->recv.coher_cnt
361 <= 0x1000 - MPPE_NOLDKEY64) {
362 mppe_log(_this, LOG_INFO6,
363 "Workaround the out-of-sequence PPP framing problem: "
364 "%d => %d", _this->recv.coher_cnt, coher_cnt);
365 return;
366 }
367 delayed = 1;
368 }
369 }
370
371 if (_this->recv.stateless != 0) {
372 if (!delayed) {
373 mppe_key_change(_this, &_this->recv);
374 while (_this->recv.coher_cnt != coher_cnt) {
375 _this->recv.coher_cnt++;
376 _this->recv.coher_cnt &= COHERENCY_CNT_MASK0x0fff;;
377 mppe_key_change(_this, &_this->recv);
378 pktloss++;
379 }
380 }
381 mppe_rc4_setoldkey(_this, &_this->recv, coher_cnt);
382 flushed = 1;
Value stored to 'flushed' is never read
383 } else {
384 if (flushed) {
385 if (coher_cnt < _this->recv.coher_cnt) {
386 /* in case of carrying up. */
387 coher_cnt += 0x1000;
388 }
389 pktloss += coher_cnt - _this->recv.coher_cnt;
390 m = _this->recv.coher_cnt / 256;
391 n = coher_cnt / 256;
392 while (m++ < n)
393 mppe_key_change(_this, &_this->recv);
394
395 coher_cnt &= COHERENCY_CNT_MASK0x0fff;;
396 _this->recv.coher_cnt = coher_cnt;
397 } else if (_this->recv.coher_cnt != coher_cnt) {
398 _this->recv.resetreq = 1;
399
400 opktp0 = ppp_packetbuf(_this->ppp,
401 PPP_PROTO_NCP0x8000 | NCP_CCP0xfd);
402 opktp = opktp0;
403
404 PUTLONG(_this->ppp->ccp.mppe_p_bits, opktp){ *(opktp)++ = (u_char) ((_this->ppp->ccp.mppe_p_bits) >>
24); *(opktp)++ = (u_char) ((_this->ppp->ccp.mppe_p_bits
) >> 16); *(opktp)++ = (u_char) ((_this->ppp->ccp
.mppe_p_bits) >> 8); *(opktp)++ = (u_char) (_this->ppp
->ccp.mppe_p_bits); }
;
405
406 ppp_output(_this->ppp, PPP_PROTO_NCP0x8000 | NCP_CCP0xfd,
407 RESETREQ14, _this->recv.resetreq, opktp0,
408 opktp - opktp0);
409 return;
410 }
411 if ((coher_cnt & 0xff) == 0xff) {
412 mppe_key_change(_this, &_this->recv);
413 flushed = 1;
414 }
415 if (flushed) {
416 mppe_rc4_setkey(_this, &_this->recv);
417 }
418 }
419
420 if (pktloss > 1000) {
421 /*
422 * In case of many packets losing or out of sequence.
423 * The latter is not able to communicate because the key is
424 * out of place soon.
425 *
426 */
427 mppe_log(_this, LOG_WARNING4, "%d packets loss", pktloss);
428 }
429
430 mppe_rc4_encrypt(_this, &_this->recv, len - 2, pktp, pktp);
431
432 if (!delayed) {
433 _this->recv.coher_cnt++;
434 _this->recv.coher_cnt &= COHERENCY_CNT_MASK0x0fff;;
435 }
436
437 if (pktp[0] & 1)
438 proto = pktp[0];
439 else
440 proto = pktp[0] << 8 | pktp[1];
441 /*
442 * According to RFC3078 section 3,
443 * MPPE only accept protocol number 0021-00FA.
444 * If decrypted protocol number is out of range,
445 * it indicates loss of coherency.
446 */
447 if (!(proto & 1) || proto < 0x21 || proto > 0xfa) {
448 mppe_log(_this, LOG_INFO6, "MPPE coherency is lost");
449 return; /* drop frame */
450 }
451
452 _this->ppp->recv_packet(_this->ppp, pktp, len - 2,
453 PPP_IO_FLAGS_MPPE_ENCRYPTED0x0001);
454}
455
456/**
457 * The call out function in case of receiving CCP Reset (key reset in case
458 * of MPPE).
459 */
460void
461mppe_recv_ccp_reset(mppe *_this)
462{
463 MPPE_DBG((_this, DEBUG_LEVEL_2, "%s() is called.", __func__));
464 _this->send.resetreq = 1;
465}
466
467/**
468 * sending packet via MPPE.
469 */
470void
471mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len)
472{
473 int encrypt, flushed;
474 uint16_t coher_cnt;
475 u_char *outp, *outp0;
476
477 MPPE_ASSERT(proto == PPP_PROTO_IP);
478
479 flushed = 0;
480 encrypt = 1;
481
482 outp = ppp_packetbuf(_this->ppp, PPP_PROTO_MPPE0x00FD);
483 outp0 = outp;
484
485 if (_this->send.stateless != 0) {
486 flushed = 1;
487 mppe_key_change(_this, &_this->send);
488 } else {
489 if ((_this->send.coher_cnt % 0x100) == 0xff) {
490 flushed = 1;
491 mppe_key_change(_this, &_this->send);
492 } else if (_this->send.resetreq != 0) {
493 flushed = 1;
494 _this->send.resetreq = 0;
495 }
496 }
497
498 if (flushed) {
499 mppe_rc4_setkey(_this, &_this->send);
500 }
501
502 MPPE_DBG((_this, DEBUG_LEVEL_2, "out coher_cnt=%03x %s%s",
503 _this->send.coher_cnt, (flushed)? "[flushed]" : "",
504 (encrypt)? "[encrypt]" : ""));
505
506 coher_cnt = _this->send.coher_cnt & COHERENCY_CNT_MASK0x0fff;;
507 if (flushed)
508 coher_cnt |= 0x8000;
509 if (encrypt)
510 coher_cnt |= 0x1000;
511
512 PUTSHORT(coher_cnt, outp){ *(outp)++ = (u_char) ((coher_cnt) >> 8); *(outp)++ = (
u_char) (coher_cnt); }
;
513 proto = htons(proto)(__uint16_t)(__builtin_constant_p(proto) ? (__uint16_t)(((__uint16_t
)(proto) & 0xffU) << 8 | ((__uint16_t)(proto) &
0xff00U) >> 8) : __swap16md(proto))
;
514 mppe_rc4_encrypt(_this, &_this->send, 2, (u_char *)&proto, outp);
515 mppe_rc4_encrypt(_this, &_this->send, len, pktp, outp + 2);
516
517 ppp_output(_this->ppp, PPP_PROTO_MPPE0x00FD, 0, 0, outp0, len + 4);
518 _this->send.coher_cnt++;
519 _this->send.coher_cnt &= COHERENCY_CNT_MASK0x0fff;;
520}
521
522static void
523mppe_log(mppe *_this, uint32_t prio, const char *fmt, ...)
524{
525 char logbuf[BUFSIZ1024];
526 va_list ap;
527
528 va_start(ap, fmt)__builtin_va_start(ap, fmt);
529 snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=mppe %s",
530 _this->ppp->id, fmt);
531 vlog_printf(prio, logbuf, ap);
532 va_end(ap)__builtin_va_end(ap);
533}
534
535static const char *
536mppe_bits_to_string(uint32_t bits)
537{
538 static char buf[128];
539
540 snprintf(buf, sizeof(buf), "%s%s%s%s%s%s"
541 , ((CCP_MPPC_ALONE0x00000001 & bits) != 0)? ",mppc" : ""
542 , ((CCP_MPPE_LM_40bit0x00000010& bits) != 0)? ",40bit(LM)" : ""
543 , ((CCP_MPPE_NT_40bit0x00000020& bits) != 0)? ",40bit" : ""
544 , ((CCP_MPPE_NT_128bit0x00000040& bits) != 0)? ",128bit" : ""
545 , ((CCP_MPPE_NT_56bit0x00000080& bits) != 0)? ",56bit" : ""
546 , ((CCP_MPPE_STATELESS0x01000000& bits) != 0)? ",stateless" : ",stateful");
547
548 if (buf[0] == '\0')
549 return "";
550
551 return buf + 1;
552}
553
554/************************************************************************
555 * implementations of authentication/cipher algorism.
556 ************************************************************************/
557static u_char SHAPad1[] = {
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563}, SHAPad2[] = {
564 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
565 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
566 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
567 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
568 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
569};
570#define ZeroMemory(dst, len)memset(dst, 0, len) memset(dst, 0, len)
571#define MoveMemory(dst, src, len)memcpy(dst, src, len) memcpy(dst, src, len)
572
573#include <openssl/rc4.h>
574#include <openssl/sha.h>
575
576#define SHA_CTXSHA_CTX SHA_CTXSHA_CTX
577#define SHAInitSHA1_Init SHA1_Init
578#define SHAUpdateSHA1_Update SHA1_Update
579#define SHAFinal(ctx,digest)SHA1_Final(digest, ctx) SHA1_Final(digest, ctx)
580
581/************************************************************************
582 * implementations of OpenSSL version
583 ************************************************************************/
584static void *
585rc4_create_ctx(void)
586{
587 return malloc(sizeof(RC4_KEY));
588}
589
590static int
591rc4_key(void *rc4ctx, int lkey, u_char *key)
592{
593
594 RC4_set_key(rc4ctx, lkey, key);
595
596 return 0;
597}
598
599static void
600rc4(void *rc4ctx, int len, u_char *indata, u_char *outdata)
601{
602 RC4(rc4ctx, len, indata, outdata);
603}
604
605static void
606GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
607 u_char *InterimKey)
608{
609 u_char Digest[20];
610 SHA_CTXSHA_CTX Context;
611
612 ZeroMemory(Digest, 20)memset(Digest, 0, 20);
613
614 SHAInitSHA1_Init(&Context);
615 SHAUpdateSHA1_Update(&Context, StartKey, SessionKeyLength);
616 SHAUpdateSHA1_Update(&Context, SHAPad1, 40);
617 SHAUpdateSHA1_Update(&Context, SessionKey, SessionKeyLength);
618 SHAUpdateSHA1_Update(&Context, SHAPad2, 40);
619 SHAFinal(&Context, Digest)SHA1_Final(Digest, &Context);
620
621 MoveMemory(InterimKey, Digest, SessionKeyLength)memcpy(InterimKey, Digest, SessionKeyLength);
622}
623
624static int
625mppe_rc4_init(mppe *_mppe, mppe_rc4_t *_this, int has_oldkey)
626{
627 if ((_this->rc4ctx = rc4_create_ctx()) == NULL((void*)0)) {
628 mppe_log(_mppe, LOG_ERR3, "malloc() failed at %s: %m",
629 __func__);
630 return 1;
631 }
632
633 if (has_oldkey)
634 _this->old_session_keys = reallocarray(NULL((void*)0),
635 MPPE_KEYLEN16, MPPE_NOLDKEY64);
636 else
637 _this->old_session_keys = NULL((void*)0);
638
639 return 0;
640}
641
642static int
643mppe_rc4_setkey(mppe *_mppe, mppe_rc4_t *_this)
644{
645 return rc4_key(_this->rc4ctx, _this->keylen, _this->session_key);
646}
647
648static int
649mppe_rc4_setoldkey(mppe *_mppe, mppe_rc4_t *_this, uint16_t coher_cnt)
650{
651 return rc4_key(_this->rc4ctx, _this->keylen,
652 _this->old_session_keys[coher_cnt % MPPE_NOLDKEY64]);
653}
654
655static void
656mppe_rc4_encrypt(mppe *_mppe, mppe_rc4_t *_this, int len, u_char *indata, u_char *outdata)
657{
658 rc4(_this->rc4ctx, len, indata, outdata);
659}
660
661static void
662mppe_rc4_destroy(mppe *_mppe, mppe_rc4_t *_this)
663{
664 free(_this->rc4ctx);
665 free(_this->old_session_keys);
666 _this->rc4ctx = NULL((void*)0);
667}