xref: /freebsd/contrib/ntp/libntp/authusekey.c (revision b52b9d56d4e96089873a75f9e29062eec19fabba)
1 /*
2  * authusekey - decode a key from ascii and use it
3  */
4 #include <stdio.h>
5 #include <ctype.h>
6 
7 #include "ntp_types.h"
8 #include "ntp_string.h"
9 #include "ntp_stdlib.h"
10 
11 /*
12  * Types of ascii representations for keys.  "Standard" means a 64 bit
13  * hex number in NBS format, i.e. with the low order bit of each byte
14  * a parity bit.  "NTP" means a 64 bit key in NTP format, with the
15  * high order bit of each byte a parity bit.  "Ascii" means a 1-to-8
16  * character string whose ascii representation is used as the key.
17  */
18 #ifdef	DES
19 #define	KEY_TYPE_STD	1
20 #define	KEY_TYPE_NTP	2
21 #define	KEY_TYPE_ASCII	3
22 
23 #define	STD_PARITY_BITS	((unsigned)0x01010101)
24 
25 #endif
26 
27 #define	KEY_TYPE_MD5	4
28 
29 int
30 authusekey(
31 	keyid_t keyno,
32 	int keytype,
33 	const u_char *str
34 	)
35 {
36 #ifdef DES
37 	u_int32 key[2];
38 	u_char keybytes[8];
39 	char *xdigit;
40 	int i;
41 	static const char *hex = "0123456789abcdef";
42 #endif
43 	const u_char *cp;
44 	int len;
45 
46 	cp = str;
47 	len = strlen((const char *)cp);
48 	if (len == 0)
49 	    return 0;
50 
51 	switch(keytype) {
52 #ifdef	DES
53 	    case KEY_TYPE_STD:
54 	    case KEY_TYPE_NTP:
55 		if (len != 16)		/* Lazy.  Should define constant */
56 		    return 0;
57 		/*
58 		 * Decode hex key.
59 		 */
60 		key[0] = 0;
61 		key[1] = 0;
62 		for (i = 0; i < 16; i++) {
63 			if (!isascii(*cp))
64 			    return 0;
65 			xdigit = strchr(hex, isupper(*cp) ? tolower(*cp) : *cp);
66 			cp++;
67 			if (xdigit == 0)
68 			    return 0;
69 			key[i>>3] <<= 4;
70 			key[i>>3] |= (u_int32)(xdigit - hex) & 0xf;
71 		}
72 
73 		/*
74 		 * If this is an NTP format key, put it into NBS format
75 		 */
76 		if (keytype == KEY_TYPE_NTP) {
77 			for (i = 0; i < 2; i++)
78 			    key[i] = ((key[i] << 1) & ~STD_PARITY_BITS)
79 				    | ((key[i] >> 7) & STD_PARITY_BITS);
80 		}
81 
82 		/*
83 		 * Check the parity, reject the key if the check fails
84 		 */
85 		if (!DESauth_parity(key)) {
86 			return 0;
87 		}
88 
89 		/*
90 		 * We can't find a good reason not to use this key.
91 		 * So use it.
92 		 */
93 		DESauth_setkey(keyno, key);
94 		break;
95 
96 	    case KEY_TYPE_ASCII:
97 		/*
98 		 * Make up key from ascii representation
99 		 */
100 		memset((char *) keybytes, 0, sizeof(keybytes));
101 		for (i = 0; i < 8 && i < len; i++)
102 		    keybytes[i] = *cp++ << 1;
103 		key[0] = (u_int32)keybytes[0] << 24 | (u_int32)keybytes[1] << 16
104 			| (u_int32)keybytes[2] << 8 | (u_int32)keybytes[3];
105 		key[1] = (u_int32)keybytes[4] << 24 | (u_int32)keybytes[5] << 16
106 			| (u_int32)keybytes[6] << 8 | (u_int32)keybytes[7];
107 
108 		/*
109 		 * Set parity on key
110 		 */
111 		(void)DESauth_parity(key);
112 
113 		/*
114 		 * Now set key in.
115 		 */
116 		DESauth_setkey(keyno, key);
117 		break;
118 #endif
119 
120 	    case KEY_TYPE_MD5:
121 		MD5auth_setkey(keyno, str, (int)strlen((const char *)str));
122 		break;
123 
124 	    default:
125 		/* Oh, well */
126 		return 0;
127 	}
128 
129 	return 1;
130 }
131