Beispiel #1
0
void 
gldns_buffer_copy(gldns_buffer* result, gldns_buffer* from)
{
	size_t tocopy = gldns_buffer_limit(from);

	if(tocopy > gldns_buffer_capacity(result))
		tocopy = gldns_buffer_capacity(result);
	gldns_buffer_clear(result);
	gldns_buffer_write(result, gldns_buffer_begin(from), tocopy);
	gldns_buffer_flip(result);
}
Beispiel #2
0
getdns_return_t
getdns_rr_dict2str_scan(
    const getdns_dict *rr_dict, char **str, int *str_len)
{
	getdns_return_t r;
	gldns_buffer gbuf;
	uint8_t buf_spc[4096], *buf = buf_spc, *scan_buf;
	size_t sz, scan_sz;
	int prev_str_len;
	char *prev_str;
	int sz_needed;

	if (!rr_dict || !str || !*str || !str_len)
		return GETDNS_RETURN_INVALID_PARAMETER;

	gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
	r = _getdns_rr_dict2wire(rr_dict, &gbuf);
	if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
		if (!(buf = GETDNS_XMALLOC(
		    rr_dict->mf, uint8_t, (sz = gldns_buffer_position(&gbuf))))) {
			return GETDNS_RETURN_MEMORY_ERROR;
		}
		gldns_buffer_init_frm_data(&gbuf, buf, sz);
		r = _getdns_rr_dict2wire(rr_dict, &gbuf);
	}
	if (r) {
		if (buf != buf_spc)
			GETDNS_FREE(rr_dict->mf, buf);
		return r;
	}
	scan_buf = gldns_buffer_begin(&gbuf);
	scan_sz  = gldns_buffer_position(&gbuf);
	prev_str = *str;
	prev_str_len = *str_len;
	sz = (size_t)*str_len;
	sz_needed = gldns_wire2str_rr_scan(
	    &scan_buf, &scan_sz, str, &sz, NULL, 0);

	if (sz_needed > prev_str_len) {
		*str = prev_str + sz_needed;
		*str_len = prev_str_len - sz_needed;
		r = GETDNS_RETURN_NEED_MORE_SPACE;
	} else  {
		*str_len = sz;
		**str = 0;
	}
	if (buf != buf_spc)
		GETDNS_FREE(rr_dict->mf, buf);
	return r;
}
Beispiel #3
0
/**
 * Check a canonical sig+rrset and signature against a dnskey
 * @param buf: buffer with data to verify, the first rrsig part and the
 *	canonicalized rrset.
 * @param algo: DNSKEY algorithm.
 * @param sigblock: signature rdata field from RRSIG
 * @param sigblock_len: length of sigblock data.
 * @param key: public key data from DNSKEY RR.
 * @param keylen: length of keydata.
 * @param reason: bogus reason in more detail.
 * @return secure if verification succeeded, bogus on crypto failure,
 *	unchecked on format errors and alloc failures.
 */
int
_getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, 
	unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
	char** reason)
{
	const EVP_MD *digest_type;
	EVP_MD_CTX* ctx;
	int res, dofree = 0;
	EVP_PKEY *evp_key = NULL;
	
	if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
		verbose(VERB_QUERY, "verify: failed to setup key");
		*reason = "use of key for crypto failed";
		EVP_PKEY_free(evp_key);
		return 0;
	}
#ifdef USE_DSA
	/* if it is a DSA signature in bind format, convert to DER format */
	if((algo == GLDNS_DSA || algo == GLDNS_DSA_NSEC3) && 
		sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
		if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
			verbose(VERB_QUERY, "verify: failed to setup DSA sig");
			*reason = "use of key for DSA crypto failed";
			EVP_PKEY_free(evp_key);
			return 0;
		}
		dofree = 1;
	}
#endif
#if defined(USE_ECDSA) && defined(USE_DSA)
	else 
#endif
#ifdef USE_ECDSA
	if(algo == GLDNS_ECDSAP256SHA256 || algo == GLDNS_ECDSAP384SHA384) {
		/* EVP uses ASN prefix on sig, which is not in the wire data */
		if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
			verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
			*reason = "use of signature for ECDSA crypto failed";
			EVP_PKEY_free(evp_key);
			return 0;
		}
		dofree = 1;
	}
#endif /* USE_ECDSA */

	/* do the signature cryptography work */
#ifdef HAVE_EVP_MD_CTX_NEW
	ctx = EVP_MD_CTX_new();
#else
	ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
	if(ctx) EVP_MD_CTX_init(ctx);
#endif
	if(!ctx) {
		log_err("EVP_MD_CTX_new: malloc failure");
		EVP_PKEY_free(evp_key);
		if(dofree) free(sigblock);
		return 0;
	}
	if(EVP_VerifyInit(ctx, digest_type) == 0) {
		verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
		EVP_MD_CTX_destroy(ctx);
		EVP_PKEY_free(evp_key);
		if(dofree) free(sigblock);
		return 0;
	}
	if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), 
		(unsigned int)gldns_buffer_limit(buf)) == 0) {
		verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
		EVP_MD_CTX_destroy(ctx);
		EVP_PKEY_free(evp_key);
		if(dofree) free(sigblock);
		return 0;
	}

	res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
	EVP_MD_CTX_destroy(ctx);
	EVP_PKEY_free(evp_key);

	if(dofree)
		free(sigblock);

	if(res == 1) {
		return 1;
	} else if(res == 0) {
		verbose(VERB_QUERY, "verify: signature mismatch");
		*reason = "signature crypto failed";
		return 0;
	}

	log_crypto_error("verify:", ERR_get_error());
	return 0;
}
Beispiel #4
0
static char *
_verify_nettle_ecdsa(gldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
	unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
{
	int res = 0;
	struct ecc_point pubkey;
	struct dsa_signature signature;

	/* Always matched strength, as per RFC 6605 sec. 1 */
	if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
		return "wrong ECDSA signature length";
	}

	/* Parse ECDSA signature as per RFC 6605 sec. 4 */
	nettle_dsa_signature_init(&signature);
	switch (digest_size) {
		case SHA256_DIGEST_SIZE:
		{
			uint8_t digest[SHA256_DIGEST_SIZE];
			mpz_t x, y;
			nettle_ecc_point_init(&pubkey, &nettle_secp_256r1);
			nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
			nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
			nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
			nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
			res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
			res &= nettle_ecc_point_set(&pubkey, x, y);
			res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
			mpz_clear(x);
			mpz_clear(y);
			break;
		}
		case SHA384_DIGEST_SIZE:
		{
			uint8_t digest[SHA384_DIGEST_SIZE];
			mpz_t x, y;
			nettle_ecc_point_init(&pubkey, &nettle_secp_384r1);
			nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
			nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
			nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
			nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
			res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
			res &= nettle_ecc_point_set(&pubkey, x, y);
			res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
			mpz_clear(x);
			mpz_clear(y);
			nettle_ecc_point_clear(&pubkey);
			break;
		}
		default:
			return "unknown ECDSA algorithm";
	}

	/* Clear and return */
	nettle_dsa_signature_clear(&signature);
	if (!res)
		return "ECDSA signature verification failed";
	else
		return NULL;
}
Beispiel #5
0
static char *
_verify_nettle_rsa(gldns_buffer* buf, unsigned int digest_size, char* sigblock,
	unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
{
	uint16_t exp_len = 0;
	size_t exp_offset = 0, mod_offset = 0;
	struct rsa_public_key pubkey;
	mpz_t signature;
	int res = 0;

	/* RSA pubkey parsing as per RFC 3110 sec. 2 */
	if( keylen <= 1) {
		return "null RSA key";
	}
	if (key[0] != 0) {
		/* 1-byte length */
		exp_len = key[0];
		exp_offset = 1;
	} else {
		/* 1-byte NUL + 2-bytes exponent length */
		if (keylen < 3) {
			return "incorrect RSA key length";
		}
		exp_len = READ_UINT16(key+1);
		if (exp_len == 0)
			return "null RSA exponent length";
		exp_offset = 3;
	}
	/* Check that we are not over-running input length */
	if (keylen < exp_offset + exp_len + 1) {
		return "RSA key content shorter than expected";
	}
	mod_offset = exp_offset + exp_len;
	nettle_rsa_public_key_init(&pubkey);
	pubkey.size = keylen - mod_offset;
	nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
	nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);

	/* Digest content of "buf" and verify its RSA signature in "sigblock"*/
	nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
	switch (digest_size) {
		case SHA1_DIGEST_SIZE:
		{
			uint8_t digest[SHA1_DIGEST_SIZE];
			res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
			res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
			break;
		}
		case SHA256_DIGEST_SIZE:
		{
			uint8_t digest[SHA256_DIGEST_SIZE];
			res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
			res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
			break;
		}
		case SHA512_DIGEST_SIZE:
		{
			uint8_t digest[SHA512_DIGEST_SIZE];
			res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
			res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
			break;
		}
		default:
			break;
	}

	/* Clear and return */
	nettle_rsa_public_key_clear(&pubkey);
	mpz_clear(signature);
	if (!res) {
		return "RSA signature verification failed";
	} else {
		return NULL;
	}
}
Beispiel #6
0
static char *
_verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock,
	unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
{
	uint8_t digest[SHA1_DIGEST_SIZE];
	uint8_t key_t;
	int res = 0;
	size_t offset;
	struct dsa_public_key pubkey;
	struct dsa_signature signature;
	unsigned int expected_len;

	/* Extract DSA signature from the record */
	nettle_dsa_signature_init(&signature);
	/* Signature length: 41 bytes - RFC 2536 sec. 3 */
	if(sigblock_len == 41) {
		if(key[0] != sigblock[0])
			return "invalid T value in DSA signature or pubkey";
		nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
		nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
	} else {
		/* DER encoded, decode the ASN1 notated R and S bignums */
		/* SEQUENCE { r INTEGER, s INTEGER } */
		struct asn1_der_iterator i, seq;
		if(asn1_der_iterator_first(&i, sigblock_len,
			(uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
			|| i.type != ASN1_SEQUENCE)
			return "malformed DER encoded DSA signature";
		/* decode this element of i using the seq iterator */
		if(asn1_der_decode_constructed(&i, &seq) !=
			ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
			return "malformed DER encoded DSA signature";
		if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
			return "malformed DER encoded DSA signature";
		if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
			|| seq.type != ASN1_INTEGER)
			return "malformed DER encoded DSA signature";
		if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
			return "malformed DER encoded DSA signature";
		if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
			return "malformed DER encoded DSA signature";
	}

	/* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
	key_t = key[0];
	if (key_t > 8) {
		return "invalid T value in DSA pubkey";
	}

	/* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
	if (keylen < 21) {
		return "DSA pubkey too short";
	}

	expected_len =   1 +		/* T */
		        20 +		/* Q */
		       (64 + key_t*8) +	/* P */
		       (64 + key_t*8) +	/* G */
		       (64 + key_t*8);	/* Y */
	if (keylen != expected_len ) {
		return "invalid DSA pubkey length";
	}

	/* Extract DSA pubkey from the record */
	nettle_dsa_public_key_init(&pubkey);
	offset = 1;
	nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
	offset += 20;
	nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset);
	offset += (64 + key_t*8);
	nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset);
	offset += (64 + key_t*8);
	nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset);

	/* Digest content of "buf" and verify its DSA signature in "sigblock"*/
	res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf),
						(unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest);
	res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);

	/* Clear and return */
	nettle_dsa_signature_clear(&signature);
	nettle_dsa_public_key_clear(&pubkey);
	if (!res)
		return "DSA signature verification failed";
	else
		return NULL;
}
Beispiel #7
0
/**
 * Check a canonical sig+rrset and signature against a dnskey
 * @param buf: buffer with data to verify, the first rrsig part and the
 *	canonicalized rrset.
 * @param algo: DNSKEY algorithm.
 * @param sigblock: signature rdata field from RRSIG
 * @param sigblock_len: length of sigblock data.
 * @param key: public key data from DNSKEY RR.
 * @param keylen: length of keydata.
 * @param reason: bogus reason in more detail.
 * @return secure if verification succeeded, bogus on crypto failure,
 *	unchecked on format errors and alloc failures.
 */
int
_getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, 
	unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
	char** reason)
{
	/* uses libNSS */
	/* large enough for the different hashes */
	unsigned char hash[HASH_LENGTH_MAX];
	unsigned char hash2[HASH_LENGTH_MAX*2];
	HASH_HashType htype = 0;
	SECKEYPublicKey* pubkey = NULL;
	SECItem secsig = {siBuffer, sigblock, sigblock_len};
	SECItem sechash = {siBuffer, hash, 0};
	SECStatus res;
	unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
	size_t prefixlen = 0;
	int err;

	if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
		&prefix, &prefixlen)) {
		verbose(VERB_QUERY, "verify: failed to setup key");
		*reason = "use of key for crypto failed";
		SECKEY_DestroyPublicKey(pubkey);
		return 0;
	}

#ifdef USE_DSA
	/* need to convert DSA, ECDSA signatures? */
	if((algo == GLDNS_DSA || algo == GLDNS_DSA_NSEC3)) {
		if(sigblock_len == 1+2*SHA1_LENGTH) {
			secsig.data ++;
			secsig.len --;
		} else {
			SECItem* p = DSAU_DecodeDerSig(&secsig);
			if(!p) {
				verbose(VERB_QUERY, "verify: failed DER decode");
				*reason = "signature DER decode failed";
				SECKEY_DestroyPublicKey(pubkey);
				return 0;
			}
			if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
				log_err("alloc failure in DER decode");
				SECKEY_DestroyPublicKey(pubkey);
				SECITEM_FreeItem(p, PR_TRUE);
				return 0;
			}
			SECITEM_FreeItem(p, PR_TRUE);
		}
	}
#endif /* USE_DSA */

	/* do the signature cryptography work */
	/* hash the data */
	sechash.len = HASH_ResultLen(htype);
	if(sechash.len > sizeof(hash)) {
		verbose(VERB_QUERY, "verify: hash too large for buffer");
		SECKEY_DestroyPublicKey(pubkey);
		return 0;
	}
	if(HASH_HashBuf(htype, hash, (unsigned char*)gldns_buffer_begin(buf),
		(unsigned int)gldns_buffer_limit(buf)) != SECSuccess) {
		verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
		SECKEY_DestroyPublicKey(pubkey);
		return 0;
	}
	if(prefix) {
		int hashlen = sechash.len;
		if(prefixlen+hashlen > sizeof(hash2)) {
			verbose(VERB_QUERY, "verify: hashprefix too large");
			SECKEY_DestroyPublicKey(pubkey);
			return 0;
		}
		sechash.data = hash2;
		sechash.len = prefixlen+hashlen;
		memcpy(sechash.data, prefix, prefixlen);
		memmove(sechash.data+prefixlen, hash, hashlen);
	}

	/* verify the signature */
	res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
	SECKEY_DestroyPublicKey(pubkey);

	if(res == SECSuccess) {
		return 1;
	}
	err = PORT_GetError();
	if(err != SEC_ERROR_BAD_SIGNATURE) {
		/* failed to verify */
		verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
			PORT_ErrorToString(err));
		/* if it is not supported, like ECC is removed, we get,
		 * SEC_ERROR_NO_MODULE */
		if(err == SEC_ERROR_NO_MODULE)
			return 0;
		/* but other errors are commonly returned
		 * for a bad signature from NSS.  Thus we return bogus,
		 * not unchecked */
		*reason = "signature crypto failed";
		return 0;
	}
	verbose(VERB_QUERY, "verify: signature mismatch: %s",
		PORT_ErrorToString(err));
	*reason = "signature crypto failed";
	return 0;
}