Add X509CertificateInfo to poppler
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6aaaa76..4eb74a3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -395,6 +395,7 @@
poppler/ViewerPreferences.cc
poppler/Movie.cc
poppler/Rendition.cc
+ poppler/CertificateInfo.cc
)
set(poppler_LIBS ${FREETYPE_LIBRARIES})
if(ENABLE_SPLASH)
diff --git a/poppler/CertificateInfo.cc b/poppler/CertificateInfo.cc
new file mode 100644
index 0000000..dc78631
--- /dev/null
+++ b/poppler/CertificateInfo.cc
@@ -0,0 +1,127 @@
+//========================================================================
+//
+// CertificateInfo.cc
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
+//
+//========================================================================
+
+#include "CertificateInfo.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+X509CertificateInfo::X509CertificateInfo()
+{
+ memset(&issuer_info, 0, sizeof issuer_info);
+ memset(&subject_info, 0, sizeof subject_info);
+ cert_serial = nullptr;
+ cert_der = nullptr;
+ ku_extensions = KU_NONE;
+ cert_version = -1;
+ is_self_signed = false;
+}
+
+X509CertificateInfo::~X509CertificateInfo()
+{
+ free(issuer_info.commonName);
+ free(issuer_info.distinguishedName);
+ free(issuer_info.email);
+ free(issuer_info.organization);
+ free(subject_info.commonName);
+ free(subject_info.distinguishedName);
+ free(subject_info.email);
+ free(subject_info.organization);
+}
+
+int X509CertificateInfo::getVersion() const
+{
+ return cert_version;
+}
+
+GooString *X509CertificateInfo::getSerialNumber() const
+{
+ return cert_serial;
+}
+
+X509CertificateInfo::EntityInfo X509CertificateInfo::getIssuerInfo() const
+{
+ return issuer_info;
+}
+
+X509CertificateInfo::Validity X509CertificateInfo::getValidity() const
+{
+ return cert_validity;
+}
+
+X509CertificateInfo::EntityInfo X509CertificateInfo::getSubjectInfo() const
+{
+ return subject_info;
+}
+
+X509CertificateInfo::PublicKeyInfo X509CertificateInfo::getPublicKeyInfo() const
+{
+ return public_key_info;
+}
+
+unsigned int X509CertificateInfo::getKeyUsageExtensions() const
+{
+ return ku_extensions;
+}
+
+GooString *X509CertificateInfo::getCertificateDER() const
+{
+ return cert_der;
+}
+
+bool X509CertificateInfo::getIsSelfSigned() const
+{
+ return is_self_signed;
+}
+
+void X509CertificateInfo::setVersion(int version)
+{
+ cert_version = version;
+}
+
+void X509CertificateInfo::setSerialNumber(GooString *serialNumber)
+{
+ cert_serial = serialNumber;
+}
+
+void X509CertificateInfo::setIssuerInfo(EntityInfo issuerInfo)
+{
+ issuer_info = issuerInfo;
+}
+
+void X509CertificateInfo::setValidity(Validity validity)
+{
+ cert_validity = validity;
+}
+
+void X509CertificateInfo::setSubjectInfo(EntityInfo subjectInfo)
+{
+ subject_info = subjectInfo;
+}
+
+void X509CertificateInfo::setPublicKeyInfo(PublicKeyInfo pkInfo)
+{
+ public_key_info = pkInfo;
+}
+
+void X509CertificateInfo::setKeyUsageExtensions(unsigned int keyUsages)
+{
+ ku_extensions = keyUsages;
+}
+
+void X509CertificateInfo::setCertificateDER(GooString *certDer)
+{
+ cert_der = certDer;
+}
+
+void X509CertificateInfo::setIsSelfSigned(bool isSelfSigned)
+{
+ is_self_signed = isSelfSigned;
+}
diff --git a/poppler/CertificateInfo.h b/poppler/CertificateInfo.h
new file mode 100644
index 0000000..3010d13
--- /dev/null
+++ b/poppler/CertificateInfo.h
@@ -0,0 +1,98 @@
+//========================================================================
+//
+// CertificateInfo.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
+//
+//========================================================================
+
+#ifndef CERTIFICATEINFO_H
+#define CERTIFICATEINFO_H
+
+#include <time.h>
+#include "goo/GooString.h"
+
+enum CertificateKeyUsageExtension
+{
+ KU_DIGITAL_SIGNATURE = 0x80,
+ KU_NON_REPUDIATION = 0x40,
+ KU_KEY_ENCIPHERMENT = 0x20,
+ KU_DATA_ENCIPHERMENT = 0x10,
+ KU_KEY_AGREEMENT = 0x08,
+ KU_KEY_CERT_SIGN = 0x04,
+ KU_CRL_SIGN = 0x02,
+ KU_ENCIPHER_ONLY = 0x01,
+ KU_NONE = 0x00
+};
+
+enum PublicKeyType
+{
+ RSAKEY,
+ DSAKEY,
+ ECKEY,
+ OTHERKEY
+};
+
+class X509CertificateInfo {
+public:
+ X509CertificateInfo();
+ ~X509CertificateInfo();
+
+ struct PublicKeyInfo {
+ GooString *publicKey;
+ PublicKeyType publicKeyType;
+ unsigned int publicKeyStrength; // in bits
+ };
+
+ struct EntityInfo {
+ char *commonName;
+ char *distinguishedName;
+ char *email;
+ char *organization;
+ };
+
+ struct Validity {
+ time_t notBefore;
+ time_t notAfter;
+ };
+
+ /* GETTERS */
+ int getVersion() const;
+ GooString *getSerialNumber() const;
+ EntityInfo getIssuerInfo() const;
+ Validity getValidity() const;
+ EntityInfo getSubjectInfo() const;
+ PublicKeyInfo getPublicKeyInfo() const;
+ unsigned int getKeyUsageExtensions() const;
+ GooString *getCertificateDER() const;
+ bool getIsSelfSigned() const;
+
+ /* SETTERS */
+ void setVersion(int);
+ void setSerialNumber(GooString *);
+ void setIssuerInfo(EntityInfo);
+ void setValidity(Validity);
+ void setSubjectInfo(EntityInfo);
+ void setPublicKeyInfo(PublicKeyInfo);
+ void setKeyUsageExtensions(unsigned int);
+ void setCertificateDER(GooString *);
+ void setIsSelfSigned(bool);
+
+private:
+ X509CertificateInfo(const X509CertificateInfo &);
+ X509CertificateInfo& operator=(const X509CertificateInfo &);
+
+ EntityInfo issuer_info;
+ EntityInfo subject_info;
+ PublicKeyInfo public_key_info;
+ Validity cert_validity;
+ GooString *cert_serial;
+ GooString *cert_der;
+ unsigned int ku_extensions;
+ int cert_version;
+ bool is_self_signed;
+};
+
+#endif
diff --git a/poppler/Form.cc b/poppler/Form.cc
index fc4ce88..51caa4d 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1761,6 +1761,7 @@
cert_val_state = signature_handler.validateCertificate(validationTime);
signature_info->setCertificateValStatus(SignatureHandler::NSS_CertTranslate(cert_val_state));
+ signature_info->setCertificateInfo(signature_handler.getCertificateInfo());
#endif
return signature_info;
diff --git a/poppler/SignatureHandler.cc b/poppler/SignatureHandler.cc
index 116aab9..87ca859 100644
--- a/poppler/SignatureHandler.cc
+++ b/poppler/SignatureHandler.cc
@@ -10,6 +10,7 @@
// Copyright 2015 Markus Kilås <digital@markuspage.com>
// Copyright 2017 Sebastian Rasmussen <sebras@gmail.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
+// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
//
//========================================================================
@@ -18,6 +19,8 @@
#include "SignatureHandler.h"
#include "goo/gmem.h"
#include <secmod.h>
+#include <keyhi.h>
+#include <secder.h>
#include <dirent.h>
#include <Error.h>
@@ -78,6 +81,104 @@
return static_cast<time_t>(sTime/1000000);
}
+void SignatureHandler::getEntityInfo(X509CertificateInfo::EntityInfo *info, CERTName *entityName)
+{
+ if (!info || !entityName)
+ return;
+
+ memset(info, 0, sizeof *info);
+
+ char *dn = CERT_NameToAscii(entityName);
+ if (dn) {
+ info->distinguishedName = copyString(dn);
+ PORT_Free(dn);
+ }
+
+ char *cn = CERT_GetCommonName(entityName);
+ if (cn) {
+ info->commonName = copyString(cn);
+ PORT_Free(cn);
+ }
+
+ char *email = CERT_GetCertEmailAddress(entityName);
+ if (email) {
+ info->email = copyString(email);
+ PORT_Free(email);
+ }
+
+ char *org = CERT_GetOrgName(entityName);
+ if (org) {
+ info->organization = copyString(org);
+ PORT_Free(org);
+ }
+}
+
+X509CertificateInfo *SignatureHandler::getCertificateInfo()
+{
+ if (!CMSSignerInfo)
+ return nullptr;
+
+ CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB());
+ if (!cert)
+ return nullptr;
+
+ X509CertificateInfo *certInfo = new X509CertificateInfo;
+ if (!certInfo)
+ return nullptr;
+
+ certInfo->setVersion(DER_GetInteger(&cert->version) + 1);
+ certInfo->setSerialNumber(SECItemToGooString(cert->serialNumber));
+
+ //issuer info
+ X509CertificateInfo::EntityInfo issuerInfo;
+ getEntityInfo(&issuerInfo, &cert->issuer);
+ certInfo->setIssuerInfo(issuerInfo);
+
+ //validity
+ PRTime notBefore, notAfter;
+ CERT_GetCertTimes(cert, ¬Before, ¬After);
+ X509CertificateInfo::Validity certValidity;
+ certValidity.notBefore = static_cast<time_t>(notBefore/1000000);
+ certValidity.notAfter = static_cast<time_t>(notAfter/1000000);
+ certInfo->setValidity(certValidity);
+
+ //subject info
+ X509CertificateInfo::EntityInfo subjectInfo;
+ getEntityInfo(&subjectInfo, &cert->subject);
+ certInfo->setSubjectInfo(subjectInfo);
+
+ //public key info
+ X509CertificateInfo::PublicKeyInfo pkInfo;
+ SECKEYPublicKey *pk = CERT_ExtractPublicKey(cert);
+ switch (pk->keyType)
+ {
+ case rsaKey:
+ pkInfo.publicKey = SECItemToGooString(pk->u.rsa.modulus);
+ pkInfo.publicKeyType = RSAKEY;
+ break;
+ case dsaKey:
+ pkInfo.publicKey = SECItemToGooString(pk->u.dsa.publicValue);
+ pkInfo.publicKeyType = DSAKEY;
+ break;
+ case ecKey:
+ pkInfo.publicKey = SECItemToGooString(pk->u.ec.publicValue);
+ pkInfo.publicKeyType = ECKEY;
+ break;
+ default:
+ pkInfo.publicKey = SECItemToGooString(cert->subjectPublicKeyInfo.subjectPublicKey);
+ pkInfo.publicKeyType = OTHERKEY;
+ break;
+ }
+ pkInfo.publicKeyStrength = SECKEY_PublicKeyStrengthInBits(pk);
+ certInfo->setPublicKeyInfo(pkInfo);
+
+ certInfo->setKeyUsageExtensions(cert->keyUsage);
+ certInfo->setCertificateDER(SECItemToGooString(cert->derCert));
+ certInfo->setIsSelfSigned(CERT_CompareName(&cert->subject, &cert->issuer) == SECEqual);
+
+ return certInfo;
+}
+
GooString *SignatureHandler::getDefaultFirefoxCertDB_Linux()
{
@@ -96,9 +197,9 @@
do {
if ((subFolder = readdir(toSearchIn)) != nullptr) {
if (strstr(subFolder->d_name, "default") != nullptr) {
- finalPath = homePath->append(subFolder->d_name);
- closedir(toSearchIn);
- return finalPath;
+ finalPath = homePath->append(subFolder->d_name);
+ closedir(toSearchIn);
+ return finalPath;
}
}
} while (subFolder != nullptr);
@@ -111,7 +212,7 @@
/**
* Initialise NSS
*/
-void SignatureHandler::init_nss()
+void SignatureHandler::init_nss()
{
GooString *certDBPath = getDefaultFirefoxCertDB_Linux();
bool initSuccess = false;
@@ -372,3 +473,8 @@
return CERTIFICATE_GENERIC_ERROR;
}
}
+
+GooString *SignatureHandler::SECItemToGooString(SECItem secItem)
+{
+ return new GooString((const char *)secItem.data, secItem.len);
+}
diff --git a/poppler/SignatureHandler.h b/poppler/SignatureHandler.h
index 3b2f62b..5c47d24 100644
--- a/poppler/SignatureHandler.h
+++ b/poppler/SignatureHandler.h
@@ -16,6 +16,7 @@
#include "goo/GooString.h"
#include "SignatureInfo.h"
+#include "CertificateInfo.h"
/* NSPR Headers */
#include <nspr.h>
@@ -44,11 +45,14 @@
NSSCMSVerificationStatus validateSignature();
// Use -1 as validation_time for now
SECErrorCodes validateCertificate(time_t validation_time);
+ X509CertificateInfo *getCertificateInfo();
//Translate NSS error codes
static SignatureValidationStatus NSS_SigTranslate(NSSCMSVerificationStatus nss_code);
static CertificateValidationStatus NSS_CertTranslate(SECErrorCodes nss_code);
+ static GooString *SECItemToGooString(SECItem secItem);
+
private:
SignatureHandler(const SignatureHandler &);
SignatureHandler& operator=(const SignatureHandler &);
@@ -61,6 +65,7 @@
NSSCMSSignedData *CMS_SignedDataCreate(NSSCMSMessage * cms_msg);
NSSCMSSignerInfo *CMS_SignerInfoCreate(NSSCMSSignedData * cms_sig_data);
HASHContext * initHashContext();
+ void getEntityInfo(X509CertificateInfo::EntityInfo *info, CERTName *entityName);
unsigned int hash_length;
SECItem CMSitem;
diff --git a/poppler/SignatureInfo.cc b/poppler/SignatureInfo.cc
index 11e47e5..3be9160 100644
--- a/poppler/SignatureInfo.cc
+++ b/poppler/SignatureInfo.cc
@@ -15,6 +15,7 @@
#include <config.h>
#include "SignatureInfo.h"
+#include "CertificateInfo.h"
#include "goo/gmem.h"
#include <stdlib.h>
#include <string.h>
@@ -31,6 +32,7 @@
{
sig_status = SIGNATURE_NOT_VERIFIED;
cert_status = CERTIFICATE_NOT_VERIFIED;
+ cert_info = nullptr;
signer_name = nullptr;
subject_dn = nullptr;
location = nullptr;
@@ -44,6 +46,7 @@
{
sig_status = sig_val_status;
cert_status = cert_val_status;
+ cert_info = nullptr;
signer_name = nullptr;
subject_dn = nullptr;
location = nullptr;
@@ -59,6 +62,7 @@
free(reason);
free(signer_name);
free(subject_dn);
+ delete cert_info;
}
/* GETTERS */
@@ -103,6 +107,11 @@
return signing_time;
}
+X509CertificateInfo *SignatureInfo::getCertificateInfo()
+{
+ return cert_info;
+}
+
/* SETTERS */
void SignatureInfo::setSignatureValStatus(enum SignatureValidationStatus sig_val_status)
@@ -148,3 +157,8 @@
{
signing_time = signingTime;
}
+
+void SignatureInfo::setCertificateInfo(X509CertificateInfo *certInfo)
+{
+ cert_info = certInfo;
+}
diff --git a/poppler/SignatureInfo.h b/poppler/SignatureInfo.h
index f4554c6..de79062 100644
--- a/poppler/SignatureInfo.h
+++ b/poppler/SignatureInfo.h
@@ -39,6 +39,8 @@
CERTIFICATE_NOT_VERIFIED
};
+class X509CertificateInfo;
+
class SignatureInfo {
public:
SignatureInfo();
@@ -55,6 +57,7 @@
int getHashAlgorithm(); // Returns a NSS3 HASH_HashType or -1 if compiled without NSS3
time_t getSigningTime();
bool isSubfilterSupported() { return sig_subfilter_supported; }
+ X509CertificateInfo *getCertificateInfo();
/* SETTERS */
void setSignatureValStatus(enum SignatureValidationStatus );
@@ -66,6 +69,7 @@
void setHashAlgorithm(int);
void setSigningTime(time_t);
void setSubFilterSupport(bool isSupported) { sig_subfilter_supported = isSupported; }
+ void setCertificateInfo(X509CertificateInfo *);
private:
SignatureInfo(const SignatureInfo &);
@@ -73,6 +77,7 @@
SignatureValidationStatus sig_status;
CertificateValidationStatus cert_status;
+ X509CertificateInfo *cert_info;
char *signer_name;
char *subject_dn;
char *location;