1 #include <config.h> 2 #include "crypto.h" 3 #include <ctype.h> 4 #include "isc/string.h" 5 6 struct key *key_ptr; 7 size_t key_cnt = 0; 8 9 int 10 make_mac( 11 const void *pkt_data, 12 int pkt_size, 13 int mac_size, 14 const struct key *cmp_key, 15 void * digest 16 ) 17 { 18 u_int len = mac_size; 19 int key_type; 20 EVP_MD_CTX ctx; 21 22 if (cmp_key->key_len > 64) 23 return 0; 24 if (pkt_size % 4 != 0) 25 return 0; 26 27 INIT_SSL(); 28 key_type = keytype_from_text(cmp_key->type, NULL); 29 EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); 30 EVP_DigestUpdate(&ctx, (const u_char *)cmp_key->key_seq, (u_int)cmp_key->key_len); 31 EVP_DigestUpdate(&ctx, pkt_data, (u_int)pkt_size); 32 EVP_DigestFinal(&ctx, digest, &len); 33 34 return (int)len; 35 } 36 37 38 /* Generates a md5 digest of the key specified in keyid concatenated with the 39 * ntp packet (exluding the MAC) and compares this digest to the digest in 40 * the packet's MAC. If they're equal this function returns 1 (packet is 41 * authentic) or else 0 (not authentic). 42 */ 43 int 44 auth_md5( 45 const void *pkt_data, 46 int pkt_size, 47 int mac_size, 48 const struct key *cmp_key 49 ) 50 { 51 int hash_len; 52 int authentic; 53 char digest[20]; 54 const u_char *pkt_ptr; 55 if (mac_size > (int)sizeof(digest)) 56 return 0; 57 pkt_ptr = pkt_data; 58 hash_len = make_mac(pkt_ptr, pkt_size, sizeof(digest), cmp_key, 59 digest); 60 if (!hash_len) { 61 authentic = FALSE; 62 } else { 63 /* isc_tsmemcmp will be better when its easy to link 64 * with. sntp is a 1-shot program, so snooping for 65 * timing attacks is Harder. 66 */ 67 authentic = !memcmp(digest, pkt_data + pkt_size + 4, 68 hash_len); 69 } 70 return authentic; 71 } 72 73 static int 74 hex_val( 75 unsigned char x 76 ) 77 { 78 int val; 79 80 if ('0' <= x && x <= '9') 81 val = x - '0'; 82 else if ('a' <= x && x <= 'f') 83 val = x - 'a' + 0xa; 84 else if ('A' <= x && x <= 'F') 85 val = x - 'A' + 0xA; 86 else 87 val = -1; 88 89 return val; 90 } 91 92 /* Load keys from the specified keyfile into the key structures. 93 * Returns -1 if the reading failed, otherwise it returns the 94 * number of keys it read 95 */ 96 int 97 auth_init( 98 const char *keyfile, 99 struct key **keys 100 ) 101 { 102 FILE *keyf = fopen(keyfile, "r"); 103 struct key *prev = NULL; 104 int scan_cnt, line_cnt = 0; 105 char kbuf[200]; 106 char keystring[129]; 107 108 if (keyf == NULL) { 109 if (debug) 110 printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 111 return -1; 112 } 113 if (feof(keyf)) { 114 if (debug) 115 printf("sntp auth_init: Key file %s is empty!\n", keyfile); 116 fclose(keyf); 117 return -1; 118 } 119 key_cnt = 0; 120 while (!feof(keyf)) { 121 char * octothorpe; 122 struct key *act; 123 int goodline = 0; 124 125 if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 126 continue; 127 128 kbuf[sizeof(kbuf) - 1] = '\0'; 129 octothorpe = strchr(kbuf, '#'); 130 if (octothorpe) 131 *octothorpe = '\0'; 132 act = emalloc(sizeof(*act)); 133 scan_cnt = sscanf(kbuf, "%d %9s %128s", &act->key_id, act->type, keystring); 134 if (scan_cnt == 3) { 135 int len = strlen(keystring); 136 if (len <= 20) { 137 act->key_len = len; 138 memcpy(act->key_seq, keystring, len + 1); 139 goodline = 1; 140 } else if ((len & 1) != 0) { 141 goodline = 0; /* it's bad */ 142 } else { 143 int j; 144 goodline = 1; 145 act->key_len = len >> 1; 146 for (j = 0; j < len; j+=2) { 147 int val; 148 val = (hex_val(keystring[j]) << 4) | 149 hex_val(keystring[j+1]); 150 if (val < 0) { 151 goodline = 0; /* it's bad */ 152 break; 153 } 154 act->key_seq[j>>1] = (char)val; 155 } 156 } 157 } 158 if (goodline) { 159 act->next = NULL; 160 if (NULL == prev) 161 *keys = act; 162 else 163 prev->next = act; 164 prev = act; 165 key_cnt++; 166 } else { 167 msyslog(LOG_DEBUG, "auth_init: scanf %d items, skipping line %d.", 168 scan_cnt, line_cnt); 169 free(act); 170 } 171 line_cnt++; 172 } 173 fclose(keyf); 174 175 key_ptr = *keys; 176 return key_cnt; 177 } 178 179 /* Looks for the key with keyid key_id and sets the d_key pointer to the 180 * address of the key. If no matching key is found the pointer is not touched. 181 */ 182 void 183 get_key( 184 int key_id, 185 struct key **d_key 186 ) 187 { 188 struct key *itr_key; 189 190 if (key_cnt == 0) 191 return; 192 for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 193 if (itr_key->key_id == key_id) { 194 *d_key = itr_key; 195 break; 196 } 197 } 198 return; 199 } 200