1/* $NetBSD: crypto.c,v 1.3 2012/02/01 07:46:23 kardel Exp $ */ 2 3#include <config.h> 4#include "crypto.h" 5#include <ctype.h> 6 7struct key *key_ptr; 8size_t key_cnt = 0; 9 10int 11make_mac( 12 char *pkt_data, 13 int pkt_size, 14 int mac_size, 15 struct key *cmp_key, 16 char * 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 EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); 31 EVP_DigestUpdate(&ctx, (u_char *)cmp_key->key_seq, (u_int)cmp_key->key_len); 32 EVP_DigestUpdate(&ctx, (u_char *)pkt_data, (u_int)pkt_size); 33 EVP_DigestFinal(&ctx, (u_char *)digest, &len); 34 35 return (int)len; 36} 37 38 39/* Generates a md5 digest of the key specified in keyid concatinated with the 40 * ntp packet (exluding the MAC) and compares this digest to the digest in 41 * the packet's MAC. If they're equal this function returns 1 (packet is 42 * authentic) or else 0 (not authentic). 43 */ 44int 45auth_md5( 46 char *pkt_data, 47 int pkt_size, 48 int mac_size, 49 struct key *cmp_key 50 ) 51{ 52 int hash_len; 53 int authentic; 54 char digest[20]; 55 56 if (mac_size > (int)sizeof(digest)) 57 return 0; 58 hash_len = make_mac(pkt_data, pkt_size, sizeof(digest), cmp_key, 59 digest); 60 if (!hash_len) 61 authentic = FALSE; 62 else 63 authentic = !memcmp(digest, pkt_data + pkt_size + 4, 64 hash_len); 65 return authentic; 66} 67 68static int 69hex_val( 70 unsigned char x 71 ) 72{ 73 int val; 74 75 if ('0' <= x && x <= '9') 76 val = x - '0'; 77 else if ('a' <= x && x <= 'f') 78 val = x - 'a' + 0xa; 79 else if ('A' <= x && x <= 'F') 80 val = x - 'A' + 0xA; 81 else 82 val = -1; 83 84 return val; 85} 86 87/* Load keys from the specified keyfile into the key structures. 88 * Returns -1 if the reading failed, otherwise it returns the 89 * number of keys it read 90 */ 91int 92auth_init( 93 const char *keyfile, 94 struct key **keys 95 ) 96{ 97 FILE *keyf = fopen(keyfile, "r"); 98 struct key *prev = NULL; 99 int scan_cnt, line_cnt = 0; 100 char kbuf[200]; 101 char keystring[129]; 102 103 if (keyf == NULL) { 104 if (ENABLED_OPT(NORMALVERBOSE)) 105 printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 106 return -1; 107 } 108 if (feof(keyf)) { 109 if (ENABLED_OPT(NORMALVERBOSE)) 110 printf("sntp auth_init: Key file %s is empty!\n", keyfile); 111 fclose(keyf); 112 return -1; 113 } 114 key_cnt = 0; 115 while (!feof(keyf)) { 116 char * octothorpe; 117 struct key *act = emalloc(sizeof(struct key)); 118 int goodline = 0; 119 120 if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 121 continue; 122 123 kbuf[sizeof(kbuf) - 1] = '\0'; 124 octothorpe = strchr(kbuf, '#'); 125 if (octothorpe) 126 *octothorpe = '\0'; 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 */ 176void 177get_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