summaryrefslogtreecommitdiffstats
path: root/usr.sbin/xntpd/lib/authdecrypt.c
blob: 7462941bf662bb8650077b9de14ebb9117ec2377 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * authdecrypt - routine to decrypt a packet to see if this guy knows our key.
 */
#include "ntp_stdlib.h"

/*
 * For our purposes an NTP packet looks like:
 *
 *	a variable amount of unencrypted data, multiple of 8 bytes, followed by:
 *	NOCRYPT_OCTETS worth of unencrypted data, followed by:
 *	BLOCK_OCTETS worth of ciphered checksum.
 */ 
#define	NOCRYPT_OCTETS	4
#define	BLOCK_OCTETS	8

#define	NOCRYPT_LONGS	((NOCRYPT_OCTETS)/sizeof(U_LONG))
#define	BLOCK_LONGS	((BLOCK_OCTETS)/sizeof(U_LONG))

/*
 * Imported from the key data base module
 */
extern u_long cache_keyid;	/* cached key ID */
extern u_char DEScache_dkeys[];	/* cached decryption keys */
extern u_char DESzerodkeys[];	/* zero key decryption keys */

/*
 * Stat counters, imported from data base module
 */
extern U_LONG authdecryptions;
extern U_LONG authkeyuncached;

int
DESauthdecrypt(keyno, pkt, length)
	u_long keyno;
	const U_LONG *pkt;
	int length;	/* length of variable data in octets */
{
	register const U_LONG *pd;
	register int i;
	register u_char *keys;
	register int longlen;
	U_LONG work[2];

	authdecryptions++;
	
	if (keyno == 0)
		keys = DESzerodkeys;
	else {
		if (keyno != cache_keyid) {
			authkeyuncached++;
			if (!authhavekey(keyno))
				return 0;
		}
		keys = DEScache_dkeys;
	}

	/*
	 * Get encryption block data in host byte order and decrypt it.
	 */
	longlen = length / sizeof(U_LONG);
	pd = pkt + longlen;		/* points at NOCRYPT area */
	work[0] = *(pd + NOCRYPT_LONGS);
	work[1] = *(pd + NOCRYPT_LONGS + 1);

	if (longlen & 0x1) {
		DESauth_des(work, keys);
		work[0] ^= *(--pd);
	}

	for (i = longlen/2; i > 0; i--) {
		DESauth_des(work, keys);
		work[1] ^= *(--pd);
		work[0] ^= *(--pd);
	}

	/*
	 * Success if the encryption data is zero
	 */
	if ((work[0] == 0) && (work[1] == 0))
		return 1;
	return 0;
}
OpenPOWER on IntegriCloud