LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/libdane - dane.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.12 Code Coverage Lines: 239 416 57.5 %
Date: 2020-01-19 05:02:27 Functions: 15 18 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2012 KU Leuven
       3             :  * Copyright (C) 2013 Christian Grothoff
       4             :  * Copyright (C) 2013 Nikos Mavrogiannopoulos
       5             :  *
       6             :  * Author: Nikos Mavrogiannopoulos
       7             :  *
       8             :  * This file is part of libdane.
       9             :  *
      10             :  * The libdane library is free software; you can redistribute it
      11             :  * and/or modify it under the terms of the GNU Lesser General Public
      12             :  * License as published by the Free Software Foundation; either
      13             :  * version 2.1 of the License, or (at your option) any later version.
      14             :  *
      15             :  * This library is distributed in the hope that it will be useful, but
      16             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :  * Lesser General Public License for more details.
      19             :  *
      20             :  * You should have received a copy of the GNU Lesser General Public License
      21             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      22             :  *
      23             :  */
      24             : 
      25             : #include <config.h>
      26             : 
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : #include <string.h>
      30             : #include <errno.h>
      31             : #include <arpa/inet.h>
      32             : #include <unbound.h>
      33             : #include <gnutls/dane.h>
      34             : #include <gnutls/x509.h>
      35             : #include <gnutls/abstract.h>
      36             : #include <gnutls/crypto.h>
      37             : #include "../lib/gnutls_int.h"
      38             : 
      39             : #define MAX_DATA_ENTRIES 100
      40             : 
      41             : #undef gnutls_assert
      42             : #undef gnutls_assert_val
      43             : 
      44             : #ifdef DEBUG
      45             : #define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__);
      46             : #define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__)
      47             : static int gnutls_assert_val_int(int val, const char *file, int line)
      48             : {
      49             :         fprintf(stderr, "ASSERT: %s: %d\n", file, line);
      50             :         return val;
      51             : }
      52             : #else
      53             : #define gnutls_assert()
      54             : #define gnutls_assert_val(x) (x)
      55             : #endif
      56             : 
      57             : struct dane_state_st {
      58             :         struct ub_ctx *ctx;
      59             :         unsigned int flags;
      60             : };
      61             : 
      62             : struct dane_query_st {
      63             :         struct ub_result *result;
      64             :         unsigned int data_entries;
      65             :         dane_cert_usage_t usage[MAX_DATA_ENTRIES];
      66             :         dane_cert_type_t type[MAX_DATA_ENTRIES];
      67             :         dane_match_type_t match[MAX_DATA_ENTRIES];
      68             :         gnutls_datum_t data[MAX_DATA_ENTRIES];
      69             :         unsigned int flags;
      70             :         dane_query_status_t status;
      71             : };
      72             : 
      73             : /**
      74             :  * dane_query_status:
      75             :  * @q: The query result structure
      76             :  *
      77             :  * This function will return the status of the query response.
      78             :  * See %dane_query_status_t for the possible types.
      79             :  *
      80             :  * Returns: The status type.
      81             :  **/
      82           0 : dane_query_status_t dane_query_status(dane_query_t q)
      83             : {
      84           0 :         return q->status;
      85             : }
      86             : 
      87             : /**
      88             :  * dane_query_entries:
      89             :  * @q: The query result structure
      90             :  *
      91             :  * This function will return the number of entries in a query.
      92             :  *
      93             :  * Returns: The number of entries.
      94             :  **/
      95           3 : unsigned int dane_query_entries(dane_query_t q)
      96             : {
      97           3 :         return q->data_entries;
      98             : }
      99             : 
     100             : /**
     101             :  * dane_query_data:
     102             :  * @q: The query result structure
     103             :  * @idx: The index of the query response.
     104             :  * @usage: The certificate usage (see %dane_cert_usage_t)
     105             :  * @type: The certificate type (see %dane_cert_type_t)
     106             :  * @match: The DANE matching type (see %dane_match_type_t)
     107             :  * @data: The DANE data.
     108             :  *
     109             :  * This function will provide the DANE data from the query
     110             :  * response.
     111             :  *
     112             :  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
     113             :  *   negative error value.
     114             :  **/
     115             : int
     116          17 : dane_query_data(dane_query_t q, unsigned int idx,
     117             :                 unsigned int *usage, unsigned int *type,
     118             :                 unsigned int *match, gnutls_datum_t * data)
     119             : {
     120          17 :         if (idx >= q->data_entries)
     121             :                 return
     122             :                     gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
     123             : 
     124          14 :         if (usage)
     125          14 :                 *usage = q->usage[idx];
     126          14 :         if (type)
     127          14 :                 *type = q->type[idx];
     128          14 :         if (match)
     129          14 :                 *match = q->match[idx];
     130          14 :         if (data) {
     131          14 :                 data->data = q->data[idx].data;
     132          14 :                 data->size = q->data[idx].size;
     133             :         }
     134             : 
     135             :         return DANE_E_SUCCESS;
     136             : }
     137             : 
     138             : /**
     139             :  * dane_query_to_raw_tlsa:
     140             :  * @q: The query result structure
     141             :  * @data_entries: Pointer set to the number of entries in the query
     142             :  * @dane_data: Pointer to contain an array of DNS rdata items, terminated with a NULL pointer;
     143             :  *             caller must guarantee that the referenced data remains
     144             :  *             valid until dane_query_deinit() is called.
     145             :  * @dane_data_len: Pointer to contain the length n bytes of the dane_data items
     146             :  * @secure: Pointer set true if the result is validated securely, false if
     147             :  *               validation failed or the domain queried has no security info
     148             :  * @bogus: Pointer set true if the result was not secure due to a security failure
     149             :  *
     150             :  * This function will provide the DANE data from the query
     151             :  * response.
     152             :  *
     153             :  * The pointers dane_data and dane_data_len are allocated with gnutls_malloc()
     154             :  * to contain the data from the query result structure (individual
     155             :  * @dane_data items simply point to the original data and are not allocated separately).
     156             :  * The returned @dane_data are only valid during the lifetime of @q.
     157             :  *
     158             :  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
     159             :  *   negative error value.
     160             :  */
     161             : int
     162           8 : dane_query_to_raw_tlsa(dane_query_t q, unsigned int *data_entries,
     163             :                 char ***dane_data, int **dane_data_len, int *secure, int *bogus)
     164             : {
     165           8 :         size_t data_sz;
     166           8 :         char *data_buf;
     167           8 :         unsigned int idx;
     168             : 
     169           8 :         *data_entries = 0;
     170           8 :         *dane_data = NULL;
     171           8 :         *dane_data_len = NULL;
     172             : 
     173           8 :         if (secure) {
     174           8 :                 if (q->status & DANE_QUERY_DNSSEC_VERIFIED)
     175           8 :                         *secure = 1;
     176             :                 else
     177           0 :                         *secure = 0;
     178             :         }
     179             : 
     180           8 :         if (bogus) {
     181           8 :                 if (q->status & DANE_QUERY_BOGUS)
     182           0 :                         *bogus = 1;
     183             :                 else
     184           8 :                         *bogus = 0;
     185             :         }
     186             : 
     187             :         /* pack dane_data pointer list followed by dane_data contents */
     188           8 :         data_sz = sizeof (**dane_data) * (q->data_entries + 1);
     189          23 :         for (idx = 0; idx < q->data_entries; idx++)
     190          15 :                 data_sz += 3 + q->data[idx].size;
     191             : 
     192           8 :         *dane_data = gnutls_calloc (1, data_sz);
     193           8 :         if (*dane_data == NULL)
     194             :                 return DANE_E_MEMORY_ERROR;
     195           8 :         data_buf = (char *)*dane_data;
     196           8 :         data_buf += sizeof (**dane_data) * (q->data_entries + 1);
     197             : 
     198           8 :         *dane_data_len = gnutls_calloc (q->data_entries + 1, sizeof (**dane_data_len));
     199           8 :         if (*dane_data_len == NULL) {
     200           0 :                 free(*dane_data);
     201           0 :                 *dane_data = NULL;
     202           0 :                 return DANE_E_MEMORY_ERROR;
     203             :         }
     204             : 
     205          23 :         for (idx = 0; idx < q->data_entries; idx++) {
     206          15 :                 (*dane_data)[idx] = data_buf;
     207          15 :                 (*dane_data)[idx][0] = q->usage[idx];
     208          15 :                 (*dane_data)[idx][1] = q->type[idx];
     209          15 :                 (*dane_data)[idx][2] = q->match[idx];
     210          15 :                 memcpy(&(*dane_data)[idx][3], q->data[idx].data, q->data[idx].size);
     211          15 :                 (*dane_data_len)[idx] = 3 + q->data[idx].size;
     212          15 :                 data_buf += 3 + q->data[idx].size;
     213             :         }
     214           8 :         (*dane_data)[idx] = NULL;
     215           8 :         (*dane_data_len)[idx] = 0;
     216           8 :         *data_entries = q->data_entries;
     217             : 
     218           8 :         return DANE_E_SUCCESS;
     219             : }
     220             : 
     221             : /**
     222             :  * dane_state_init:
     223             :  * @s: The structure to be initialized
     224             :  * @flags: flags from the %dane_state_flags enumeration
     225             :  *
     226             :  * This function will initialize the backend resolver. It is
     227             :  * intended to be used in scenarios where multiple resolvings
     228             :  * occur, to optimize against multiple re-initializations.
     229             :  *
     230             :  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
     231             :  *   negative error value.
     232             :  **/
     233           4 : int dane_state_init(dane_state_t * s, unsigned int flags)
     234             : {
     235           4 :         struct ub_ctx *ctx;
     236           4 :         int ret;
     237             : 
     238           4 :         *s = calloc(1, sizeof(struct dane_state_st));
     239           4 :         if (*s == NULL)
     240             :                 return gnutls_assert_val(DANE_E_MEMORY_ERROR);
     241             : 
     242           4 :         ctx = ub_ctx_create();
     243           4 :         if (!ctx) {
     244           0 :                 gnutls_assert();
     245           0 :                 ret = DANE_E_INITIALIZATION_ERROR;
     246           0 :                 goto cleanup;
     247             :         }
     248           4 :         ub_ctx_debugout(ctx, stderr);
     249             : 
     250           4 :         if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) {
     251           0 :                 if ((ret = ub_ctx_resolvconf(ctx, NULL)) != 0) {
     252           0 :                         gnutls_assert();
     253           0 :                         ret = DANE_E_INITIALIZATION_ERROR;
     254           0 :                         goto cleanup;
     255             :                 }
     256             : 
     257           0 :                 if ((ret = ub_ctx_hosts(ctx, NULL)) != 0) {
     258           0 :                         gnutls_assert();
     259           0 :                         ret = DANE_E_INITIALIZATION_ERROR;
     260           0 :                         goto cleanup;
     261             :                 }
     262             :         }
     263             : 
     264             :         /* read public keys for DNSSEC verification */
     265           4 :         if (!(flags & DANE_F_IGNORE_DNSSEC)) {
     266           8 :                 if ((ret =
     267           4 :                      ub_ctx_add_ta_file(ctx,
     268             :                                         (char *) UNBOUND_ROOT_KEY_FILE)) !=
     269             :                     0) {
     270           0 :                         gnutls_assert();
     271           0 :                         ret = DANE_E_INITIALIZATION_ERROR;
     272           0 :                         goto cleanup;
     273             :                 }
     274             :         }
     275             : 
     276           4 :         (*s)->ctx = ctx;
     277           4 :         (*s)->flags = flags;
     278             : 
     279           4 :         return DANE_E_SUCCESS;
     280           0 :       cleanup:
     281             : 
     282           0 :         if (ctx)
     283           0 :                 ub_ctx_delete(ctx);
     284           0 :         free(*s);
     285             : 
     286           0 :         return ret;
     287             : }
     288             : 
     289             : /**
     290             :  * dane_state_deinit:
     291             :  * @s: The structure to be deinitialized
     292             :  *
     293             :  * This function will deinitialize a DANE query structure.
     294             :  *
     295             :  **/
     296           4 : void dane_state_deinit(dane_state_t s)
     297             : {
     298           4 :         ub_ctx_delete(s->ctx);
     299           4 :         free(s);
     300           4 : }
     301             : 
     302             : /**
     303             :  * dane_state_set_dlv_file:
     304             :  * @s: The structure to be deinitialized
     305             :  * @file: The file holding the DLV keys.
     306             :  *
     307             :  * This function will set a file with trusted keys
     308             :  * for DLV (DNSSEC Lookaside Validation).
     309             :  *
     310             :  **/
     311           0 : int dane_state_set_dlv_file(dane_state_t s, const char *file)
     312             : {
     313           0 :         int ret;
     314             : 
     315           0 :         ret =
     316           0 :             ub_ctx_set_option(s->ctx, (char *) "dlv-anchor-file:",
     317             :                               (void *) file);
     318           0 :         if (ret != 0)
     319           0 :                 return gnutls_assert_val(DANE_E_FILE_ERROR);
     320             : 
     321             :         return 0;
     322             : }
     323             : 
     324             : /**
     325             :  * dane_query_deinit:
     326             :  * @q: The structure to be deinitialized
     327             :  *
     328             :  * This function will deinitialize a DANE query result structure.
     329             :  *
     330             :  **/
     331          14 : void dane_query_deinit(dane_query_t q)
     332             : {
     333          14 :         if (q->result)
     334           6 :                 ub_resolve_free(q->result);
     335          14 :         free(q);
     336          14 : }
     337             : 
     338             : 
     339             : /**
     340             :  * dane_raw_tlsa:
     341             :  * @s: The DANE state structure
     342             :  * @r: A structure to place the result
     343             :  * @dane_data: array of DNS rdata items, terminated with a NULL pointer;
     344             :  *             caller must guarantee that the referenced data remains
     345             :  *             valid until dane_query_deinit() is called.
     346             :  * @dane_data_len: the length n bytes of the dane_data items
     347             :  * @secure: true if the result is validated securely, false if
     348             :  *               validation failed or the domain queried has no security info
     349             :  * @bogus: if the result was not secure (secure = 0) due to a security failure,
     350             :  *              and the result is due to a security failure, bogus is true.
     351             :  *
     352             :  * This function will fill in the TLSA (DANE) structure from
     353             :  * the given raw DNS record data. The @dane_data must be valid
     354             :  * during the lifetime of the query.
     355             :  *
     356             :  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
     357             :  *   negative error value.
     358             :  **/
     359             : int
     360          14 : dane_raw_tlsa(dane_state_t s, dane_query_t * r, char *const *dane_data,
     361             :               const int *dane_data_len, int secure, int bogus)
     362             : {
     363          14 :         int ret = DANE_E_SUCCESS;
     364          14 :         unsigned int i;
     365             : 
     366          14 :         *r = calloc(1, sizeof(struct dane_query_st));
     367          14 :         if (*r == NULL)
     368             :                 return gnutls_assert_val(DANE_E_MEMORY_ERROR);
     369             : 
     370          14 :         (*r)->data_entries = 0;
     371             : 
     372          35 :         for (i = 0; i < MAX_DATA_ENTRIES; i++) {
     373          35 :                 if (dane_data[i] == NULL)
     374             :                         break;
     375             : 
     376          21 :                 if (dane_data_len[i] <= 3)
     377             :                         return
     378             :                             gnutls_assert_val
     379             :                             (DANE_E_RECEIVED_CORRUPT_DATA);
     380             : 
     381          21 :                 (*r)->usage[i] = dane_data[i][0];
     382          21 :                 (*r)->type[i] = dane_data[i][1];
     383          21 :                 (*r)->match[i] = dane_data[i][2];
     384          21 :                 (*r)->data[i].data = (void *) &dane_data[i][3];
     385          21 :                 (*r)->data[i].size = dane_data_len[i] - 3;
     386          21 :                 (*r)->data_entries++;
     387             :         }
     388             : 
     389          14 :         if (!(s->flags & DANE_F_INSECURE) && !secure) {
     390           0 :                 if (bogus)
     391             :                         ret = gnutls_assert_val(DANE_E_INVALID_DNSSEC_SIG);
     392             :                 else
     393           0 :                         ret = gnutls_assert_val(DANE_E_NO_DNSSEC_SIG);
     394             :         }
     395             : 
     396             :         /* show security status */
     397          14 :         if (secure) {
     398          14 :                 (*r)->status = DANE_QUERY_DNSSEC_VERIFIED;
     399           0 :         } else if (bogus) {
     400           0 :                 gnutls_assert();
     401           0 :                 (*r)->status = DANE_QUERY_BOGUS;
     402             :         } else {
     403           0 :                 gnutls_assert();
     404           0 :                 (*r)->status = DANE_QUERY_NO_DNSSEC;
     405             :         }
     406             : 
     407             :         return ret;
     408             : }
     409             : 
     410             : 
     411             : /**
     412             :  * dane_query_tlsa:
     413             :  * @s: The DANE state structure
     414             :  * @r: A structure to place the result
     415             :  * @host: The host name to resolve.
     416             :  * @proto: The protocol type (tcp, udp, etc.)
     417             :  * @port: The service port number (eg. 443).
     418             :  *
     419             :  * This function will query the DNS server for the TLSA (DANE)
     420             :  * data for the given host.
     421             :  *
     422             :  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
     423             :  *   negative error value.
     424             :  **/
     425             : int
     426           6 : dane_query_tlsa(dane_state_t s, dane_query_t * r, const char *host,
     427             :                 const char *proto, unsigned int port)
     428             : {
     429           6 :         char ns[1024];
     430           6 :         int ret;
     431           6 :         struct ub_result *result;
     432             : 
     433           6 :         snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
     434             : 
     435             :         /* query for webserver */
     436           6 :         ret = ub_resolve(s->ctx, ns, 52, 1, &result);
     437           6 :         if (ret != 0) {
     438             :                 return gnutls_assert_val(DANE_E_RESOLVING_ERROR);
     439             :         }
     440             : 
     441             : /* show first result */
     442           6 :         if (!result->havedata) {
     443           0 :                 ub_resolve_free(result);
     444           0 :                 return gnutls_assert_val(DANE_E_NO_DANE_DATA);
     445             :         }
     446             : 
     447           6 :         ret =
     448           6 :             dane_raw_tlsa(s, r, result->data, result->len, result->secure,
     449             :                           result->bogus);
     450           6 :         if (*r == NULL) {
     451           0 :                 ub_resolve_free(result);
     452           0 :                 return ret;
     453             :         }
     454           6 :         (*r)->result = result;
     455           6 :         return ret;
     456             : }
     457             : 
     458             : 
     459             : static unsigned int
     460           9 : matches(const gnutls_datum_t * raw1, const gnutls_datum_t * raw2,
     461             :         dane_match_type_t match)
     462             : {
     463           9 :         uint8_t digest[64];
     464           9 :         int ret;
     465             : 
     466           9 :         if (match == DANE_MATCH_EXACT) {
     467           0 :                 if (raw1->size != raw2->size)
     468             :                         return gnutls_assert_val(0);
     469             : 
     470           0 :                 if (memcmp(raw1->data, raw2->data, raw1->size) != 0)
     471             :                         return gnutls_assert_val(0);
     472             : 
     473           0 :                 return 1;
     474           9 :         } else if (match == DANE_MATCH_SHA2_256) {
     475             : 
     476           9 :                 if (raw2->size != 32)
     477             :                         return gnutls_assert_val(0);
     478             : 
     479           9 :                 ret =
     480          18 :                     gnutls_hash_fast(GNUTLS_DIG_SHA256, raw1->data,
     481           9 :                                      raw1->size, digest);
     482           9 :                 if (ret < 0)
     483             :                         return gnutls_assert_val(0);
     484             : 
     485           9 :                 if (memcmp(digest, raw2->data, 32) != 0)
     486             :                         return gnutls_assert_val(0);
     487             : 
     488           7 :                 return 1;
     489           0 :         } else if (match == DANE_MATCH_SHA2_512) {
     490           0 :                 if (raw2->size != 64)
     491             :                         return gnutls_assert_val(0);
     492             : 
     493           0 :                 ret =
     494           0 :                     gnutls_hash_fast(GNUTLS_DIG_SHA512, raw1->data,
     495           0 :                                      raw1->size, digest);
     496           0 :                 if (ret < 0)
     497             :                         return gnutls_assert_val(0);
     498             : 
     499           0 :                 if (memcmp(digest, raw2->data, 64) != 0)
     500             :                         return gnutls_assert_val(0);
     501             : 
     502           0 :                 return 1;
     503             :         }
     504             : 
     505             :         return gnutls_assert_val(0);
     506             : }
     507             : 
     508             : static int
     509           5 : crt_to_pubkey(const gnutls_datum_t * raw_crt, gnutls_datum_t * out)
     510             : {
     511           5 :         gnutls_pubkey_t pub = NULL;
     512           5 :         gnutls_x509_crt_t crt = NULL;
     513           5 :         int ret;
     514             : 
     515           5 :         out->data = NULL;
     516             : 
     517           5 :         ret = gnutls_x509_crt_init(&crt);
     518           5 :         if (ret < 0)
     519             :                 return gnutls_assert_val(DANE_E_PUBKEY_ERROR);
     520             : 
     521           5 :         ret = gnutls_pubkey_init(&pub);
     522           5 :         if (ret < 0) {
     523           0 :                 gnutls_assert();
     524           0 :                 ret = DANE_E_PUBKEY_ERROR;
     525           0 :                 goto cleanup;
     526             :         }
     527             : 
     528           5 :         ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
     529           5 :         if (ret < 0) {
     530           0 :                 gnutls_assert();
     531           0 :                 ret = DANE_E_PUBKEY_ERROR;
     532           0 :                 goto cleanup;
     533             :         }
     534             : 
     535           5 :         ret = gnutls_pubkey_import_x509(pub, crt, 0);
     536           5 :         if (ret < 0) {
     537           0 :                 gnutls_assert();
     538           0 :                 ret = DANE_E_PUBKEY_ERROR;
     539           0 :                 goto cleanup;
     540             :         }
     541             : 
     542           5 :         ret = gnutls_pubkey_export2(pub, GNUTLS_X509_FMT_DER, out);
     543           5 :         if (ret < 0) {
     544           0 :                 gnutls_assert();
     545           0 :                 ret = DANE_E_PUBKEY_ERROR;
     546           0 :                 goto cleanup;
     547             :         }
     548             : 
     549           5 :         ret = 0;
     550           5 :         goto clean_certs;
     551             : 
     552           0 :       cleanup:
     553           0 :         free(out->data);
     554           0 :         out->data = NULL;
     555           5 :       clean_certs:
     556           5 :         if (pub)
     557           5 :                 gnutls_pubkey_deinit(pub);
     558           5 :         if (crt)
     559           5 :                 gnutls_x509_crt_deinit(crt);
     560             : 
     561             :         return ret;
     562             : }
     563             : 
     564             : static int
     565           6 : verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
     566             :           gnutls_certificate_type_t crt_type,
     567             :           dane_cert_type_t ctype,
     568             :           dane_match_type_t match, gnutls_datum_t * data,
     569             :           unsigned int *verify)
     570             : {
     571           6 :         gnutls_datum_t pubkey = { NULL, 0 };
     572           6 :         int ret, i;
     573           6 :         unsigned int vstatus = 0;
     574           6 :         gnutls_x509_crt_t crt = NULL, ca = NULL;
     575           6 :         unsigned is_ok = 0;
     576             : 
     577           6 :         if (raw_crt_size < 2) /* we cannot verify the CA */
     578             :                 return gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
     579             : 
     580           4 :         if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
     581           4 :                 is_ok = 0;
     582           5 :                 for (i=raw_crt_size-1;i>=1;i--) {
     583           4 :                         if (matches(&raw_crt[i], data, match)) {
     584             :                                 is_ok = 1;
     585             :                                 break;
     586             :                         }
     587             :                 }
     588             : 
     589           4 :                 if (is_ok == 0) {
     590           1 :                         gnutls_assert();
     591           1 :                         *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
     592             :                 }
     593             : 
     594           0 :         } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
     595           0 :                 is_ok = 0;
     596             : 
     597           0 :                 for (i=raw_crt_size-1;i>=1;i--) {
     598           0 :                         ret = crt_to_pubkey(&raw_crt[i], &pubkey);
     599           0 :                         if (ret < 0) {
     600           0 :                                 gnutls_assert();
     601           0 :                                 goto cleanup;
     602             :                         }
     603             : 
     604           0 :                         if (matches(&pubkey, data, match)) {
     605             :                                 is_ok = 1;
     606             :                                 break;
     607             :                         }
     608             : 
     609           0 :                         free(pubkey.data);
     610           0 :                         pubkey.data = NULL;
     611             :                 }
     612             : 
     613           0 :                 if (is_ok == 0) {
     614           0 :                         gnutls_assert();
     615           0 :                         *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
     616             :                 }
     617             :         } else {
     618           0 :                 ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
     619           0 :                 goto cleanup;
     620             :         }
     621             : 
     622             :         /* check if the certificate chain is actually a chain */
     623           4 :         ret = gnutls_x509_crt_init(&crt);
     624           4 :         if (ret < 0) {
     625           0 :                 ret = gnutls_assert_val(DANE_E_CERT_ERROR);
     626           0 :                 goto cleanup;
     627             :         }
     628             : 
     629           4 :         ret =
     630           4 :             gnutls_x509_crt_import(crt, &raw_crt[0], GNUTLS_X509_FMT_DER);
     631           4 :         if (ret < 0) {
     632           0 :                 ret = gnutls_assert_val(DANE_E_CERT_ERROR);
     633           0 :                 goto cleanup;
     634             :         }
     635             : 
     636           4 :         for (i=raw_crt_size-1;i>=1;i--) {
     637           4 :                 ret = gnutls_x509_crt_init(&ca);
     638           4 :                 if (ret < 0) {
     639           0 :                         ret = gnutls_assert_val(DANE_E_CERT_ERROR);
     640           0 :                         goto cleanup;
     641             :                 }
     642             : 
     643           4 :                 ret = gnutls_x509_crt_import(ca, &raw_crt[i], GNUTLS_X509_FMT_DER);
     644           4 :                 if (ret < 0) {
     645           0 :                         ret = gnutls_assert_val(DANE_E_CERT_ERROR);
     646           0 :                         goto cleanup;
     647             :                 }
     648             : 
     649           4 :                 ret = gnutls_x509_crt_check_issuer(crt, ca);
     650           4 :                 if (ret != 0)
     651             :                         break;
     652             : 
     653           0 :                 gnutls_x509_crt_deinit(ca);
     654           0 :                 ca = NULL;
     655             :         }
     656             : 
     657           4 :         if (ca == NULL) {
     658           0 :                 gnutls_assert();
     659           0 :                 *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
     660             :         } else {
     661           4 :                 ret = gnutls_x509_crt_verify(crt, &ca, 1, 0, &vstatus);
     662           4 :                 if (ret < 0) {
     663           0 :                         ret = gnutls_assert_val(DANE_E_CERT_ERROR);
     664           0 :                         goto cleanup;
     665             :                 }
     666             : 
     667           4 :                 if (vstatus != 0)
     668           0 :                         *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
     669             :         }
     670             : 
     671             :         ret = 0;
     672           4 :       cleanup:
     673           4 :         free(pubkey.data);
     674           4 :         if (crt != NULL)
     675           4 :                 gnutls_x509_crt_deinit(crt);
     676           4 :         if (ca != NULL)
     677           4 :                 gnutls_x509_crt_deinit(ca);
     678             :         return ret;
     679             : }
     680             : 
     681             : static int
     682           5 : verify_ee(const gnutls_datum_t * raw_crt,
     683             :           gnutls_certificate_type_t crt_type, dane_cert_type_t ctype,
     684             :           dane_match_type_t match, gnutls_datum_t * data,
     685             :           unsigned int *verify)
     686             : {
     687           5 :         gnutls_datum_t pubkey = { NULL, 0 };
     688           5 :         int ret;
     689             : 
     690           5 :         if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
     691             : 
     692           0 :                 if (!matches(raw_crt, data, match)) {
     693           0 :                         gnutls_assert();
     694           0 :                         *verify |= DANE_VERIFY_CERT_DIFFERS;
     695             :                 }
     696             : 
     697           5 :         } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
     698             : 
     699           5 :                 ret = crt_to_pubkey(raw_crt, &pubkey);
     700           5 :                 if (ret < 0) {
     701           0 :                         gnutls_assert();
     702           0 :                         goto cleanup;
     703             :                 }
     704             : 
     705           5 :                 if (!matches(&pubkey, data, match)) {
     706           1 :                         gnutls_assert();
     707           1 :                         *verify |= DANE_VERIFY_CERT_DIFFERS;
     708             :                 }
     709             :         } else {
     710           0 :                 ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
     711           0 :                 goto cleanup;
     712             :         }
     713             : 
     714             :         ret = 0;
     715           5 :       cleanup:
     716           5 :         free(pubkey.data);
     717           5 :         return ret;
     718             : }
     719             : 
     720             : #define CHECK_VRET(ret, checked, record_status, status) \
     721             :                         if (ret == DANE_E_UNKNOWN_DANE_DATA) { \
     722             :                                 /* skip that entry */ \
     723             :                                 continue; \
     724             :                         } else if (ret < 0) { \
     725             :                                 gnutls_assert(); \
     726             :                                 goto cleanup; \
     727             :                         } \
     728             :                         checked = 1; \
     729             :                         if (record_status == 0) { \
     730             :                                 status = 0; \
     731             :                                 break; \
     732             :                         } else { \
     733             :                                 status |= record_status; \
     734             :                         }
     735             : 
     736             : /**
     737             :  * dane_verify_crt_raw:
     738             :  * @s: A DANE state structure (may be NULL)
     739             :  * @chain: A certificate chain
     740             :  * @chain_size: The size of the chain
     741             :  * @chain_type: The type of the certificate chain
     742             :  * @r: DANE data to check against
     743             :  * @sflags: Flags for the initialization of @s (if NULL)
     744             :  * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
     745             :  * @verify: An OR'ed list of %dane_verify_status_t.
     746             :  *
     747             :  * This is the low-level function of dane_verify_crt(). See the
     748             :  * high level function for documentation.
     749             :  *
     750             :  * This function does not perform any resolving, it utilizes
     751             :  * cached entries from @r.
     752             :  *
     753             :  * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
     754             :  * when the DANE entries were successfully parsed, irrespective of
     755             :  * whether they were verified (see @verify for that information). If
     756             :  * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
     757             :  * will be returned.
     758             :  *
     759             :  **/
     760             : int
     761          10 : dane_verify_crt_raw(dane_state_t s,
     762             :                     const gnutls_datum_t * chain, unsigned chain_size,
     763             :                     gnutls_certificate_type_t chain_type,
     764             :                     dane_query_t r,
     765             :                     unsigned int sflags, unsigned int vflags,
     766             :                     unsigned int *verify)
     767             : {
     768          10 :         int ret;
     769          10 :         unsigned checked = 0;
     770          10 :         unsigned int usage, type, match, idx;
     771          10 :         gnutls_datum_t data;
     772             : 
     773          10 :         if (chain_type != GNUTLS_CRT_X509)
     774             :                 return gnutls_assert_val(DANE_E_INVALID_REQUEST);
     775             : 
     776          10 :         if (chain_size == 0)
     777             :                 return gnutls_assert_val(DANE_E_NO_CERT);
     778             : 
     779          10 :         *verify = 0;
     780          10 :         idx = 0;
     781          14 :         do {
     782          14 :                 unsigned int record_verify = 0;
     783             : 
     784          14 :                 ret =
     785          14 :                     dane_query_data(r, idx++, &usage, &type, &match,
     786             :                                     &data);
     787          14 :                 if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
     788             :                         break;
     789             : 
     790          11 :                 if (ret < 0) {
     791           0 :                         gnutls_assert();
     792           0 :                         goto cleanup;
     793             :                 }
     794             : 
     795          11 :                 if (!(vflags & DANE_VFLAG_ONLY_CHECK_EE_USAGE)
     796          11 :                     && (usage == DANE_CERT_USAGE_LOCAL_CA
     797          11 :                         || usage == DANE_CERT_USAGE_CA)) {
     798           6 :                         ret =
     799           6 :                             verify_ca(chain, chain_size, chain_type, type,
     800             :                                       match, &data, &record_verify);
     801           6 :                         CHECK_VRET(ret, checked, record_verify, *verify);
     802             : 
     803           5 :                 } else if (!(vflags & DANE_VFLAG_ONLY_CHECK_CA_USAGE)
     804           5 :                            && (usage == DANE_CERT_USAGE_LOCAL_EE
     805           5 :                                || usage == DANE_CERT_USAGE_EE)) {
     806           5 :                         ret =
     807           5 :                             verify_ee(&chain[0], chain_type, type, match,
     808             :                                       &data, &record_verify);
     809           6 :                         CHECK_VRET(ret, checked, record_verify, *verify);
     810             :                 }
     811             :         }
     812             :         while (1);
     813             : 
     814          10 :         if ((vflags & DANE_VFLAG_FAIL_IF_NOT_CHECKED) && checked == 0) {
     815             :                 ret =
     816             :                     gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
     817          10 :         } else if (checked == 0) {
     818           1 :                 *verify |= DANE_VERIFY_UNKNOWN_DANE_INFO;
     819             :         } else {
     820             :                 ret = 0;
     821             :         }
     822             : 
     823             :       cleanup:
     824             :         return ret;
     825             : }
     826             : 
     827             : 
     828             : /**
     829             :  * dane_verify_crt:
     830             :  * @s: A DANE state structure (may be NULL)
     831             :  * @chain: A certificate chain
     832             :  * @chain_size: The size of the chain
     833             :  * @chain_type: The type of the certificate chain
     834             :  * @hostname: The hostname associated with the chain
     835             :  * @proto: The protocol of the service connecting (e.g. tcp)
     836             :  * @port: The port of the service connecting (e.g. 443)
     837             :  * @sflags: Flags for the initialization of @s (if NULL)
     838             :  * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
     839             :  * @verify: An OR'ed list of %dane_verify_status_t.
     840             :  *
     841             :  * This function will verify the given certificate chain against the
     842             :  * CA constrains and/or the certificate available via DANE.
     843             :  * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
     844             :  * is set. If a DNSSEC signature is not available for the DANE
     845             :  * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
     846             :  *
     847             :  * Due to the many possible options of DANE, there is no single threat
     848             :  * model countered. When notifying the user about DANE verification results
     849             :  * it may be better to mention: DANE verification did not reject the certificate,
     850             :  * rather than mentioning a successful DANE verication.
     851             :  *
     852             :  * Note that this function is designed to be run in addition to
     853             :  * PKIX - certificate chain - verification. To be run independently
     854             :  * the %DANE_VFLAG_ONLY_CHECK_EE_USAGE flag should be specified;
     855             :  * then the function will check whether the key of the peer matches the
     856             :  * key advertized in the DANE entry.
     857             :  *
     858             :  * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
     859             :  * when the DANE entries were successfully parsed, irrespective of
     860             :  * whether they were verified (see @verify for that information). If
     861             :  * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
     862             :  * will be returned.
     863             :  *
     864             :  **/
     865             : int
     866           3 : dane_verify_crt(dane_state_t s,
     867             :                 const gnutls_datum_t * chain, unsigned chain_size,
     868             :                 gnutls_certificate_type_t chain_type,
     869             :                 const char *hostname, const char *proto, unsigned int port,
     870             :                 unsigned int sflags, unsigned int vflags,
     871             :                 unsigned int *verify)
     872             : {
     873           3 :         dane_state_t state = NULL;
     874           3 :         dane_query_t r = NULL;
     875           3 :         int ret;
     876             : 
     877           3 :         *verify = 0;
     878           3 :         if (s == NULL) {
     879           0 :                 ret = dane_state_init(&state, sflags);
     880           0 :                 if (ret < 0) {
     881             :                         gnutls_assert();
     882             :                         return ret;
     883             :                 }
     884             :         } else
     885           3 :                 state = s;
     886             : 
     887           3 :         ret = dane_query_tlsa(state, &r, hostname, proto, port);
     888           3 :         if (ret < 0) {
     889           0 :                 gnutls_assert();
     890           0 :                 goto cleanup;
     891             :         }
     892           3 :         ret = dane_verify_crt_raw(state, chain, chain_size, chain_type,
     893             :                                   r, sflags, vflags, verify);
     894           3 :       cleanup:
     895           3 :         if (state != s)
     896           0 :                 dane_state_deinit(state);
     897           3 :         if (r != NULL)
     898           3 :                 dane_query_deinit(r);
     899             :         return ret;
     900             : }
     901             : 
     902             : /**
     903             :  * dane_verify_session_crt:
     904             :  * @s: A DANE state structure (may be NULL)
     905             :  * @session: A gnutls session
     906             :  * @hostname: The hostname associated with the chain
     907             :  * @proto: The protocol of the service connecting (e.g. tcp)
     908             :  * @port: The port of the service connecting (e.g. 443)
     909             :  * @sflags: Flags for the initialization of @s (if NULL)
     910             :  * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
     911             :  * @verify: An OR'ed list of %dane_verify_status_t.
     912             :  *
     913             :  * This function will verify session's certificate chain against the
     914             :  * CA constrains and/or the certificate available via DANE.
     915             :  * See dane_verify_crt() for more information.
     916             :  *
     917             :  * This will not verify the chain for validity; unless the DANE
     918             :  * verification is restricted to end certificates, this must be
     919             :  * be performed separately using gnutls_certificate_verify_peers3().
     920             :  *
     921             :  * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
     922             :  * when the DANE entries were successfully parsed, irrespective of
     923             :  * whether they were verified (see @verify for that information). If
     924             :  * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
     925             :  * will be returned.
     926             :  *
     927             :  **/
     928             : int
     929           0 : dane_verify_session_crt(dane_state_t s,
     930             :                         gnutls_session_t session,
     931             :                         const char *hostname, const char *proto,
     932             :                         unsigned int port, unsigned int sflags,
     933             :                         unsigned int vflags, unsigned int *verify)
     934             : {
     935           0 :         const gnutls_datum_t *cert_list;
     936           0 :         unsigned int cert_list_size = 0;
     937           0 :         unsigned int type;
     938           0 :         int ret;
     939             : 
     940           0 :         cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
     941           0 :         if (cert_list_size == 0) {
     942             :                 return gnutls_assert_val(DANE_E_NO_CERT);
     943             :         }
     944             : 
     945           0 :         type = gnutls_certificate_type_get(session);
     946             : 
     947             :         /* this list may be incomplete, try to get the self-signed CA if any */
     948           0 :         if (cert_list_size > 0) {
     949           0 :                 gnutls_x509_crt_t crt, ca;
     950           0 :                 gnutls_certificate_credentials_t sc;
     951             : 
     952           0 :                 ret = gnutls_x509_crt_init(&crt);
     953           0 :                 if (ret < 0) {
     954           0 :                         gnutls_assert();
     955           0 :                         goto failsafe;
     956             :                 }
     957             : 
     958           0 :                 ret = gnutls_x509_crt_import(crt, &cert_list[cert_list_size-1], GNUTLS_X509_FMT_DER);
     959           0 :                 if (ret < 0) {
     960           0 :                         gnutls_assert();
     961           0 :                         gnutls_x509_crt_deinit(crt);
     962           0 :                         goto failsafe;
     963             :                 }
     964             : 
     965             :                 /* if it is already self signed continue normally */
     966           0 :                 ret = gnutls_x509_crt_check_issuer(crt, crt);
     967           0 :                 if (ret != 0) {
     968           0 :                         gnutls_assert();
     969           0 :                         gnutls_x509_crt_deinit(crt);
     970           0 :                         goto failsafe;
     971             :                 }
     972             : 
     973             :                 /* chain does not finish in a self signed cert, try to obtain the issuer */
     974           0 :                 ret = gnutls_credentials_get(session, GNUTLS_CRD_CERTIFICATE, (void**)&sc);
     975           0 :                 if (ret < 0) {
     976           0 :                         gnutls_assert();
     977           0 :                         gnutls_x509_crt_deinit(crt);
     978           0 :                         goto failsafe;
     979             :                 }
     980             : 
     981           0 :                 ret = gnutls_certificate_get_issuer(sc, crt, &ca, 0);
     982           0 :                 if (ret < 0) {
     983           0 :                         gnutls_assert();
     984           0 :                         gnutls_x509_crt_deinit(crt);
     985           0 :                         goto failsafe;
     986             :                 }
     987             : 
     988             :                 /* make the new list */
     989           0 :                 gnutls_datum_t *new_cert_list;
     990             : 
     991           0 :                 new_cert_list = gnutls_malloc((cert_list_size + 1) * sizeof(gnutls_datum_t));
     992           0 :                 if (new_cert_list == NULL) {
     993           0 :                         gnutls_assert();
     994           0 :                         gnutls_x509_crt_deinit(crt);
     995           0 :                         goto failsafe;
     996             :                 }
     997             : 
     998           0 :                 memcpy(new_cert_list, cert_list, cert_list_size*sizeof(gnutls_datum_t));
     999             : 
    1000           0 :                 ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_DER, &new_cert_list[cert_list_size]);
    1001           0 :                 if (ret < 0) {
    1002           0 :                         gnutls_assert();
    1003           0 :                         free(new_cert_list);
    1004           0 :                         gnutls_x509_crt_deinit(crt);
    1005           0 :                         goto failsafe;
    1006             :                 }
    1007             : 
    1008           0 :                 ret = dane_verify_crt(s, new_cert_list, cert_list_size+1, type,
    1009             :                                hostname, proto, port, sflags, vflags,
    1010             :                                verify);
    1011           0 :                 if (ret < 0) {
    1012           0 :                         gnutls_assert();
    1013             :                 }
    1014           0 :                 gnutls_free(new_cert_list[cert_list_size].data);
    1015           0 :                 free(new_cert_list);
    1016           0 :                 return ret;
    1017             :         }
    1018             : 
    1019           0 :  failsafe:
    1020           0 :         return dane_verify_crt(s, cert_list, cert_list_size, type,
    1021             :                                hostname, proto, port, sflags, vflags,
    1022             :                                verify);
    1023             : }
    1024             : 
    1025             : /**
    1026             :  * dane_verification_status_print:
    1027             :  * @status: The status flags to be printed
    1028             :  * @type: The certificate type
    1029             :  * @out: Newly allocated datum with (0) terminated string.
    1030             :  * @flags: should be zero
    1031             :  *
    1032             :  * This function will pretty print the status of a verification
    1033             :  * process -- eg. the one obtained by dane_verify_crt().
    1034             :  *
    1035             :  * The output @out needs to be deallocated using gnutls_free().
    1036             :  *
    1037             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1038             :  *   negative error value.
    1039             :  **/
    1040             : int
    1041           3 : dane_verification_status_print(unsigned int status,
    1042             :                                gnutls_datum_t * out, unsigned int flags)
    1043             : {
    1044           3 :         gnutls_buffer_st str;
    1045             : 
    1046           3 :         _gnutls_buffer_init(&str);
    1047             : 
    1048           3 :         if (status == 0)
    1049           3 :                 _gnutls_buffer_append_str(&str,
    1050           3 :                                           _("Certificate matches. "));
    1051             :         else
    1052           0 :                 _gnutls_buffer_append_str(&str,
    1053           0 :                                           _("Verification failed. "));
    1054             : 
    1055           3 :         if (status & DANE_VERIFY_CA_CONSTRAINTS_VIOLATED)
    1056           0 :                 _gnutls_buffer_append_str(&str,
    1057           0 :                                           _
    1058             :                                           ("CA constrains were violated. "));
    1059             : 
    1060           3 :         if (status & DANE_VERIFY_CERT_DIFFERS)
    1061           0 :                 _gnutls_buffer_append_str(&str,
    1062           0 :                                           _("The certificate differs. "));
    1063             : 
    1064           3 :         if (status & DANE_VERIFY_NO_DANE_INFO)
    1065           0 :                 _gnutls_buffer_append_str(&str,
    1066           0 :                                           _
    1067             :                                           ("There were no DANE information. "));
    1068             : 
    1069           3 :         return _gnutls_buffer_to_datum(&str, out, 1);
    1070             : }

Generated by: LCOV version 1.14