aboutsummaryrefslogtreecommitdiff
path: root/contrib/ntp/libntp/authusekey.c
blob: 18b8ba00ecab1ce3afe3382d5c8b37e30a067e2f (plain) (blame)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * authusekey - decode a key from ascii and use it
 */
#include <stdio.h>
#include <ctype.h>

#include "ntp_types.h"
#include "ntp_string.h"
#include "ntp_stdlib.h"

/*
 * Types of ascii representations for keys.  "Standard" means a 64 bit
 * hex number in NBS format, i.e. with the low order bit of each byte
 * a parity bit.  "NTP" means a 64 bit key in NTP format, with the
 * high order bit of each byte a parity bit.  "Ascii" means a 1-to-8
 * character string whose ascii representation is used as the key.
 */
#ifdef	DES
#define	KEY_TYPE_STD	1
#define	KEY_TYPE_NTP	2
#define	KEY_TYPE_ASCII	3

#define	STD_PARITY_BITS	((unsigned)0x01010101)

#endif

#define	KEY_TYPE_MD5	4

int
authusekey(
	keyid_t keyno,
	int keytype,
	const u_char *str
	)
{
#ifdef DES
	u_int32 key[2];
	u_char keybytes[8];
	char *xdigit;
	int i;
	static const char *hex = "0123456789abcdef";
#endif
	const u_char *cp;
	int len;

	cp = str;
	len = strlen((const char *)cp);
	if (len == 0)
	    return 0;

	switch(keytype) {
#ifdef	DES
	    case KEY_TYPE_STD:
	    case KEY_TYPE_NTP:
		if (len != 16)		/* Lazy.  Should define constant */
		    return 0;
		/*
		 * Decode hex key.
		 */
		key[0] = 0;
		key[1] = 0;
		for (i = 0; i < 16; i++) {
			if (!isascii(*cp))
			    return 0;
			xdigit = strchr(hex, isupper(*cp) ? tolower(*cp) : *cp);
			cp++;
			if (xdigit == 0)
			    return 0;
			key[i>>3] <<= 4;
			key[i>>3] |= (u_int32)(xdigit - hex) & 0xf;
		}

		/*
		 * If this is an NTP format key, put it into NBS format
		 */
		if (keytype == KEY_TYPE_NTP) {
			for (i = 0; i < 2; i++)
			    key[i] = ((key[i] << 1) & ~STD_PARITY_BITS)
				    | ((key[i] >> 7) & STD_PARITY_BITS);
		}

		/*
		 * Check the parity, reject the key if the check fails
		 */
		if (!DESauth_parity(key)) {
			return 0;
		}
		
		/*
		 * We can't find a good reason not to use this key.
		 * So use it.
		 */
		DESauth_setkey(keyno, key);
		break;
	
	    case KEY_TYPE_ASCII:
		/*
		 * Make up key from ascii representation
		 */
		memset((char *) keybytes, 0, sizeof(keybytes));
		for (i = 0; i < 8 && i < len; i++)
		    keybytes[i] = *cp++ << 1;
		key[0] = (u_int32)keybytes[0] << 24 | (u_int32)keybytes[1] << 16
			| (u_int32)keybytes[2] << 8 | (u_int32)keybytes[3];
		key[1] = (u_int32)keybytes[4] << 24 | (u_int32)keybytes[5] << 16
			| (u_int32)keybytes[6] << 8 | (u_int32)keybytes[7];
		
		/*
		 * Set parity on key
		 */
		(void)DESauth_parity(key);

		/*
		 * Now set key in.
		 */
		DESauth_setkey(keyno, key);
		break;
#endif

	    case KEY_TYPE_MD5:
		MD5auth_setkey(keyno, str, (int)strlen((const char *)str));
		break;

	    default:
		/* Oh, well */
		return 0;
	}

	return 1;
}