Initial import from FreeBSD RELENG_4:
[games.git] / contrib / ntp / libntp / authusekey.c
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 }