109100258SXin LI /* 209100258SXin LI * HMS: we need to test: 309100258SXin LI * - OpenSSL versions, if we are building with them 409100258SXin LI * - our versions 509100258SXin LI * 609100258SXin LI * We may need to test with(out) OPENSSL separately. 709100258SXin LI */ 809100258SXin LI 92b15cb3dSCy Schubert #include <config.h> 102b15cb3dSCy Schubert #include "crypto.h" 112b15cb3dSCy Schubert #include <ctype.h> 124990d495SXin LI #include "isc/string.h" 13f0574f5cSXin LI #include "ntp_md5.h" 142b15cb3dSCy Schubert 1509100258SXin LI #ifndef EVP_MAX_MD_SIZE 1609100258SXin LI # define EVP_MAX_MD_SIZE 32 1709100258SXin LI #endif 1809100258SXin LI 192b15cb3dSCy Schubert struct key *key_ptr; 202b15cb3dSCy Schubert size_t key_cnt = 0; 212b15cb3dSCy Schubert 2209100258SXin LI typedef struct key Key_T; 2309100258SXin LI 2409100258SXin LI static u_int 2509100258SXin LI compute_mac( 2609100258SXin LI u_char digest[EVP_MAX_MD_SIZE], 2709100258SXin LI char const * macname, 2809100258SXin LI void const * pkt_data, 2909100258SXin LI u_int pkt_size, 3009100258SXin LI void const * key_data, 3109100258SXin LI u_int key_size 3209100258SXin LI ) 3309100258SXin LI { 3409100258SXin LI u_int len = 0; 352d4e511cSCy Schubert #if defined(OPENSSL) && defined(ENABLE_CMAC) 3609100258SXin LI size_t slen = 0; 372d4e511cSCy Schubert #endif 3809100258SXin LI int key_type; 3909100258SXin LI 4009100258SXin LI INIT_SSL(); 4109100258SXin LI key_type = keytype_from_text(macname, NULL); 4209100258SXin LI 434e1ef62aSXin LI #if defined(OPENSSL) && defined(ENABLE_CMAC) 4409100258SXin LI /* Check if CMAC key type specific code required */ 4509100258SXin LI if (key_type == NID_cmac) { 4609100258SXin LI CMAC_CTX * ctx = NULL; 4709100258SXin LI u_char keybuf[AES_128_KEY_SIZE]; 4809100258SXin LI 4909100258SXin LI /* adjust key size (zero padded buffer) if necessary */ 5009100258SXin LI if (AES_128_KEY_SIZE > key_size) { 5109100258SXin LI memcpy(keybuf, key_data, key_size); 5209100258SXin LI memset((keybuf + key_size), 0, 5309100258SXin LI (AES_128_KEY_SIZE - key_size)); 5409100258SXin LI key_data = keybuf; 5509100258SXin LI } 5609100258SXin LI 5709100258SXin LI if (!(ctx = CMAC_CTX_new())) { 5809100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.", CMAC); 5909100258SXin LI } 6009100258SXin LI else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE, 6109100258SXin LI EVP_aes_128_cbc(), NULL)) { 6209100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.", CMAC); 6309100258SXin LI } 6409100258SXin LI else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) { 6509100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.", CMAC); 6609100258SXin LI } 6709100258SXin LI else if (!CMAC_Final(ctx, digest, &slen)) { 6809100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.", CMAC); 6909100258SXin LI slen = 0; 7009100258SXin LI } 7109100258SXin LI len = (u_int)slen; 7209100258SXin LI 73767173ceSCy Schubert if (ctx) 74767173ceSCy Schubert CMAC_CTX_free(ctx); 7509100258SXin LI /* Test our AES-128-CMAC implementation */ 7609100258SXin LI 7709100258SXin LI } else /* MD5 MAC handling */ 7809100258SXin LI #endif 7909100258SXin LI { 8009100258SXin LI EVP_MD_CTX * ctx; 8109100258SXin LI 8209100258SXin LI if (!(ctx = EVP_MD_CTX_new())) { 8309100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.", 8409100258SXin LI macname); 8509100258SXin LI goto mac_fail; 8609100258SXin LI } 8709100258SXin LI #ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */ 8809100258SXin LI # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 8909100258SXin LI EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 9009100258SXin LI # endif 9109100258SXin LI /* [Bug 3457] DON'T use plain EVP_DigestInit! It would 9209100258SXin LI * kill the flags! */ 9309100258SXin LI if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) { 9409100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.", 9509100258SXin LI macname); 9609100258SXin LI goto mac_fail; 9709100258SXin LI } 9809100258SXin LI if (!EVP_DigestUpdate(ctx, key_data, key_size)) { 9909100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.", 10009100258SXin LI macname); 10109100258SXin LI goto mac_fail; 10209100258SXin LI } 10309100258SXin LI if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) { 10409100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.", 10509100258SXin LI macname); 10609100258SXin LI goto mac_fail; 10709100258SXin LI } 10809100258SXin LI if (!EVP_DigestFinal(ctx, digest, &len)) { 10909100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.", 11009100258SXin LI macname); 11109100258SXin LI len = 0; 11209100258SXin LI } 11309100258SXin LI #else /* !OPENSSL */ 114*a466cc55SCy Schubert (void)key_type; /* unused, so try to prevent compiler from croaks */ 115*a466cc55SCy Schubert if (!EVP_DigestInit(ctx, EVP_get_digestbynid(key_type))) { 116*a466cc55SCy Schubert msyslog(LOG_ERR, "make_mac: MAC MD5 Digest Init failed."); 117*a466cc55SCy Schubert goto mac_fail; 118*a466cc55SCy Schubert } 11909100258SXin LI EVP_DigestUpdate(ctx, key_data, key_size); 12009100258SXin LI EVP_DigestUpdate(ctx, pkt_data, pkt_size); 12109100258SXin LI EVP_DigestFinal(ctx, digest, &len); 12209100258SXin LI #endif 12309100258SXin LI mac_fail: 12409100258SXin LI EVP_MD_CTX_free(ctx); 12509100258SXin LI } 12609100258SXin LI 12709100258SXin LI return len; 12809100258SXin LI } 12909100258SXin LI 1302b15cb3dSCy Schubert int 1312b15cb3dSCy Schubert make_mac( 13268ba7e87SXin LI const void * pkt_data, 1332b15cb3dSCy Schubert int pkt_size, 1342b15cb3dSCy Schubert int mac_size, 13509100258SXin LI Key_T const * cmp_key, 13668ba7e87SXin LI void * digest 1372b15cb3dSCy Schubert ) 1382b15cb3dSCy Schubert { 13909100258SXin LI u_int len; 14009100258SXin LI u_char dbuf[EVP_MAX_MD_SIZE]; 1412b15cb3dSCy Schubert 14209100258SXin LI if (cmp_key->key_len > 64 || mac_size <= 0) 1432b15cb3dSCy Schubert return 0; 1442b15cb3dSCy Schubert if (pkt_size % 4 != 0) 1452b15cb3dSCy Schubert return 0; 1462b15cb3dSCy Schubert 14709100258SXin LI len = compute_mac(dbuf, cmp_key->typen, 14809100258SXin LI pkt_data, (u_int)pkt_size, 14909100258SXin LI cmp_key->key_seq, (u_int)cmp_key->key_len); 150f391d6bcSXin LI 1512b15cb3dSCy Schubert 15209100258SXin LI if (len) { 15309100258SXin LI if (len > (u_int)mac_size) 15409100258SXin LI len = (u_int)mac_size; 15509100258SXin LI memcpy(digest, dbuf, len); 15609100258SXin LI } 1572b15cb3dSCy Schubert return (int)len; 1582b15cb3dSCy Schubert } 1592b15cb3dSCy Schubert 1602b15cb3dSCy Schubert 16168ba7e87SXin LI /* Generates a md5 digest of the key specified in keyid concatenated with the 1622b15cb3dSCy Schubert * ntp packet (exluding the MAC) and compares this digest to the digest in 1632b15cb3dSCy Schubert * the packet's MAC. If they're equal this function returns 1 (packet is 1642b15cb3dSCy Schubert * authentic) or else 0 (not authentic). 1652b15cb3dSCy Schubert */ 1662b15cb3dSCy Schubert int 1672b15cb3dSCy Schubert auth_md5( 16809100258SXin LI void const * pkt_data, 1692b15cb3dSCy Schubert int pkt_size, 1702b15cb3dSCy Schubert int mac_size, 17109100258SXin LI Key_T const * cmp_key 1722b15cb3dSCy Schubert ) 1732b15cb3dSCy Schubert { 17409100258SXin LI u_int len = 0; 17509100258SXin LI u_char const * pkt_ptr = pkt_data; 17609100258SXin LI u_char dbuf[EVP_MAX_MD_SIZE]; 17709100258SXin LI 17809100258SXin LI if (mac_size <= 0 || (size_t)mac_size > sizeof(dbuf)) 17909100258SXin LI return FALSE; 18009100258SXin LI 18109100258SXin LI len = compute_mac(dbuf, cmp_key->typen, 18209100258SXin LI pkt_ptr, (u_int)pkt_size, 18309100258SXin LI cmp_key->key_seq, (u_int)cmp_key->key_len); 18409100258SXin LI 18509100258SXin LI pkt_ptr += pkt_size + 4; 18609100258SXin LI if (len > (u_int)mac_size) 18709100258SXin LI len = (u_int)mac_size; 18809100258SXin LI 18909100258SXin LI /* isc_tsmemcmp will be better when its easy to link with. sntp 19009100258SXin LI * is a 1-shot program, so snooping for timing attacks is 19109100258SXin LI * Harder. 1924990d495SXin LI */ 19309100258SXin LI return ((u_int)mac_size == len) && !memcmp(dbuf, pkt_ptr, len); 1942b15cb3dSCy Schubert } 1952b15cb3dSCy Schubert 1962b15cb3dSCy Schubert static int 1972b15cb3dSCy Schubert hex_val( 1982b15cb3dSCy Schubert unsigned char x 1992b15cb3dSCy Schubert ) 2002b15cb3dSCy Schubert { 2012b15cb3dSCy Schubert int val; 2022b15cb3dSCy Schubert 2032b15cb3dSCy Schubert if ('0' <= x && x <= '9') 2042b15cb3dSCy Schubert val = x - '0'; 2052b15cb3dSCy Schubert else if ('a' <= x && x <= 'f') 2062b15cb3dSCy Schubert val = x - 'a' + 0xa; 2072b15cb3dSCy Schubert else if ('A' <= x && x <= 'F') 2082b15cb3dSCy Schubert val = x - 'A' + 0xA; 2092b15cb3dSCy Schubert else 2102b15cb3dSCy Schubert val = -1; 2112b15cb3dSCy Schubert 2122b15cb3dSCy Schubert return val; 2132b15cb3dSCy Schubert } 2142b15cb3dSCy Schubert 2152b15cb3dSCy Schubert /* Load keys from the specified keyfile into the key structures. 2162b15cb3dSCy Schubert * Returns -1 if the reading failed, otherwise it returns the 2172b15cb3dSCy Schubert * number of keys it read 2182b15cb3dSCy Schubert */ 2192b15cb3dSCy Schubert int 2202b15cb3dSCy Schubert auth_init( 2212b15cb3dSCy Schubert const char *keyfile, 2222b15cb3dSCy Schubert struct key **keys 2232b15cb3dSCy Schubert ) 2242b15cb3dSCy Schubert { 2252b15cb3dSCy Schubert FILE *keyf = fopen(keyfile, "r"); 2262b15cb3dSCy Schubert struct key *prev = NULL; 22709100258SXin LI int scan_cnt, line_cnt = 1; 2282b15cb3dSCy Schubert char kbuf[200]; 2292b15cb3dSCy Schubert char keystring[129]; 2302b15cb3dSCy Schubert 23109100258SXin LI /* HMS: Is it OK to do this later, after we know we have a key file? */ 23209100258SXin LI INIT_SSL(); 23309100258SXin LI 2342b15cb3dSCy Schubert if (keyf == NULL) { 2352b15cb3dSCy Schubert if (debug) 2362b15cb3dSCy Schubert printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 2372b15cb3dSCy Schubert return -1; 2382b15cb3dSCy Schubert } 2392b15cb3dSCy Schubert if (feof(keyf)) { 2402b15cb3dSCy Schubert if (debug) 2412b15cb3dSCy Schubert printf("sntp auth_init: Key file %s is empty!\n", keyfile); 2422b15cb3dSCy Schubert fclose(keyf); 2432b15cb3dSCy Schubert return -1; 2442b15cb3dSCy Schubert } 2452b15cb3dSCy Schubert key_cnt = 0; 2462b15cb3dSCy Schubert while (!feof(keyf)) { 2472b15cb3dSCy Schubert char * octothorpe; 2482b15cb3dSCy Schubert struct key *act; 2492b15cb3dSCy Schubert int goodline = 0; 2502b15cb3dSCy Schubert 2512b15cb3dSCy Schubert if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 2522b15cb3dSCy Schubert continue; 2532b15cb3dSCy Schubert 2542b15cb3dSCy Schubert kbuf[sizeof(kbuf) - 1] = '\0'; 2552b15cb3dSCy Schubert octothorpe = strchr(kbuf, '#'); 2562b15cb3dSCy Schubert if (octothorpe) 2572b15cb3dSCy Schubert *octothorpe = '\0'; 2582b15cb3dSCy Schubert act = emalloc(sizeof(*act)); 25909100258SXin LI /* keep width 15 = sizeof struct key.typen - 1 synced */ 26009100258SXin LI scan_cnt = sscanf(kbuf, "%d %15s %128s", 26109100258SXin LI &act->key_id, act->typen, keystring); 2622b15cb3dSCy Schubert if (scan_cnt == 3) { 2632b15cb3dSCy Schubert int len = strlen(keystring); 26409100258SXin LI goodline = 1; /* assume best for now */ 2652b15cb3dSCy Schubert if (len <= 20) { 2662b15cb3dSCy Schubert act->key_len = len; 2672b15cb3dSCy Schubert memcpy(act->key_seq, keystring, len + 1); 2682b15cb3dSCy Schubert } else if ((len & 1) != 0) { 2692b15cb3dSCy Schubert goodline = 0; /* it's bad */ 2702b15cb3dSCy Schubert } else { 2712b15cb3dSCy Schubert int j; 2722b15cb3dSCy Schubert act->key_len = len >> 1; 2732b15cb3dSCy Schubert for (j = 0; j < len; j+=2) { 2742b15cb3dSCy Schubert int val; 2752b15cb3dSCy Schubert val = (hex_val(keystring[j]) << 4) | 2762b15cb3dSCy Schubert hex_val(keystring[j+1]); 2772b15cb3dSCy Schubert if (val < 0) { 2782b15cb3dSCy Schubert goodline = 0; /* it's bad */ 2792b15cb3dSCy Schubert break; 2802b15cb3dSCy Schubert } 2812b15cb3dSCy Schubert act->key_seq[j>>1] = (char)val; 2822b15cb3dSCy Schubert } 2832b15cb3dSCy Schubert } 28409100258SXin LI act->typei = keytype_from_text(act->typen, NULL); 28509100258SXin LI if (0 == act->typei) { 28609100258SXin LI printf("%s: line %d: key %d, %s not supported - ignoring\n", 28709100258SXin LI keyfile, line_cnt, 28809100258SXin LI act->key_id, act->typen); 28909100258SXin LI goodline = 0; /* it's bad */ 29009100258SXin LI } 2912b15cb3dSCy Schubert } 2922b15cb3dSCy Schubert if (goodline) { 2932b15cb3dSCy Schubert act->next = NULL; 2942b15cb3dSCy Schubert if (NULL == prev) 2952b15cb3dSCy Schubert *keys = act; 2962b15cb3dSCy Schubert else 2972b15cb3dSCy Schubert prev->next = act; 2982b15cb3dSCy Schubert prev = act; 2992b15cb3dSCy Schubert key_cnt++; 3002b15cb3dSCy Schubert } else { 30109100258SXin LI if (debug) { 30209100258SXin LI printf("auth_init: scanf %d items, skipping line %d.", 3032b15cb3dSCy Schubert scan_cnt, line_cnt); 30409100258SXin LI } 3052b15cb3dSCy Schubert free(act); 3062b15cb3dSCy Schubert } 3072b15cb3dSCy Schubert line_cnt++; 3082b15cb3dSCy Schubert } 3092b15cb3dSCy Schubert fclose(keyf); 3102b15cb3dSCy Schubert 3112b15cb3dSCy Schubert key_ptr = *keys; 3122b15cb3dSCy Schubert return key_cnt; 3132b15cb3dSCy Schubert } 3142b15cb3dSCy Schubert 3152b15cb3dSCy Schubert /* Looks for the key with keyid key_id and sets the d_key pointer to the 3162b15cb3dSCy Schubert * address of the key. If no matching key is found the pointer is not touched. 3172b15cb3dSCy Schubert */ 3182b15cb3dSCy Schubert void 3192b15cb3dSCy Schubert get_key( 3202b15cb3dSCy Schubert int key_id, 3212b15cb3dSCy Schubert struct key **d_key 3222b15cb3dSCy Schubert ) 3232b15cb3dSCy Schubert { 3242b15cb3dSCy Schubert struct key *itr_key; 3252b15cb3dSCy Schubert 3262b15cb3dSCy Schubert if (key_cnt == 0) 3272b15cb3dSCy Schubert return; 3282b15cb3dSCy Schubert for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 3292b15cb3dSCy Schubert if (itr_key->key_id == key_id) { 3302b15cb3dSCy Schubert *d_key = itr_key; 3312b15cb3dSCy Schubert break; 3322b15cb3dSCy Schubert } 3332b15cb3dSCy Schubert } 3342b15cb3dSCy Schubert return; 3352b15cb3dSCy Schubert } 336