[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