mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'devel/codebase-maintenance2' into release/v1.0.0beta
This commit is contained in:
commit
7df26b6068
14
configure.ac
14
configure.ac
|
@ -223,7 +223,7 @@ else
|
|||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
|
@ -404,6 +404,18 @@ case "$enable_ecdsa" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
|
||||
case "$enable_dsa" in
|
||||
no)
|
||||
;;
|
||||
*) dnl default
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
AC_CHECK_FUNC(EVP_dss1, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(draft-dnssec-roadblock-avoidance, AC_HELP_STRING([--enable-draft-dnssec-roadblock-avoidance], [Enable experimental dnssec roadblock avoidance]))
|
||||
AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies]))
|
||||
|
|
|
@ -47,16 +47,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
|||
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
|
||||
AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
|
||||
LIBS="-lssl -lcrypto $LIBS"
|
||||
LIBSSL_LIBS="-lssl -lcrypto $LIBSSL_LIBS"
|
||||
AC_TRY_LINK(, [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
int HMAC_Update(void);
|
||||
(void)HMAC_Update();
|
||||
], [
|
||||
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
|
||||
[If you have HMAC_Update])
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
# check if -lwsock32 or -lgdi32 are needed.
|
||||
|
@ -66,11 +66,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
|||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
int HMAC_Update(void);
|
||||
(void)HMAC_Update();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
|
||||
[If you have HMAC_Update])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
|
@ -80,11 +80,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
|||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_TRY_LINK([], [
|
||||
int HMAC_CTX_init(void);
|
||||
(void)HMAC_CTX_init();
|
||||
int HMAC_Update(void);
|
||||
(void)HMAC_Update();
|
||||
],[
|
||||
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
|
||||
[If you have HMAC_CTX_init])
|
||||
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
|
||||
[If you have HMAC_Update])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
|
|
|
@ -1942,7 +1942,8 @@ getdns_return_t
|
|||
getdns_context_set_dns_root_servers(
|
||||
getdns_context *context, getdns_list *addresses)
|
||||
{
|
||||
#if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB)
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
# ifndef HAVE_UB_CTX_SET_STUB
|
||||
char tmpfn[FILENAME_MAX] = P_tmpdir "/getdns-root-dns-servers-XXXXXX";
|
||||
FILE *fh;
|
||||
int fd;
|
||||
|
@ -1953,6 +1954,7 @@ getdns_context_set_dns_root_servers(
|
|||
getdns_return_t r;
|
||||
getdns_bindata *addr_bd;
|
||||
char dst[2048];
|
||||
#endif
|
||||
getdns_list *newlist;
|
||||
|
||||
if (!context)
|
||||
|
@ -2909,9 +2911,22 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
|
|||
if (context->tls_ctx == NULL) {
|
||||
#ifdef HAVE_TLS_v1_2
|
||||
/* Create client context, use TLS v1.2 only for now */
|
||||
# ifdef HAVE_TLS_CLIENT_METHOD
|
||||
context->tls_ctx = SSL_CTX_new(TLS_client_method());
|
||||
# else
|
||||
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
|
||||
# endif
|
||||
if(context->tls_ctx == NULL)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
|
||||
# ifdef HAVE_TLS_CLIENT_METHOD
|
||||
if (!SSL_CTX_set_min_proto_version(
|
||||
context->tls_ctx, TLS1_2_VERSION)) {
|
||||
SSL_CTX_free(context->tls_ctx);
|
||||
context->tls_ctx = NULL;
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
# endif
|
||||
/* Be strict and only use the cipher suites recommended in RFC7525
|
||||
Unless we later fallback to opportunistic. */
|
||||
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
|
||||
|
|
|
@ -144,6 +144,12 @@ static const gldns_rdf_type type_dhcid_wireformat[] = {
|
|||
static const gldns_rdf_type type_talink_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_DNAME, GLDNS_RDF_TYPE_DNAME
|
||||
};
|
||||
static const gldns_rdf_type type_openpgpkey_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_B64
|
||||
};
|
||||
static const gldns_rdf_type type_csync_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_NSEC
|
||||
};
|
||||
/* nsec3 is some vars, followed by same type of data of nsec */
|
||||
static const gldns_rdf_type type_nsec3_wireformat[] = {
|
||||
/* GLDNS_RDF_TYPE_NSEC3_VARS, GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER, GLDNS_RDF_TYPE_NSEC*/
|
||||
|
@ -361,8 +367,10 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
|
|||
{GLDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 60 */
|
||||
{GLDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 61 */
|
||||
{GLDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 62 */
|
||||
{GLDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
|
|
|
@ -182,6 +182,8 @@ enum gldns_enum_rr_type
|
|||
GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
|
||||
GLDNS_RR_TYPE_NSEC3PARAMS = 51,
|
||||
GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
|
||||
GLDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may
|
||||
be extended */
|
||||
|
||||
GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
|
||||
|
||||
|
@ -193,6 +195,8 @@ enum gldns_enum_rr_type
|
|||
GLDNS_RR_TYPE_TALINK = 58,
|
||||
GLDNS_RR_TYPE_CDS = 59, /** RFC 7344 */
|
||||
GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
|
||||
GLDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */
|
||||
GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
|
||||
|
||||
GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ rrinternal_get_owner(gldns_buffer* strbuf, uint8_t* rr, size_t* len,
|
|||
return RET_ERR(GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
|
||||
gldns_buffer_position(strbuf));
|
||||
memmove(rr, tocopy, *dname_len);
|
||||
} else if(strlen(token) == 0) {
|
||||
} else if(*token == '\0') {
|
||||
/* no ownername was given, try prev, if that fails
|
||||
* origin, else default to root */
|
||||
uint8_t* tocopy;
|
||||
|
@ -1091,7 +1091,7 @@ int gldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
uint8_t prefix;
|
||||
size_t i;
|
||||
|
||||
if(strlen(my_str) == 0) {
|
||||
if(*my_str == '\0') {
|
||||
/* empty APL element, no data, no string */
|
||||
*len = 0;
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
|
|
|
@ -393,18 +393,13 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
|
|||
}
|
||||
|
||||
x = sk_X509_value(store->untrusted, i);
|
||||
if (x->cert_info == NULL)
|
||||
continue;
|
||||
#if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
DEBUG_STUB("%s %-35s: Name of cert: %d ",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i);
|
||||
if (x->cert_info->subject != NULL)
|
||||
X509_NAME_print_ex_fp(stderr, x->cert_info->subject, 1, XN_FLAG_ONELINE);
|
||||
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (x->cert_info->key == NULL)
|
||||
continue;
|
||||
|
||||
/* digest the cert with sha256 */
|
||||
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
|
||||
if (len > sizeof(raw)) {
|
||||
|
|
|
@ -461,7 +461,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
unsigned int result_mac_len = EVP_MAX_MD_SIZE;
|
||||
uint16_t original_id;
|
||||
const EVP_MD *digester;
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
|
||||
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNCTION__);
|
||||
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
|
||||
|
@ -589,14 +592,18 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
#endif
|
||||
default : return;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&ctx);
|
||||
(void) HMAC_Init_ex(&ctx, req->upstream->tsig_key,
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
ctx = HMAC_CTX_new();
|
||||
#else
|
||||
ctx = &ctx_space;
|
||||
HMAC_CTX_init(ctx);
|
||||
#endif
|
||||
(void) HMAC_Init_ex(ctx, req->upstream->tsig_key,
|
||||
req->upstream->tsig_size, digester, NULL);
|
||||
(void) HMAC_Update(&ctx, request_mac - 2, request_mac_len + 2);
|
||||
(void) HMAC_Update(&ctx, req->response, rr->pos - req->response);
|
||||
(void) HMAC_Update(&ctx, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
HMAC_Final(&ctx, result_mac, &result_mac_len);
|
||||
(void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2);
|
||||
(void) HMAC_Update(ctx, req->response, rr->pos - req->response);
|
||||
(void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
HMAC_Final(ctx, result_mac, &result_mac_len);
|
||||
|
||||
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
||||
STUB_DEBUG_TSIG, __FUNCTION__, (int)(result_mac_len));
|
||||
|
@ -604,8 +611,11 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
memcmp(result_mac, response_mac, result_mac_len) == 0)
|
||||
req->tsig_status = GETDNS_DNSSEC_SECURE;
|
||||
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_FREE
|
||||
HMAC_CTX_free(ctx);
|
||||
#else
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
#endif
|
||||
gldns_write_uint16(req->response, gldns_read_uint16(req->query));
|
||||
gldns_write_uint16(req->response + 10,
|
||||
gldns_read_uint16(req->response + 10) + 1);
|
||||
|
|
|
@ -57,7 +57,9 @@ typedef struct getdns_sync_data {
|
|||
static getdns_return_t
|
||||
getdns_sync_data_init(getdns_context *context, getdns_sync_data *data)
|
||||
{
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
getdns_eventloop *ext = &context->sync_eventloop.loop;
|
||||
#endif
|
||||
|
||||
data->context = context;
|
||||
data->to_run = 1;
|
||||
|
|
|
@ -154,10 +154,10 @@ nolibcheck:
|
|||
test: $(NOLIBCHECK) all
|
||||
(cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}')
|
||||
rm -f fails
|
||||
CK_LOG_FILE_NAME="$(CHECK_GETDNS).log" ./$(CHECK_GETDNS) || echo "$(CHECK_GETDNS) failed" >> fails
|
||||
if test $(have_libevent) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_EVENT_PROG).log" ./$(CHECK_EVENT_PROG) || echo "$(CHECK_EVENT_PROG) failed" >> fails; fi
|
||||
if test $(have_libev) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_EV_PROG).log" ./$(CHECK_EV_PROG) || echo "$(CHECK_EV_PROG) failed" >> fails; fi
|
||||
if test $(have_libuv) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_UV_PROG).log" ./$(CHECK_UV_PROG) || echo "$(CHECK_UV_PROG) failed" >> fails; fi
|
||||
CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_GETDNS).log" ./$(CHECK_GETDNS) || echo "$(CHECK_GETDNS) failed" >> fails
|
||||
if test $(have_libevent) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_EVENT_PROG).log" ./$(CHECK_EVENT_PROG) || echo "$(CHECK_EVENT_PROG) failed" >> fails; fi
|
||||
if test $(have_libev) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_EV_PROG).log" ./$(CHECK_EV_PROG) || echo "$(CHECK_EV_PROG) failed" >> fails; fi
|
||||
if test $(have_libuv) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_UV_PROG).log" ./$(CHECK_UV_PROG) || echo "$(CHECK_UV_PROG) failed" >> fails; fi
|
||||
test ! -e fails
|
||||
@echo "All tests OK"
|
||||
|
||||
|
|
|
@ -401,7 +401,7 @@
|
|||
struct getdns_context *context = NULL;
|
||||
struct getdns_dict *address = NULL;
|
||||
struct getdns_bindata address_type = { 5, (void *)"IPv6" };
|
||||
struct getdns_bindata address_data = { 16, (void *)"\x2a\x04\xb9\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x37" };
|
||||
struct getdns_bindata address_data = { 16, (void *)"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88" };
|
||||
void* eventloop = NULL;
|
||||
getdns_transaction_t transaction_id = 0;
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@
|
|||
struct getdns_context *context = NULL;
|
||||
struct getdns_dict *address = NULL;
|
||||
struct getdns_bindata address_type = { 5, (void *)"IPv6" };
|
||||
struct getdns_bindata address_data = { 16, (void *)"\x2a\x04\xb9\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x37" };
|
||||
struct getdns_bindata address_data = { 16, (void *)"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88" };
|
||||
struct getdns_dict *response = NULL;
|
||||
|
||||
CONTEXT_CREATE(TRUE);
|
||||
|
|
|
@ -39,6 +39,7 @@ do
|
|||
-e '/^#include "util\/data\/packed_rrset.h"$/d' \
|
||||
-e 's/^#include "validator/#include "util/g' \
|
||||
-e 's/^#include "gldns\/sbuffer/#include "gldns\/gbuffer/g' \
|
||||
-e 's/^#include "util\/val_nsec3.h"/#define NSEC3_HASH_SHA1 0x01/g' \
|
||||
-e 's/ds_digest_size_supported/_getdns_ds_digest_size_supported/g' \
|
||||
-e 's/secalgo_ds_digest/_getdns_secalgo_ds_digest/g' \
|
||||
-e 's/dnskey_algo_id_is_supported/_getdns_dnskey_algo_id_is_supported/g' \
|
||||
|
|
|
@ -68,7 +68,7 @@ static void _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode
|
|||
static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* child, _getdns_rbnode_t* child_parent);
|
||||
|
||||
/*
|
||||
* Creates a new red black tree, intializes and returns a pointer to it.
|
||||
* Creates a new red black tree, initializes and returns a pointer to it.
|
||||
*
|
||||
* Return NULL on failure.
|
||||
*
|
||||
|
|
|
@ -42,12 +42,13 @@
|
|||
*/
|
||||
#include "config.h"
|
||||
#include "util/val_secalgo.h"
|
||||
#define NSEC3_HASH_SHA1 0x01
|
||||
#include "util/log.h"
|
||||
#include "gldns/rrdef.h"
|
||||
#include "gldns/keyraw.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
|
||||
#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
|
||||
#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
|
||||
#error "Need crypto library to do digital signature cryptography"
|
||||
#endif
|
||||
|
||||
|
@ -69,6 +70,32 @@
|
|||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
/* return size of digest if supported, or 0 otherwise */
|
||||
size_t
|
||||
nsec3_hash_algo_size_supported(int id)
|
||||
{
|
||||
switch(id) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
return SHA_DIGEST_LENGTH;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform nsec3 hash. return false on failure */
|
||||
int
|
||||
secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res)
|
||||
{
|
||||
switch(algo) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
(void)SHA1(buf, len, res);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of DS digest according to its hash algorithm.
|
||||
* @param algo: DS digest algo.
|
||||
|
@ -88,6 +115,7 @@ _getdns_ds_digest_size_supported(int algo)
|
|||
#endif
|
||||
#ifdef USE_GOST
|
||||
case GLDNS_HASH_GOST:
|
||||
/* we support GOST if it can be loaded */
|
||||
(void)gldns_key_EVP_load_gost_id();
|
||||
if(EVP_get_digestbyname("md_gost94"))
|
||||
return 32;
|
||||
|
@ -156,8 +184,10 @@ _getdns_dnskey_algo_id_is_supported(int id)
|
|||
case GLDNS_RSAMD5:
|
||||
/* RFC 6725 deprecates RSAMD5 */
|
||||
return 0;
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
#endif
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
|
@ -197,6 +227,7 @@ log_crypto_error(const char* str, unsigned long e)
|
|||
log_err("%s crypto %s", str, buf);
|
||||
}
|
||||
|
||||
#ifdef USE_DSA
|
||||
/**
|
||||
* Setup DSA key digest in DER encoding ...
|
||||
* @param sig: input is signature output alloced ptr (unless failure).
|
||||
|
@ -238,6 +269,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
|
|||
DSA_SIG_free(dsasig);
|
||||
return 1;
|
||||
}
|
||||
#endif /* USE_DSA */
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
/**
|
||||
|
@ -251,32 +283,61 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
|
|||
static int
|
||||
setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
|
||||
{
|
||||
ECDSA_SIG* ecdsa_sig;
|
||||
int newlen;
|
||||
/* convert from two BIGNUMs in the rdata buffer, to ASN notation.
|
||||
* ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
|
||||
* the '20' is the length of that field (=bnsize).
|
||||
i * the '44' is the total remaining length.
|
||||
* if negative, start with leading zero.
|
||||
* if starts with 00s, remove them from the number.
|
||||
*/
|
||||
uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
|
||||
int pre_len = 4;
|
||||
uint8_t mid[] = {0x02, 0x20};
|
||||
int mid_len = 2;
|
||||
int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
|
||||
int bnsize = (int)((*len)/2);
|
||||
unsigned char* d = *sig;
|
||||
uint8_t* p;
|
||||
/* if too short or not even length, fails */
|
||||
if(*len < 16 || bnsize*2 != (int)*len)
|
||||
return 0;
|
||||
/* use the raw data to parse two evenly long BIGNUMs, "r | s". */
|
||||
ecdsa_sig = ECDSA_SIG_new();
|
||||
if(!ecdsa_sig) return 0;
|
||||
ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
|
||||
ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
|
||||
if(!ecdsa_sig->r || !ecdsa_sig->s) {
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* spool it into ASN format */
|
||||
*sig = NULL;
|
||||
newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
|
||||
if(newlen <= 0) {
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
free(*sig);
|
||||
/* strip leading zeroes from r (but not last one) */
|
||||
while(r_rem < bnsize-1 && d[r_rem] == 0)
|
||||
r_rem++;
|
||||
/* strip leading zeroes from s (but not last one) */
|
||||
while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
|
||||
s_rem++;
|
||||
|
||||
r_high = ((d[0+r_rem]&0x80)?1:0);
|
||||
s_high = ((d[bnsize+s_rem]&0x80)?1:0);
|
||||
raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
|
||||
s_high + bnsize - s_rem;
|
||||
*sig = (unsigned char*)malloc((size_t)raw_sig_len);
|
||||
if(!*sig)
|
||||
return 0;
|
||||
p = (uint8_t*)*sig;
|
||||
p[0] = pre[0];
|
||||
p[1] = (uint8_t)(raw_sig_len-2);
|
||||
p[2] = pre[2];
|
||||
p[3] = (uint8_t)(bnsize + r_high - r_rem);
|
||||
p += 4;
|
||||
if(r_high) {
|
||||
*p = 0;
|
||||
p += 1;
|
||||
}
|
||||
*len = (unsigned int)newlen;
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
memmove(p, d+r_rem, (size_t)bnsize-r_rem);
|
||||
p += bnsize-r_rem;
|
||||
memmove(p, mid, (size_t)mid_len-1);
|
||||
p += mid_len-1;
|
||||
*p = (uint8_t)(bnsize + s_high - s_rem);
|
||||
p += 1;
|
||||
if(s_high) {
|
||||
*p = 0;
|
||||
p += 1;
|
||||
}
|
||||
memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
|
||||
*len = (unsigned int)raw_sig_len;
|
||||
return 1;
|
||||
}
|
||||
#endif /* USE_ECDSA */
|
||||
|
@ -295,10 +356,13 @@ static int
|
|||
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
||||
unsigned char* key, size_t keylen)
|
||||
{
|
||||
#ifdef USE_DSA
|
||||
DSA* dsa;
|
||||
#endif
|
||||
RSA* rsa;
|
||||
|
||||
switch(algo) {
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
*evp_key = EVP_PKEY_new();
|
||||
|
@ -320,6 +384,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
|||
*digest_type = EVP_dss1();
|
||||
|
||||
break;
|
||||
#endif /* USE_DSA */
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
|
@ -478,7 +543,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
char** reason)
|
||||
{
|
||||
const EVP_MD *digest_type;
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX* ctx;
|
||||
int res, dofree = 0;
|
||||
EVP_PKEY *evp_key = NULL;
|
||||
|
||||
|
@ -488,6 +553,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
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) {
|
||||
|
@ -499,8 +565,12 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
}
|
||||
dofree = 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_ECDSA) && defined(USE_DSA)
|
||||
else
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
else if(algo == GLDNS_ECDSAP256SHA256 || algo == GLDNS_ECDSAP384SHA384) {
|
||||
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");
|
||||
|
@ -513,28 +583,36 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
#endif /* USE_ECDSA */
|
||||
|
||||
/* do the signature cryptography work */
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
if(EVP_VerifyInit(&ctx, digest_type) == 0) {
|
||||
verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
|
||||
#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_VerifyUpdate(&ctx, (unsigned char*)gldns_buffer_begin(buf),
|
||||
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);
|
||||
if(EVP_MD_CTX_cleanup(&ctx) == 0) {
|
||||
verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
|
||||
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)
|
||||
|
@ -564,6 +642,32 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
/* nspr4 */
|
||||
#include "prerror.h"
|
||||
|
||||
/* return size of digest if supported, or 0 otherwise */
|
||||
size_t
|
||||
nsec3_hash_algo_size_supported(int id)
|
||||
{
|
||||
switch(id) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
return SHA1_LENGTH;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform nsec3 hash. return false on failure */
|
||||
int
|
||||
secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res)
|
||||
{
|
||||
switch(algo) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
(void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
_getdns_ds_digest_size_supported(int algo)
|
||||
{
|
||||
|
@ -622,8 +726,10 @@ _getdns_dnskey_algo_id_is_supported(int id)
|
|||
case GLDNS_RSAMD5:
|
||||
/* RFC 6725 deprecates RSAMD5 */
|
||||
return 0;
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
#endif
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
#ifdef USE_SHA2
|
||||
|
@ -864,6 +970,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
|||
*/
|
||||
|
||||
switch(algo) {
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
*pubkey = nss_buf2dsa(key, keylen);
|
||||
|
@ -874,6 +981,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
|||
*htype = HASH_AlgSHA1;
|
||||
/* no prefix for DSA verification */
|
||||
break;
|
||||
#endif
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
#ifdef USE_SHA2
|
||||
|
@ -990,6 +1098,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
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) {
|
||||
|
@ -1012,6 +1121,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
SECITEM_FreeItem(p, PR_TRUE);
|
||||
}
|
||||
}
|
||||
#endif /* USE_DSA */
|
||||
|
||||
/* do the signature cryptography work */
|
||||
/* hash the data */
|
||||
|
@ -1068,5 +1178,470 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_NETTLE)
|
||||
|
||||
#endif /* HAVE_SSL or HAVE_NSS */
|
||||
#include "sha.h"
|
||||
#include "bignum.h"
|
||||
#include "macros.h"
|
||||
#include "rsa.h"
|
||||
#include "dsa.h"
|
||||
#include "asn1.h"
|
||||
#ifdef USE_ECDSA
|
||||
#include "ecdsa.h"
|
||||
#include "ecc-curve.h"
|
||||
#endif
|
||||
|
||||
static int
|
||||
_digest_nettle(int algo, uint8_t* buf, size_t len,
|
||||
unsigned char* res)
|
||||
{
|
||||
switch(algo) {
|
||||
case SHA1_DIGEST_SIZE:
|
||||
{
|
||||
struct sha1_ctx ctx;
|
||||
sha1_init(&ctx);
|
||||
sha1_update(&ctx, len, buf);
|
||||
sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
|
||||
return 1;
|
||||
}
|
||||
case SHA256_DIGEST_SIZE:
|
||||
{
|
||||
struct sha256_ctx ctx;
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, len, buf);
|
||||
sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
|
||||
return 1;
|
||||
}
|
||||
case SHA384_DIGEST_SIZE:
|
||||
{
|
||||
struct sha384_ctx ctx;
|
||||
sha384_init(&ctx);
|
||||
sha384_update(&ctx, len, buf);
|
||||
sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
|
||||
return 1;
|
||||
}
|
||||
case SHA512_DIGEST_SIZE:
|
||||
{
|
||||
struct sha512_ctx ctx;
|
||||
sha512_init(&ctx);
|
||||
sha512_update(&ctx, len, buf);
|
||||
sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return size of digest if supported, or 0 otherwise */
|
||||
size_t
|
||||
nsec3_hash_algo_size_supported(int id)
|
||||
{
|
||||
switch(id) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
return SHA1_DIGEST_SIZE;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform nsec3 hash. return false on failure */
|
||||
int
|
||||
secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res)
|
||||
{
|
||||
switch(algo) {
|
||||
case NSEC3_HASH_SHA1:
|
||||
return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len,
|
||||
res);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of DS digest according to its hash algorithm.
|
||||
* @param algo: DS digest algo.
|
||||
* @return size in bytes of digest, or 0 if not supported.
|
||||
*/
|
||||
size_t
|
||||
_getdns_ds_digest_size_supported(int algo)
|
||||
{
|
||||
switch(algo) {
|
||||
case GLDNS_SHA1:
|
||||
return SHA1_DIGEST_SIZE;
|
||||
#ifdef USE_SHA2
|
||||
case GLDNS_SHA256:
|
||||
return SHA256_DIGEST_SIZE;
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
case GLDNS_SHA384:
|
||||
return SHA384_DIGEST_SIZE;
|
||||
#endif
|
||||
/* GOST not supported */
|
||||
case GLDNS_HASH_GOST:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res)
|
||||
{
|
||||
switch(algo) {
|
||||
case GLDNS_SHA1:
|
||||
return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
|
||||
#if defined(USE_SHA2)
|
||||
case GLDNS_SHA256:
|
||||
return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
case GLDNS_SHA384:
|
||||
return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
|
||||
|
||||
#endif
|
||||
case GLDNS_HASH_GOST:
|
||||
default:
|
||||
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
||||
algo);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_getdns_dnskey_algo_id_is_supported(int id)
|
||||
{
|
||||
/* uses libnettle */
|
||||
switch(id) {
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
#endif
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
#ifdef USE_SHA2
|
||||
case GLDNS_RSASHA256:
|
||||
case GLDNS_RSASHA512:
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
case GLDNS_ECDSAP256SHA256:
|
||||
case GLDNS_ECDSAP384SHA384:
|
||||
#endif
|
||||
return 1;
|
||||
case GLDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
|
||||
case GLDNS_ECC_GOST:
|
||||
default:
|
||||
return 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
unsigned int digest_size = 0;
|
||||
|
||||
if (sigblock_len == 0 || keylen == 0) {
|
||||
*reason = "null signature";
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(algo) {
|
||||
#ifdef USE_DSA
|
||||
case GLDNS_DSA:
|
||||
case GLDNS_DSA_NSEC3:
|
||||
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
|
||||
if (*reason != NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
#endif /* USE_DSA */
|
||||
|
||||
case GLDNS_RSASHA1:
|
||||
case GLDNS_RSASHA1_NSEC3:
|
||||
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
|
||||
#ifdef USE_SHA2
|
||||
case GLDNS_RSASHA256:
|
||||
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
|
||||
case GLDNS_RSASHA512:
|
||||
digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
|
||||
|
||||
#endif
|
||||
*reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
|
||||
sigblock_len, key, keylen);
|
||||
if (*reason != NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
case GLDNS_ECDSAP256SHA256:
|
||||
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
|
||||
case GLDNS_ECDSAP384SHA384:
|
||||
digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
|
||||
*reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
|
||||
sigblock_len, key, keylen);
|
||||
if (*reason != NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
case GLDNS_RSAMD5:
|
||||
case GLDNS_ECC_GOST:
|
||||
default:
|
||||
*reason = "unable to verify signature, unknown algorithm";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
|
||||
|
|
|
@ -44,6 +44,21 @@
|
|||
#define VALIDATOR_VAL_SECALGO_H
|
||||
struct gldns_buffer;
|
||||
|
||||
/** Return size of nsec3 hash algorithm, 0 if not supported */
|
||||
size_t nsec3_hash_algo_size_supported(int id);
|
||||
|
||||
/**
|
||||
* Hash a single hash call of an NSEC3 hash algorithm.
|
||||
* Iterations and salt are done by the caller.
|
||||
* @param algo: nsec3 hash algorithm.
|
||||
* @param buf: the buffer to digest
|
||||
* @param len: length of buffer to digest.
|
||||
* @param res: result stored here (must have sufficient space).
|
||||
* @return false on failure.
|
||||
*/
|
||||
int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res);
|
||||
|
||||
/**
|
||||
* Return size of DS digest according to its hash algorithm.
|
||||
* @param algo: DS digest algo.
|
||||
|
|
Loading…
Reference in New Issue