summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSune Vuorela <sune@vuorela.dk>2023-03-23 16:40:59 +0100
committerSune Vuorela <sune@vuorela.dk>2023-04-13 10:05:18 +0200
commitcb96047d029e2145191d79b7ece17b4a215794cd (patch)
tree83da265d2e8ae9b0a69ecb4db93036f267b768c1
parent1be35ee8b2d6418dfafc6a8a9bbf6d70eafb2d2e (diff)
Backending infrastructure
-rw-r--r--poppler/CryptoSignBackend.cc97
-rw-r--r--poppler/CryptoSignBackend.h101
2 files changed, 198 insertions, 0 deletions
diff --git a/poppler/CryptoSignBackend.cc b/poppler/CryptoSignBackend.cc
new file mode 100644
index 00000000..86703470
--- /dev/null
+++ b/poppler/CryptoSignBackend.cc
@@ -0,0 +1,97 @@
+//========================================================================
+//
+// CryptoSignBackend.cc
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright 2023 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
+//========================================================================
+#include "CryptoSignBackend.h"
+#include "config.h"
+#ifdef ENABLE_NSS3
+# include "SignatureHandler.h"
+#endif
+
+namespace CryptoSign {
+
+void Factory::setPreferredBackend(CryptoSign::Backend::Type backend)
+{
+ preferredBackend = backend;
+}
+static std::string_view toStringView(const char *str)
+{
+ if (str) {
+ return std::string_view(str);
+ }
+ return {};
+}
+
+std::optional<CryptoSign::Backend::Type> Factory::typeFromString(std::string_view string)
+{
+ if (string.empty()) {
+ return std::nullopt;
+ }
+ if ("NSS" == string) {
+ return Backend::Type::NSS3;
+ }
+ return std::nullopt;
+}
+
+CryptoSign::Backend::Type Factory::getActive()
+{
+ if (preferredBackend) {
+ return *preferredBackend;
+ }
+ static auto backendFromEnvironment = typeFromString(toStringView(getenv("POPPLER_SIGNATURE_BACKEND")));
+ if (backendFromEnvironment) {
+ return *backendFromEnvironment;
+ }
+ static auto backendFromCompiledDefault = typeFromString(toStringView(DEFAULT_SIGNATURE_BACKEND));
+ if (backendFromCompiledDefault) {
+ return *backendFromCompiledDefault;
+ }
+
+ return Backend::Type::None;
+}
+static std::vector<Backend::Type> createAvailableBackends()
+{
+ std::vector<Backend::Type> backends;
+#ifdef ENABLE_NSS3
+ backends.push_back(Backend::Type::NSS3);
+#endif
+ return backends;
+}
+std::vector<Backend::Type> Factory::getAvailable()
+{
+ static std::vector<Backend::Type> availableBackends = createAvailableBackends();
+ return availableBackends;
+}
+std::unique_ptr<Backend> Factory::createActive()
+{
+ return create(getActive());
+}
+std::unique_ptr<CryptoSign::Backend> CryptoSign::Factory::create(Backend::Type backend)
+{
+ switch (backend) {
+ case Backend::Type::NSS3:
+#ifdef ENABLE_NSS3
+ return std::make_unique<NSSCryptoSignBackend>();
+#else
+ return nullptr;
+#endif
+ case Backend::Type::None: {
+ return nullptr;
+ }
+ }
+ return nullptr;
+}
+/// backend specific settings
+
+// Android build wants some methods out of line in the interfaces
+Backend::~Backend() = default;
+SigningInterface::~SigningInterface() = default;
+VerificationInterface::~VerificationInterface() = default;
+
+std::optional<Backend::Type> Factory::preferredBackend = std::nullopt;
+
+} // namespace Signature;
diff --git a/poppler/CryptoSignBackend.h b/poppler/CryptoSignBackend.h
new file mode 100644
index 00000000..b106ec47
--- /dev/null
+++ b/poppler/CryptoSignBackend.h
@@ -0,0 +1,101 @@
+//========================================================================
+//
+// CryptoSignBackend.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright 2023 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
+//========================================================================
+
+#ifndef SIGNATUREBACKEND_H
+#define SIGNATUREBACKEND_H
+
+#include <vector>
+#include <memory>
+#include <chrono>
+#include <optional>
+#include "HashAlgorithm.h"
+#include "CertificateInfo.h"
+#include "SignatureInfo.h"
+#include "goo/GooString.h"
+#include "poppler_private_export.h"
+
+namespace CryptoSign {
+
+// experiments seems to say that this is a bit above
+// what we have seen in the wild, and much larger than
+// what we have managed to get nss and gpgme to create.
+static const int maxSupportedSignatureSize = 10000;
+
+// Classes to help manage signature backends
+
+class VerificationInterface
+{
+public:
+ virtual void addData(unsigned char *data_block, int data_len) = 0;
+ virtual SignatureValidationStatus validateSignature() = 0;
+ virtual std::chrono::system_clock::time_point getSigningTime() const = 0;
+ virtual std::string getSignerName() const = 0;
+ virtual std::string getSignerSubjectDN() const = 0;
+ virtual HashAlgorithm getHashAlgorithm() const = 0;
+ virtual CertificateValidationStatus validateCertificate(std::chrono::system_clock::time_point validation_time, bool ocspRevocationCheck, bool useAIACertFetch) = 0;
+ virtual std::unique_ptr<X509CertificateInfo> getCertificateInfo() const = 0;
+ virtual ~VerificationInterface();
+ VerificationInterface() = default;
+ VerificationInterface(const VerificationInterface &other) = delete;
+ VerificationInterface &operator=(const VerificationInterface &other) = delete;
+};
+
+class SigningInterface
+{
+public:
+ virtual void addData(unsigned char *data_block, int data_len) = 0;
+ virtual std::unique_ptr<X509CertificateInfo> getCertificateInfo() const = 0;
+ virtual std::optional<GooString> signDetached(const std::string &password) = 0;
+ virtual ~SigningInterface();
+ SigningInterface() = default;
+ SigningInterface(const SigningInterface &other) = delete;
+ SigningInterface &operator=(const SigningInterface &other) = delete;
+};
+
+class Backend
+{
+public:
+ enum class Type
+ {
+ None,
+ NSS3
+ };
+ virtual std::unique_ptr<VerificationInterface> createVerificationHandler(std::vector<unsigned char> &&pkcs7) = 0;
+ virtual std::unique_ptr<SigningInterface> createSigningHandler(const std::string &certID, HashAlgorithm digestAlgTag) = 0;
+ virtual std::vector<std::unique_ptr<X509CertificateInfo>> getAvailableSigningCertificates() = 0;
+ virtual ~Backend();
+ Backend() = default;
+ Backend(const Backend &other) = delete;
+ Backend &operator=(const Backend &other) = delete;
+};
+
+class POPPLER_PRIVATE_EXPORT Factory
+{
+public:
+ // Sets the user preferred backend
+ static void setPreferredBackend(Backend::Type backend);
+ // Gets the current active backend
+ // prioritized from 1) setPreferredBackend,
+ // 2) POPPLER_SIGNATURE_BACKEND
+ // 3) Compiled in default
+ static Backend::Type getActive();
+ static std::vector<Backend::Type> getAvailable();
+ static std::unique_ptr<Backend> createActive();
+ static std::unique_ptr<Backend> create(Backend::Type);
+ static std::optional<Backend::Type> typeFromString(std::string_view string);
+ Factory() = delete;
+ /// backend specific settings
+
+private:
+ static std::optional<Backend::Type> preferredBackend;
+};
+
+}
+
+#endif // SIGNATUREBACKEND_H