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"
1309100258SXin LI
142b15cb3dSCy Schubert struct key *key_ptr;
152b15cb3dSCy Schubert size_t key_cnt = 0;
162b15cb3dSCy Schubert
1709100258SXin LI typedef struct key Key_T;
1809100258SXin LI
19*f5f40dd6SCy Schubert static size_t
compute_mac(u_char * digest,size_t dig_sz,char const * macname,void const * pkt_data,size_t pkt_len,void const * key_data,size_t key_size)2009100258SXin LI compute_mac(
21*f5f40dd6SCy Schubert u_char * digest,
22*f5f40dd6SCy Schubert size_t dig_sz,
2309100258SXin LI char const * macname,
2409100258SXin LI void const * pkt_data,
25*f5f40dd6SCy Schubert size_t pkt_len,
2609100258SXin LI void const * key_data,
27*f5f40dd6SCy Schubert size_t key_size
2809100258SXin LI )
2909100258SXin LI {
3009100258SXin LI u_int len = 0;
312d4e511cSCy Schubert #if defined(OPENSSL) && defined(ENABLE_CMAC)
3209100258SXin LI size_t slen = 0;
332d4e511cSCy Schubert #endif
3409100258SXin LI int key_type;
3509100258SXin LI
3609100258SXin LI INIT_SSL();
3709100258SXin LI key_type = keytype_from_text(macname, NULL);
3809100258SXin LI
394e1ef62aSXin LI #if defined(OPENSSL) && defined(ENABLE_CMAC)
4009100258SXin LI /* Check if CMAC key type specific code required */
4109100258SXin LI if (key_type == NID_cmac) {
4209100258SXin LI CMAC_CTX * ctx = NULL;
4309100258SXin LI u_char keybuf[AES_128_KEY_SIZE];
4409100258SXin LI
4509100258SXin LI /* adjust key size (zero padded buffer) if necessary */
4609100258SXin LI if (AES_128_KEY_SIZE > key_size) {
4709100258SXin LI memcpy(keybuf, key_data, key_size);
4809100258SXin LI memset((keybuf + key_size), 0,
4909100258SXin LI (AES_128_KEY_SIZE - key_size));
5009100258SXin LI key_data = keybuf;
5109100258SXin LI }
5209100258SXin LI
5309100258SXin LI if (!(ctx = CMAC_CTX_new())) {
5409100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.", CMAC);
5509100258SXin LI }
5609100258SXin LI else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE,
5709100258SXin LI EVP_aes_128_cbc(), NULL)) {
5809100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.", CMAC);
5909100258SXin LI }
60*f5f40dd6SCy Schubert else if (!CMAC_Update(ctx, pkt_data, pkt_len)) {
6109100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.", CMAC);
6209100258SXin LI }
6309100258SXin LI else if (!CMAC_Final(ctx, digest, &slen)) {
6409100258SXin LI msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.", CMAC);
6509100258SXin LI slen = 0;
6609100258SXin LI }
6709100258SXin LI len = (u_int)slen;
6809100258SXin LI
69767173ceSCy Schubert if (ctx)
70767173ceSCy Schubert CMAC_CTX_free(ctx);
7109100258SXin LI /* Test our AES-128-CMAC implementation */
7209100258SXin LI
7309100258SXin LI } else /* MD5 MAC handling */
7409100258SXin LI #endif
7509100258SXin LI {
7609100258SXin LI EVP_MD_CTX * ctx;
7709100258SXin LI
7809100258SXin LI if (!(ctx = EVP_MD_CTX_new())) {
7909100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.",
8009100258SXin LI macname);
8109100258SXin LI goto mac_fail;
8209100258SXin LI }
8309100258SXin LI #ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */
8409100258SXin LI # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
8509100258SXin LI EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
8609100258SXin LI # endif
8709100258SXin LI /* [Bug 3457] DON'T use plain EVP_DigestInit! It would
8809100258SXin LI * kill the flags! */
8909100258SXin LI if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) {
9009100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.",
9109100258SXin LI macname);
9209100258SXin LI goto mac_fail;
9309100258SXin LI }
9409100258SXin LI if (!EVP_DigestUpdate(ctx, key_data, key_size)) {
9509100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.",
9609100258SXin LI macname);
9709100258SXin LI goto mac_fail;
9809100258SXin LI }
99*f5f40dd6SCy Schubert if (!EVP_DigestUpdate(ctx, pkt_data, pkt_len)) {
10009100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.",
10109100258SXin LI macname);
10209100258SXin LI goto mac_fail;
10309100258SXin LI }
10409100258SXin LI if (!EVP_DigestFinal(ctx, digest, &len)) {
10509100258SXin LI msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.",
10609100258SXin LI macname);
10709100258SXin LI len = 0;
10809100258SXin LI }
10909100258SXin LI #else /* !OPENSSL */
110a466cc55SCy Schubert (void)key_type; /* unused, so try to prevent compiler from croaks */
111a466cc55SCy Schubert if (!EVP_DigestInit(ctx, EVP_get_digestbynid(key_type))) {
112a466cc55SCy Schubert msyslog(LOG_ERR, "make_mac: MAC MD5 Digest Init failed.");
113a466cc55SCy Schubert goto mac_fail;
114a466cc55SCy Schubert }
11509100258SXin LI EVP_DigestUpdate(ctx, key_data, key_size);
116*f5f40dd6SCy Schubert EVP_DigestUpdate(ctx, pkt_data, pkt_len);
11709100258SXin LI EVP_DigestFinal(ctx, digest, &len);
11809100258SXin LI #endif
11909100258SXin LI mac_fail:
12009100258SXin LI EVP_MD_CTX_free(ctx);
12109100258SXin LI }
12209100258SXin LI
12309100258SXin LI return len;
12409100258SXin LI }
12509100258SXin LI
126*f5f40dd6SCy Schubert
127*f5f40dd6SCy Schubert size_t
make_mac(const void * pkt_data,size_t pkt_len,Key_T const * cmp_key,void * digest,size_t dig_sz)1282b15cb3dSCy Schubert make_mac(
12968ba7e87SXin LI const void * pkt_data,
130*f5f40dd6SCy Schubert size_t pkt_len,
13109100258SXin LI Key_T const * cmp_key,
132*f5f40dd6SCy Schubert void * digest,
133*f5f40dd6SCy Schubert size_t dig_sz
1342b15cb3dSCy Schubert )
1352b15cb3dSCy Schubert {
13609100258SXin LI u_int len;
13709100258SXin LI u_char dbuf[EVP_MAX_MD_SIZE];
1382b15cb3dSCy Schubert
139*f5f40dd6SCy Schubert if (cmp_key->key_len > 64 || pkt_len % 4 != 0) {
1402b15cb3dSCy Schubert return 0;
14109100258SXin LI }
142*f5f40dd6SCy Schubert len = compute_mac(dbuf, sizeof(dbuf), cmp_key->typen, pkt_data,
143*f5f40dd6SCy Schubert pkt_len, cmp_key->key_seq, cmp_key->key_len);
144*f5f40dd6SCy Schubert INSIST(len <= dig_sz);
145*f5f40dd6SCy Schubert memcpy(digest, dbuf, len);
146*f5f40dd6SCy Schubert
147*f5f40dd6SCy Schubert return len;
1482b15cb3dSCy Schubert }
1492b15cb3dSCy Schubert
1502b15cb3dSCy Schubert
15168ba7e87SXin LI /* Generates a md5 digest of the key specified in keyid concatenated with the
1522b15cb3dSCy Schubert * ntp packet (exluding the MAC) and compares this digest to the digest in
1532b15cb3dSCy Schubert * the packet's MAC. If they're equal this function returns 1 (packet is
1542b15cb3dSCy Schubert * authentic) or else 0 (not authentic).
1552b15cb3dSCy Schubert */
1562b15cb3dSCy Schubert int
auth_md5(void const * pkt_data,size_t pkt_len,size_t mac_len,Key_T const * cmp_key)1572b15cb3dSCy Schubert auth_md5(
15809100258SXin LI void const * pkt_data,
159*f5f40dd6SCy Schubert size_t pkt_len,
160*f5f40dd6SCy Schubert size_t mac_len,
16109100258SXin LI Key_T const * cmp_key
1622b15cb3dSCy Schubert )
1632b15cb3dSCy Schubert {
16409100258SXin LI u_int len = 0;
16509100258SXin LI u_char const * pkt_ptr = pkt_data;
16609100258SXin LI u_char dbuf[EVP_MAX_MD_SIZE];
16709100258SXin LI
168*f5f40dd6SCy Schubert if (0 == mac_len || mac_len > sizeof(dbuf)) {
16909100258SXin LI return FALSE;
170*f5f40dd6SCy Schubert }
171*f5f40dd6SCy Schubert len = compute_mac(dbuf, sizeof(dbuf), cmp_key->typen,
172*f5f40dd6SCy Schubert pkt_ptr, pkt_len, cmp_key->key_seq,
173*f5f40dd6SCy Schubert cmp_key->key_len);
17409100258SXin LI
175*f5f40dd6SCy Schubert pkt_ptr += pkt_len + sizeof(keyid_t);
17609100258SXin LI
17709100258SXin LI /* isc_tsmemcmp will be better when its easy to link with. sntp
17809100258SXin LI * is a 1-shot program, so snooping for timing attacks is
17909100258SXin LI * Harder.
1804990d495SXin LI */
181*f5f40dd6SCy Schubert return mac_len == len && !memcmp(dbuf, pkt_ptr, mac_len);
1822b15cb3dSCy Schubert }
1832b15cb3dSCy Schubert
1842b15cb3dSCy Schubert static int
hex_val(unsigned char x)1852b15cb3dSCy Schubert hex_val(
1862b15cb3dSCy Schubert unsigned char x
1872b15cb3dSCy Schubert )
1882b15cb3dSCy Schubert {
1892b15cb3dSCy Schubert int val;
1902b15cb3dSCy Schubert
1912b15cb3dSCy Schubert if ('0' <= x && x <= '9')
1922b15cb3dSCy Schubert val = x - '0';
1932b15cb3dSCy Schubert else if ('a' <= x && x <= 'f')
1942b15cb3dSCy Schubert val = x - 'a' + 0xa;
1952b15cb3dSCy Schubert else if ('A' <= x && x <= 'F')
1962b15cb3dSCy Schubert val = x - 'A' + 0xA;
1972b15cb3dSCy Schubert else
1982b15cb3dSCy Schubert val = -1;
1992b15cb3dSCy Schubert
2002b15cb3dSCy Schubert return val;
2012b15cb3dSCy Schubert }
2022b15cb3dSCy Schubert
2032b15cb3dSCy Schubert /* Load keys from the specified keyfile into the key structures.
2042b15cb3dSCy Schubert * Returns -1 if the reading failed, otherwise it returns the
2052b15cb3dSCy Schubert * number of keys it read
2062b15cb3dSCy Schubert */
2072b15cb3dSCy Schubert int
auth_init(const char * keyfile,struct key ** keys)2082b15cb3dSCy Schubert auth_init(
2092b15cb3dSCy Schubert const char *keyfile,
2102b15cb3dSCy Schubert struct key **keys
2112b15cb3dSCy Schubert )
2122b15cb3dSCy Schubert {
2132b15cb3dSCy Schubert FILE *keyf = fopen(keyfile, "r");
2142b15cb3dSCy Schubert struct key *prev = NULL;
21509100258SXin LI int scan_cnt, line_cnt = 1;
2162b15cb3dSCy Schubert char kbuf[200];
2172b15cb3dSCy Schubert char keystring[129];
2182b15cb3dSCy Schubert
21909100258SXin LI /* HMS: Is it OK to do this later, after we know we have a key file? */
22009100258SXin LI INIT_SSL();
22109100258SXin LI
2222b15cb3dSCy Schubert if (keyf == NULL) {
2232b15cb3dSCy Schubert if (debug)
2242b15cb3dSCy Schubert printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile);
2252b15cb3dSCy Schubert return -1;
2262b15cb3dSCy Schubert }
2272b15cb3dSCy Schubert if (feof(keyf)) {
2282b15cb3dSCy Schubert if (debug)
2292b15cb3dSCy Schubert printf("sntp auth_init: Key file %s is empty!\n", keyfile);
2302b15cb3dSCy Schubert fclose(keyf);
2312b15cb3dSCy Schubert return -1;
2322b15cb3dSCy Schubert }
2332b15cb3dSCy Schubert key_cnt = 0;
2342b15cb3dSCy Schubert while (!feof(keyf)) {
2352b15cb3dSCy Schubert char * octothorpe;
2362b15cb3dSCy Schubert struct key *act;
2372b15cb3dSCy Schubert int goodline = 0;
2382b15cb3dSCy Schubert
2392b15cb3dSCy Schubert if (NULL == fgets(kbuf, sizeof(kbuf), keyf))
2402b15cb3dSCy Schubert continue;
2412b15cb3dSCy Schubert
2422b15cb3dSCy Schubert kbuf[sizeof(kbuf) - 1] = '\0';
2432b15cb3dSCy Schubert octothorpe = strchr(kbuf, '#');
2442b15cb3dSCy Schubert if (octothorpe)
2452b15cb3dSCy Schubert *octothorpe = '\0';
2462b15cb3dSCy Schubert act = emalloc(sizeof(*act));
24709100258SXin LI /* keep width 15 = sizeof struct key.typen - 1 synced */
24809100258SXin LI scan_cnt = sscanf(kbuf, "%d %15s %128s",
24909100258SXin LI &act->key_id, act->typen, keystring);
2502b15cb3dSCy Schubert if (scan_cnt == 3) {
2512b15cb3dSCy Schubert int len = strlen(keystring);
25209100258SXin LI goodline = 1; /* assume best for now */
2532b15cb3dSCy Schubert if (len <= 20) {
2542b15cb3dSCy Schubert act->key_len = len;
2552b15cb3dSCy Schubert memcpy(act->key_seq, keystring, len + 1);
2562b15cb3dSCy Schubert } else if ((len & 1) != 0) {
2572b15cb3dSCy Schubert goodline = 0; /* it's bad */
2582b15cb3dSCy Schubert } else {
2592b15cb3dSCy Schubert int j;
2602b15cb3dSCy Schubert act->key_len = len >> 1;
2612b15cb3dSCy Schubert for (j = 0; j < len; j+=2) {
2622b15cb3dSCy Schubert int val;
2632b15cb3dSCy Schubert val = (hex_val(keystring[j]) << 4) |
2642b15cb3dSCy Schubert hex_val(keystring[j+1]);
2652b15cb3dSCy Schubert if (val < 0) {
2662b15cb3dSCy Schubert goodline = 0; /* it's bad */
2672b15cb3dSCy Schubert break;
2682b15cb3dSCy Schubert }
2692b15cb3dSCy Schubert act->key_seq[j>>1] = (char)val;
2702b15cb3dSCy Schubert }
2712b15cb3dSCy Schubert }
27209100258SXin LI act->typei = keytype_from_text(act->typen, NULL);
27309100258SXin LI if (0 == act->typei) {
27409100258SXin LI printf("%s: line %d: key %d, %s not supported - ignoring\n",
27509100258SXin LI keyfile, line_cnt,
27609100258SXin LI act->key_id, act->typen);
27709100258SXin LI goodline = 0; /* it's bad */
27809100258SXin LI }
2792b15cb3dSCy Schubert }
2802b15cb3dSCy Schubert if (goodline) {
2812b15cb3dSCy Schubert act->next = NULL;
2822b15cb3dSCy Schubert if (NULL == prev)
2832b15cb3dSCy Schubert *keys = act;
2842b15cb3dSCy Schubert else
2852b15cb3dSCy Schubert prev->next = act;
2862b15cb3dSCy Schubert prev = act;
2872b15cb3dSCy Schubert key_cnt++;
2882b15cb3dSCy Schubert } else {
28909100258SXin LI if (debug) {
29009100258SXin LI printf("auth_init: scanf %d items, skipping line %d.",
2912b15cb3dSCy Schubert scan_cnt, line_cnt);
29209100258SXin LI }
2932b15cb3dSCy Schubert free(act);
2942b15cb3dSCy Schubert }
2952b15cb3dSCy Schubert line_cnt++;
2962b15cb3dSCy Schubert }
2972b15cb3dSCy Schubert fclose(keyf);
2982b15cb3dSCy Schubert
2992b15cb3dSCy Schubert key_ptr = *keys;
3002b15cb3dSCy Schubert return key_cnt;
3012b15cb3dSCy Schubert }
3022b15cb3dSCy Schubert
3032b15cb3dSCy Schubert /* Looks for the key with keyid key_id and sets the d_key pointer to the
3042b15cb3dSCy Schubert * address of the key. If no matching key is found the pointer is not touched.
3052b15cb3dSCy Schubert */
3062b15cb3dSCy Schubert void
get_key(keyid_t key_id,struct key ** d_key)3072b15cb3dSCy Schubert get_key(
308*f5f40dd6SCy Schubert keyid_t key_id,
3092b15cb3dSCy Schubert struct key ** d_key
3102b15cb3dSCy Schubert )
3112b15cb3dSCy Schubert {
3122b15cb3dSCy Schubert struct key *itr_key;
3132b15cb3dSCy Schubert
314*f5f40dd6SCy Schubert if (key_cnt == 0) {
3152b15cb3dSCy Schubert return;
316*f5f40dd6SCy Schubert }
3172b15cb3dSCy Schubert for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) {
3182b15cb3dSCy Schubert if (itr_key->key_id == key_id) {
3192b15cb3dSCy Schubert *d_key = itr_key;
3202b15cb3dSCy Schubert break;
3212b15cb3dSCy Schubert }
3222b15cb3dSCy Schubert }
3232b15cb3dSCy Schubert return;
3242b15cb3dSCy Schubert }
325