GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/mppe.c Lines: 0 221 0.0 %
Date: 2017-11-07 Branches: 0 115 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mppe.c,v 1.14 2017/05/30 17:22:00 yasuoka 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.14 2017/05/30 17:22:00 yasuoka 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_FRAMING	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 "slist.h"
57
#include "npppd.h"
58
#include "debugutil.h"
59
60
#ifdef	MPPE_DEBUG
61
#define	MPPE_DBG(x)	mppe_log x
62
#define	MPPE_ASSERT(x)	\
63
	if (!(x)) { \
64
	    fprintf(stderr, \
65
		"\nASSERT(%s) failed on %s() at %s:%d.\n" \
66
		, #x, __func__, __FILE__, __LINE__); \
67
	    abort(); \
68
	}
69
#else
70
#define	MPPE_DBG(x)
71
#define MPPE_ASSERT(x)
72
#endif
73
74
#define	SESS_KEY_LEN(len)	(len < 16)?		8 : 16
75
76
#define COHER_EQ(a, b) ((((a) - (b)) & 0xfff) == 0)
77
#define COHER_LT(a, b) (((int16_t)(((a) - (b)) << 4)) < 0)
78
#define COHER_GT(a, b) COHER_LT((b), (a))
79
#define COHER_NE(a, b) (!COHER_EQ((a), (b)))
80
#define COHER_LE(a, b) (!COHER_GE((b), (a)))
81
#define COHER_GE(a, b) (!COHER_LT((a), (b)))
82
83
84
static const char  *mppe_bits_to_string(uint32_t);
85
static void        mppe_log(mppe *, uint32_t, const char *, ...) __printflike(3,4);
86
static int         mppe_rc4_init(mppe *, mppe_rc4_t *, int);
87
static int         mppe_rc4_setkey(mppe *, mppe_rc4_t *);
88
static int         mppe_rc4_setoldkey(mppe *, mppe_rc4_t *, uint16_t);
89
static void        mppe_rc4_destroy(mppe *, mppe_rc4_t *);
90
static void        mppe_rc4_encrypt(mppe *, mppe_rc4_t *, int, u_char *, u_char *);
91
static void        *rc4_create_ctx(void);
92
static int         rc4_key(void *, int, u_char *);
93
static void        rc4(void *, int, u_char *, u_char *);
94
static void        GetNewKeyFromSHA(u_char *, u_char *, int, u_char *);
95
96
/**
97
 * initializing mppe context.
98
 * 	- reading configuration.
99
 */
100
void
101
mppe_init(mppe *_this, npppd_ppp *ppp)
102
{
103
	struct tunnconf *conf;
104
105
	MPPE_ASSERT(ppp != NULL);
106
	MPPE_ASSERT(_this != NULL);
107
108
	memset(_this, 0, sizeof(mppe));
109
110
	_this->ppp = ppp;
111
112
	_this->mode_auto = 1;
113
	_this->mode_stateless = 0;
114
115
	conf = ppp_get_tunnconf(ppp);
116
	_this->enabled = conf->mppe_yesno;
117
	if (_this->enabled == 0)
118
		goto mppe_config_done;
119
120
	_this->required = conf->mppe_required;
121
122
	if (conf->mppe_keystate == (NPPPD_MPPE_STATEFUL|NPPPD_MPPE_STATELESS)) {
123
		/* no need to change from default. */
124
	} else if (conf->mppe_keystate == NPPPD_MPPE_STATELESS) {
125
		_this->mode_auto = 0;
126
		_this->mode_stateless = 1;
127
	} else if (conf->mppe_keystate == NPPPD_MPPE_STATEFUL) {
128
		_this->mode_auto = 0;
129
		_this->mode_stateless = 0;
130
	}
131
132
	_this->keylenbits = 0;
133
	if ((conf->mppe_keylen & NPPPD_MPPE_40BIT) != 0)
134
		_this->keylenbits |= CCP_MPPE_NT_40bit;
135
	if ((conf->mppe_keylen & NPPPD_MPPE_56BIT) != 0)
136
		_this->keylenbits |= CCP_MPPE_NT_56bit;
137
	if ((conf->mppe_keylen & NPPPD_MPPE_128BIT) != 0)
138
		_this->keylenbits |= CCP_MPPE_NT_128bit;
139
140
mppe_config_done:
141
	/* nothing */;
142
}
143
144
void
145
mppe_fini(mppe *_this)
146
{
147
	mppe_rc4_destroy(_this, &_this->send);
148
	mppe_rc4_destroy(_this, &_this->recv);
149
}
150
151
static void
152
mppe_reduce_key(mppe_rc4_t *_this)
153
{
154
	switch (_this->keybits) {
155
	case 40:
156
		_this->session_key[1] = 0x26;
157
		_this->session_key[2] = 0x9e;
158
	case 56:
159
		_this->session_key[0] = 0xd1;
160
	}
161
}
162
163
static void
164
mppe_key_change(mppe *_mppe, mppe_rc4_t *_this)
165
{
166
	u_char interim[16];
167
	void *keychg;
168
169
	keychg = rc4_create_ctx();
170
171
	GetNewKeyFromSHA(_this->master_key, _this->session_key,
172
	    _this->keylen, interim);
173
174
	rc4_key(keychg, _this->keylen, interim);
175
	rc4(keychg, _this->keylen, interim, _this->session_key);
176
	mppe_reduce_key(_this);
177
178
	if (_this->old_session_keys) {
179
		int idx = _this->coher_cnt % MPPE_NOLDKEY;
180
		memcpy(_this->old_session_keys[idx],
181
		    _this->session_key, MPPE_KEYLEN);
182
	}
183
184
	free(keychg);
185
}
186
187
/**
188
 * starting mppe protocol.
189
 */
190
void
191
mppe_start(mppe *_this)
192
{
193
	char buf[256];
194
195
	strlcpy(buf, mppe_bits_to_string(_this->ppp->ccp.mppe_o_bits),
196
	    sizeof(buf));
197
198
	mppe_log(_this, LOG_INFO, "logtype=Opened our=%s peer=%s", buf,
199
	    mppe_bits_to_string(_this->ppp->ccp.mppe_p_bits));
200
201
	_this->ppp->mppe_started = 1;
202
203
	_this->send.stateless =
204
	    ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_STATELESS) != 0)? 1 : 0;
205
206
	if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_40bit) != 0) {
207
		_this->send.keylen = 8;
208
		_this->send.keybits = 40;
209
	} else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_56bit) != 0) {
210
		_this->send.keylen = 8;
211
		_this->send.keybits = 56;
212
	} else if ((_this->ppp->ccp.mppe_o_bits & CCP_MPPE_NT_128bit) != 0) {
213
		_this->send.keylen = 16;
214
		_this->send.keybits = 128;
215
	}
216
217
	_this->recv.stateless =
218
	    ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_STATELESS) != 0)? 1 : 0;
219
	if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_40bit) != 0) {
220
		_this->recv.keylen = 8;
221
		_this->recv.keybits = 40;
222
	} else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_56bit) != 0) {
223
		_this->recv.keylen = 8;
224
		_this->recv.keybits = 56;
225
	} else if ((_this->ppp->ccp.mppe_p_bits & CCP_MPPE_NT_128bit) != 0) {
226
		_this->recv.keylen = 16;
227
		_this->recv.keybits = 128;
228
	}
229
230
	if (_this->send.keybits > 0) {
231
		mppe_rc4_init(_this, &_this->send, 0);
232
		GetNewKeyFromSHA(_this->send.master_key, _this->send.master_key,
233
		    _this->send.keylen, _this->send.session_key);
234
		mppe_reduce_key(&_this->send);
235
		mppe_rc4_setkey(_this, &_this->send);
236
	}
237
	if (_this->recv.keybits > 0) {
238
		mppe_rc4_init(_this, &_this->recv, _this->recv.stateless);
239
		GetNewKeyFromSHA(_this->recv.master_key, _this->recv.master_key,
240
		    _this->recv.keylen, _this->recv.session_key);
241
		mppe_reduce_key(&_this->recv);
242
		mppe_rc4_setkey(_this, &_this->recv);
243
	}
244
}
245
246
/**
247
 * creating the mppe bits. In case of first proposal, it specifies the
248
 * peer_bits as 0 value. If it specifies the peer_bits, it returns the
249
 * value as peer's proposal.
250
 */
251
uint32_t
252
mppe_create_our_bits(mppe *_this, uint32_t peer_bits)
253
{
254
	uint32_t our_bits;
255
256
	/* default proposal */
257
	our_bits = _this->keylenbits;
258
	if (peer_bits != 0 && (peer_bits & our_bits) != 0) {
259
		if ((peer_bits & CCP_MPPE_NT_128bit) != 0)
260
			our_bits = CCP_MPPE_NT_128bit;
261
		else if ((peer_bits & CCP_MPPE_NT_56bit) != 0)
262
			our_bits = CCP_MPPE_NT_56bit;
263
		else if ((peer_bits & CCP_MPPE_NT_40bit) != 0)
264
			our_bits = CCP_MPPE_NT_40bit;
265
	}
266
267
	if (_this->mode_auto != 0) {
268
		/* in case of auto_mode */
269
		if (peer_bits == 0) {
270
			/*
271
			 * It proposes stateless mode in first time. Windows 9x has
272
			 * a bug that it is reverse to stateful and stateless in
273
			 * sending and receiving packets.
274
			 * Windows 9x is prior to negotiate in stateless mode, so
275
			 * it will avoid the Windows bug to be prior to negotiate
276
			 * in stateless mode.
277
			 *
278
			 * Even if this bug doesn't exists, the stateful mode is high
279
			 * cost from user's viewpoint when packets may loss more than a
280
			 * certain rate, so it is not good choice to use via Internet or
281
			 * wireless LAN.
282
			 */
283
			our_bits |= CCP_MPPE_STATELESS;
284
		} else {
285
			/* giving up */
286
			our_bits |= peer_bits & CCP_MPPE_STATELESS;
287
		}
288
	} else {
289
		/* it doesn't give up in case of setting non-auto value. */
290
		if (_this->mode_stateless != 0)
291
			our_bits |= CCP_MPPE_STATELESS;
292
	}
293
	if (peer_bits != 0 && our_bits != peer_bits) {
294
		char obuf[128], pbuf[128];
295
296
		/* in case of failure, it puts a log. */
297
		strlcpy(obuf, mppe_bits_to_string(our_bits), sizeof(obuf));
298
		strlcpy(pbuf, mppe_bits_to_string(peer_bits), sizeof(pbuf));
299
		mppe_log(_this, LOG_INFO,
300
		    "mismatch our=%s peer=%s", obuf, pbuf);
301
	}
302
303
	return our_bits;
304
}
305
306
#define	COHERENCY_CNT_MASK	0x0fff;
307
308
/**
309
 * receiving packets via MPPE.
310
 * len must be 4 at least.
311
 */
312
void
313
mppe_input(mppe *_this, u_char *pktp, int len)
314
{
315
	int pktloss, encrypt, flushed, m, n;
316
	uint16_t coher_cnt;
317
	u_char *pktp0, *opktp, *opktp0;
318
	uint16_t proto;
319
	int delayed = 0;
320
321
	encrypt = 0;
322
	flushed = 0;
323
324
	MPPE_ASSERT(len >= 4);
325
326
	pktp0 = pktp;
327
	GETSHORT(coher_cnt, pktp);
328
329
	flushed = (coher_cnt & 0x8000)? 1 : 0;
330
	encrypt = (coher_cnt & 0x1000)? 1 : 0;
331
	coher_cnt &= COHERENCY_CNT_MASK;
332
	pktloss = 0;
333
334
	MPPE_DBG((_this, DEBUG_LEVEL_2, "in coher_cnt=%03x/%03x %s%s",
335
	    _this->recv.coher_cnt, coher_cnt, (flushed)? "[flushed]" : "",
336
	    (encrypt)? "[encrypt]" : ""));
337
338
	if (encrypt == 0) {
339
		mppe_log(_this, LOG_WARNING,
340
		    "Received unexpected MPPE packet.  (no encrypt)");
341
		return;
342
	}
343
344
	/*
345
	 * In L2TP/IPsec implementation, in case that the ppp frame sequence
346
	 * is not able to reconstruct and the ppp frame is out of sequence, it
347
	 * is unable to identify with many packets losing. If it does so, MPPE
348
	 * key is out of place.
349
	 * To avoid this problem, when it seems that more than 4096-256 packets
350
	 * drops, it assumes that the packet doesn't lose but the packet is out
351
	 * of sequence.
352
	 */
353
    {
354
	int coher_cnt0;
355
356
	coher_cnt0 = coher_cnt;
357
	if (coher_cnt < _this->recv.coher_cnt)
358
		coher_cnt0 += 0x1000;
359
	if (coher_cnt0 - _this->recv.coher_cnt > 0x0f00) {
360
		if (!_this->recv.stateless ||
361
		    coher_cnt0 - _this->recv.coher_cnt
362
		    <= 0x1000 - MPPE_NOLDKEY) {
363
			mppe_log(_this, LOG_INFO,
364
			    "Workaround the out-of-sequence PPP framing problem: "
365
			    "%d => %d", _this->recv.coher_cnt, coher_cnt);
366
			return;
367
		}
368
		delayed = 1;
369
	}
370
    }
371
372
	if (_this->recv.stateless != 0) {
373
		if (!delayed) {
374
			mppe_key_change(_this, &_this->recv);
375
			while (_this->recv.coher_cnt != coher_cnt) {
376
				_this->recv.coher_cnt++;
377
				_this->recv.coher_cnt &= COHERENCY_CNT_MASK;
378
				mppe_key_change(_this, &_this->recv);
379
				pktloss++;
380
			}
381
		}
382
		mppe_rc4_setoldkey(_this, &_this->recv, coher_cnt);
383
		flushed = 1;
384
	} else {
385
		if (flushed) {
386
			if (coher_cnt < _this->recv.coher_cnt) {
387
				/* in case of carrying up. */
388
				coher_cnt += 0x1000;
389
			}
390
			pktloss += coher_cnt - _this->recv.coher_cnt;
391
			m = _this->recv.coher_cnt / 256;
392
			n = coher_cnt / 256;
393
			while (m++ < n)
394
				mppe_key_change(_this, &_this->recv);
395
396
			coher_cnt &= COHERENCY_CNT_MASK;
397
			_this->recv.coher_cnt = coher_cnt;
398
		} else if (_this->recv.coher_cnt != coher_cnt) {
399
			_this->recv.resetreq = 1;
400
401
			opktp0 = ppp_packetbuf(_this->ppp,
402
			    PPP_PROTO_NCP | NCP_CCP);
403
			opktp = opktp0;
404
405
			PUTLONG(_this->ppp->ccp.mppe_p_bits, opktp);
406
407
			ppp_output(_this->ppp, PPP_PROTO_NCP | NCP_CCP,
408
			    RESETREQ, _this->recv.resetreq, opktp0,
409
				opktp - opktp0);
410
			return;
411
		}
412
		if ((coher_cnt & 0xff) == 0xff) {
413
			mppe_key_change(_this, &_this->recv);
414
			flushed = 1;
415
		}
416
		if (flushed) {
417
			mppe_rc4_setkey(_this, &_this->recv);
418
		}
419
	}
420
421
	if (pktloss > 1000) {
422
		/*
423
		 * In case of many packets losing or out of sequence.
424
		 * The latter is not able to communicate because the key is
425
		 * out of place soon.
426
		 *
427
		 */
428
		mppe_log(_this, LOG_WARNING, "%d packets loss", pktloss);
429
	}
430
431
	mppe_rc4_encrypt(_this, &_this->recv, len - 2, pktp, pktp);
432
433
	if (!delayed) {
434
		_this->recv.coher_cnt++;
435
		_this->recv.coher_cnt &= COHERENCY_CNT_MASK;
436
	}
437
438
	if (pktp[0] & 1)
439
		proto = pktp[0];
440
	else
441
		proto = pktp[0] << 8 | pktp[1];
442
	/*
443
	 * According to RFC3078 section 3,
444
	 * MPPE only accept protocol number 0021-00FA.
445
	 * If decrypted protocol number is out of range,
446
	 * it indicates loss of coherency.
447
	 */
448
	if (!(proto & 1) || proto < 0x21 || proto > 0xfa) {
449
		mppe_log(_this, LOG_INFO, "MPPE coherency is lost");
450
		return; /* drop frame */
451
	}
452
453
	_this->ppp->recv_packet(_this->ppp, pktp, len - 2,
454
	    PPP_IO_FLAGS_MPPE_ENCRYPTED);
455
}
456
457
/**
458
 * The call out function in case of receiving CCP Reset (key reset in case
459
 * of MPPE).
460
 */
461
void
462
mppe_recv_ccp_reset(mppe *_this)
463
{
464
	MPPE_DBG((_this, DEBUG_LEVEL_2, "%s() is called.", __func__));
465
	_this->send.resetreq = 1;
466
}
467
468
/**
469
 * sending packet via MPPE.
470
 */
471
void
472
mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len)
473
{
474
	int encrypt, flushed;
475
	uint16_t coher_cnt;
476
	u_char *outp, *outp0;
477
478
	MPPE_ASSERT(proto == PPP_PROTO_IP);
479
480
	flushed = 0;
481
	encrypt = 1;
482
483
	outp = ppp_packetbuf(_this->ppp, PPP_PROTO_MPPE);
484
	outp0 = outp;
485
486
	if (_this->send.stateless != 0) {
487
		flushed = 1;
488
		mppe_key_change(_this, &_this->send);
489
	} else {
490
		if ((_this->send.coher_cnt % 0x100) == 0xff) {
491
			flushed = 1;
492
			mppe_key_change(_this, &_this->send);
493
		} else if (_this->send.resetreq != 0) {
494
			flushed = 1;
495
			_this->send.resetreq = 0;
496
		}
497
	}
498
499
	if (flushed) {
500
		mppe_rc4_setkey(_this, &_this->send);
501
	}
502
503
	MPPE_DBG((_this, DEBUG_LEVEL_2, "out coher_cnt=%03x %s%s",
504
	    _this->send.coher_cnt, (flushed)? "[flushed]" : "",
505
	    (encrypt)? "[encrypt]" : ""));
506
507
	coher_cnt = _this->send.coher_cnt & COHERENCY_CNT_MASK;
508
	if (flushed)
509
		coher_cnt |= 0x8000;
510
	if (encrypt)
511
		coher_cnt |= 0x1000;
512
513
	PUTSHORT(coher_cnt, outp);
514
	proto = htons(proto);
515
	mppe_rc4_encrypt(_this, &_this->send, 2, (u_char *)&proto, outp);
516
	mppe_rc4_encrypt(_this, &_this->send, len, pktp, outp + 2);
517
518
	ppp_output(_this->ppp, PPP_PROTO_MPPE, 0, 0, outp0, len + 4);
519
	_this->send.coher_cnt++;
520
	_this->send.coher_cnt &= COHERENCY_CNT_MASK;
521
}
522
523
static void
524
mppe_log(mppe *_this, uint32_t prio, const char *fmt, ...)
525
{
526
	char logbuf[BUFSIZ];
527
	va_list ap;
528
529
	va_start(ap, fmt);
530
	snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=mppe %s",
531
	    _this->ppp->id, fmt);
532
	vlog_printf(prio, logbuf, ap);
533
	va_end(ap);
534
}
535
536
static const char *
537
mppe_bits_to_string(uint32_t bits)
538
{
539
	static char buf[128];
540
541
	snprintf(buf, sizeof(buf), "%s%s%s%s%s%s"
542
	, ((CCP_MPPC_ALONE & bits) != 0)?	",mppc" : ""
543
	, ((CCP_MPPE_LM_40bit& bits) != 0)?	",40bit(LM)" : ""
544
	, ((CCP_MPPE_NT_40bit& bits) != 0)?	",40bit" : ""
545
	, ((CCP_MPPE_NT_128bit& bits) != 0)?	",128bit" : ""
546
	, ((CCP_MPPE_NT_56bit& bits) != 0)?	",56bit" : ""
547
	, ((CCP_MPPE_STATELESS& bits) != 0)?	",stateless" : ",stateful");
548
549
	if (buf[0] == '\0')
550
		return "";
551
552
	return buf + 1;
553
}
554
555
/************************************************************************
556
 * implementations of authentication/cipher algorism.
557
 ************************************************************************/
558
static u_char SHAPad1[] = {
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
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564
}, SHAPad2[] = {
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
	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
570
};
571
#define	ZeroMemory(dst, len)		memset(dst, 0, len)
572
#define	MoveMemory(dst, src, len)	memcpy(dst, src, len)
573
574
#include <openssl/rc4.h>
575
#include <openssl/sha.h>
576
577
#define	SHA_CTX			SHA_CTX
578
#define	SHAInit			SHA1_Init
579
#define	SHAUpdate		SHA1_Update
580
#define	SHAFinal(ctx,digest)	SHA1_Final(digest, ctx)
581
582
/************************************************************************
583
 * implementations of OpenSSL version
584
 ************************************************************************/
585
static void *
586
rc4_create_ctx(void)
587
{
588
	return malloc(sizeof(RC4_KEY));
589
}
590
591
static int
592
rc4_key(void *rc4ctx, int lkey, u_char *key)
593
{
594
595
	RC4_set_key(rc4ctx, lkey, key);
596
597
	return 0;
598
}
599
600
static void
601
rc4(void *rc4ctx, int len, u_char *indata, u_char *outdata)
602
{
603
	RC4(rc4ctx, len, indata, outdata);
604
}
605
606
static void
607
GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
608
    u_char *InterimKey)
609
{
610
	u_char Digest[20];
611
	SHA_CTX Context;
612
613
	ZeroMemory(Digest, 20);
614
615
	SHAInit(&Context);
616
	SHAUpdate(&Context, StartKey, SessionKeyLength);
617
	SHAUpdate(&Context, SHAPad1, 40);
618
	SHAUpdate(&Context, SessionKey, SessionKeyLength);
619
	SHAUpdate(&Context, SHAPad2, 40);
620
	SHAFinal(&Context, Digest);
621
622
	MoveMemory(InterimKey, Digest, SessionKeyLength);
623
}
624
625
static int
626
mppe_rc4_init(mppe *_mppe, mppe_rc4_t *_this, int has_oldkey)
627
{
628
	if ((_this->rc4ctx = rc4_create_ctx()) == NULL) {
629
		mppe_log(_mppe, LOG_ERR, "malloc() failed at %s: %m",
630
		    __func__);
631
		return 1;
632
	}
633
634
	if (has_oldkey)
635
		_this->old_session_keys = reallocarray(NULL,
636
		    MPPE_KEYLEN, MPPE_NOLDKEY);
637
	else
638
		_this->old_session_keys = NULL;
639
640
	return 0;
641
}
642
643
static int
644
mppe_rc4_setkey(mppe *_mppe, mppe_rc4_t *_this)
645
{
646
	return rc4_key(_this->rc4ctx, _this->keylen, _this->session_key);
647
}
648
649
static int
650
mppe_rc4_setoldkey(mppe *_mppe, mppe_rc4_t *_this, uint16_t coher_cnt)
651
{
652
	return rc4_key(_this->rc4ctx, _this->keylen,
653
	    _this->old_session_keys[coher_cnt % MPPE_NOLDKEY]);
654
}
655
656
static void
657
mppe_rc4_encrypt(mppe *_mppe, mppe_rc4_t *_this, int len, u_char *indata, u_char *outdata)
658
{
659
	rc4(_this->rc4ctx, len, indata, outdata);
660
}
661
662
static void
663
mppe_rc4_destroy(mppe *_mppe, mppe_rc4_t *_this)
664
{
665
	free(_this->rc4ctx);
666
	free(_this->old_session_keys);
667
	_this->rc4ctx = NULL;
668
}