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