LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - verify-tofu.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 214 293 73.0 %
Date: 2020-10-30 04:50:48 Functions: 10 15 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2012 Free Software Foundation, Inc.
       3             :  *
       4             :  * Author: Nikos Mavrogiannopoulos
       5             :  *
       6             :  * This file is part of GnuTLS.
       7             :  *
       8             :  * The GnuTLS is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public License
      10             :  * as published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * This library is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public License
      19             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20             :  *
      21             :  */
      22             : 
      23             : #include "gnutls_int.h"
      24             : #include "errors.h"
      25             : #include <libtasn1.h>
      26             : #include <global.h>
      27             : #include <num.h>          /* MAX */
      28             : #include <tls-sig.h>
      29             : #include "str.h"
      30             : #include <datum.h>
      31             : #include "x509_int.h"
      32             : #include <nettle/base64.h>
      33             : #include <common.h>
      34             : #include <gnutls/abstract.h>
      35             : #include <system.h>
      36             : #include <locks.h>
      37             : 
      38             : struct gnutls_tdb_int {
      39             :         gnutls_tdb_store_func store;
      40             :         gnutls_tdb_store_commitment_func cstore;
      41             :         gnutls_tdb_verify_func verify;
      42             : };
      43             : 
      44             : static int raw_pubkey_to_base64(const gnutls_datum_t * raw,
      45             :                                 gnutls_datum_t * b64);
      46             : static int verify_pubkey(const char *file, const char *host,
      47             :                          const char *service, const gnutls_datum_t * skey);
      48             : 
      49             : static
      50             : int store_commitment(const char *db_name, const char *host,
      51             :                      const char *service, time_t expiration,
      52             :                      gnutls_digest_algorithm_t hash_algo,
      53             :                      const gnutls_datum_t * hash);
      54             : static
      55             : int store_pubkey(const char *db_name, const char *host,
      56             :                  const char *service, time_t expiration,
      57             :                  const gnutls_datum_t * pubkey);
      58             : 
      59             : static int find_config_file(char *file, size_t max_size);
      60             : 
      61             : extern void *_gnutls_file_mutex;
      62             : 
      63             : struct gnutls_tdb_int default_tdb = {
      64             :         store_pubkey,
      65             :         store_commitment,
      66             :         verify_pubkey
      67             : };
      68             : 
      69             : 
      70             : /**
      71             :  * gnutls_verify_stored_pubkey:
      72             :  * @db_name: A file specifying the stored keys (use NULL for the default)
      73             :  * @tdb: A storage structure or NULL to use the default
      74             :  * @host: The peer's name
      75             :  * @service: non-NULL if this key is specific to a service (e.g. http)
      76             :  * @cert_type: The type of the certificate
      77             :  * @cert: The raw (der) data of the certificate
      78             :  * @flags: should be 0.
      79             :  *
      80             :  * This function will try to verify a raw public-key or a public-key provided via
      81             :  * a raw (DER-encoded) certificate using a list of stored public keys.
      82             :  * The @service field if non-NULL should be a port number.
      83             :  *
      84             :  * The @db_name variable if non-null specifies a custom backend for
      85             :  * the retrieval of entries. If it is NULL then the
      86             :  * default file backend will be used. In POSIX-like systems the
      87             :  * file backend uses the $HOME/.gnutls/known_hosts file.
      88             :  *
      89             :  * Note that if the custom storage backend is provided the
      90             :  * retrieval function should return %GNUTLS_E_CERTIFICATE_KEY_MISMATCH
      91             :  * if the host/service pair is found but key doesn't match,
      92             :  * %GNUTLS_E_NO_CERTIFICATE_FOUND if no such host/service with
      93             :  * the given key is found, and 0 if it was found. The storage
      94             :  * function should return 0 on success.
      95             :  *
      96             :  * As of GnuTLS 3.6.6 this function also verifies raw public keys.
      97             :  *
      98             :  * Returns: If no associated public key is found
      99             :  * then %GNUTLS_E_NO_CERTIFICATE_FOUND will be returned. If a key
     100             :  * is found but does not match %GNUTLS_E_CERTIFICATE_KEY_MISMATCH
     101             :  * is returned. On success, %GNUTLS_E_SUCCESS (0) is returned,
     102             :  * or a negative error value on other errors.
     103             :  *
     104             :  * Since: 3.0.13
     105             :  **/
     106             : int
     107           6 : gnutls_verify_stored_pubkey(const char *db_name,
     108             :                             gnutls_tdb_t tdb,
     109             :                             const char *host,
     110             :                             const char *service,
     111             :                             gnutls_certificate_type_t cert_type,
     112             :                             const gnutls_datum_t * cert,
     113             :                             unsigned int flags)
     114             : {
     115           6 :         gnutls_datum_t pubkey = { NULL, 0 }; // Holds the pubkey in subjectPublicKeyInfo format (DER encoded)
     116           6 :         int ret;
     117           6 :         char local_file[MAX_FILENAME];
     118           6 :         bool need_free;
     119             : 
     120             : 
     121           6 :         if (db_name == NULL && tdb == NULL) {
     122           1 :                 ret = find_config_file(local_file, sizeof(local_file));
     123           1 :                 if (ret < 0)
     124           0 :                         return gnutls_assert_val(ret);
     125             :                 db_name = local_file;
     126             :         }
     127             : 
     128           6 :         if (tdb == NULL)
     129           6 :                 tdb = &default_tdb;
     130             : 
     131             :         /* Import the public key depending on the provided certificate type */
     132           6 :         switch (cert_type) {
     133           4 :                 case GNUTLS_CRT_X509:
     134             :                         /* Extract the pubkey from the cert. This function does a malloc
     135             :                          * deep down the call chain. We are responsible for freeing. */
     136           4 :                         ret = _gnutls_x509_raw_crt_to_raw_pubkey(cert, &pubkey);
     137             : 
     138           4 :                         if (ret < 0) {
     139           0 :                                 _gnutls_free_datum(&pubkey);
     140           0 :                                 return gnutls_assert_val(ret);
     141             :                         }
     142             : 
     143             :                         need_free = true;
     144             :                         break;
     145           2 :                 case GNUTLS_CRT_RAWPK:
     146           2 :                         pubkey.data = cert->data;
     147           2 :                         pubkey.size = cert->size;
     148           2 :                         need_free = false;
     149           2 :                         break;
     150             :                 default:
     151           0 :                         return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
     152             :         }
     153             : 
     154             :         // Verify our pubkey against the database
     155           6 :         ret = tdb->verify(db_name, host, service, &pubkey);
     156           6 :         if (ret < 0 && ret != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
     157           0 :                 ret = gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
     158             : 
     159           6 :         if (need_free) {
     160           4 :                 _gnutls_free_datum(&pubkey);
     161             :         }
     162             : 
     163             :         return ret;
     164             : }
     165             : 
     166           2 : static int parse_commitment_line(char *line,
     167             :                                  const char *host, size_t host_len,
     168             :                                  const char *service, size_t service_len,
     169             :                                  time_t now, const gnutls_datum_t * skey)
     170             : {
     171           2 :         char *p, *kp;
     172           2 :         char *savep = NULL;
     173           2 :         size_t kp_len, phash_size;
     174           2 :         time_t expiration;
     175           2 :         int ret;
     176           2 :         const mac_entry_st *hash_algo;
     177           2 :         uint8_t phash[MAX_HASH_SIZE];
     178           2 :         uint8_t hphash[MAX_HASH_SIZE * 2 + 1];
     179             : 
     180             :         /* read host */
     181           2 :         p = strtok_r(line, "|", &savep);
     182           2 :         if (p == NULL)
     183           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     184             : 
     185           2 :         if (p[0] != '*' && host != NULL && strcmp(p, host) != 0)
     186           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     187             : 
     188             :         /* read service */
     189           2 :         p = strtok_r(NULL, "|", &savep);
     190           2 :         if (p == NULL)
     191           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     192             : 
     193           2 :         if (p[0] != '*' && service != NULL && strcmp(p, service) != 0)
     194           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     195             : 
     196             :         /* read expiration */
     197           2 :         p = strtok_r(NULL, "|", &savep);
     198           2 :         if (p == NULL)
     199           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     200             : 
     201           2 :         expiration = (time_t) atol(p);
     202           2 :         if (expiration > 0 && now > expiration)
     203           0 :                 return gnutls_assert_val(GNUTLS_E_EXPIRED);
     204             : 
     205             :         /* read hash algorithm */
     206           2 :         p = strtok_r(NULL, "|", &savep);
     207           2 :         if (p == NULL)
     208           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     209             : 
     210           2 :         hash_algo = mac_to_entry(atol(p));
     211           2 :         if (_gnutls_digest_get_name(hash_algo) == NULL)
     212           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     213             : 
     214             :         /* read hash */
     215           2 :         kp = strtok_r(NULL, "|", &savep);
     216           2 :         if (kp == NULL)
     217           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     218             : 
     219           2 :         p = strpbrk(kp, "\n \r\t|");
     220           2 :         if (p != NULL)
     221           2 :                 *p = 0;
     222             : 
     223             :         /* hash and hex encode */
     224           2 :         ret =
     225           4 :             _gnutls_hash_fast((gnutls_digest_algorithm_t)hash_algo->id,
     226           2 :                                 skey->data, skey->size, phash);
     227           2 :         if (ret < 0)
     228           0 :                 return gnutls_assert_val(ret);
     229             : 
     230           2 :         phash_size = _gnutls_hash_get_algo_len(hash_algo);
     231             : 
     232           2 :         p = _gnutls_bin2hex(phash, phash_size, (void *) hphash,
     233             :                             sizeof(hphash), NULL);
     234           2 :         if (p == NULL)
     235           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     236             : 
     237           2 :         kp_len = strlen(kp);
     238           2 :         if (kp_len != phash_size * 2)
     239           0 :                 return
     240           0 :                     gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
     241             : 
     242           2 :         if (memcmp(kp, hphash, kp_len) != 0)
     243           0 :                 return
     244           0 :                     gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
     245             : 
     246             :         /* key found and matches */
     247             :         return 0;
     248             : }
     249             : 
     250             : 
     251           8 : static int parse_line(char *line,
     252             :                       const char *host, size_t host_len,
     253             :                       const char *service, size_t service_len,
     254             :                       time_t now,
     255             :                       const gnutls_datum_t * rawkey,
     256             :                       const gnutls_datum_t * b64key)
     257             : {
     258           8 :         char *p, *kp;
     259           8 :         char *savep = NULL;
     260           8 :         size_t kp_len;
     261           8 :         time_t expiration;
     262             : 
     263             :         /* read version */
     264           8 :         p = strtok_r(line, "|", &savep);
     265           8 :         if (p == NULL)
     266           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     267             : 
     268           8 :         if (strncmp(p, "c0", 2) == 0)
     269           2 :                 return parse_commitment_line(p + 3, host, host_len,
     270             :                                              service, service_len, now,
     271             :                                              rawkey);
     272             : 
     273           6 :         if (strncmp(p, "g0", 2) != 0)
     274           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     275             : 
     276             :         /* read host */
     277           6 :         p = strtok_r(NULL, "|", &savep);
     278           6 :         if (p == NULL)
     279           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     280             : 
     281           6 :         if (p[0] != '*' && host != NULL && strcmp(p, host) != 0)
     282           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     283             : 
     284             :         /* read service */
     285           6 :         p = strtok_r(NULL, "|", &savep);
     286           6 :         if (p == NULL)
     287           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     288             : 
     289           6 :         if (p[0] != '*' && service != NULL && strcmp(p, service) != 0)
     290           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     291             : 
     292             :         /* read expiration */
     293           6 :         p = strtok_r(NULL, "|", &savep);
     294           6 :         if (p == NULL)
     295           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     296             : 
     297           6 :         expiration = (time_t) atol(p);
     298           6 :         if (expiration > 0 && now > expiration)
     299           0 :                 return gnutls_assert_val(GNUTLS_E_EXPIRED);
     300             : 
     301             :         /* read key */
     302           6 :         kp = strtok_r(NULL, "|", &savep);
     303           6 :         if (kp == NULL)
     304           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     305             : 
     306           6 :         p = strpbrk(kp, "\n \r\t|");
     307           6 :         if (p != NULL)
     308           6 :                 *p = 0;
     309             : 
     310           6 :         kp_len = strlen(kp);
     311           6 :         if (kp_len != b64key->size)
     312           2 :                 return
     313           2 :                     gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
     314             : 
     315           4 :         if (memcmp(kp, b64key->data, b64key->size) != 0)
     316           2 :                 return
     317           2 :                     gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
     318             : 
     319             :         /* key found and matches */
     320             :         return 0;
     321             : }
     322             : 
     323             : /* Returns the base64 key if found
     324             :  */
     325           6 : static int verify_pubkey(const char *file,
     326             :                          const char *host, const char *service,
     327             :                          const gnutls_datum_t * pubkey)
     328             : {
     329           6 :         FILE *fp;
     330           6 :         char *line = NULL;
     331           6 :         size_t line_size = 0;
     332           6 :         int ret, l2, mismatch = 0;
     333           6 :         size_t host_len = 0, service_len = 0;
     334           6 :         time_t now = gnutls_time(0);
     335           6 :         gnutls_datum_t b64key = { NULL, 0 };
     336             : 
     337           6 :         ret = raw_pubkey_to_base64(pubkey, &b64key);
     338           6 :         if (ret < 0)
     339           0 :                 return gnutls_assert_val(ret);
     340             : 
     341           6 :         if (host != NULL)
     342           6 :                 host_len = strlen(host);
     343           6 :         if (service != NULL)
     344           6 :                 service_len = strlen(service);
     345             : 
     346           6 :         fp = fopen(file, "rbe");
     347           6 :         if (fp == NULL) {
     348           0 :                 ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
     349           0 :                 goto cleanup;
     350             :         }
     351             : 
     352          10 :         do {
     353          10 :                 l2 = getline(&line, &line_size, fp);
     354          10 :                 if (l2 > 0) {
     355           8 :                         ret =
     356           8 :                             parse_line(line, host, host_len, service,
     357             :                                        service_len, now, pubkey, &b64key);
     358           8 :                         if (ret == 0) { /* found */
     359           4 :                                 goto cleanup;
     360           4 :                         } else if (ret ==
     361             :                                    GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
     362           4 :                                 mismatch = 1;
     363             :                 }
     364             :         }
     365           6 :         while (l2 >= 0);
     366             : 
     367           2 :         if (mismatch)
     368             :                 ret = GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
     369             :         else
     370           0 :                 ret = GNUTLS_E_NO_CERTIFICATE_FOUND;
     371             : 
     372           6 :       cleanup:
     373           6 :         free(line);
     374           6 :         if (fp != NULL)
     375           6 :                 fclose(fp);
     376           6 :         gnutls_free(b64key.data);
     377             : 
     378           6 :         return ret;
     379             : }
     380             : 
     381           8 : static int raw_pubkey_to_base64(const gnutls_datum_t * raw,
     382             :                                 gnutls_datum_t * b64)
     383             : {
     384           8 :         size_t size;
     385             : 
     386           8 :         size = BASE64_ENCODE_RAW_LENGTH(raw->size);
     387             : 
     388           8 :         b64->data = gnutls_malloc(size);
     389           8 :         if (b64->data == NULL)
     390           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     391             : 
     392           8 :         base64_encode_raw((void*)b64->data, raw->size, raw->data);
     393           8 :         b64->size = size;
     394             : 
     395           8 :         return 0;
     396             : }
     397             : 
     398             : static
     399           2 : int store_pubkey(const char *db_name, const char *host,
     400             :                  const char *service, time_t expiration,
     401             :                  const gnutls_datum_t * pubkey)
     402             : {
     403           2 :         FILE *fp = NULL;
     404           2 :         gnutls_datum_t b64key = { NULL, 0 };
     405           2 :         int ret;
     406             : 
     407           2 :         ret = gnutls_mutex_lock(&_gnutls_file_mutex);
     408           2 :         if (ret != 0)
     409           0 :                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
     410             : 
     411           2 :         ret = raw_pubkey_to_base64(pubkey, &b64key);
     412           2 :         if (ret < 0) {
     413           0 :                 gnutls_assert();
     414           0 :                 goto cleanup;
     415             :         }
     416             : 
     417           2 :         fp = fopen(db_name, "abe+");
     418           2 :         if (fp == NULL) {
     419           0 :                 ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
     420           0 :                 goto cleanup;
     421             :         }
     422             : 
     423           2 :         if (service == NULL)
     424           0 :                 service = "*";
     425           2 :         if (host == NULL)
     426           0 :                 host = "*";
     427             : 
     428           2 :         fprintf(fp, "|g0|%s|%s|%lu|%.*s\n", host, service,
     429             :                 (unsigned long) expiration, b64key.size, b64key.data);
     430             : 
     431           2 :         ret = 0;
     432             : 
     433           2 :       cleanup:
     434           2 :         if (fp != NULL)
     435           2 :                 fclose(fp);
     436             : 
     437           2 :         gnutls_mutex_unlock(&_gnutls_file_mutex);
     438           2 :         gnutls_free(b64key.data);
     439             : 
     440           2 :         return ret;
     441             : }
     442             : 
     443             : static
     444           2 : int store_commitment(const char *db_name, const char *host,
     445             :                      const char *service, time_t expiration,
     446             :                      gnutls_digest_algorithm_t hash_algo,
     447             :                      const gnutls_datum_t * hash)
     448             : {
     449           2 :         FILE *fp;
     450           2 :         char buffer[MAX_HASH_SIZE * 2 + 1];
     451             : 
     452           2 :         fp = fopen(db_name, "abe+");
     453           2 :         if (fp == NULL)
     454           0 :                 return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
     455             : 
     456           2 :         if (service == NULL)
     457           0 :                 service = "*";
     458           2 :         if (host == NULL)
     459           0 :                 host = "*";
     460             : 
     461           2 :         fprintf(fp, "|c0|%s|%s|%lu|%u|%s\n", host, service,
     462             :                 (unsigned long) expiration, (unsigned) hash_algo,
     463           2 :                 _gnutls_bin2hex(hash->data, hash->size, buffer,
     464             :                                 sizeof(buffer), NULL));
     465             : 
     466           2 :         fclose(fp);
     467             : 
     468           2 :         return 0;
     469             : }
     470             : 
     471             : /**
     472             :  * gnutls_store_pubkey:
     473             :  * @db_name: A file specifying the stored keys (use NULL for the default)
     474             :  * @tdb: A storage structure or NULL to use the default
     475             :  * @host: The peer's name
     476             :  * @service: non-NULL if this key is specific to a service (e.g. http)
     477             :  * @cert_type: The type of the certificate
     478             :  * @cert: The data of the certificate
     479             :  * @expiration: The expiration time (use 0 to disable expiration)
     480             :  * @flags: should be 0.
     481             :  *
     482             :  * This function will store a raw public-key or a public-key provided via
     483             :  * a raw (DER-encoded) certificate to the list of stored public keys. The key
     484             :  * will be considered valid until the provided expiration time.
     485             :  *
     486             :  * The @tdb variable if non-null specifies a custom backend for
     487             :  * the storage of entries. If it is NULL then the
     488             :  * default file backend will be used.
     489             :  *
     490             :  * Unless an alternative @tdb is provided, the storage format is a textual format
     491             :  * consisting of a line for each host with fields separated by '|'. The contents of
     492             :  * the fields are a format-identifier which is set to 'g0', the hostname that the
     493             :  * rest of the data applies to, the numeric port or host name, the expiration
     494             :  * time in seconds since the epoch (0 for no expiration), and a base64
     495             :  * encoding of the raw (DER) public key information (SPKI) of the peer.
     496             :  *
     497             :  * As of GnuTLS 3.6.6 this function also accepts raw public keys.
     498             :  *
     499             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     500             :  *   negative error value.
     501             :  *
     502             :  * Since: 3.0.13
     503             :  **/
     504             : int
     505           2 : gnutls_store_pubkey(const char *db_name,
     506             :                     gnutls_tdb_t tdb,
     507             :                     const char *host,
     508             :                     const char *service,
     509             :                     gnutls_certificate_type_t cert_type,
     510             :                     const gnutls_datum_t * cert,
     511             :                     time_t expiration, unsigned int flags)
     512             : {
     513           2 :         gnutls_datum_t pubkey = { NULL, 0 }; // Holds the pubkey in subjectPublicKeyInfo format (DER encoded)
     514           2 :         int ret;
     515           2 :         char local_file[MAX_FILENAME];
     516           2 :         bool need_free;
     517             : 
     518             : 
     519           2 :         if (db_name == NULL && tdb == NULL) {
     520           0 :                 ret =
     521           0 :                     _gnutls_find_config_path(local_file,
     522             :                                              sizeof(local_file));
     523           0 :                 if (ret < 0)
     524           0 :                         return gnutls_assert_val(ret);
     525             : 
     526           0 :                 _gnutls_debug_log("Configuration path: %s\n", local_file);
     527           0 :                 mkdir(local_file, 0700);
     528             : 
     529           0 :                 ret = find_config_file(local_file, sizeof(local_file));
     530           0 :                 if (ret < 0)
     531           0 :                         return gnutls_assert_val(ret);
     532             :                 db_name = local_file;
     533             :         }
     534             : 
     535           2 :         if (tdb == NULL)
     536           2 :                 tdb = &default_tdb;
     537             : 
     538             :         /* Import the public key depending on the provided certificate type */
     539           2 :         switch (cert_type) {
     540           1 :                 case GNUTLS_CRT_X509:
     541             :                         /* Extract the pubkey from the cert. This function does a malloc
     542             :                          * deep down the call chain. We are responsible for freeing. */
     543           1 :                         ret = _gnutls_x509_raw_crt_to_raw_pubkey(cert, &pubkey);
     544             : 
     545           1 :                         if (ret < 0) {
     546           0 :                                 _gnutls_free_datum(&pubkey);
     547           0 :                                 return gnutls_assert_val(ret);
     548             :                         }
     549             : 
     550             :                         need_free = true;
     551             :                         break;
     552           1 :                 case GNUTLS_CRT_RAWPK:
     553           1 :                         pubkey.data = cert->data;
     554           1 :                         pubkey.size = cert->size;
     555           1 :                         need_free = false;
     556           1 :                         break;
     557             :                 default:
     558           0 :                         return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
     559             :         }
     560             : 
     561           2 :         _gnutls_debug_log("Configuration file: %s\n", db_name);
     562             : 
     563           2 :         tdb->store(db_name, host, service, expiration, &pubkey);
     564             : 
     565           2 :         if (need_free) {
     566           1 :                 _gnutls_free_datum(&pubkey);
     567             :         }
     568             : 
     569             :         return GNUTLS_E_SUCCESS;
     570             : }
     571             : 
     572             : /**
     573             :  * gnutls_store_commitment:
     574             :  * @db_name: A file specifying the stored keys (use NULL for the default)
     575             :  * @tdb: A storage structure or NULL to use the default
     576             :  * @host: The peer's name
     577             :  * @service: non-NULL if this key is specific to a service (e.g. http)
     578             :  * @hash_algo: The hash algorithm type
     579             :  * @hash: The raw hash
     580             :  * @expiration: The expiration time (use 0 to disable expiration)
     581             :  * @flags: should be 0 or %GNUTLS_SCOMMIT_FLAG_ALLOW_BROKEN.
     582             :  *
     583             :  * This function will store the provided hash commitment to
     584             :  * the list of stored public keys. The key with the given
     585             :  * hash will be considered valid until the provided expiration time.
     586             :  *
     587             :  * The @tdb variable if non-null specifies a custom backend for
     588             :  * the storage of entries. If it is NULL then the
     589             :  * default file backend will be used.
     590             :  *
     591             :  * Note that this function is not thread safe with the default backend.
     592             :  *
     593             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     594             :  *   negative error value.
     595             :  *
     596             :  * Since: 3.0
     597             :  **/
     598             : int
     599           2 : gnutls_store_commitment(const char *db_name,
     600             :                         gnutls_tdb_t tdb,
     601             :                         const char *host,
     602             :                         const char *service,
     603             :                         gnutls_digest_algorithm_t hash_algo,
     604             :                         const gnutls_datum_t * hash,
     605             :                         time_t expiration, unsigned int flags)
     606             : {
     607           2 :         int ret;
     608           2 :         char local_file[MAX_FILENAME];
     609           2 :         const mac_entry_st *me = hash_to_entry(hash_algo);
     610             : 
     611           2 :         if (me == NULL)
     612           0 :                 return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
     613             : 
     614           2 :         if (!(flags & GNUTLS_SCOMMIT_FLAG_ALLOW_BROKEN) && _gnutls_digest_is_secure(me) == 0)
     615           0 :                 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
     616             : 
     617           2 :         if (_gnutls_hash_get_algo_len(me) != hash->size)
     618           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     619             : 
     620           2 :         if (db_name == NULL && tdb == NULL) {
     621           1 :                 ret =
     622           1 :                     _gnutls_find_config_path(local_file,
     623             :                                              sizeof(local_file));
     624           1 :                 if (ret < 0)
     625           0 :                         return gnutls_assert_val(ret);
     626             : 
     627           1 :                 _gnutls_debug_log("Configuration path: %s\n", local_file);
     628           1 :                 mkdir(local_file, 0700);
     629             : 
     630           1 :                 ret = find_config_file(local_file, sizeof(local_file));
     631           1 :                 if (ret < 0)
     632           0 :                         return gnutls_assert_val(ret);
     633             :                 db_name = local_file;
     634             :         }
     635             : 
     636           2 :         if (tdb == NULL)
     637           2 :                 tdb = &default_tdb;
     638             : 
     639           2 :         _gnutls_debug_log("Configuration file: %s\n", db_name);
     640             : 
     641           2 :         tdb->cstore(db_name, host, service, expiration,
     642           2 :                 (gnutls_digest_algorithm_t)me->id, hash);
     643             : 
     644           2 :         return 0;
     645             : }
     646             : 
     647             : #define CONFIG_FILE "known_hosts"
     648             : 
     649           2 : static int find_config_file(char *file, size_t max_size)
     650             : {
     651           2 :         char path[MAX_FILENAME];
     652           2 :         int ret;
     653             : 
     654           2 :         ret = _gnutls_find_config_path(path, sizeof(path));
     655           2 :         if (ret < 0)
     656           0 :                 return gnutls_assert_val(ret);
     657             : 
     658           2 :         if (path[0] == 0)
     659           0 :                 snprintf(file, max_size, "%s", CONFIG_FILE);
     660             :         else
     661           2 :                 snprintf(file, max_size, "%s/%s", path, CONFIG_FILE);
     662             : 
     663             :         return 0;
     664             : }
     665             : 
     666             : /**
     667             :  * gnutls_tdb_init:
     668             :  * @tdb: A pointer to the type to be initialized
     669             :  *
     670             :  * This function will initialize a public key trust storage structure.
     671             :  *
     672             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     673             :  *   negative error value.
     674             :  **/
     675           0 : int gnutls_tdb_init(gnutls_tdb_t * tdb)
     676             : {
     677           0 :         *tdb = gnutls_calloc(1, sizeof(struct gnutls_tdb_int));
     678             : 
     679           0 :         if (!*tdb)
     680           0 :                 return GNUTLS_E_MEMORY_ERROR;
     681             : 
     682             :         return 0;
     683             : }
     684             : 
     685             : /**
     686             :  * gnutls_set_store_func:
     687             :  * @tdb: The trust storage
     688             :  * @store: The storage function
     689             :  *
     690             :  * This function will associate a storage function with the
     691             :  * trust storage structure. The function is of the following form.
     692             :  *
     693             :  * int gnutls_tdb_store_func(const char* db_name, const char* host,
     694             :  *                     const char* service, time_t expiration,
     695             :  *                     const gnutls_datum_t* pubkey);
     696             :  *
     697             :  * The @db_name should be used to pass any private data to this function.
     698             :  *
     699             :  **/
     700           0 : void gnutls_tdb_set_store_func(gnutls_tdb_t tdb,
     701             :                                gnutls_tdb_store_func store)
     702             : {
     703           0 :         tdb->store = store;
     704           0 : }
     705             : 
     706             : /**
     707             :  * gnutls_set_store_commitment_func:
     708             :  * @tdb: The trust storage
     709             :  * @cstore: The commitment storage function
     710             :  *
     711             :  * This function will associate a commitment (hash) storage function with the
     712             :  * trust storage structure. The function is of the following form.
     713             :  *
     714             :  * int gnutls_tdb_store_commitment_func(const char* db_name, const char* host,
     715             :  *                     const char* service, time_t expiration,
     716             :  *                     gnutls_digest_algorithm_t, const gnutls_datum_t* hash);
     717             :  *
     718             :  * The @db_name should be used to pass any private data to this function.
     719             :  *
     720             :  **/
     721           0 : void gnutls_tdb_set_store_commitment_func(gnutls_tdb_t tdb,
     722             :                                           gnutls_tdb_store_commitment_func
     723             :                                           cstore)
     724             : {
     725           0 :         tdb->cstore = cstore;
     726           0 : }
     727             : 
     728             : /**
     729             :  * gnutls_set_verify_func:
     730             :  * @tdb: The trust storage
     731             :  * @verify: The verification function
     732             :  *
     733             :  * This function will associate a retrieval function with the
     734             :  * trust storage structure. The function is of the following form.
     735             :  *
     736             :  * int gnutls_tdb_verify_func(const char* db_name, const char* host,
     737             :  *                    const char* service, const gnutls_datum_t* pubkey);
     738             :  *
     739             :  * The verify function should return zero on a match, %GNUTLS_E_CERTIFICATE_KEY_MISMATCH
     740             :  * if there is a mismatch and any other negative error code otherwise.
     741             :  *
     742             :  * The @db_name should be used to pass any private data to this function.
     743             :  *
     744             :  **/
     745           0 : void gnutls_tdb_set_verify_func(gnutls_tdb_t tdb,
     746             :                                 gnutls_tdb_verify_func verify)
     747             : {
     748           0 :         tdb->verify = verify;
     749           0 : }
     750             : 
     751             : /**
     752             :  * gnutls_tdb_deinit:
     753             :  * @tdb: The structure to be deinitialized
     754             :  *
     755             :  * This function will deinitialize a public key trust storage structure.
     756             :  **/
     757           0 : void gnutls_tdb_deinit(gnutls_tdb_t tdb)
     758             : {
     759           0 :         gnutls_free(tdb);
     760           0 : }

Generated by: LCOV version 1.14