diff options
Diffstat (limited to 'lib/verify-tofu.c')
-rw-r--r-- | lib/verify-tofu.c | 116 |
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" |