crypto.c revision 310419
159769Sgrog#include <config.h> 259769Sgrog#include "crypto.h" 324424Swosch#include <ctype.h> 424424Swosch#include "isc/string.h" 524424Swosch#include "libssl_compat.h" 624424Swosch 724424Swoschstruct key *key_ptr; 824424Swoschsize_t key_cnt = 0; 924424Swosch 1024424Swoschint 1124424Swoschmake_mac( 1224424Swosch const void *pkt_data, 1324424Swosch int pkt_size, 1424424Swosch int mac_size, 1542704Swosch const struct key *cmp_key, 1642704Swosch void * digest 1742704Swosch ) 1824424Swosch{ 1942704Swosch u_int len = mac_size; 2042704Swosch int key_type; 2142704Swosch EVP_MD_CTX * ctx; 2242704Swosch 2342704Swosch if (cmp_key->key_len > 64) 2442704Swosch return 0; 2542704Swosch if (pkt_size % 4 != 0) 2642704Swosch return 0; 2742704Swosch 2842704Swosch INIT_SSL(); 2942704Swosch key_type = keytype_from_text(cmp_key->type, NULL); 3059769Sgrog 3159769Sgrog ctx = EVP_MD_CTX_new(); 3259769Sgrog EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); 3359769Sgrog EVP_DigestUpdate(ctx, (const u_char *)cmp_key->key_seq, (u_int)cmp_key->key_len); 3459769Sgrog EVP_DigestUpdate(ctx, pkt_data, (u_int)pkt_size); 3559769Sgrog EVP_DigestFinal(ctx, digest, &len); 3659769Sgrog EVP_MD_CTX_free(ctx); 3759769Sgrog 3859769Sgrog return (int)len; 3924424Swosch} 4042704Swosch 4124424Swosch 4242704Swosch/* Generates a md5 digest of the key specified in keyid concatenated with the 4324424Swosch * ntp packet (exluding the MAC) and compares this digest to the digest in 4442704Swosch * the packet's MAC. If they're equal this function returns 1 (packet is 4524424Swosch * authentic) or else 0 (not authentic). 4624424Swosch */ 4724424Swoschint 4842704Swoschauth_md5( 4925031Swosch const void *pkt_data, 5059156Swosch int pkt_size, 5125031Swosch int mac_size, 5225031Swosch const struct key *cmp_key 5324424Swosch ) 5424424Swosch{ 5524424Swosch int hash_len; 5624424Swosch int authentic; 5771231Sitojun char digest[20]; 5824424Swosch const u_char *pkt_ptr; 5971231Sitojun if (mac_size > (int)sizeof(digest)) 6025031Swosch return 0; 6171231Sitojun pkt_ptr = pkt_data; 6224424Swosch hash_len = make_mac(pkt_ptr, pkt_size, sizeof(digest), cmp_key, 6325031Swosch digest); 6425031Swosch if (!hash_len) { 6571231Sitojun authentic = FALSE; 6625031Swosch } else { 6771231Sitojun /* isc_tsmemcmp will be better when its easy to link 6870110Swosch * with. sntp is a 1-shot program, so snooping for 6970110Swosch * timing attacks is Harder. 7070110Swosch */ 7170110Swosch authentic = !memcmp(digest, (const char*)pkt_data + pkt_size + 4, 7270110Swosch hash_len); 7370110Swosch } 7470110Swosch return authentic; 7570110Swosch} 7670110Swosch 7770110Swoschstatic int 7870110Swoschhex_val( 7980675Sasmodai unsigned char x 8080675Sasmodai ) 8180675Sasmodai{ 8280675Sasmodai int val; 8380675Sasmodai 8480675Sasmodai if ('0' <= x && x <= '9') 8580675Sasmodai val = x - '0'; 8680675Sasmodai else if ('a' <= x && x <= 'f') 8780675Sasmodai val = x - 'a' + 0xa; 8880675Sasmodai else if ('A' <= x && x <= 'F') 8980675Sasmodai val = x - 'A' + 0xA; 9080675Sasmodai else 9180675Sasmodai val = -1; 9280675Sasmodai 9380675Sasmodai return val; 9480675Sasmodai} 9580675Sasmodai 9680675Sasmodai/* Load keys from the specified keyfile into the key structures. 9780675Sasmodai * Returns -1 if the reading failed, otherwise it returns the 9880675Sasmodai * number of keys it read 9980675Sasmodai */ 10080675Sasmodaiint 10180675Sasmodaiauth_init( 10280675Sasmodai const char *keyfile, 10380675Sasmodai struct key **keys 10480675Sasmodai ) 10580675Sasmodai{ 10680675Sasmodai FILE *keyf = fopen(keyfile, "r"); 10780675Sasmodai struct key *prev = NULL; 10880675Sasmodai int scan_cnt, line_cnt = 0; 10980675Sasmodai char kbuf[200]; 11080675Sasmodai char keystring[129]; 11180675Sasmodai 11280675Sasmodai if (keyf == NULL) { 11380675Sasmodai if (debug) 11480675Sasmodai printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 11580675Sasmodai return -1; 11680675Sasmodai } 11780675Sasmodai if (feof(keyf)) { 11880675Sasmodai if (debug) 11980675Sasmodai printf("sntp auth_init: Key file %s is empty!\n", keyfile); 12080675Sasmodai fclose(keyf); 12180675Sasmodai return -1; 12280675Sasmodai } 12380675Sasmodai key_cnt = 0; 12480675Sasmodai while (!feof(keyf)) { 12580675Sasmodai char * octothorpe; 12680675Sasmodai struct key *act; 12780675Sasmodai int goodline = 0; 12880675Sasmodai 12980675Sasmodai if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 13080675Sasmodai continue; 13180675Sasmodai 13280675Sasmodai kbuf[sizeof(kbuf) - 1] = '\0'; 13380675Sasmodai octothorpe = strchr(kbuf, '#'); 13480675Sasmodai if (octothorpe) 13580675Sasmodai *octothorpe = '\0'; 13680675Sasmodai act = emalloc(sizeof(*act)); 13780675Sasmodai scan_cnt = sscanf(kbuf, "%d %9s %128s", &act->key_id, act->type, keystring); 138101401Swosch if (scan_cnt == 3) { 13980675Sasmodai int len = strlen(keystring); 140147593Shrs if (len <= 20) { 14187200Swosch act->key_len = len; 142147593Shrs memcpy(act->key_seq, keystring, len + 1); 14380675Sasmodai goodline = 1; 144104772Smaxim } else if ((len & 1) != 0) { 145104772Smaxim goodline = 0; /* it's bad */ 146104772Smaxim } else { 147104772Smaxim int j; 148104781Sjhb goodline = 1; 149104781Sjhb act->key_len = len >> 1; 150104781Sjhb for (j = 0; j < len; j+=2) { 151104781Sjhb int val; 152104781Sjhb val = (hex_val(keystring[j]) << 4) | 153104781Sjhb hex_val(keystring[j+1]); 154119217Smurray if (val < 0) { 155147593Shrs goodline = 0; /* it's bad */ 156147593Shrs break; 157119217Smurray } 158119217Smurray act->key_seq[j>>1] = (char)val; 159119217Smurray } 160119217Smurray } 161132652Sosa } 162132652Sosa if (goodline) { 163132652Sosa act->next = NULL; 164132652Sosa if (NULL == prev) 165132652Sosa *keys = act; 166132652Sosa else 167132652Sosa prev->next = act; 168132652Sosa prev = act; 169132652Sosa key_cnt++; 170132652Sosa } else { 171140831Smaxim msyslog(LOG_DEBUG, "auth_init: scanf %d items, skipping line %d.", 172176637Smaxim scan_cnt, line_cnt); 173176637Smaxim free(act); 174132652Sosa } 175132652Sosa line_cnt++; 176132652Sosa } 177171778Smaxim fclose(keyf); 178132652Sosa 179132652Sosa key_ptr = *keys; 180132652Sosa return key_cnt; 181132652Sosa} 182132652Sosa 183132652Sosa/* Looks for the key with keyid key_id and sets the d_key pointer to the 184132652Sosa * address of the key. If no matching key is found the pointer is not touched. 185158916Smaxim */ 186158916Smaximvoid 187158916Smaximget_key( 188171778Smaxim int key_id, 189158916Smaxim struct key **d_key 190158916Smaxim ) 191158916Smaxim{ 192158916Smaxim struct key *itr_key; 193158916Smaxim 194158916Smaxim if (key_cnt == 0) 195158916Smaxim return; 196158916Smaxim for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 197158916Smaxim if (itr_key->key_id == key_id) { 198158916Smaxim *d_key = itr_key; 199158916Smaxim break; 200158916Smaxim } 201171778Smaxim } 202164001Smaxim return; 203164001Smaxim} 204164001Smaxim