diff --git a/examples/aes-cmac/aes-cmac.cpp b/examples/aes-cmac/aes-cmac.cpp index 194c0037..ff921190 100644 --- a/examples/aes-cmac/aes-cmac.cpp +++ b/examples/aes-cmac/aes-cmac.cpp @@ -195,6 +195,11 @@ protected: class ClientSideProvider : public QCA::Provider { public: + int version() const + { + return QCA_VERSION; + } + QString name() const { return "exampleClientSideProvider"; diff --git a/include/QtCrypto/qca_core.h b/include/QtCrypto/qca_core.h index 758cadc2..014315d3 100644 --- a/include/QtCrypto/qca_core.h +++ b/include/QtCrypto/qca_core.h @@ -46,6 +46,8 @@ #include "qca_support.h" #include "qca_tools.h" +QCA_EXPORT int qcaVersion(); + /** * QCA - the Qt Cryptographic Architecture */ @@ -605,6 +607,19 @@ namespace QCA */ virtual void init(); + /** + * Target QCA version for the provider. + * + * This is used to verify compatibility between the + * provider and QCA. For a provider to be used, it + * must have major and minor version numbers that are + * less-than or equal to the QCA version (the patch + * version number is ignored). This means an older + * provider may be used with a newer QCA, but a newer + * provider cannot be used with an older QCA. + */ + virtual int version() const = 0; + /** * The name of the provider. * diff --git a/plugins/qca-openssl/qca-openssl.cpp b/plugins/qca-openssl/qca-openssl.cpp index ee5bbe15..3000f4cd 100644 --- a/plugins/qca-openssl/qca-openssl.cpp +++ b/plugins/qca-openssl/qca-openssl.cpp @@ -5882,6 +5882,11 @@ public: // todo: any shutdown? } + int version() const + { + return QCA_VERSION; + } + QString name() const { return "qca-openssl"; diff --git a/src/qca_core.cpp b/src/qca_core.cpp index 1b8e7b59..7a5eb351 100644 --- a/src/qca_core.cpp +++ b/src/qca_core.cpp @@ -31,6 +31,11 @@ # include #endif +int qcaVersion() +{ + return QCA_VERSION; +} + namespace QCA { // from qca_tools diff --git a/src/qca_default.cpp b/src/qca_default.cpp index 67133714..8e72121f 100644 --- a/src/qca_default.cpp +++ b/src/qca_default.cpp @@ -900,6 +900,11 @@ public: srand(t); } + int version() const + { + return QCA_VERSION; + } + QString name() const { return "default"; diff --git a/src/qca_plugin.cpp b/src/qca_plugin.cpp index 6277eba4..5b5f7e66 100644 --- a/src/qca_plugin.cpp +++ b/src/qca_plugin.cpp @@ -34,6 +34,14 @@ static void logDebug(const QString &str) g_pluginman->appendDiagnosticText(str + '\n'); } +static bool validVersion(int ver) +{ + // make sure the provider isn't newer than qca + if((ver & 0xffff00) <= (QCA_VERSION & 0xffff00)) + return true; + return false; +} + class PluginInstance { private: @@ -263,6 +271,14 @@ void ProviderManager::scan() continue; } + int ver = i->p->version(); + if(!validVersion(ver)) + { + logDebug(QString().sprintf("plugin version 0x%06x is in the future", ver)); + delete i; + continue; + } + addItem(i, -1); } scanned_static = true; @@ -322,6 +338,14 @@ void ProviderManager::scan() continue; } + int ver = i->p->version(); + if(!validVersion(ver)) + { + logDebug(QString().sprintf("plugin version 0x%06x is in the future", ver)); + delete i; + continue; + } + addItem(i, -1); } } @@ -336,6 +360,13 @@ bool ProviderManager::add(Provider *p, int priority) return false; } + int ver = p->version(); + if(!validVersion(ver)) + { + logDebug(QString().sprintf("plugin version 0x%06x is in the future", ver)); + return false; + } + ProviderItem *i = ProviderItem::fromClass(p); addItem(i, priority); return true; diff --git a/unittest/clientplugin/clientplugin.cpp b/unittest/clientplugin/clientplugin.cpp index efca0e7d..b6b63a05 100644 --- a/unittest/clientplugin/clientplugin.cpp +++ b/unittest/clientplugin/clientplugin.cpp @@ -54,6 +54,11 @@ void ClientPlugin::cleanupTestCase() class TestClientProvider : public QCA::Provider { public: + int version() const + { + return QCA_VERSION; + } + QString name() const { return "testClientSideProvider";