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