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 #include -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;