[poppler] Branch 'signatureHandling' - poppler/Form.cc poppler/Form.h poppler/SignatureHandler.cc poppler/SignatureHandler.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Wed Oct 14 13:57:56 PDT 2015
poppler/Form.cc | 63 ++++++++++++++++++++++++++++++++------------
poppler/Form.h | 1
poppler/SignatureHandler.cc | 34 ++++++++++++++---------
poppler/SignatureHandler.h | 9 ++++--
4 files changed, 76 insertions(+), 31 deletions(-)
New commits:
commit 02d3564faa5d8174ed93ce66fcda975b1a898ec5
Author: André Guerreiro <aguerreiro1985 at gmail.com>
Date: Wed Oct 14 22:50:05 2015 +0200
Incremental hashing + large file support for digital signatures
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 42ef2c1..d94757a 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1435,6 +1435,32 @@ void FormFieldSignature::parseInfo()
sig_dict.free();
}
+void FormFieldSignature::hashSignedDataBlock(SignatureHandler *handler, Goffset block_len)
+{
+ const int BLOCK_SIZE = 4096;
+ unsigned char signed_data_buffer[BLOCK_SIZE];
+
+ Goffset i = 0;
+ while(i < block_len)
+ {
+ Goffset bytes_left = block_len - i;
+ if (bytes_left < BLOCK_SIZE)
+ {
+ doc->getBaseStream()->doGetChars(bytes_left, signed_data_buffer);
+ handler->updateHash(signed_data_buffer, bytes_left);
+ i = block_len;
+ }
+ else
+ {
+ doc->getBaseStream()->doGetChars(BLOCK_SIZE, signed_data_buffer);
+ handler->updateHash(signed_data_buffer, BLOCK_SIZE);
+ i += BLOCK_SIZE;
+ }
+ }
+
+}
+
+
SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation)
{
#ifdef ENABLE_NSS3
@@ -1459,32 +1485,38 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for
byte_range.arrayGet(2, &r3);
byte_range.arrayGet(3, &r4);
- unsigned int signed_data_len = 0;
-
Goffset fileLength = doc->getBaseStream()->getLength();
+ Goffset r_values[3];
+
+ r_values[0] = r2.isInt64() ? r2.getInt64() : r2.getInt();
+ r_values[1] = r3.isInt64() ? r3.getInt64() : r3.getInt();
+ r_values[2] = r4.isInt64() ? r4.getInt64() : r4.getInt();
- if (r2.getInt() <= 0 || r3.getInt() <= 0 || r4.getInt() <= 0 || r3.getInt() <= r2.getInt() ||
- r3.getInt() + r4.getInt() > fileLength)
+ if (r_values[0] <= 0 || r_values[1] <= 0 || r_values[2] <= 0 || r_values[1] <= r_values[0] ||
+ r_values[1] + r_values[2] > fileLength)
{
error(errSyntaxError, 0, "Illegal values in ByteRange array");
return signature_info;
}
- signed_data_len = r2.getInt() + r4.getInt();
- unsigned char *to_check = (unsigned char *)gmalloc(signed_data_len);
-
- //Read the 2 slices of data that are signed
- doc->getBaseStream()->setPos(0);
- doc->getBaseStream()->doGetChars(r2.getInt(), to_check);
- doc->getBaseStream()->setPos(r3.getInt());
- doc->getBaseStream()->doGetChars(r4.getInt(), to_check+r2.getInt());
-
const int signature_len = signature->getLength();
+
unsigned char *signatureuchar = (unsigned char *)gmalloc(signature_len);
memcpy(signatureuchar, signature->getCString(), signature_len);
SignatureHandler signature_handler(signatureuchar, signature_len);
- sig_val_state = signature_handler.validateSignature(to_check, signed_data_len);
+ //Read the 2 slices of data that are signed
+ doc->getBaseStream()->setPos(0);
+ Goffset block_len = r_values[0];
+
+ hashSignedDataBlock(&signature_handler, block_len);
+
+ doc->getBaseStream()->setPos(r_values[1]);
+ block_len = r_values[2];
+
+ hashSignedDataBlock(&signature_handler, block_len);
+
+ sig_val_state = signature_handler.validateSignature();
signature_info->setSignatureValStatus(SignatureHandler::NSS_SigTranslate(sig_val_state));
signature_info->setSignerName(signature_handler.getSignerName());
@@ -1493,8 +1525,6 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for
signature_info->setSigningTime(signature_handler.getSigningTime());
}
- free(to_check);
-
if (sig_val_state != NSSCMSVS_GoodSignature || !doVerifyCert) {
return signature_info;
}
@@ -1504,6 +1534,7 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for
#endif
return signature_info;
+
}
#ifdef DEBUG_FORMS
diff --git a/poppler/Form.h b/poppler/Form.h
index ff4dc1e..b566fe0 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -500,6 +500,7 @@ public:
private:
void parseInfo();
+ void hashSignedDataBlock(SignatureHandler *handler, Goffset block_len);
Object byte_range;
GooString *signature;
SignatureInfo *signature_info;
diff --git a/poppler/SignatureHandler.cc b/poppler/SignatureHandler.cc
index 357bac4..10caed7 100644
--- a/poppler/SignatureHandler.cc
+++ b/poppler/SignatureHandler.cc
@@ -18,14 +18,6 @@
#include <dirent.h>
#include <Error.h>
-void SignatureHandler::digestFile(unsigned char *digest_buffer, unsigned char *input_data, int input_data_len, SECOidTag hashOIDTag)
-{
- HASH_HashType hashType;
- hashType = HASH_GetHashTypeByOidTag(hashOIDTag);
- HASH_HashBuf(hashType, digest_buffer, input_data, input_data_len);
-
-}
-
unsigned int SignatureHandler::digestLength(SECOidTag digestAlgId)
{
switch(digestAlgId){
@@ -119,8 +111,23 @@ SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length)
CMSMessage = CMS_MessageCreate(&CMSitem);
CMSSignedData = CMS_SignedDataCreate(CMSMessage);
CMSSignerInfo = CMS_SignerInfoCreate(CMSSignedData);
+ hash_context = initHashContext();
+}
+
+HASHContext * SignatureHandler::initHashContext()
+{
+
+ SECItem usedAlgorithm = NSS_CMSSignedData_GetDigestAlgs(CMSSignedData)[0]->algorithm;
+ hash_length = digestLength(SECOID_FindOIDTag(&usedAlgorithm));
+ HASH_HashType hashType;
+ hashType = HASH_GetHashTypeByOidTag(SECOID_FindOIDTag(&usedAlgorithm));
+ return HASH_Create(hashType);
}
+void SignatureHandler::updateHash(unsigned char * data_block, int data_len)
+{
+ HASH_Update(hash_context, data_block, data_len);
+}
SignatureHandler::~SignatureHandler()
{
@@ -132,6 +139,9 @@ SignatureHandler::~SignatureHandler()
if (CMSMessage)
NSS_CMSMessage_Destroy(CMSMessage);
+ if (hash_context)
+ HASH_Destroy(hash_context);
+
free(temp_certs);
if (NSS_Shutdown()!=SECSuccess)
@@ -198,19 +208,17 @@ NSSCMSSignerInfo *SignatureHandler::CMS_SignerInfoCreate(NSSCMSSignedData * cms_
}
}
-NSSCMSVerificationStatus SignatureHandler::validateSignature(unsigned char *signed_data, int signed_data_len)
+NSSCMSVerificationStatus SignatureHandler::validateSignature()
{
unsigned char *digest_buffer = NULL;
if (!CMSSignedData)
return NSSCMSVS_MalformedSignature;
- SECItem usedAlgorithm = NSS_CMSSignedData_GetDigestAlgs(CMSSignedData)[0]->algorithm;
- unsigned int hash_length = digestLength(SECOID_FindOIDTag(&usedAlgorithm));
-
digest_buffer = (unsigned char *)PORT_Alloc(hash_length);
+ unsigned int result_len = 0;
- digestFile(digest_buffer, signed_data, signed_data_len, SECOID_FindOIDTag(&usedAlgorithm));
+ HASH_End(hash_context, digest_buffer, &result_len, hash_length);
SECItem digest;
digest.data = digest_buffer;
diff --git a/poppler/SignatureHandler.h b/poppler/SignatureHandler.h
index 7946d25..e6ace24 100644
--- a/poppler/SignatureHandler.h
+++ b/poppler/SignatureHandler.h
@@ -41,8 +41,10 @@ public:
time_t getSigningTime();
char * getSignerName();
void setSignature(unsigned char *, int);
- NSSCMSVerificationStatus validateSignature(unsigned char *signed_data, int signed_data_len);
+ void updateHash(unsigned char * data_block, int data_len);
+ NSSCMSVerificationStatus validateSignature();
SECErrorCodes validateCertificate();
+
//Translate NSS error codes
static SignatureValidationStatus NSS_SigTranslate(NSSCMSVerificationStatus nss_code);
static CertificateValidationStatus NSS_CertTranslate(SECErrorCodes nss_code);
@@ -52,14 +54,17 @@ private:
SignatureHandler& operator=(const SignatureHandler &);
void init_nss();
+
GooString * getDefaultFirefoxCertDB_Linux();
unsigned int digestLength(SECOidTag digestAlgId);
NSSCMSMessage *CMS_MessageCreate(SECItem * cms_item);
NSSCMSSignedData *CMS_SignedDataCreate(NSSCMSMessage * cms_msg);
NSSCMSSignerInfo *CMS_SignerInfoCreate(NSSCMSSignedData * cms_sig_data);
- void digestFile(unsigned char *digest_buffer, unsigned char *input_data, int input_data_len, SECOidTag hashOIDTag);
+ HASHContext * initHashContext();
+ unsigned int hash_length;
SECItem CMSitem;
+ HASHContext *hash_context;
NSSCMSMessage *CMSMessage;
NSSCMSSignedData *CMSSignedData;
NSSCMSSignerInfo *CMSSignerInfo;
More information about the poppler
mailing list