summaryrefslogtreecommitdiff
path: root/lib/verify-tofu.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/verify-tofu.c')
-rw-r--r--lib/verify-tofu.c116
1 files changed, 74 insertions, 42 deletions
diff --git a/lib/verify-tofu.c b/lib/verify-tofu.c
index 310778629b..66a583ded7 100644
--- a/lib/verify-tofu.c
+++ b/lib/verify-tofu.c
@@ -77,11 +77,11 @@ struct gnutls_tdb_int default_tdb = {
* @cert: The raw (der) data of the certificate
* @flags: should be 0.
*
- * This function will try to verify the provided (raw or DER-encoded) certificate
- * using a list of stored public keys. The @service field if non-NULL should
- * be a port number.
+ * This function will try to verify a raw public-key or a public-key provided via
+ * a raw (DER-encoded) certificate using a list of stored public keys.
+ * The @service field if non-NULL should be a port number.
*
- * The @retrieve variable if non-null specifies a custom backend for
+ * The @db_name variable if non-null specifies a custom backend for
* the retrieval of entries. If it is NULL then the
* default file backend will be used. In POSIX-like systems the
* file backend uses the $HOME/.gnutls/known_hosts file.
@@ -93,10 +93,12 @@ struct gnutls_tdb_int default_tdb = {
* the given key is found, and 0 if it was found. The storage
* function should return 0 on success.
*
+ * As of GnuTLS 3.6.6 this function also verifies raw public keys.
+ *
* Returns: If no associated public key is found
* then %GNUTLS_E_NO_CERTIFICATE_FOUND will be returned. If a key
* is found but does not match %GNUTLS_E_CERTIFICATE_KEY_MISMATCH
- * is returned. On success, %GNUTLS_E_SUCCESS (0) is returned,
+ * is returned. On success, %GNUTLS_E_SUCCESS (0) is returned,
* or a negative error value on other errors.
*
* Since: 3.0.13
@@ -110,14 +112,11 @@ gnutls_verify_stored_pubkey(const char *db_name,
const gnutls_datum_t * cert,
unsigned int flags)
{
- gnutls_datum_t pubkey = { NULL, 0 };
+ gnutls_datum_t pubkey = { NULL, 0 }; // Holds the pubkey in subjectPublicKeyInfo format (DER encoded)
int ret;
char local_file[MAX_FILENAME];
+ bool need_free;
- if (cert_type != GNUTLS_CRT_X509)
- return
- gnutls_assert_val
- (GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
if (db_name == NULL && tdb == NULL) {
ret = find_config_file(local_file, sizeof(local_file));
@@ -129,18 +128,38 @@ gnutls_verify_stored_pubkey(const char *db_name,
if (tdb == NULL)
tdb = &default_tdb;
- ret = x509_raw_crt_to_raw_pubkey(cert, &pubkey);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
+ /* Import the public key depending on the provided certificate type */
+ switch (cert_type) {
+ case GNUTLS_CRT_X509:
+ /* Extract the pubkey from the cert. This function does a malloc
+ * deep down the call chain. We are responsible for freeing. */
+ ret = _gnutls_x509_raw_crt_to_raw_pubkey(cert, &pubkey);
+
+ if (ret < 0) {
+ _gnutls_free_datum(&pubkey);
+ return gnutls_assert_val(ret);
+ }
+
+ need_free = true;
+ break;
+ case GNUTLS_CRT_RAWPK:
+ pubkey.data = cert->data;
+ pubkey.size = cert->size;
+ need_free = false;
+ break;
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
}
+ // Verify our pubkey against the database
ret = tdb->verify(db_name, host, service, &pubkey);
if (ret < 0 && ret != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
ret = gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
- cleanup:
- gnutls_free(pubkey.data);
+ if (need_free) {
+ _gnutls_free_datum(&pubkey);
+ }
+
return ret;
}
@@ -203,7 +222,7 @@ static int parse_commitment_line(char *line,
/* hash and hex encode */
ret =
- _gnutls_hash_fast((gnutls_digest_algorithm_t)hash_algo->id,
+ _gnutls_hash_fast((gnutls_digest_algorithm_t)hash_algo->id,
skey->data, skey->size, phash);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -301,7 +320,7 @@ static int parse_line(char *line,
return 0;
}
-/* Returns the base64 key if found
+/* Returns the base64 key if found
*/
static int verify_pubkey(const char *file,
const char *host, const char *service,
@@ -460,11 +479,11 @@ int store_commitment(const char *db_name, const char *host,
* @expiration: The expiration time (use 0 to disable expiration)
* @flags: should be 0.
*
- * This function will store the provided (raw or DER-encoded) certificate to
- * the list of stored public keys. The key will be considered valid until
- * the provided expiration time.
+ * This function will store a raw public-key or a public-key provided via
+ * a raw (DER-encoded) certificate to the list of stored public keys. The key
+ * will be considered valid until the provided expiration time.
*
- * The @store variable if non-null specifies a custom backend for
+ * The @tdb variable if non-null specifies a custom backend for
* the storage of entries. If it is NULL then the
* default file backend will be used.
*
@@ -475,6 +494,8 @@ int store_commitment(const char *db_name, const char *host,
* time in seconds since the epoch (0 for no expiration), and a base64
* encoding of the raw (DER) public key information (SPKI) of the peer.
*
+ * As of GnuTLS 3.6.6 this function also accepts raw public keys.
+ *
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
*
@@ -489,14 +510,11 @@ gnutls_store_pubkey(const char *db_name,
const gnutls_datum_t * cert,
time_t expiration, unsigned int flags)
{
- gnutls_datum_t pubkey = { NULL, 0 };
+ gnutls_datum_t pubkey = { NULL, 0 }; // Holds the pubkey in subjectPublicKeyInfo format (DER encoded)
int ret;
char local_file[MAX_FILENAME];
+ bool need_free;
- if (cert_type != GNUTLS_CRT_X509)
- return
- gnutls_assert_val
- (GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
if (db_name == NULL && tdb == NULL) {
ret =
@@ -517,22 +535,38 @@ gnutls_store_pubkey(const char *db_name,
if (tdb == NULL)
tdb = &default_tdb;
- ret = x509_raw_crt_to_raw_pubkey(cert, &pubkey);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
+ /* Import the public key depending on the provided certificate type */
+ switch (cert_type) {
+ case GNUTLS_CRT_X509:
+ /* Extract the pubkey from the cert. This function does a malloc
+ * deep down the call chain. We are responsible for freeing. */
+ ret = _gnutls_x509_raw_crt_to_raw_pubkey(cert, &pubkey);
+
+ if (ret < 0) {
+ _gnutls_free_datum(&pubkey);
+ return gnutls_assert_val(ret);
+ }
+
+ need_free = true;
+ break;
+ case GNUTLS_CRT_RAWPK:
+ pubkey.data = cert->data;
+ pubkey.size = cert->size;
+ need_free = false;
+ break;
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
}
_gnutls_debug_log("Configuration file: %s\n", db_name);
tdb->store(db_name, host, service, expiration, &pubkey);
- ret = 0;
-
- cleanup:
- gnutls_free(pubkey.data);
+ if (need_free) {
+ _gnutls_free_datum(&pubkey);
+ }
- return ret;
+ return GNUTLS_E_SUCCESS;
}
/**
@@ -546,11 +580,11 @@ gnutls_store_pubkey(const char *db_name,
* @expiration: The expiration time (use 0 to disable expiration)
* @flags: should be 0 or %GNUTLS_SCOMMIT_FLAG_ALLOW_BROKEN.
*
- * This function will store the provided hash commitment to
+ * This function will store the provided hash commitment to
* the list of stored public keys. The key with the given
* hash will be considered valid until the provided expiration time.
*
- * The @store variable if non-null specifies a custom backend for
+ * The @tdb variable if non-null specifies a custom backend for
* the storage of entries. If it is NULL then the
* default file backend will be used.
*
@@ -604,12 +638,10 @@ gnutls_store_commitment(const char *db_name,
_gnutls_debug_log("Configuration file: %s\n", db_name);
- tdb->cstore(db_name, host, service, expiration,
+ tdb->cstore(db_name, host, service, expiration,
(gnutls_digest_algorithm_t)me->id, hash);
- ret = 0;
-
- return ret;
+ return 0;
}
#define CONFIG_FILE "known_hosts"