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