/** * gnutls_verify_stored_pubkey: * @db_name: A file specifying the stored keys (use NULL for the default) * @tdb: A storage structure or NULL to use the default * @host: The peer's name * @service: non-NULL if this key is specific to a service (e.g. http) * @cert_type: The type of the certificate * @cert: The raw (der) data of the certificate * @flags: should be 0. * * 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 @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. * * Note that if the custom storage backend is provided the * retrieval function should return %GNUTLS_E_CERTIFICATE_KEY_MISMATCH * if the host/service pair is found but key doesn't match, * %GNUTLS_E_NO_CERTIFICATE_FOUND if no such host/service with * 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, * or a negative error value on other errors. * * Since: 3.0.13 **/ int gnutls_verify_stored_pubkey(const char *db_name, gnutls_tdb_t tdb, const char *host, const char *service, gnutls_certificate_type_t cert_type, const gnutls_datum_t * cert, unsigned int flags) { 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 (db_name == NULL && tdb == NULL) { ret = find_config_file(local_file, sizeof(local_file)); if (ret < 0) return gnutls_assert_val(ret); db_name = local_file; } if (tdb == NULL) tdb = &default_tdb; /* 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); if (need_free) { _gnutls_free_datum(&pubkey); } return ret; }
/** * gnutls_verify_stored_pubkey: * @db_name: A file specifying the stored keys (use NULL for the default) * @tdb: A storage structure or NULL to use the default * @host: The peer's name * @service: non-NULL if this key is specific to a service (e.g. http) * @cert_type: The type of the certificate * @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. * * The @retrieve 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. * * Note that if the custom storage backend is provided the * retrieval function should return %GNUTLS_E_CERTIFICATE_KEY_MISMATCH * if the host/service pair is found but key doesn't match, * %GNUTLS_E_NO_CERTIFICATE_FOUND if no such host/service with * the given key is found, and 0 if it was found. The storage * function should return 0 on success. * * 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, * or a negative error value on other errors. * * Since: 3.0.13 **/ int gnutls_verify_stored_pubkey(const char *db_name, gnutls_tdb_t tdb, const char *host, const char *service, gnutls_certificate_type_t cert_type, const gnutls_datum_t * cert, unsigned int flags) { gnutls_datum_t pubkey = { NULL, 0 }; int ret; char local_file[MAX_FILENAME]; if (cert_type != GNUTLS_CRT_X509 && cert_type != GNUTLS_CRT_OPENPGP) return gnutls_assert_val (GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE); if (db_name == NULL && tdb == NULL) { ret = find_config_file(local_file, sizeof(local_file)); if (ret < 0) return gnutls_assert_val(ret); db_name = local_file; } if (tdb == NULL) tdb = &default_tdb; if (cert_type == GNUTLS_CRT_X509) ret = x509_crt_to_raw_pubkey(cert, &pubkey); else ret = pgp_crt_to_raw_pubkey(cert, &pubkey); if (ret < 0) { gnutls_assert(); goto cleanup; } 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); return ret; }