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