/* * This file is part of smolbote. It's copyrighted by the contributors recorded * in the version control history of the file, available from its original * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote * * SPDX-License-Identifier: GPL-3.0 */ #include "pluginloader.h" #include #include #include #include "publicKey.h" PluginLoader::PluginLoader(const QString &fileName, PluginLoader::SignatureState state, QObject *parent) : QPluginLoader(fileName, parent) , m_state(state) { } bool PluginLoader::verify(const char *hashName) { const QString sigName = this->fileName() + ".sig"; if(!QFile::exists(sigName)) { if(m_state.ignored || m_state.checked) return true; m_sigError = tr("A signature is required, but none was found."); return false; } auto *bio = BIO_new_mem_buf(publicKey_pem, publicKey_pem_len); Q_CHECK_PTR(bio); auto *key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); Q_CHECK_PTR(key); auto *ctx = EVP_MD_CTX_new(); Q_CHECK_PTR(ctx); const auto *md = EVP_get_digestbyname(hashName); Q_CHECK_PTR(md); int rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, key); if(rc != 1) { m_sigError = tr("Failed to compute signature (stage=init)"); return false; } // read plugin into DigestVerifyUpdate QFile plugin(this->fileName()); plugin.open(QIODevice::ReadOnly); int len = plugin.size(); int read = 0; auto *buf = new unsigned char[1024]; while(len > 0) { read = plugin.read(reinterpret_cast(buf), 1024); len -= read; rc = EVP_DigestVerifyUpdate(ctx, buf, read); if(rc != 1) { m_sigError = tr("Failed to compute signature (staga=update)"); return false; } } delete[] buf; plugin.close(); // read signature into DigestVerifyFinal QFile sigFile(sigName); sigFile.open(QIODevice::ReadOnly); const int sig_len = sigFile.size(); const auto* sig = [&sigFile, sig_len]() { auto* buf = new unsigned char[sig_len]; sigFile.read(reinterpret_cast(buf), sig_len); return buf; }(); sigFile.close(); rc = EVP_DigestVerifyFinal(ctx, sig, sig_len); delete sig; if(rc == 1) return true; else { if(m_state.ignored) return true; m_sigError = tr("Signature does not match"); return false; } }