1//========================================================================
2//
3// SignatureHandler.h
4//
5// This file is licensed under the GPLv2 or later
6//
7// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
8// Copyright 2015 André Esser <bepandre@hotmail.com>
9// Copyright 2015, 2017, 2019, 2021 Albert Astals Cid <aacid@kde.org>
10// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
11// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
12// Copyright 2018 Oliver Sander <oliver.sander@tu-dresden.de>
13// Copyright 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
14// Copyright 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
15// Copyright 2021 Theofilos Intzoglou <int.teo@gmail.com>
16// Copyright 2021 Marek Kasik <mkasik@redhat.com>
17// Copyright 2023, 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
18//
19//========================================================================
20
21#ifndef SIGNATURE_HANDLER_H
22#define SIGNATURE_HANDLER_H
23
24#include "goo/GooString.h"
25#include "SignatureInfo.h"
26#include "CertificateInfo.h"
27#include "poppler_private_export.h"
28#include "HashAlgorithm.h"
29
30#include <vector>
31#include <functional>
32#include <memory>
33#include <future>
34
35/* NSPR Headers */
36#include <nspr.h>
37
38/* NSS headers */
39#include <cms.h>
40#include <nss.h>
41#include <cert.h>
42#include <cryptohi.h>
43#include <secerr.h>
44#include <secoid.h>
45#include <secmodt.h>
46#include <sechash.h>
47#include "CryptoSignBackend.h"
48
49class HashContext
50{
51 class private_tag
52 {
53 };
54
55public:
56 HashContext(HashAlgorithm algorithm, private_tag);
57 void updateHash(unsigned char *data_block, int data_len);
58 std::vector<unsigned char> endHash();
59 HashAlgorithm getHashAlgorithm() const;
60 ~HashContext() = default;
61 static std::unique_ptr<HashContext> create(HashAlgorithm algorithm);
62
63private:
64 struct HashDestroyer
65 {
66 void operator()(HASHContext *hash) { HASH_Destroy(context: hash); }
67 };
68 std::unique_ptr<HASHContext, HashDestroyer> hash_context;
69 HashAlgorithm digest_alg_tag;
70};
71
72class NSSSignatureVerification final : public CryptoSign::VerificationInterface
73{
74public:
75 explicit NSSSignatureVerification(std::vector<unsigned char> &&p7data);
76 ~NSSSignatureVerification() final;
77 SignatureValidationStatus validateSignature() final;
78 std::chrono::system_clock::time_point getSigningTime() const final;
79 std::string getSignerName() const final;
80 std::string getSignerSubjectDN() const final;
81 // Use -1 as validation_time for now
82
83 CertificateValidationStatus validateCertificateResult() final;
84 void validateCertificateAsync(std::chrono::system_clock::time_point validation_time, bool ocspRevocationCheck, bool useAIACertFetch, const std::function<void()> &doneCallback) final;
85 std::unique_ptr<X509CertificateInfo> getCertificateInfo() const final;
86 void addData(unsigned char *data_block, int data_len) final;
87 HashAlgorithm getHashAlgorithm() const final;
88
89 NSSSignatureVerification(const NSSSignatureVerification &) = delete;
90 NSSSignatureVerification &operator=(const NSSSignatureVerification &) = delete;
91
92private:
93 std::vector<unsigned char> p7;
94 NSSCMSMessage *CMSMessage;
95 NSSCMSSignedData *CMSSignedData;
96 NSSCMSSignerInfo *CMSSignerInfo;
97 SECItem CMSitem;
98 std::unique_ptr<HashContext> hashContext;
99 std::future<CertificateValidationStatus> validationStatus;
100 std::optional<CertificateValidationStatus> cachedValidationStatus;
101};
102
103class NSSSignatureCreation final : public CryptoSign::SigningInterface
104{
105public:
106 NSSSignatureCreation(const std::string &certNickname, HashAlgorithm digestAlgTag);
107 ~NSSSignatureCreation() final;
108 std::unique_ptr<X509CertificateInfo> getCertificateInfo() const final;
109 void addData(unsigned char *data_block, int data_len) final;
110 std::optional<GooString> signDetached(const std::string &password) final;
111
112 NSSSignatureCreation(const NSSSignatureCreation &) = delete;
113 NSSSignatureCreation &operator=(const NSSSignatureCreation &) = delete;
114
115private:
116 std::unique_ptr<HashContext> hashContext;
117 CERTCertificate *signing_cert;
118};
119
120class POPPLER_PRIVATE_EXPORT NSSSignatureConfiguration
121{
122public:
123 // Initializes the NSS dir with the custom given directory
124 // calling it with an empty string means use the default firefox db, /etc/pki/nssdb, ~/.pki/nssdb
125 // If you don't want a custom NSS dir and the default entries are fine for you, not calling this function is fine
126 // If wanted, this has to be called before doing signature validation calls
127 static void setNSSDir(const GooString &nssDir);
128
129 // Gets the currently in use NSS dir
130 static std::string getNSSDir();
131
132 static void setNSSPasswordCallback(const std::function<char *(const char *)> &f);
133
134 NSSSignatureConfiguration() = delete;
135
136private:
137 static std::string sNssDir;
138};
139
140class NSSCryptoSignBackend final : public CryptoSign::Backend
141{
142public:
143 std::unique_ptr<CryptoSign::VerificationInterface> createVerificationHandler(std::vector<unsigned char> &&pkcs7) final;
144 std::unique_ptr<CryptoSign::SigningInterface> createSigningHandler(const std::string &certID, HashAlgorithm digestAlgTag) final;
145 std::vector<std::unique_ptr<X509CertificateInfo>> getAvailableSigningCertificates() final;
146 ~NSSCryptoSignBackend() final;
147};
148
149#endif
150

source code of poppler/poppler/NSSCryptoSignBackend.h