コード例 #1
0
ファイル: val_sigcrypt.c プロジェクト: 2trill2spill/freebsd
/**
 * 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);
}
コード例 #2
0
ファイル: val_utils.c プロジェクト: RS-liuyang/rsdns
int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
{
	size_t i, num = rrset_get_count(ds_rrset);
	int d, digest_algo = 0; /* DS digest algo 0 is not used. */
	/* find favorite algo, for now, highest number supported */
	for(i=0; i<num; i++) {
		if(!ds_digest_algo_is_supported(ds_rrset, i) ||
			!ds_key_algo_is_supported(ds_rrset, i)) {
			continue;
		}
		d = ds_get_digest_algo(ds_rrset, i);
		if(d > digest_algo)
			digest_algo = d;
	}
	return digest_algo;
}
コード例 #3
0
ファイル: val_sigcrypt.c プロジェクト: Bluecoreg/monero
int ds_digest_match_dnskey(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* ds;	/* DS digest */
	size_t dslen;
	uint8_t* digest; /* generated digest */
	size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx);

	if(digestlen == 0) {
		verbose(VERB_QUERY, "DS fail: not supported, or DS RR "
			"format error");
		return 0; /* not supported, or DS RR format error */
	}
#ifndef USE_SHA1
	if(fake_sha1 && ds_get_digest_algo(ds_rrset, ds_idx)==LDNS_SHA1)
		return 1;
#endif
	
	/* check digest length in DS with length from hash function */
	ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen);
	if(!ds || dslen != digestlen) {
		verbose(VERB_QUERY, "DS fail: DS RR algo and digest do not "
			"match each other");
		return 0; /* DS algorithm and digest do not match */
	}

	digest = regional_alloc(env->scratch, digestlen);
	if(!digest) {
		verbose(VERB_QUERY, "DS fail: out of memory");
		return 0; /* mem error */
	}
	if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, 
		ds_idx, digest)) {
		verbose(VERB_QUERY, "DS fail: could not calc key digest");
		return 0; /* digest algo failed */
	}
	if(memcmp(digest, ds, dslen) != 0) {
		verbose(VERB_QUERY, "DS fail: digest is different");
		return 0; /* digest different */
	}
	return 1;
}
コード例 #4
0
ファイル: val_sigcrypt.c プロジェクト: 2trill2spill/freebsd
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
	int fav_ds_algo, uint8_t* sigalg)
{
	uint8_t algo;
	size_t i, total = 0;
	size_t num = rrset_get_count(ds);

	memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
	for(i=0; i<num; i++) {
		if(ds_get_digest_algo(ds, i) != fav_ds_algo)
			continue;
		algo = (uint8_t)ds_get_key_algo(ds, i);
		if(!dnskey_algo_id_is_supported((int)algo))
			continue;
		log_assert(algo != 0); /* we do not support 0 and is EOS */
		if(n->needs[algo] == 0) {
			n->needs[algo] = 1;
			sigalg[total] = algo;		
			total++;
		}
	}
	sigalg[total] = 0;
	n->num = total;
}
コード例 #5
0
ファイル: val_utils.c プロジェクト: RS-liuyang/rsdns
enum sec_status 
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
	struct ub_packed_rrset_key* dnskey_rrset,
	struct ub_packed_rrset_key* ds_rrset, char** reason)
{
	/* as long as this is false, we can consider this DS rrset to be
	 * equivalent to no DS rrset. */
	int has_useful_ds = 0, digest_algo, alg;
	struct algo_needs needs;
	size_t i, num;
	enum sec_status sec;

	if(dnskey_rrset->rk.dname_len != ds_rrset->rk.dname_len ||
		query_dname_compare(dnskey_rrset->rk.dname, ds_rrset->rk.dname)
		!= 0) {
		verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
			"by name");
		*reason = "DNSKEY RRset did not match DS RRset by name";
		return sec_status_bogus;
	}

	digest_algo = val_favorite_ds_algo(ds_rrset);
	algo_needs_init_ds(&needs, ds_rrset, digest_algo);
	num = rrset_get_count(ds_rrset);
	for(i=0; i<num; i++) {
		/* Check to see if we can understand this DS. 
		 * And check it is the strongest digest */
		if(!ds_digest_algo_is_supported(ds_rrset, i) ||
			!ds_key_algo_is_supported(ds_rrset, i) ||
			ds_get_digest_algo(ds_rrset, i) != digest_algo) {
			continue;
		}

		/* Once we see a single DS with a known digestID and 
		 * algorithm, we cannot return INSECURE (with a 
		 * "null" KeyEntry). */
		has_useful_ds = true;

		sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, 
			ds_rrset, i, reason);
		if(sec == sec_status_secure) {
			if(algo_needs_set_secure(&needs,
				(uint8_t)ds_get_key_algo(ds_rrset, i))) {
				verbose(VERB_ALGO, "DS matched DNSKEY.");
				return sec_status_secure;
			}
		} else if(sec == sec_status_bogus) {
			algo_needs_set_bogus(&needs,
				(uint8_t)ds_get_key_algo(ds_rrset, i));
		}
	}

	/* None of the DS's worked out. */

	/* If no DSs were understandable, then this is OK. */
	if(!has_useful_ds) {
		verbose(VERB_ALGO, "No usable DS records were found -- "
			"treating as insecure.");
		return sec_status_insecure;
	}
	/* If any were understandable, then it is bad. */
	verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
	if((alg=algo_needs_missing(&needs)) != 0) {
		algo_needs_reason(env, alg, reason, "missing verification of "
			"DNSKEY signature");
	}
	return sec_status_bogus;
}
コード例 #6
0
ファイル: val_utils.c プロジェクト: schvin/unbound
enum sec_status 
val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
	struct ub_packed_rrset_key* dnskey_rrset,
	struct ub_packed_rrset_key* ta_ds,
	struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason)
{
	/* as long as this is false, we can consider this anchor to be
	 * equivalent to no anchor. */
	int has_useful_ta = 0, digest_algo = 0, alg;
	struct algo_needs needs;
	size_t i, num;
	enum sec_status sec;

	if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len ||
		query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname)
		!= 0)) {
		verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
			"by name");
		*reason = "DNSKEY RRset did not match DS RRset by name";
		return sec_status_bogus;
	}
	if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
	     || query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname)
		!= 0)) {
		verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
			"by name");
		*reason = "DNSKEY RRset did not match anchor RRset by name";
		return sec_status_bogus;
	}

	if(ta_ds)
		digest_algo = val_favorite_ds_algo(ta_ds);
	if(sigalg) {
		if(ta_ds)
			algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg);
		else	memset(&needs, 0, sizeof(needs));
		if(ta_dnskey)
			algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg);
	}
	if(ta_ds) {
	    num = rrset_get_count(ta_ds);
	    for(i=0; i<num; i++) {
		/* Check to see if we can understand this DS. 
		 * And check it is the strongest digest */
		if(!ds_digest_algo_is_supported(ta_ds, i) ||
			!ds_key_algo_is_supported(ta_ds, i) ||
			ds_get_digest_algo(ta_ds, i) != digest_algo)
			continue;

		/* Once we see a single DS with a known digestID and 
		 * algorithm, we cannot return INSECURE (with a 
		 * "null" KeyEntry). */
		has_useful_ta = 1;

		sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, 
			ta_ds, i, reason);
		if(sec == sec_status_secure) {
			if(!sigalg || algo_needs_set_secure(&needs,
				(uint8_t)ds_get_key_algo(ta_ds, i))) {
				verbose(VERB_ALGO, "DS matched DNSKEY.");
				return sec_status_secure;
			}
		} else if(sigalg && sec == sec_status_bogus) {
			algo_needs_set_bogus(&needs,
				(uint8_t)ds_get_key_algo(ta_ds, i));
		}
	    }
	}

	/* None of the DS's worked out: check the DNSKEYs. */
	if(ta_dnskey) {
	    num = rrset_get_count(ta_dnskey);
	    for(i=0; i<num; i++) {
		/* Check to see if we can understand this DNSKEY */
		if(!dnskey_algo_is_supported(ta_dnskey, i))
			continue;

		/* we saw a useful TA */
		has_useful_ta = 1;

		sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
			ta_dnskey, i, reason);
		if(sec == sec_status_secure) {
			if(!sigalg || algo_needs_set_secure(&needs,
				(uint8_t)dnskey_get_algo(ta_dnskey, i))) {
				verbose(VERB_ALGO, "anchor matched DNSKEY.");
				return sec_status_secure;
			}
		} else if(sigalg && sec == sec_status_bogus) {
			algo_needs_set_bogus(&needs,
				(uint8_t)dnskey_get_algo(ta_dnskey, i));
		}
	    }
	}

	/* If no DSs were understandable, then this is OK. */
	if(!has_useful_ta) {
		verbose(VERB_ALGO, "No usable trust anchors were found -- "
			"treating as insecure.");
		return sec_status_insecure;
	}
	/* If any were understandable, then it is bad. */
	verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
	if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
		algo_needs_reason(env, alg, reason, "missing verification of "
			"DNSKEY signature");
	}
	return sec_status_bogus;
}
コード例 #7
0
ファイル: val_sigcrypt.c プロジェクト: 2trill2spill/freebsd
/**
 * Return size of DS digest according to its hash algorithm.
 * @param k: DS rrset.
 * @param idx: which DS.
 * @return size in bytes of digest, or 0 if not supported. 
 */
static size_t
ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx)
{
	return ds_digest_size_supported(ds_get_digest_algo(k, idx));
}