xref: /freebsd/contrib/ntp/libntp/authusekey.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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 #ifdef	MD5
28 #define	KEY_TYPE_MD5	4
29 #endif
30 
31 int
32 authusekey(
33 	u_long keyno,
34 	int keytype,
35 	const u_char *str
36 	)
37 {
38 #ifdef DES
39 	u_int32 key[2];
40 	u_char keybytes[8];
41 	char *xdigit;
42 	int i;
43 	static const char *hex = "0123456789abcdef";
44 #endif
45 	const u_char *cp;
46 	int len;
47 
48 	cp = str;
49 	len = strlen((const char *)cp);
50 	if (len == 0)
51 	    return 0;
52 
53 	switch(keytype) {
54 #ifdef	DES
55 	    case KEY_TYPE_STD:
56 	    case KEY_TYPE_NTP:
57 		if (len != 16)		/* Lazy.  Should define constant */
58 		    return 0;
59 		/*
60 		 * Decode hex key.
61 		 */
62 		key[0] = 0;
63 		key[1] = 0;
64 		for (i = 0; i < 16; i++) {
65 			if (!isascii(*cp))
66 			    return 0;
67 			xdigit = strchr(hex, isupper(*cp) ? tolower(*cp) : *cp);
68 			cp++;
69 			if (xdigit == 0)
70 			    return 0;
71 			key[i>>3] <<= 4;
72 			key[i>>3] |= (u_int32)(xdigit - hex) & 0xf;
73 		}
74 
75 		/*
76 		 * If this is an NTP format key, put it into NBS format
77 		 */
78 		if (keytype == KEY_TYPE_NTP) {
79 			for (i = 0; i < 2; i++)
80 			    key[i] = ((key[i] << 1) & ~STD_PARITY_BITS)
81 				    | ((key[i] >> 7) & STD_PARITY_BITS);
82 		}
83 
84 		/*
85 		 * Check the parity, reject the key if the check fails
86 		 */
87 		if (!DESauth_parity(key)) {
88 			return 0;
89 		}
90 
91 		/*
92 		 * We can't find a good reason not to use this key.
93 		 * So use it.
94 		 */
95 		DESauth_setkey(keyno, key);
96 		break;
97 
98 	    case KEY_TYPE_ASCII:
99 		/*
100 		 * Make up key from ascii representation
101 		 */
102 		memset((char *) keybytes, 0, sizeof(keybytes));
103 		for (i = 0; i < 8 && i < len; i++)
104 		    keybytes[i] = *cp++ << 1;
105 		key[0] = (u_int32)keybytes[0] << 24 | (u_int32)keybytes[1] << 16
106 			| (u_int32)keybytes[2] << 8 | (u_int32)keybytes[3];
107 		key[1] = (u_int32)keybytes[4] << 24 | (u_int32)keybytes[5] << 16
108 			| (u_int32)keybytes[6] << 8 | (u_int32)keybytes[7];
109 
110 		/*
111 		 * Set parity on key
112 		 */
113 		(void)DESauth_parity(key);
114 
115 		/*
116 		 * Now set key in.
117 		 */
118 		DESauth_setkey(keyno, key);
119 		break;
120 #endif
121 
122 #ifdef	MD5
123 	    case KEY_TYPE_MD5:
124 		MD5auth_setkey(keyno, str, (int)strlen((const char *)str));
125 		break;
126 #endif
127 
128 	    default:
129 		/* Oh, well */
130 		return 0;
131 	}
132 
133 	return 1;
134 }
135