Beispiel #1
0
/**
 * Inser canonical owner name into buffer.
 * @param buf: buffer to insert into at current position.
 * @param k: rrset with its owner name.
 * @param sig: signature with signer name and label count.
 * 	must be length checked, at least 18 bytes long.
 * @param can_owner: position in buffer returned for future use.
 * @param can_owner_len: length of canonical owner name.
 */
static void
insert_can_owner(sldns_buffer* buf, struct ub_packed_rrset_key* k,
	uint8_t* sig, uint8_t** can_owner, size_t* can_owner_len)
{
	int rrsig_labels = (int)sig[3];
	int fqdn_labels = dname_signame_label_count(k->rk.dname);
	*can_owner = sldns_buffer_current(buf);
	if(rrsig_labels == fqdn_labels) {
		/* no change */
		sldns_buffer_write(buf, k->rk.dname, k->rk.dname_len);
		query_dname_tolower(*can_owner);
		*can_owner_len = k->rk.dname_len;
		return;
	}
	log_assert(rrsig_labels < fqdn_labels);
	/* *. | fqdn(rightmost rrsig_labels) */
	if(rrsig_labels < fqdn_labels) {
		int i;
		uint8_t* nm = k->rk.dname;
		size_t len = k->rk.dname_len;
		/* so skip fqdn_labels-rrsig_labels */
		for(i=0; i<fqdn_labels-rrsig_labels; i++) {
			dname_remove_label(&nm, &len);	
		}
		*can_owner_len = len+2;
		sldns_buffer_write(buf, (uint8_t*)"\001*", 2);
		sldns_buffer_write(buf, nm, len);
		query_dname_tolower(*can_owner);
	}
}
Beispiel #2
0
size_t
nsec3_get_hashed(sldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo, 
	size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max)
{
	size_t i, hash_len;
	/* prepare buffer for first iteration */
	sldns_buffer_clear(buf);
	sldns_buffer_write(buf, nm, nmlen);
	query_dname_tolower(sldns_buffer_begin(buf));
	sldns_buffer_write(buf, salt, saltlen);
	sldns_buffer_flip(buf);
	hash_len = nsec3_hash_algo_size_supported(algo);
	if(hash_len == 0) {
		log_err("nsec3 hash of unknown algo %d", algo);
		return 0;
	}
	if(hash_len > max)
		return 0;
	if(!secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf),
		sldns_buffer_limit(buf), (unsigned char*)res))
		return 0;
	for(i=0; i<iter; i++) {
		sldns_buffer_clear(buf);
		sldns_buffer_write(buf, res, hash_len);
		sldns_buffer_write(buf, salt, saltlen);
		sldns_buffer_flip(buf);
		if(!secalgo_nsec3_hash(algo,
			(unsigned char*)sldns_buffer_begin(buf),
			sldns_buffer_limit(buf), (unsigned char*)res))
			return 0;
	}
	return hash_len;
}
Beispiel #3
0
/**
 * Create a DS digest for a DNSKEY entry.
 *
 * @param env: module environment. Uses scratch space.
 * @param dnskey_rrset: DNSKEY rrset.
 * @param dnskey_idx: index of RR in rrset.
 * @param ds_rrset: DS rrset
 * @param ds_idx: index of RR in DS rrset.
 * @param digest: digest is returned in here (must be correctly sized).
 * @return false on error.
 */
static int
ds_create_dnskey_digest(struct module_env* env, 
	struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx,
	struct ub_packed_rrset_key* ds_rrset, size_t ds_idx,
	uint8_t* digest)
{
	sldns_buffer* b = env->scratch_buffer;
	uint8_t* dnskey_rdata;
	size_t dnskey_len;
	rrset_get_rdata(dnskey_rrset, dnskey_idx, &dnskey_rdata, &dnskey_len);

	/* create digest source material in buffer 
	 * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
	 *	DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. */
	sldns_buffer_clear(b);
	sldns_buffer_write(b, dnskey_rrset->rk.dname, 
		dnskey_rrset->rk.dname_len);
	query_dname_tolower(sldns_buffer_begin(b));
	sldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/
	sldns_buffer_flip(b);
	
	return secalgo_ds_digest(ds_get_digest_algo(ds_rrset, ds_idx),
		(unsigned char*)sldns_buffer_begin(b), sldns_buffer_limit(b),
		(unsigned char*)digest);
}
Beispiel #4
0
size_t
nsec3_get_hashed(ldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo, 
	size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max)
{
	size_t i, hash_len;
	/* prepare buffer for first iteration */
	ldns_buffer_clear(buf);
	ldns_buffer_write(buf, nm, nmlen);
	query_dname_tolower(ldns_buffer_begin(buf));
	ldns_buffer_write(buf, salt, saltlen);
	ldns_buffer_flip(buf);
	switch(algo) {
#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
		case NSEC3_HASH_SHA1:
#ifdef HAVE_SSL
			hash_len = SHA_DIGEST_LENGTH;
#else
			hash_len = SHA1_LENGTH;
#endif
			if(hash_len > max)
				return 0;
#  ifdef HAVE_SSL
			(void)SHA1((unsigned char*)ldns_buffer_begin(buf),
				(unsigned long)ldns_buffer_limit(buf),
				(unsigned char*)res);
#  else
			(void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
				(unsigned char*)ldns_buffer_begin(buf),
				(unsigned long)ldns_buffer_limit(buf));
#  endif
			for(i=0; i<iter; i++) {
				ldns_buffer_clear(buf);
				ldns_buffer_write(buf, res, hash_len);
				ldns_buffer_write(buf, salt, saltlen);
				ldns_buffer_flip(buf);
#  ifdef HAVE_SSL
				(void)SHA1(
					(unsigned char*)ldns_buffer_begin(buf),
					(unsigned long)ldns_buffer_limit(buf),
					(unsigned char*)res);
#  else
				(void)HASH_HashBuf(HASH_AlgSHA1,
					(unsigned char*)res,
					(unsigned char*)ldns_buffer_begin(buf),
					(unsigned long)ldns_buffer_limit(buf));
#  endif
			}
			break;
#endif /* HAVE_EVP_SHA1 or NSS */
		default:
			log_err("nsec3 hash of unknown algo %d", algo);
			return 0;
	}
	return hash_len;
}
Beispiel #5
0
/**
 * Create canonical form of rrset in the scratch buffer.
 * @param region: temporary region.
 * @param buf: the buffer to use.
 * @param k: the rrset to insert.
 * @param sig: RRSIG rdata to include.
 * @param siglen: RRSIG rdata len excluding signature field, but inclusive
 * 	signer name length.
 * @param sortree: if NULL is passed a new sorted rrset tree is built.
 * 	Otherwise it is reused.
 * @return false on alloc error.
 */
static int
rrset_canonical(struct regional* region, sldns_buffer* buf, 
	struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen,
	struct rbtree_t** sortree)
{
	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
	uint8_t* can_owner = NULL;
	size_t can_owner_len = 0;
	struct canon_rr* walk;
	struct canon_rr* rrs;

	if(!*sortree) {
		*sortree = (struct rbtree_t*)regional_alloc(region, 
			sizeof(rbtree_t));
		if(!*sortree)
			return 0;
		if(d->count > RR_COUNT_MAX)
			return 0; /* integer overflow protection */
		rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count);
		if(!rrs) {
			*sortree = NULL;
			return 0;
		}
		rbtree_init(*sortree, &canonical_tree_compare);
		canonical_sort(k, d, *sortree, rrs);
	}

	sldns_buffer_clear(buf);
	sldns_buffer_write(buf, sig, siglen);
	/* canonicalize signer name */
	query_dname_tolower(sldns_buffer_begin(buf)+18); 
	RBTREE_FOR(walk, struct canon_rr*, (*sortree)) {
		/* see if there is enough space left in the buffer */
		if(sldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4
			+ d->rr_len[walk->rr_idx]) {
			log_err("verify: failed to canonicalize, "
				"rrset too big");
			return 0;
		}
		/* determine canonical owner name */
		if(can_owner)
			sldns_buffer_write(buf, can_owner, can_owner_len);
		else	insert_can_owner(buf, k, sig, &can_owner, 
				&can_owner_len);
		sldns_buffer_write(buf, &k->rk.type, 2);
		sldns_buffer_write(buf, &k->rk.rrset_class, 2);
		sldns_buffer_write(buf, sig+4, 4);
		sldns_buffer_write(buf, d->rr_data[walk->rr_idx], 
			d->rr_len[walk->rr_idx]);
		canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]);
	}
	sldns_buffer_flip(buf);
	return 1;
}
Beispiel #6
0
/** test query_dname_tolower */
static void
dname_test_qdtl(sldns_buffer* buff)
{
	unit_show_func("util/data/dname.c", "query_dname_tolower");
	sldns_buffer_write_at(buff, 0, "\012abCDeaBCde\003cOm\000", 16);
	query_dname_tolower(sldns_buffer_begin(buff));
	unit_assert( memcmp(sldns_buffer_begin(buff), 
		"\012abcdeabcde\003com\000", 16) == 0);

	sldns_buffer_write_at(buff, 0, "\001+\012abC{e-ZYXe\003NET\000", 18);
	query_dname_tolower(sldns_buffer_begin(buff));
	unit_assert( memcmp(sldns_buffer_begin(buff), 
		"\001+\012abc{e-zyxe\003net\000", 18) == 0);

	sldns_buffer_write_at(buff, 0, "\000", 1);
	query_dname_tolower(sldns_buffer_begin(buff));
	unit_assert( memcmp(sldns_buffer_begin(buff), "\000", 1) == 0);

	sldns_buffer_write_at(buff, 0, "\002NL\000", 4);
	query_dname_tolower(sldns_buffer_begin(buff));
	unit_assert( memcmp(sldns_buffer_begin(buff), "\002nl\000", 4) == 0);
}
Beispiel #7
0
/** perform hash of name */
static int
nsec3_calc_hash(struct regional* region, sldns_buffer* buf, 
	struct nsec3_cached_hash* c)
{
	int algo = nsec3_get_algo(c->nsec3, c->rr);
	size_t iter = nsec3_get_iter(c->nsec3, c->rr);
	uint8_t* salt;
	size_t saltlen, i;
	if(!nsec3_get_salt(c->nsec3, c->rr, &salt, &saltlen))
		return -1;
	/* prepare buffer for first iteration */
	sldns_buffer_clear(buf);
	sldns_buffer_write(buf, c->dname, c->dname_len);
	query_dname_tolower(sldns_buffer_begin(buf));
	sldns_buffer_write(buf, salt, saltlen);
	sldns_buffer_flip(buf);
	c->hash_len = nsec3_hash_algo_size_supported(algo);
	if(c->hash_len == 0) {
		log_err("nsec3 hash of unknown algo %d", algo);
		return -1;
	}
	c->hash = (uint8_t*)regional_alloc(region, c->hash_len);
	if(!c->hash)
		return 0;
	(void)secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf),
		sldns_buffer_limit(buf), (unsigned char*)c->hash);
	for(i=0; i<iter; i++) {
		sldns_buffer_clear(buf);
		sldns_buffer_write(buf, c->hash, c->hash_len);
		sldns_buffer_write(buf, salt, saltlen);
		sldns_buffer_flip(buf);
		(void)secalgo_nsec3_hash(algo,
			(unsigned char*)sldns_buffer_begin(buf),
			sldns_buffer_limit(buf), (unsigned char*)c->hash);
	}
	return 1;
}
Beispiel #8
0
/** perform hash of name */
static int
nsec3_calc_hash(struct regional* region, ldns_buffer* buf, 
	struct nsec3_cached_hash* c)
{
	int algo = nsec3_get_algo(c->nsec3, c->rr);
	size_t iter = nsec3_get_iter(c->nsec3, c->rr);
	uint8_t* salt;
	size_t saltlen, i;
	if(!nsec3_get_salt(c->nsec3, c->rr, &salt, &saltlen))
		return -1;
	/* prepare buffer for first iteration */
	ldns_buffer_clear(buf);
	ldns_buffer_write(buf, c->dname, c->dname_len);
	query_dname_tolower(ldns_buffer_begin(buf));
	ldns_buffer_write(buf, salt, saltlen);
	ldns_buffer_flip(buf);
	switch(algo) {
#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
		case NSEC3_HASH_SHA1:
#ifdef HAVE_SSL
			c->hash_len = SHA_DIGEST_LENGTH;
#else
			c->hash_len = SHA1_LENGTH;
#endif
			c->hash = (uint8_t*)regional_alloc(region, 
				c->hash_len);
			if(!c->hash)
				return 0;
#  ifdef HAVE_SSL
			(void)SHA1((unsigned char*)ldns_buffer_begin(buf),
				(unsigned long)ldns_buffer_limit(buf),
				(unsigned char*)c->hash);
#  else
			(void)HASH_HashBuf(HASH_AlgSHA1,
				(unsigned char*)c->hash,
				(unsigned char*)ldns_buffer_begin(buf),
				(unsigned long)ldns_buffer_limit(buf));
#  endif
			for(i=0; i<iter; i++) {
				ldns_buffer_clear(buf);
				ldns_buffer_write(buf, c->hash, c->hash_len);
				ldns_buffer_write(buf, salt, saltlen);
				ldns_buffer_flip(buf);
#  ifdef HAVE_SSL
				(void)SHA1(
					(unsigned char*)ldns_buffer_begin(buf),
					(unsigned long)ldns_buffer_limit(buf),
					(unsigned char*)c->hash);
#  else
				(void)HASH_HashBuf(HASH_AlgSHA1,
					(unsigned char*)c->hash,
					(unsigned char*)ldns_buffer_begin(buf),
					(unsigned long)ldns_buffer_limit(buf));
#  endif
			}
			break;
#endif /* HAVE_EVP_SHA1 or NSS */
		default:
			log_err("nsec3 hash of unknown algo %d", algo);
			return -1;
	}
	return 1;
}
Beispiel #9
0
/**
 * Canonicalize Rdata in buffer.
 * @param buf: buffer at position just after the rdata.
 * @param rrset: rrset with type.
 * @param len: length of the rdata (including rdatalen uint16).
 */
static void
canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
	size_t len)
{
	uint8_t* datstart = sldns_buffer_current(buf)-len+2;
	switch(ntohs(rrset->rk.type)) {
		case LDNS_RR_TYPE_NXT: 
		case LDNS_RR_TYPE_NS:
		case LDNS_RR_TYPE_MD:
		case LDNS_RR_TYPE_MF:
		case LDNS_RR_TYPE_CNAME:
		case LDNS_RR_TYPE_MB:
		case LDNS_RR_TYPE_MG:
		case LDNS_RR_TYPE_MR:
		case LDNS_RR_TYPE_PTR:
		case LDNS_RR_TYPE_DNAME:
			/* type only has a single argument, the name */
			query_dname_tolower(datstart);
			return;
		case LDNS_RR_TYPE_MINFO:
		case LDNS_RR_TYPE_RP:
		case LDNS_RR_TYPE_SOA:
			/* two names after another */
			query_dname_tolower(datstart);
			query_dname_tolower(datstart + 
				dname_valid(datstart, len-2));
			return;
		case LDNS_RR_TYPE_RT:
		case LDNS_RR_TYPE_AFSDB:
		case LDNS_RR_TYPE_KX:
		case LDNS_RR_TYPE_MX:
			/* skip fixed part */
			if(len < 2+2+1) /* rdlen, skiplen, 1byteroot */
				return;
			datstart += 2;
			query_dname_tolower(datstart);
			return;
		case LDNS_RR_TYPE_SIG:
		/* downcase the RRSIG, compat with BIND (kept it from SIG) */
		case LDNS_RR_TYPE_RRSIG:
			/* skip fixed part */
			if(len < 2+18+1)
				return;
			datstart += 18;
			query_dname_tolower(datstart);
			return;
		case LDNS_RR_TYPE_PX:
			/* skip, then two names after another */
			if(len < 2+2+1) 
				return;
			datstart += 2;
			query_dname_tolower(datstart);
			query_dname_tolower(datstart + 
				dname_valid(datstart, len-2-2));
			return;
		case LDNS_RR_TYPE_NAPTR:
			if(len < 2+4)
				return;
			len -= 2+4;
			datstart += 4;
			if(len < (size_t)datstart[0]+1) /* skip text field */
				return;
			len -= (size_t)datstart[0]+1;
			datstart += (size_t)datstart[0]+1;
			if(len < (size_t)datstart[0]+1) /* skip text field */
				return;
			len -= (size_t)datstart[0]+1;
			datstart += (size_t)datstart[0]+1;
			if(len < (size_t)datstart[0]+1) /* skip text field */
				return;
			len -= (size_t)datstart[0]+1;
			datstart += (size_t)datstart[0]+1;
			if(len < 1)	/* check name is at least 1 byte*/
				return;
			query_dname_tolower(datstart);
			return;
		case LDNS_RR_TYPE_SRV:
			/* skip fixed part */
			if(len < 2+6+1)
				return;
			datstart += 6;
			query_dname_tolower(datstart);
			return;

		/* do not canonicalize NSEC rdata name, compat with 
		 * from bind 9.4 signer, where it does not do so */
		case LDNS_RR_TYPE_NSEC: /* type starts with the name */
		case LDNS_RR_TYPE_HINFO: /* not downcased */
		/* A6 not supported */
		default:	
			/* nothing to do for unknown types */
			return;
	}
}