crypto.c revision 338531
1139969Simp/* 21556Srgrimes * HMS: we need to test: 31556Srgrimes * - OpenSSL versions, if we are building with them 41556Srgrimes * - our versions 51556Srgrimes * 61556Srgrimes * We may need to test with(out) OPENSSL separately. 71556Srgrimes */ 81556Srgrimes 91556Srgrimes#include <config.h> 101556Srgrimes#include "crypto.h" 111556Srgrimes#include <ctype.h> 121556Srgrimes#include "isc/string.h" 131556Srgrimes#include "ntp_md5.h" 141556Srgrimes 151556Srgrimes#ifndef EVP_MAX_MD_SIZE 161556Srgrimes# define EVP_MAX_MD_SIZE 32 171556Srgrimes#endif 181556Srgrimes 191556Srgrimesstruct key *key_ptr; 201556Srgrimessize_t key_cnt = 0; 211556Srgrimes 221556Srgrimestypedef struct key Key_T; 231556Srgrimes 241556Srgrimesstatic u_int 251556Srgrimescompute_mac( 261556Srgrimes u_char digest[EVP_MAX_MD_SIZE], 271556Srgrimes char const * macname, 281556Srgrimes void const * pkt_data, 291556Srgrimes u_int pkt_size, 301556Srgrimes void const * key_data, 311556Srgrimes u_int key_size 321556Srgrimes ) 331556Srgrimes{ 3450471Speter u_int len = 0; 351556Srgrimes size_t slen = 0; 36211965Sbrian int key_type; 371556Srgrimes 3879526Sru INIT_SSL(); 391556Srgrimes key_type = keytype_from_text(macname, NULL); 401556Srgrimes 411556Srgrimes#if defined(OPENSSL) && defined(ENABLE_CMAC) 421556Srgrimes /* Check if CMAC key type specific code required */ 4368935Sru if (key_type == NID_cmac) { 4476286Skris CMAC_CTX * ctx = NULL; 451556Srgrimes u_char keybuf[AES_128_KEY_SIZE]; 461556Srgrimes 471556Srgrimes /* adjust key size (zero padded buffer) if necessary */ 481556Srgrimes if (AES_128_KEY_SIZE > key_size) { 491556Srgrimes memcpy(keybuf, key_data, key_size); 5070150Sru memset((keybuf + key_size), 0, 511556Srgrimes (AES_128_KEY_SIZE - key_size)); 521556Srgrimes key_data = keybuf; 531556Srgrimes } 5470150Sru 551556Srgrimes if (!(ctx = CMAC_CTX_new())) { 561556Srgrimes msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.", CMAC); 571556Srgrimes } 5870150Sru else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE, 591556Srgrimes EVP_aes_128_cbc(), NULL)) { 601556Srgrimes msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.", CMAC); 611556Srgrimes } 621556Srgrimes else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) { 631556Srgrimes msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.", CMAC); 641556Srgrimes } 651556Srgrimes else if (!CMAC_Final(ctx, digest, &slen)) { 6670150Sru msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.", CMAC); 671556Srgrimes slen = 0; 6870150Sru } 6968935Sru len = (u_int)slen; 701556Srgrimes 7176286Skris CMAC_CTX_cleanup(ctx); 721556Srgrimes /* Test our AES-128-CMAC implementation */ 731556Srgrimes 741556Srgrimes } else /* MD5 MAC handling */ 751556Srgrimes#endif 761556Srgrimes { 7770150Sru EVP_MD_CTX * ctx; 781556Srgrimes 791556Srgrimes if (!(ctx = EVP_MD_CTX_new())) { 801556Srgrimes msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.", 8170150Sru macname); 821556Srgrimes goto mac_fail; 831556Srgrimes } 841556Srgrimes#ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */ 8570150Sru# ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 861556Srgrimes EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 871556Srgrimes# endif 881556Srgrimes /* [Bug 3457] DON'T use plain EVP_DigestInit! It would 891556Srgrimes * kill the flags! */ 9070150Sru if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) { 911556Srgrimes msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.", 921556Srgrimes macname); 931556Srgrimes goto mac_fail; 9470150Sru } 951556Srgrimes if (!EVP_DigestUpdate(ctx, key_data, key_size)) { 961556Srgrimes msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.", 971556Srgrimes macname); 981556Srgrimes goto mac_fail; 991556Srgrimes } 1001556Srgrimes if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) { 1011556Srgrimes msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.", 10270150Sru macname); 1031556Srgrimes goto mac_fail; 10470150Sru } 10568935Sru if (!EVP_DigestFinal(ctx, digest, &len)) { 1061556Srgrimes msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.", 10776286Skris macname); 1081556Srgrimes len = 0; 1091556Srgrimes } 1101556Srgrimes#else /* !OPENSSL */ 1111556Srgrimes EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); 1121556Srgrimes EVP_DigestUpdate(ctx, key_data, key_size); 1131556Srgrimes EVP_DigestUpdate(ctx, pkt_data, pkt_size); 1141556Srgrimes EVP_DigestFinal(ctx, digest, &len); 1151556Srgrimes#endif 1161556Srgrimes mac_fail: 1171556Srgrimes EVP_MD_CTX_free(ctx); 1181556Srgrimes } 1191556Srgrimes 12070150Sru return len; 1211556Srgrimes} 1221556Srgrimes 1231556Srgrimesint 12470150Srumake_mac( 1251556Srgrimes const void * pkt_data, 1261556Srgrimes int pkt_size, 1271556Srgrimes int mac_size, 12870150Sru Key_T const * cmp_key, 1291556Srgrimes void * digest 1301556Srgrimes ) 1311556Srgrimes{ 13270150Sru u_int len; 1331556Srgrimes u_char dbuf[EVP_MAX_MD_SIZE]; 1341556Srgrimes 1351556Srgrimes if (cmp_key->key_len > 64 || mac_size <= 0) 1361556Srgrimes return 0; 1371556Srgrimes if (pkt_size % 4 != 0) 1381556Srgrimes return 0; 1391556Srgrimes 1401556Srgrimes len = compute_mac(dbuf, cmp_key->typen, 1411556Srgrimes pkt_data, (u_int)pkt_size, 1421556Srgrimes cmp_key->key_seq, (u_int)cmp_key->key_len); 1431556Srgrimes 14470150Sru 1451556Srgrimes if (len) { 14672432Sru if (len > (u_int)mac_size) 14768935Sru len = (u_int)mac_size; 1481556Srgrimes memcpy(digest, dbuf, len); 1491556Srgrimes } 1501556Srgrimes return (int)len; 1511556Srgrimes} 1521556Srgrimes 15370150Sru 1541556Srgrimes/* Generates a md5 digest of the key specified in keyid concatenated with the 1551556Srgrimes * ntp packet (exluding the MAC) and compares this digest to the digest in 1561556Srgrimes * the packet's MAC. If they're equal this function returns 1 (packet is 15770150Sru * authentic) or else 0 (not authentic). 1581556Srgrimes */ 1591556Srgrimesint 1601556Srgrimesauth_md5( 16170150Sru void const * pkt_data, 1621556Srgrimes int pkt_size, 1631556Srgrimes int mac_size, 1641556Srgrimes Key_T const * cmp_key 16570150Sru ) 1661556Srgrimes{ 1671556Srgrimes u_int len = 0; 1681556Srgrimes u_char const * pkt_ptr = pkt_data; 1691556Srgrimes u_char dbuf[EVP_MAX_MD_SIZE]; 1701556Srgrimes 1711556Srgrimes if (mac_size <= 0 || (size_t)mac_size > sizeof(dbuf)) 1721556Srgrimes return FALSE; 1731556Srgrimes 17470150Sru len = compute_mac(dbuf, cmp_key->typen, 1751556Srgrimes pkt_ptr, (u_int)pkt_size, 17672432Sru cmp_key->key_seq, (u_int)cmp_key->key_len); 1771556Srgrimes 1781556Srgrimes pkt_ptr += pkt_size + 4; 17995204Scharnier if (len > (u_int)mac_size) 18095204Scharnier len = (u_int)mac_size; 18195204Scharnier 1821556Srgrimes /* isc_tsmemcmp will be better when its easy to link with. sntp 18395204Scharnier * is a 1-shot program, so snooping for timing attacks is 18495204Scharnier * Harder. 1851556Srgrimes */ 1861556Srgrimes return ((u_int)mac_size == len) && !memcmp(dbuf, pkt_ptr, len); 1871556Srgrimes} 1881556Srgrimes 1891556Srgrimesstatic int 1901556Srgrimeshex_val( 1911556Srgrimes unsigned char x 1921556Srgrimes ) 1931556Srgrimes{ 19436049Scharnier int val; 1951556Srgrimes 1961556Srgrimes if ('0' <= x && x <= '9') 1971556Srgrimes val = x - '0'; 19871895Sru else if ('a' <= x && x <= 'f') 1991556Srgrimes val = x - 'a' + 0xa; 2001556Srgrimes else if ('A' <= x && x <= 'F') 2011556Srgrimes val = x - 'A' + 0xA; 20295204Scharnier else 2031556Srgrimes val = -1; 2041556Srgrimes 2051556Srgrimes return val; 2061556Srgrimes} 20771895Sru 2081556Srgrimes/* Load keys from the specified keyfile into the key structures. 2091556Srgrimes * Returns -1 if the reading failed, otherwise it returns the 2101556Srgrimes * number of keys it read 2111556Srgrimes */ 21295204Scharnierint 2131556Srgrimesauth_init( 21479754Sdd const char *keyfile, 21571895Sru struct key **keys 2161556Srgrimes ) 2171556Srgrimes{ 2181556Srgrimes FILE *keyf = fopen(keyfile, "r"); 2191556Srgrimes struct key *prev = NULL; 2201556Srgrimes int scan_cnt, line_cnt = 1; 2211556Srgrimes char kbuf[200]; 2221556Srgrimes char keystring[129]; 2231556Srgrimes 2241556Srgrimes /* HMS: Is it OK to do this later, after we know we have a key file? */ 2251556Srgrimes INIT_SSL(); 22695204Scharnier 2271556Srgrimes if (keyf == NULL) { 2281556Srgrimes if (debug) 2291556Srgrimes printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 2301556Srgrimes return -1; 23179754Sdd } 2321556Srgrimes if (feof(keyf)) { 23379754Sdd if (debug) 2341556Srgrimes printf("sntp auth_init: Key file %s is empty!\n", keyfile); 23579754Sdd fclose(keyf); 2361556Srgrimes return -1; 2371556Srgrimes } 2381556Srgrimes key_cnt = 0; 2391556Srgrimes while (!feof(keyf)) { 2401556Srgrimes char * octothorpe; 24195204Scharnier struct key *act; 2421556Srgrimes int goodline = 0; 2431556Srgrimes 2441556Srgrimes if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 24579754Sdd continue; 2461556Srgrimes 2471556Srgrimes kbuf[sizeof(kbuf) - 1] = '\0'; 2481556Srgrimes octothorpe = strchr(kbuf, '#'); 2491556Srgrimes if (octothorpe) 2501556Srgrimes *octothorpe = '\0'; 2511556Srgrimes act = emalloc(sizeof(*act)); 2521556Srgrimes /* keep width 15 = sizeof struct key.typen - 1 synced */ 2531556Srgrimes scan_cnt = sscanf(kbuf, "%d %15s %128s", 2541556Srgrimes &act->key_id, act->typen, keystring); 2551556Srgrimes if (scan_cnt == 3) { 2561556Srgrimes int len = strlen(keystring); 2571556Srgrimes goodline = 1; /* assume best for now */ 2581556Srgrimes if (len <= 20) { 2591556Srgrimes act->key_len = len; 2601556Srgrimes memcpy(act->key_seq, keystring, len + 1); 2611556Srgrimes } else if ((len & 1) != 0) { 2621556Srgrimes goodline = 0; /* it's bad */ 2631556Srgrimes } else { 2641556Srgrimes int j; 2651556Srgrimes act->key_len = len >> 1; 2661556Srgrimes for (j = 0; j < len; j+=2) { 2671556Srgrimes int val; 2681556Srgrimes val = (hex_val(keystring[j]) << 4) | 2691556Srgrimes hex_val(keystring[j+1]); 2701556Srgrimes if (val < 0) { 2711556Srgrimes goodline = 0; /* it's bad */ 2721556Srgrimes break; 2731556Srgrimes } 2741556Srgrimes act->key_seq[j>>1] = (char)val; 2751556Srgrimes } 2761556Srgrimes } 2771556Srgrimes act->typei = keytype_from_text(act->typen, NULL); 2781556Srgrimes if (0 == act->typei) { 2791556Srgrimes printf("%s: line %d: key %d, %s not supported - ignoring\n", 28036049Scharnier keyfile, line_cnt, 2811556Srgrimes act->key_id, act->typen); 2821556Srgrimes goodline = 0; /* it's bad */ 2831556Srgrimes } 2841556Srgrimes } 2851556Srgrimes if (goodline) { 2861556Srgrimes act->next = NULL; 2871556Srgrimes if (NULL == prev) 2881556Srgrimes *keys = act; 2891556Srgrimes else 2901556Srgrimes prev->next = act; 2911556Srgrimes prev = act; 2921556Srgrimes key_cnt++; 29336049Scharnier } else { 2941556Srgrimes if (debug) { 2951556Srgrimes printf("auth_init: scanf %d items, skipping line %d.", 2961556Srgrimes scan_cnt, line_cnt); 2971556Srgrimes } 2981556Srgrimes free(act); 2991556Srgrimes } 3001556Srgrimes line_cnt++; 3011556Srgrimes } 30279754Sdd fclose(keyf); 3031556Srgrimes 3041556Srgrimes key_ptr = *keys; 30579754Sdd return key_cnt; 3061556Srgrimes} 3071556Srgrimes 3081556Srgrimes/* Looks for the key with keyid key_id and sets the d_key pointer to the 3091556Srgrimes * address of the key. If no matching key is found the pointer is not touched. 3101556Srgrimes */ 3111556Srgrimesvoid 31236049Scharnierget_key( 3131556Srgrimes int key_id, 3141556Srgrimes struct key **d_key 3151556Srgrimes ) 3161556Srgrimes{ 3171556Srgrimes struct key *itr_key; 3181556Srgrimes 3191556Srgrimes if (key_cnt == 0) 3201556Srgrimes return; 3211556Srgrimes for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 3221556Srgrimes if (itr_key->key_id == key_id) { 3231556Srgrimes *d_key = itr_key; 3241556Srgrimes break; 32536049Scharnier } 3261556Srgrimes } 3271556Srgrimes return; 3281556Srgrimes} 3291556Srgrimes