1258945Sroberto#include <config.h> 2258945Sroberto#include "crypto.h" 3258945Sroberto#include <ctype.h> 4298695Sdelphij#include "isc/string.h" 5316722Sdelphij#include "ntp_md5.h" 6258945Sroberto 7258945Srobertostruct key *key_ptr; 8280849Scysize_t key_cnt = 0; 9258945Sroberto 10258945Srobertoint 11258945Srobertomake_mac( 12294554Sdelphij const void *pkt_data, 13258945Sroberto int pkt_size, 14258945Sroberto int mac_size, 15294554Sdelphij const struct key *cmp_key, 16294554Sdelphij void * digest 17258945Sroberto ) 18258945Sroberto{ 19258945Sroberto u_int len = mac_size; 20258945Sroberto int key_type; 21310419Sdelphij EVP_MD_CTX * ctx; 22258945Sroberto 23258945Sroberto if (cmp_key->key_len > 64) 24258945Sroberto return 0; 25258945Sroberto if (pkt_size % 4 != 0) 26258945Sroberto return 0; 27258945Sroberto 28258945Sroberto INIT_SSL(); 29258945Sroberto key_type = keytype_from_text(cmp_key->type, NULL); 30310419Sdelphij 31310419Sdelphij ctx = EVP_MD_CTX_new(); 32310419Sdelphij EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); 33310419Sdelphij EVP_DigestUpdate(ctx, (const u_char *)cmp_key->key_seq, (u_int)cmp_key->key_len); 34310419Sdelphij EVP_DigestUpdate(ctx, pkt_data, (u_int)pkt_size); 35310419Sdelphij EVP_DigestFinal(ctx, digest, &len); 36310419Sdelphij EVP_MD_CTX_free(ctx); 37310419Sdelphij 38258945Sroberto return (int)len; 39258945Sroberto} 40258945Sroberto 41258945Sroberto 42294554Sdelphij/* Generates a md5 digest of the key specified in keyid concatenated with the 43258945Sroberto * ntp packet (exluding the MAC) and compares this digest to the digest in 44258945Sroberto * the packet's MAC. If they're equal this function returns 1 (packet is 45258945Sroberto * authentic) or else 0 (not authentic). 46258945Sroberto */ 47258945Srobertoint 48258945Srobertoauth_md5( 49294554Sdelphij const void *pkt_data, 50258945Sroberto int pkt_size, 51258945Sroberto int mac_size, 52294554Sdelphij const struct key *cmp_key 53258945Sroberto ) 54258945Sroberto{ 55258945Sroberto int hash_len; 56258945Sroberto int authentic; 57258945Sroberto char digest[20]; 58294554Sdelphij const u_char *pkt_ptr; 59280849Scy if (mac_size > (int)sizeof(digest)) 60258945Sroberto return 0; 61294554Sdelphij pkt_ptr = pkt_data; 62294554Sdelphij hash_len = make_mac(pkt_ptr, pkt_size, sizeof(digest), cmp_key, 63258945Sroberto digest); 64298695Sdelphij if (!hash_len) { 65258945Sroberto authentic = FALSE; 66298695Sdelphij } else { 67298695Sdelphij /* isc_tsmemcmp will be better when its easy to link 68298695Sdelphij * with. sntp is a 1-shot program, so snooping for 69298695Sdelphij * timing attacks is Harder. 70298695Sdelphij */ 71310419Sdelphij authentic = !memcmp(digest, (const char*)pkt_data + pkt_size + 4, 72258945Sroberto hash_len); 73298695Sdelphij } 74258945Sroberto return authentic; 75258945Sroberto} 76258945Sroberto 77258945Srobertostatic int 78258945Srobertohex_val( 79258945Sroberto unsigned char x 80258945Sroberto ) 81258945Sroberto{ 82258945Sroberto int val; 83258945Sroberto 84258945Sroberto if ('0' <= x && x <= '9') 85258945Sroberto val = x - '0'; 86258945Sroberto else if ('a' <= x && x <= 'f') 87258945Sroberto val = x - 'a' + 0xa; 88258945Sroberto else if ('A' <= x && x <= 'F') 89258945Sroberto val = x - 'A' + 0xA; 90258945Sroberto else 91258945Sroberto val = -1; 92258945Sroberto 93258945Sroberto return val; 94258945Sroberto} 95258945Sroberto 96258945Sroberto/* Load keys from the specified keyfile into the key structures. 97258945Sroberto * Returns -1 if the reading failed, otherwise it returns the 98258945Sroberto * number of keys it read 99258945Sroberto */ 100258945Srobertoint 101258945Srobertoauth_init( 102258945Sroberto const char *keyfile, 103258945Sroberto struct key **keys 104258945Sroberto ) 105258945Sroberto{ 106258945Sroberto FILE *keyf = fopen(keyfile, "r"); 107258945Sroberto struct key *prev = NULL; 108258945Sroberto int scan_cnt, line_cnt = 0; 109258945Sroberto char kbuf[200]; 110258945Sroberto char keystring[129]; 111258945Sroberto 112258945Sroberto if (keyf == NULL) { 113280849Scy if (debug) 114258945Sroberto printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 115258945Sroberto return -1; 116258945Sroberto } 117258945Sroberto if (feof(keyf)) { 118280849Scy if (debug) 119258945Sroberto printf("sntp auth_init: Key file %s is empty!\n", keyfile); 120258945Sroberto fclose(keyf); 121258945Sroberto return -1; 122258945Sroberto } 123258945Sroberto key_cnt = 0; 124258945Sroberto while (!feof(keyf)) { 125258945Sroberto char * octothorpe; 126280849Scy struct key *act; 127258945Sroberto int goodline = 0; 128258945Sroberto 129258945Sroberto if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 130258945Sroberto continue; 131258945Sroberto 132258945Sroberto kbuf[sizeof(kbuf) - 1] = '\0'; 133258945Sroberto octothorpe = strchr(kbuf, '#'); 134258945Sroberto if (octothorpe) 135258945Sroberto *octothorpe = '\0'; 136280849Scy act = emalloc(sizeof(*act)); 137258945Sroberto scan_cnt = sscanf(kbuf, "%d %9s %128s", &act->key_id, act->type, keystring); 138258945Sroberto if (scan_cnt == 3) { 139258945Sroberto int len = strlen(keystring); 140258945Sroberto if (len <= 20) { 141258945Sroberto act->key_len = len; 142258945Sroberto memcpy(act->key_seq, keystring, len + 1); 143258945Sroberto goodline = 1; 144258945Sroberto } else if ((len & 1) != 0) { 145258945Sroberto goodline = 0; /* it's bad */ 146258945Sroberto } else { 147258945Sroberto int j; 148258945Sroberto goodline = 1; 149258945Sroberto act->key_len = len >> 1; 150258945Sroberto for (j = 0; j < len; j+=2) { 151258945Sroberto int val; 152258945Sroberto val = (hex_val(keystring[j]) << 4) | 153258945Sroberto hex_val(keystring[j+1]); 154258945Sroberto if (val < 0) { 155258945Sroberto goodline = 0; /* it's bad */ 156258945Sroberto break; 157258945Sroberto } 158258945Sroberto act->key_seq[j>>1] = (char)val; 159258945Sroberto } 160258945Sroberto } 161258945Sroberto } 162258945Sroberto if (goodline) { 163258945Sroberto act->next = NULL; 164258945Sroberto if (NULL == prev) 165258945Sroberto *keys = act; 166258945Sroberto else 167258945Sroberto prev->next = act; 168258945Sroberto prev = act; 169258945Sroberto key_cnt++; 170258945Sroberto } else { 171258945Sroberto msyslog(LOG_DEBUG, "auth_init: scanf %d items, skipping line %d.", 172258945Sroberto scan_cnt, line_cnt); 173258945Sroberto free(act); 174258945Sroberto } 175258945Sroberto line_cnt++; 176258945Sroberto } 177258945Sroberto fclose(keyf); 178258945Sroberto 179258945Sroberto key_ptr = *keys; 180258945Sroberto return key_cnt; 181258945Sroberto} 182258945Sroberto 183258945Sroberto/* Looks for the key with keyid key_id and sets the d_key pointer to the 184258945Sroberto * address of the key. If no matching key is found the pointer is not touched. 185258945Sroberto */ 186258945Srobertovoid 187258945Srobertoget_key( 188258945Sroberto int key_id, 189258945Sroberto struct key **d_key 190258945Sroberto ) 191258945Sroberto{ 192258945Sroberto struct key *itr_key; 193258945Sroberto 194258945Sroberto if (key_cnt == 0) 195258945Sroberto return; 196258945Sroberto for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 197258945Sroberto if (itr_key->key_id == key_id) { 198258945Sroberto *d_key = itr_key; 199258945Sroberto break; 200258945Sroberto } 201258945Sroberto } 202258945Sroberto return; 203258945Sroberto} 204