From f64aa8703dde7189e3686c45e156fe2d9b78514f Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Wed, 5 Dec 2018 11:25:32 +0000 Subject: [PATCH] First pass at a mostly stubbed GnuTLS implementation. This works enough to do a TLS lookup. --- src/gnutls/anchor.c | 48 ++++ src/gnutls/keyraw-internal.c | 15 ++ src/gnutls/keyraw-internal.h | 31 +++ src/gnutls/pubkey-pinning.c | 84 ++++++ src/gnutls/tls-internal.h | 79 ++++++ src/gnutls/tls.c | 505 +++++++++++++++++++++++++++++++++++ src/gnutls/val_secalgo.c | 58 ++++ 7 files changed, 820 insertions(+) create mode 100644 src/gnutls/anchor.c create mode 100644 src/gnutls/keyraw-internal.c create mode 100644 src/gnutls/keyraw-internal.h create mode 100644 src/gnutls/pubkey-pinning.c create mode 100644 src/gnutls/tls-internal.h create mode 100644 src/gnutls/tls.c create mode 100644 src/gnutls/val_secalgo.c diff --git a/src/gnutls/anchor.c b/src/gnutls/anchor.c new file mode 100644 index 00000000..57fb60e1 --- /dev/null +++ b/src/gnutls/anchor.c @@ -0,0 +1,48 @@ +/** + * + * /brief functions for DNSSEC trust anchor management + * + */ + +/* + * Copyright (c) 2017, NLnet Labs + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "anchor.h" + +void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms) +{ +} + +void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop) +{ +} + +void _getdns_context_update_root_ksk( + getdns_context *context, _getdns_rrset *dnskey_set) +{ +} diff --git a/src/gnutls/keyraw-internal.c b/src/gnutls/keyraw-internal.c new file mode 100644 index 00000000..a674033f --- /dev/null +++ b/src/gnutls/keyraw-internal.c @@ -0,0 +1,15 @@ +/* + * keyraw.c - raw key operations and conversions - OpenSSL version + * + * (c) NLnet Labs, 2004-2008 + * + * See the file LICENSE for the license + */ +/** + * \file + * Implementation of raw DNSKEY functions (work on wire rdata). + */ + +#include "config.h" +#include "gldns/keyraw.h" +#include "gldns/rrdef.h" diff --git a/src/gnutls/keyraw-internal.h b/src/gnutls/keyraw-internal.h new file mode 100644 index 00000000..eaac30c3 --- /dev/null +++ b/src/gnutls/keyraw-internal.h @@ -0,0 +1,31 @@ +/* + * keyraw.h -- raw key and signature access and conversion - OpenSSL + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +/** + * \file + * + * raw key and signature access and conversion + * + * Since those functions heavily rely op cryptographic operations, + * this module is dependent on openssl. + * + */ + +#ifndef GLDNS_KEYRAW_INTERNAL_H +#define GLDNS_KEYRAW_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GLDNS_KEYRAW_INTERNAL_H */ diff --git a/src/gnutls/pubkey-pinning.c b/src/gnutls/pubkey-pinning.c new file mode 100644 index 00000000..c1aeedc3 --- /dev/null +++ b/src/gnutls/pubkey-pinning.c @@ -0,0 +1,84 @@ +/** + * + * /brief functions for dealing with pubkey pinsets + * + */ + +/* + * Copyright (c) 2015 ACLU + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "context.h" +#include "types-internal.h" + +#include "pubkey-pinning.h" + +/** + ** Interfaces from pubkey-pinning.h + **/ + +/* create and populate a pinset linked list from a getdns_list pinset */ +getdns_return_t +_getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list, + struct mem_funcs *mf, + sha256_pin_t **pinset_out) +{ + return GETDNS_RETURN_GENERIC_ERROR; +} + + + +/* create a getdns_list version of the pinset */ +getdns_return_t +_getdns_get_pubkey_pinset_list(getdns_context *ctx, + const sha256_pin_t *pinset_in, + getdns_list **pinset_list) +{ + return GETDNS_RETURN_GENERIC_ERROR; +} + +getdns_return_t +_getdns_associate_upstream_with_connection(_getdns_tls_connection *conn, + getdns_upstream *upstream) +{ + return GETDNS_RETURN_GOOD; +} + +/** + ** Interfaces from getdns_extra.h. + **/ + +getdns_dict* +getdns_pubkey_pin_create_from_string(getdns_context* context, const char* str) +{ + return GETDNS_RETURN_GENERIC_ERROR; +} + +getdns_return_t +getdns_pubkey_pinset_sanity_check(const getdns_list* pinset, getdns_list* errorlist) +{ + return GETDNS_RETURN_GENERIC_ERROR; +} diff --git a/src/gnutls/tls-internal.h b/src/gnutls/tls-internal.h new file mode 100644 index 00000000..2b76d564 --- /dev/null +++ b/src/gnutls/tls-internal.h @@ -0,0 +1,79 @@ +/** + * + * \file tls-internal.h + * @brief getdns TLS implementation-specific items + */ + +/* + * Copyright (c) 2018, NLnet Labs + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETDNS_TLS_INTERNAL_H +#define _GETDNS_TLS_INTERNAL_H + +#include +#include + +#include "getdns/getdns.h" + +#define SHA_DIGEST_LENGTH 20 +#define SHA224_DIGEST_LENGTH 28 +#define SHA256_DIGEST_LENGTH 32 +#define SHA384_DIGEST_LENGTH 48 +#define SHA512_DIGEST_LENGTH 64 + +#define GETDNS_TLS_MAX_DIGEST_LENGTH (SHA512_DIGEST_LENGTH) + +#define HAVE_TLS_CTX_CURVES_LIST 0 +#define HAVE_TLS_CONN_CURVES_LIST 0 + + +typedef struct _getdns_tls_context { + int unused; +} _getdns_tls_context; + +typedef struct _getdns_tls_connection { + gnutls_session_t tls; + gnutls_certificate_credentials_t cred; + int shutdown; +} _getdns_tls_connection; + +typedef struct _getdns_tls_session { + gnutls_datum_t tls; +} _getdns_tls_session; + +typedef struct _getdns_tls_x509 +{ + gnutls_datum_t tls; +} _getdns_tls_x509; + +typedef struct _getdns_tls_hmac +{ + gnutls_hmac_hd_t tls; + unsigned int md_len; +} _getdns_tls_hmac; + +#endif /* _GETDNS_TLS_INTERNAL_H */ diff --git a/src/gnutls/tls.c b/src/gnutls/tls.c new file mode 100644 index 00000000..34c1d24c --- /dev/null +++ b/src/gnutls/tls.c @@ -0,0 +1,505 @@ +/** + * + * \file tls.c + * @brief getdns TLS functions + */ + +/* + * Copyright (c) 2018, NLnet Labs + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "config.h" + +#include "debug.h" +#include "context.h" + +#include "tls.h" + +static getdns_return_t error_may_want_read_write(_getdns_tls_connection* conn, int err) +{ + switch (err) { + case GNUTLS_E_INTERRUPTED: + case GNUTLS_E_AGAIN: + case GNUTLS_E_WARNING_ALERT_RECEIVED: + case GNUTLS_E_GOT_APPLICATION_DATA: + if (gnutls_record_get_direction(conn->tls) == 0) + return GETDNS_RETURN_TLS_WANT_READ; + else + return GETDNS_RETURN_TLS_WANT_WRITE; + + default: + return GETDNS_RETURN_GENERIC_ERROR; + } +} + +static getdns_return_t get_gnu_mac_algorithm(int algorithm, gnutls_mac_algorithm_t* gnualg) +{ + switch (algorithm) { + case GETDNS_HMAC_MD5 : *gnualg = GNUTLS_MAC_MD5 ; break; + case GETDNS_HMAC_SHA1 : *gnualg = GNUTLS_MAC_SHA1 ; break; + case GETDNS_HMAC_SHA224: *gnualg = GNUTLS_MAC_SHA224; break; + case GETDNS_HMAC_SHA256: *gnualg = GNUTLS_MAC_SHA256; break; + case GETDNS_HMAC_SHA384: *gnualg = GNUTLS_MAC_SHA384; break; + case GETDNS_HMAC_SHA512: *gnualg = GNUTLS_MAC_SHA512; break; + default : return GETDNS_RETURN_GENERIC_ERROR; + } + + return GETDNS_RETURN_GOOD; +} + +static _getdns_tls_x509* _getdns_tls_x509_new(struct mem_funcs* mfs, gnutls_datum_t cert) +{ + _getdns_tls_x509* res; + + res = GETDNS_MALLOC(*mfs, _getdns_tls_x509); + if (res) + res->tls = cert; + + return res; +} + +void _getdns_tls_init() +{ + gnutls_global_init(); +} + +_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs) +{ + _getdns_tls_context* res; + + if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context))) + return NULL; + + return res; +} + +getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_context* ctx) +{ + if (!ctx) + return GETDNS_RETURN_INVALID_PARAMETER; + GETDNS_FREE(*mfs, ctx); + return GETDNS_RETURN_GOOD; +} + +void _getdns_tls_context_dane_init(_getdns_tls_context* ctx) +{ + (void) ctx; +} + +getdns_return_t _getdns_tls_context_set_min_proto_1_2(_getdns_tls_context* ctx) +{ + (void) ctx; + return GETDNS_RETURN_NOT_IMPLEMENTED; +} + +getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list) +{ + (void) list; + + if (!ctx) + return GETDNS_RETURN_INVALID_PARAMETER; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list) +{ + (void) list; + + if (!ctx) + return GETDNS_RETURN_INVALID_PARAMETER; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* file, const char* path) +{ + (void) file; + (void) path; + + if (!ctx) + return GETDNS_RETURN_INVALID_PARAMETER; + return GETDNS_RETURN_GOOD; +} + +_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd) +{ + _getdns_tls_connection* res; + int r; + + if (!ctx) + return NULL; + + if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_connection))) + return NULL; + + res->shutdown = 0; + + r = gnutls_certificate_allocate_credentials(&res->cred); + if (r == GNUTLS_E_SUCCESS) + gnutls_certificate_set_x509_system_trust(res->cred); + if (r == GNUTLS_E_SUCCESS) + r = gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK); + if (r == GNUTLS_E_SUCCESS) + r = gnutls_set_default_priority(res->tls); + if (r == GNUTLS_E_SUCCESS) + r = gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred); + if (r != GNUTLS_E_SUCCESS) { + _getdns_tls_connection_free(mfs, res); + return NULL; + } + + gnutls_transport_set_int(res->tls, fd); + return res; +} + +getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_connection* conn) +{ + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + + gnutls_deinit(conn->tls); + gnutls_certificate_free_credentials(conn->cred); + GETDNS_FREE(*mfs, conn); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn) +{ + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (conn->shutdown == 0) { + gnutls_bye(conn->tls, GNUTLS_SHUT_WR); + conn->shutdown++; + } else { + gnutls_bye(conn->tls, GNUTLS_SHUT_RDWR); + conn->shutdown++; + } + + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list) +{ + (void) list; + + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list) +{ + (void) list; + + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_set_session(_getdns_tls_connection* conn, _getdns_tls_session* s) +{ + int r; + + if (!conn || !conn->tls || !s) + return GETDNS_RETURN_INVALID_PARAMETER; + + r = gnutls_session_set_data(conn->tls, s->tls.data, s->tls.size); + if (r != GNUTLS_E_SUCCESS) + return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_GOOD; +} + +_getdns_tls_session* _getdns_tls_connection_get_session(struct mem_funcs* mfs, _getdns_tls_connection* conn) +{ + _getdns_tls_session* res; + int r; + + if (!conn || !conn->tls) + return NULL; + + if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_session))) + return NULL; + + r = gnutls_session_get_data2(conn->tls, &res->tls); + if (r != GNUTLS_E_SUCCESS) { + GETDNS_FREE(*mfs, res); + return NULL; + } + + return res; +} + +const char* _getdns_tls_connection_get_version(_getdns_tls_connection* conn) +{ + if (!conn || !conn->tls) + return NULL; + + return gnutls_protocol_get_name(gnutls_protocol_get_version(conn->tls)); +} + +getdns_return_t _getdns_tls_connection_do_handshake(_getdns_tls_connection* conn) +{ + int r; + + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + + r = gnutls_handshake(conn->tls); + if (r == GNUTLS_E_SUCCESS) + return GETDNS_RETURN_GOOD; + else + return error_may_want_read_write(conn, r); +} + +_getdns_tls_x509* _getdns_tls_connection_get_peer_certificate(struct mem_funcs* mfs, _getdns_tls_connection* conn) +{ + const gnutls_datum_t *cert_list; + unsigned int cert_list_size; + + if (!conn || !conn->tls) + return NULL; + + cert_list = gnutls_certificate_get_peers(conn->tls, &cert_list_size); + if (cert_list == NULL) + return NULL; + + return _getdns_tls_x509_new(mfs, *cert_list); +} + +getdns_return_t _getdns_tls_connection_is_session_reused(_getdns_tls_connection* conn) +{ + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (gnutls_session_is_resumed(conn->tls) != 0) + return GETDNS_RETURN_GOOD; + else + return GETDNS_RETURN_TLS_CONNECTION_FRESH; +} + +getdns_return_t _getdns_tls_connection_setup_hostname_auth(_getdns_tls_connection* conn, const char* auth_name) +{ + if (!conn || !conn->tls || !auth_name) + return GETDNS_RETURN_INVALID_PARAMETER; + + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* conn, const char* auth_name, const sha256_pin_t* pinset) +{ + (void) pinset; + + if (!conn || !conn->tls || !auth_name) + return GETDNS_RETURN_INVALID_PARAMETER; + + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_verify(_getdns_tls_connection* conn, long* errnum, const char** errmsg) +{ + (void) errnum; + (void) errmsg; + + if (!conn || !conn->tls) + return GETDNS_RETURN_INVALID_PARAMETER; + + return GETDNS_RETURN_GOOD; +} + + +getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_t* buf, size_t to_read, size_t* read) +{ + ssize_t sread; + + if (!conn || !conn->tls || !read) + return GETDNS_RETURN_INVALID_PARAMETER; + + sread = gnutls_record_recv(conn->tls, buf, to_read); + if (sread < 0) + return error_may_want_read_write(conn, sread); + + *read = sread; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written) +{ + int swritten; + + if (!conn || !conn->tls || !written) + return GETDNS_RETURN_INVALID_PARAMETER; + + swritten = gnutls_record_send(conn->tls, buf, to_write); + if (swritten < 0) + return error_may_want_read_write(conn, swritten); + + *written = swritten; + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_session_free(struct mem_funcs* mfs, _getdns_tls_session* s) +{ + if (!s) + return GETDNS_RETURN_INVALID_PARAMETER; + GETDNS_FREE(*mfs, s); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict) +{ + if (! getdns_dict_set_int( + dict, "gnutls_version_number", GNUTLS_VERSION_NUMBER) + + && ! getdns_dict_util_set_string( + dict, "gnutls_version_string", GNUTLS_VERSION) + ) + return GETDNS_RETURN_GOOD; + return GETDNS_RETURN_GENERIC_ERROR; +} + +void _getdns_tls_x509_free(struct mem_funcs* mfs, _getdns_tls_x509* cert) +{ + if (cert) + GETDNS_FREE(*mfs, cert); +} + +int _getdns_tls_x509_to_der(struct mem_funcs* mfs, _getdns_tls_x509* cert, getdns_bindata* bindata) +{ + gnutls_x509_crt_t crt; + size_t s; + + if (!cert || gnutls_x509_crt_init(&crt) != GNUTLS_E_SUCCESS) + return 0; + + gnutls_x509_crt_import(crt, &cert->tls, GNUTLS_X509_FMT_DER); + gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL, &s); + + if (!bindata) { + gnutls_x509_crt_deinit(crt); + return s; + } + + bindata->data = GETDNS_XMALLOC(*mfs, uint8_t, s); + if (!bindata->data) { + gnutls_x509_crt_deinit(crt); + return 0; + } + + gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, bindata->data, &s); + bindata->size = s; + gnutls_x509_crt_deinit(crt); + return s; +} + +unsigned char* _getdns_tls_hmac_hash(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size) +{ + gnutls_mac_algorithm_t alg; + unsigned int md_len; + unsigned char* res; + + if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD) + return NULL; + + md_len = gnutls_hmac_get_len(alg); + res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, md_len); + if (!res) + return NULL; + + (void) gnutls_hmac_fast(alg, key, key_size, data, data_size, res); + + if (output_size) + *output_size = md_len; + return res; +} + +_getdns_tls_hmac* _getdns_tls_hmac_new(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size) +{ + gnutls_mac_algorithm_t alg; + _getdns_tls_hmac* res; + + if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD) + return NULL; + + if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_hmac))) + return NULL; + + if (gnutls_hmac_init(&res->tls, alg, key, key_size) < 0) { + GETDNS_FREE(*mfs, res); + return NULL; + } + res->md_len = gnutls_hmac_get_len(alg); + return res; +} + +getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size) +{ + if (!h || !h->tls || !data) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (gnutls_hmac(h->tls, data, data_size) < 0) + return GETDNS_RETURN_GENERIC_ERROR; + else + return GETDNS_RETURN_GOOD; +} + +unsigned char* _getdns_tls_hmac_end(struct mem_funcs* mfs, _getdns_tls_hmac* h, size_t* output_size) +{ + unsigned char* res; + + if (!h || !h->tls) + return NULL; + + res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, h->md_len); + if (!res) + return NULL; + + gnutls_hmac_deinit(h->tls, res); + if (output_size) + *output_size = h->md_len; + + GETDNS_FREE(*mfs, h); + return res; +} + +void _getdns_tls_sha1(const void* data, size_t data_size, unsigned char* buf) +{ + gnutls_hash_fast(GNUTLS_DIG_SHA1, data, data_size, buf); +} + +void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen) +{ + gnutls_hash_hd_t digest; + + gnutls_hash_init(&digest, GNUTLS_DIG_SHA256); + gnutls_hash(digest, &secret, sizeof(secret)); + gnutls_hash(digest, addr, addrlen); + gnutls_hash_deinit(digest, buf); + *buflen = gnutls_hash_get_len(GNUTLS_DIG_SHA256); +} + +/* tls.c */ diff --git a/src/gnutls/val_secalgo.c b/src/gnutls/val_secalgo.c new file mode 100644 index 00000000..2290eb4c --- /dev/null +++ b/src/gnutls/val_secalgo.c @@ -0,0 +1,58 @@ +/** + * + * /brief secalgo interface. + * + */ +/* + * Copyright (c) 2017, NLnet Labs, the getdns team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "util/val_secalgo.h" + +size_t _getdns_ds_digest_size_supported(int algo) +{ + return 0; +} + +int _getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len, + unsigned char* res) +{ + return 0; +} + +int _getdns_dnskey_algo_id_is_supported(int id) +{ + return 0; +} + +enum sec_status _getdns_verify_canonrrset(struct gldns_buffer* buf, int algo, + unsigned char* sigblock, unsigned int sigblock_len, + unsigned char* key, unsigned int keylen, char** reason) +{ + return sec_status_bogus; +}