From cb769c62e55599e9f980001830bc61d9fcaa64a9 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 8 Feb 2022 09:18:08 -0500 Subject: WHITESPACE ONLY -- expand tabs in source code This comment expands all tabs using an 8-character tab-width. You should ignore this commit when using git blame or use git blame -w. In the early days, I used to use tabs where possible for indentation, since emacs did this automatically. In recent years, I have switched to only using spaces, which means qpdf source code has been a mixture of spaces and tabs. I have avoided cleaning this up because of not wanting gratuitous whitespaces change to cloud the output of git blame, but I changed my mind after discussing with users who view qpdf source code in editors/IDEs that have other tab widths by default and in light of the fact that I am planning to start applying automatic code formatting soon. --- libqpdf/QPDF_encryption.cc | 610 ++++++++++++++++++++++----------------------- 1 file changed, 305 insertions(+), 305 deletions(-) (limited to 'libqpdf/QPDF_encryption.cc') diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index c97c578d..75b45aef 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -147,7 +147,7 @@ QPDF::trim_user_password(std::string& user_password) size_t len = user_password.length(); if (len < key_bytes) { - return; + return; } char const* p1 = cstr; @@ -155,11 +155,11 @@ QPDF::trim_user_password(std::string& user_password) while ((p2 = strchr(p1, '\x28')) != 0) { size_t idx = toS(p2 - cstr); - if (memcmp(p2, padding_string, len - idx) == 0) - { - user_password = user_password.substr(0, idx); - return; - } + if (memcmp(p2, padding_string, len - idx) == 0) + { + user_password = user_password.substr(0, idx); + return; + } else { QTC::TC("qpdf", "QPDF_encryption skip 0x28"); @@ -191,30 +191,30 @@ iterate_md5_digest(MD5& md5, MD5::Digest& digest, for (int i = 0; i < iterations; ++i) { - MD5 m; - m.encodeDataIncrementally(reinterpret_cast(digest), + MD5 m; + m.encodeDataIncrementally(reinterpret_cast(digest), QIntC::to_size(key_len)); - m.digest(digest); + m.digest(digest); } } static void iterate_rc4(unsigned char* data, size_t data_len, - unsigned char* okey, int key_len, - int iterations, bool reverse) + unsigned char* okey, int key_len, + int iterations, bool reverse) { auto key_ph = std::make_unique(QIntC::to_size(key_len)); unsigned char* key = key_ph.get(); for (int i = 0; i < iterations; ++i) { - int const xor_value = (reverse ? iterations - 1 - i : i); - for (int j = 0; j < key_len; ++j) - { - key[j] = static_cast(okey[j] ^ xor_value); - } - RC4 rc4(key, QIntC::to_int(key_len)); - rc4.process(data, data_len); + int const xor_value = (reverse ? iterations - 1 - i : i); + for (int j = 0; j < key_len; ++j) + { + key[j] = static_cast(okey[j] ^ xor_value); + } + RC4 rc4(key, QIntC::to_int(key_len)); + rc4.process(data, data_len); } } @@ -354,7 +354,7 @@ void pad_short_parameter(std::string& param, size_t max_len) std::string QPDF::compute_data_key(std::string const& encryption_key, - int objid, int generation, bool use_aes, + int objid, int generation, bool use_aes, int encryption_V, int encryption_R) { // Algorithm 3.1 from the PDF 1.7 Reference Manual @@ -376,7 +376,7 @@ QPDF::compute_data_key(std::string const& encryption_key, result.append(1, static_cast((generation >> 8) & 0xff)); if (use_aes) { - result += "sAlT"; + result += "sAlT"; } MD5 md5; @@ -384,7 +384,7 @@ QPDF::compute_data_key(std::string const& encryption_key, MD5::Digest digest; md5.digest(digest); return std::string(reinterpret_cast(digest), - std::min(result.length(), toS(16))); + std::min(result.length(), toS(16))); } std::string @@ -421,7 +421,7 @@ QPDF::compute_encryption_key_from_password( MD5 md5; md5.encodeDataIncrementally( - pad_or_truncate_password_V4(password).c_str(), key_bytes); + pad_or_truncate_password_V4(password).c_str(), key_bytes); md5.encodeDataIncrementally(data.getO().c_str(), key_bytes); char pbytes[4]; int P = data.getP(); @@ -434,9 +434,9 @@ QPDF::compute_encryption_key_from_password( data.getId1().length()); if ((data.getR() >= 4) && (! data.getEncryptMetadata())) { - char bytes[4]; - memset(bytes, 0xff, 4); - md5.encodeDataIncrementally(bytes, 4); + char bytes[4]; + memset(bytes, 0xff, 4); + md5.encodeDataIncrementally(bytes, 4); } MD5::Digest digest; int key_len = @@ -448,23 +448,23 @@ QPDF::compute_encryption_key_from_password( static void compute_O_rc4_key(std::string const& user_password, - std::string const& owner_password, - QPDF::EncryptionData const& data, - unsigned char key[OU_key_bytes_V4]) + std::string const& owner_password, + QPDF::EncryptionData const& data, + unsigned char key[OU_key_bytes_V4]) { if (data.getV() >= 5) { - throw std::logic_error( - "compute_O_rc4_key called for file with V >= 5"); + throw std::logic_error( + "compute_O_rc4_key called for file with V >= 5"); } std::string password = owner_password; if (password.empty()) { - password = user_password; + password = user_password; } MD5 md5; md5.encodeDataIncrementally( - pad_or_truncate_password_V4(password).c_str(), key_bytes); + pad_or_truncate_password_V4(password).c_str(), key_bytes); MD5::Digest digest; int key_len = std::min(QIntC::to_int(sizeof(digest)), data.getLengthBytes()); @@ -474,8 +474,8 @@ compute_O_rc4_key(std::string const& user_password, static std::string compute_O_value(std::string const& user_password, - std::string const& owner_password, - QPDF::EncryptionData const& data) + std::string const& owner_password, + QPDF::EncryptionData const& data) { // Algorithm 3.3 from the PDF 1.7 Reference Manual @@ -487,7 +487,7 @@ compute_O_value(std::string const& user_password, std::string k1(reinterpret_cast(O_key), OU_key_bytes_V4); pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes())); iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes, - O_key, data.getLengthBytes(), + O_key, data.getLengthBytes(), (data.getR() >= 3) ? 20 : 1, false); return std::string(upass, key_bytes); } @@ -495,7 +495,7 @@ compute_O_value(std::string const& user_password, static std::string compute_U_value_R2(std::string const& user_password, - QPDF::EncryptionData const& data) + QPDF::EncryptionData const& data) { // Algorithm 3.4 from the PDF 1.7 Reference Manual @@ -504,7 +504,7 @@ compute_U_value_R2(std::string const& user_password, pad_or_truncate_password_V4("", udata); pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes())); iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes, - QUtil::unsigned_char_pointer(k1), + QUtil::unsigned_char_pointer(k1), data.getLengthBytes(), 1, false); return std::string(udata, key_bytes); } @@ -512,21 +512,21 @@ compute_U_value_R2(std::string const& user_password, static std::string compute_U_value_R3(std::string const& user_password, - QPDF::EncryptionData const& data) + QPDF::EncryptionData const& data) { // Algorithm 3.5 from the PDF 1.7 Reference Manual std::string k1 = QPDF::compute_encryption_key(user_password, data); MD5 md5; md5.encodeDataIncrementally( - pad_or_truncate_password_V4("").c_str(), key_bytes); + pad_or_truncate_password_V4("").c_str(), key_bytes); md5.encodeDataIncrementally(data.getId1().c_str(), data.getId1().length()); MD5::Digest digest; md5.digest(digest); pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes())); iterate_rc4(digest, sizeof(MD5::Digest), - QUtil::unsigned_char_pointer(k1), + QUtil::unsigned_char_pointer(k1), data.getLengthBytes(), 20, false); char result[key_bytes]; memcpy(result, digest, sizeof(MD5::Digest)); @@ -534,18 +534,18 @@ compute_U_value_R3(std::string const& user_password, // testing for (unsigned int i = sizeof(MD5::Digest); i < key_bytes; ++i) { - result[i] = static_cast((i * i) % 0xff); + result[i] = static_cast((i * i) % 0xff); } return std::string(result, key_bytes); } static std::string compute_U_value(std::string const& user_password, - QPDF::EncryptionData const& data) + QPDF::EncryptionData const& data) { if (data.getR() >= 3) { - return compute_U_value_R3(user_password, data); + return compute_U_value_R3(user_password, data); } return compute_U_value_R2(user_password, data); @@ -577,7 +577,7 @@ check_user_password_V5(std::string const& user_password, static bool check_user_password(std::string const& user_password, - QPDF::EncryptionData const& data) + QPDF::EncryptionData const& data) { if (data.getV() < 5) { @@ -632,8 +632,8 @@ check_owner_password_V5(std::string const& owner_password, static bool check_owner_password(std::string& user_password, - std::string const& owner_password, - QPDF::EncryptionData const& data) + std::string const& owner_password, + QPDF::EncryptionData const& data) { if (data.getV() < 5) { @@ -773,24 +773,24 @@ QPDF::interpretCF( { if (cf.isName()) { - std::string filter = cf.getName(); - if (encp->crypt_filters.count(filter) != 0) - { - return encp->crypt_filters[filter]; - } - else if (filter == "/Identity") - { - return e_none; - } - else - { - return e_unknown; - } + std::string filter = cf.getName(); + if (encp->crypt_filters.count(filter) != 0) + { + return encp->crypt_filters[filter]; + } + else if (filter == "/Identity") + { + return e_none; + } + else + { + return e_unknown; + } } else { - // Default: /Identity - return e_none; + // Default: /Identity + return e_none; } } @@ -799,7 +799,7 @@ QPDF::initializeEncryption() { if (this->m->encp->encryption_initialized) { - return; + return; } this->m->encp->encryption_initialized = true; @@ -810,7 +810,7 @@ QPDF::initializeEncryption() if (! this->m->trailer.hasKey("/Encrypt")) { - return; + return; } // Go ahead and set this->m->encrypted here. That way, isEncrypted @@ -831,7 +831,7 @@ QPDF::initializeEncryption() // Treating a missing ID as the empty string enables qpdf to // decrypt some invalid encrypted files with no /ID that // poppler can read but Adobe Reader can't. - warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "trailer", this->m->file->getLastOffset(), "invalid /ID in trailer dictionary")); } @@ -839,37 +839,37 @@ QPDF::initializeEncryption() QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt"); if (! encryption_dict.isDictionary()) { - throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), - this->m->last_object_description, - this->m->file->getLastOffset(), - "/Encrypt in trailer dictionary is not a dictionary"); + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), + "/Encrypt in trailer dictionary is not a dictionary"); } if (! (encryption_dict.getKey("/Filter").isName() && - (encryption_dict.getKey("/Filter").getName() == "/Standard"))) + (encryption_dict.getKey("/Filter").getName() == "/Standard"))) { throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(), - "encryption dictionary", this->m->file->getLastOffset(), - "unsupported encryption filter"); + "encryption dictionary", this->m->file->getLastOffset(), + "unsupported encryption filter"); } if (! encryption_dict.getKey("/SubFilter").isNull()) { - warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(), - "encryption dictionary", this->m->file->getLastOffset(), - "file uses encryption SubFilters," - " which qpdf does not support")); + warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), + "file uses encryption SubFilters," + " which qpdf does not support")); } if (! (encryption_dict.getKey("/V").isInteger() && - encryption_dict.getKey("/R").isInteger() && - encryption_dict.getKey("/O").isString() && - encryption_dict.getKey("/U").isString() && - encryption_dict.getKey("/P").isInteger())) + encryption_dict.getKey("/R").isInteger() && + encryption_dict.getKey("/O").isString() && + encryption_dict.getKey("/U").isString() && + encryption_dict.getKey("/P").isInteger())) { - throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), - "encryption dictionary", this->m->file->getLastOffset(), - "some encryption dictionary parameters are missing " - "or the wrong type"); + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), + "some encryption dictionary parameters are missing " + "or the wrong type"); } int V = encryption_dict.getKey("/V").getIntValueAsInt(); @@ -881,11 +881,11 @@ QPDF::initializeEncryption() // If supporting new encryption R/V values, remember to update // error message inside this if statement. if (! (((R >= 2) && (R <= 6)) && - ((V == 1) || (V == 2) || (V == 4) || (V == 5)))) + ((V == 1) || (V == 2) || (V == 4) || (V == 5)))) { - throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(), - "encryption dictionary", this->m->file->getLastOffset(), - "Unsupported /R or /V in encryption dictionary; R = " + + throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), + "Unsupported /R or /V in encryption dictionary; R = " + QUtil::int_to_string(R) + " (max 6), V = " + QUtil::int_to_string(V) + " (max 5)"); } @@ -969,58 +969,58 @@ QPDF::initializeEncryption() this->m->encp->encrypt_metadata = true; if ((V >= 4) && (encryption_dict.getKey("/EncryptMetadata").isBool())) { - this->m->encp->encrypt_metadata = - encryption_dict.getKey("/EncryptMetadata").getBoolValue(); + this->m->encp->encrypt_metadata = + encryption_dict.getKey("/EncryptMetadata").getBoolValue(); } if ((V == 4) || (V == 5)) { - QPDFObjectHandle CF = encryption_dict.getKey("/CF"); - std::set keys = CF.getKeys(); - for (std::set::iterator iter = keys.begin(); - iter != keys.end(); ++iter) - { - std::string const& filter = *iter; - QPDFObjectHandle cdict = CF.getKey(filter); - if (cdict.isDictionary()) - { - encryption_method_e method = e_none; - if (cdict.getKey("/CFM").isName()) - { - std::string method_name = cdict.getKey("/CFM").getName(); - if (method_name == "/V2") - { - QTC::TC("qpdf", "QPDF_encryption CFM V2"); - method = e_rc4; - } - else if (method_name == "/AESV2") - { - QTC::TC("qpdf", "QPDF_encryption CFM AESV2"); - method = e_aes; - } - else if (method_name == "/AESV3") - { - QTC::TC("qpdf", "QPDF_encryption CFM AESV3"); - method = e_aesv3; - } - else - { - // Don't complain now -- maybe we won't need - // to reference this type. - method = e_unknown; - } - } - this->m->encp->crypt_filters[filter] = method; - } - } - - QPDFObjectHandle StmF = encryption_dict.getKey("/StmF"); - QPDFObjectHandle StrF = encryption_dict.getKey("/StrF"); - QPDFObjectHandle EFF = encryption_dict.getKey("/EFF"); - this->m->encp->cf_stream = interpretCF(this->m->encp, StmF); - this->m->encp->cf_string = interpretCF(this->m->encp, StrF); - if (EFF.isName()) - { + QPDFObjectHandle CF = encryption_dict.getKey("/CF"); + std::set keys = CF.getKeys(); + for (std::set::iterator iter = keys.begin(); + iter != keys.end(); ++iter) + { + std::string const& filter = *iter; + QPDFObjectHandle cdict = CF.getKey(filter); + if (cdict.isDictionary()) + { + encryption_method_e method = e_none; + if (cdict.getKey("/CFM").isName()) + { + std::string method_name = cdict.getKey("/CFM").getName(); + if (method_name == "/V2") + { + QTC::TC("qpdf", "QPDF_encryption CFM V2"); + method = e_rc4; + } + else if (method_name == "/AESV2") + { + QTC::TC("qpdf", "QPDF_encryption CFM AESV2"); + method = e_aes; + } + else if (method_name == "/AESV3") + { + QTC::TC("qpdf", "QPDF_encryption CFM AESV3"); + method = e_aesv3; + } + else + { + // Don't complain now -- maybe we won't need + // to reference this type. + method = e_unknown; + } + } + this->m->encp->crypt_filters[filter] = method; + } + } + + QPDFObjectHandle StmF = encryption_dict.getKey("/StmF"); + QPDFObjectHandle StrF = encryption_dict.getKey("/StrF"); + QPDFObjectHandle EFF = encryption_dict.getKey("/EFF"); + this->m->encp->cf_stream = interpretCF(this->m->encp, StmF); + this->m->encp->cf_string = interpretCF(this->m->encp, StrF); + if (EFF.isName()) + { // qpdf does not use this for anything other than // informational purposes. This is intended to instruct // conforming writers on which crypt filter should be used @@ -1035,12 +1035,12 @@ QPDF::initializeEncryption() // at a file generated by something else, such as Acrobat // when specifying that only attachments should be // encrypted. - this->m->encp->cf_file = interpretCF(this->m->encp, EFF); - } - else - { - this->m->encp->cf_file = this->m->encp->cf_stream; - } + this->m->encp->cf_file = interpretCF(this->m->encp, EFF); + } + else + { + this->m->encp->cf_file = this->m->encp->cf_stream; + } } EncryptionData data(V, R, Length / 8, @@ -1128,19 +1128,19 @@ QPDF::getKeyForObject( { if (! encp->encrypted) { - throw std::logic_error( - "request for encryption key in non-encrypted PDF"); + throw std::logic_error( + "request for encryption key in non-encrypted PDF"); } if (! ((objid == encp->cached_key_objid) && - (generation == encp->cached_key_generation))) + (generation == encp->cached_key_generation))) { - encp->cached_object_encryption_key = - compute_data_key(encp->encryption_key, objid, generation, + encp->cached_object_encryption_key = + compute_data_key(encp->encryption_key, objid, generation, use_aes, encp->encryption_V, encp->encryption_R); - encp->cached_key_objid = objid; - encp->cached_key_generation = generation; + encp->cached_key_objid = objid; + encp->cached_key_generation = generation; } return encp->cached_object_encryption_key; @@ -1151,83 +1151,83 @@ QPDF::decryptString(std::string& str, int objid, int generation) { if (objid == 0) { - return; + return; } bool use_aes = false; if (this->m->encp->encryption_V >= 4) { - switch (this->m->encp->cf_string) - { - case e_none: - return; - - case e_aes: - use_aes = true; - break; - - case e_aesv3: - use_aes = true; - break; - - case e_rc4: - break; - - default: - warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), - this->m->last_object_description, - this->m->file->getLastOffset(), - "unknown encryption filter for strings" - " (check /StrF in /Encrypt dictionary);" - " strings may be decrypted improperly")); - // To avoid repeated warnings, reset cf_string. Assume - // we'd want to use AES if V == 4. - this->m->encp->cf_string = e_aes; + switch (this->m->encp->cf_string) + { + case e_none: + return; + + case e_aes: + use_aes = true; + break; + + case e_aesv3: + use_aes = true; + break; + + case e_rc4: + break; + + default: + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), + "unknown encryption filter for strings" + " (check /StrF in /Encrypt dictionary);" + " strings may be decrypted improperly")); + // To avoid repeated warnings, reset cf_string. Assume + // we'd want to use AES if V == 4. + this->m->encp->cf_string = e_aes; use_aes = true; - break; - } + break; + } } std::string key = getKeyForObject( this->m->encp, objid, generation, use_aes); try { - if (use_aes) - { - QTC::TC("qpdf", "QPDF_encryption aes decode string"); - Pl_Buffer bufpl("decrypted string"); - Pl_AES_PDF pl("aes decrypt string", &bufpl, false, - QUtil::unsigned_char_pointer(key), + if (use_aes) + { + QTC::TC("qpdf", "QPDF_encryption aes decode string"); + Pl_Buffer bufpl("decrypted string"); + Pl_AES_PDF pl("aes decrypt string", &bufpl, false, + QUtil::unsigned_char_pointer(key), key.length()); - pl.write(QUtil::unsigned_char_pointer(str), str.length()); - pl.finish(); - auto buf = bufpl.getBufferSharedPointer(); - str = std::string(reinterpret_cast(buf->getBuffer()), + pl.write(QUtil::unsigned_char_pointer(str), str.length()); + pl.finish(); + auto buf = bufpl.getBufferSharedPointer(); + str = std::string(reinterpret_cast(buf->getBuffer()), buf->getSize()); - } - else - { - QTC::TC("qpdf", "QPDF_encryption rc4 decode string"); - size_t vlen = str.length(); - // Using PointerHolder guarantees that tmp will - // be freed even if rc4.process throws an exception. - auto tmp = QUtil::make_unique_cstr(str); - RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length())); - rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen); - str = std::string(tmp.get(), vlen); - } + } + else + { + QTC::TC("qpdf", "QPDF_encryption rc4 decode string"); + size_t vlen = str.length(); + // Using PointerHolder guarantees that tmp will + // be freed even if rc4.process throws an exception. + auto tmp = QUtil::make_unique_cstr(str); + RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length())); + rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen); + str = std::string(tmp.get(), vlen); + } } catch (QPDFExc&) { - throw; + throw; } catch (std::runtime_error& e) { - throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), - this->m->last_object_description, - this->m->file->getLastOffset(), - "error decrypting string for object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation) + ": " + e.what()); + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), + "error decrypting string for object " + + QUtil::int_to_string(objid) + " " + + QUtil::int_to_string(generation) + ": " + e.what()); } } @@ -1236,26 +1236,26 @@ QPDF::decryptStream(PointerHolder encp, PointerHolder file, QPDF& qpdf_for_warning, Pipeline*& pipeline, int objid, int generation, - QPDFObjectHandle& stream_dict, - std::vector>& heap) + QPDFObjectHandle& stream_dict, + std::vector>& heap) { std::string type; if (stream_dict.getKey("/Type").isName()) { - type = stream_dict.getKey("/Type").getName(); + type = stream_dict.getKey("/Type").getName(); } if (type == "/XRef") { - QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file"); - return; + QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file"); + return; } bool use_aes = false; if (encp->encryption_V >= 4) { - encryption_method_e method = e_unknown; - std::string method_source = "/StmF from /Encrypt dictionary"; + encryption_method_e method = e_unknown; + std::string method_source = "/StmF from /Encrypt dictionary"; - if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) + if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) { if (stream_dict.getKey("/DecodeParms").isDictionary()) { @@ -1294,67 +1294,67 @@ QPDF::decryptStream(PointerHolder encp, } } } - } - - if (method == e_unknown) - { - if ((! encp->encrypt_metadata) && (type == "/Metadata")) - { - QTC::TC("qpdf", "QPDF_encryption cleartext metadata"); - method = e_none; - } - else - { + } + + if (method == e_unknown) + { + if ((! encp->encrypt_metadata) && (type == "/Metadata")) + { + QTC::TC("qpdf", "QPDF_encryption cleartext metadata"); + method = e_none; + } + else + { method = encp->cf_stream; - } - } - use_aes = false; - switch (method) - { - case e_none: - return; - break; - - case e_aes: - use_aes = true; - break; - - case e_aesv3: - use_aes = true; - break; - - case e_rc4: - break; - - default: - // filter local to this stream. - qpdf_for_warning.warn( + } + } + use_aes = false; + switch (method) + { + case e_none: + return; + break; + + case e_aes: + use_aes = true; + break; + + case e_aesv3: + use_aes = true; + break; + + case e_rc4: + break; + + default: + // filter local to this stream. + qpdf_for_warning.warn( QPDFExc(qpdf_e_damaged_pdf, file->getName(), "", file->getLastOffset(), "unknown encryption filter for streams" " (check " + method_source + ");" " streams may be decrypted improperly")); - // To avoid repeated warnings, reset cf_stream. Assume - // we'd want to use AES if V == 4. - encp->cf_stream = e_aes; + // To avoid repeated warnings, reset cf_stream. Assume + // we'd want to use AES if V == 4. + encp->cf_stream = e_aes; use_aes = true; - break; - } + break; + } } std::string key = getKeyForObject(encp, objid, generation, use_aes); std::shared_ptr new_pipeline; if (use_aes) { - QTC::TC("qpdf", "QPDF_encryption aes decode stream"); - new_pipeline = std::make_shared( + QTC::TC("qpdf", "QPDF_encryption aes decode stream"); + new_pipeline = std::make_shared( "AES stream decryption", pipeline, false, QUtil::unsigned_char_pointer(key), key.length()); } else { - QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); - new_pipeline = std::make_shared( + QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); + new_pipeline = std::make_shared( "RC4 stream decryption", pipeline, QUtil::unsigned_char_pointer(key), toI(key.length())); @@ -1371,8 +1371,8 @@ QPDF::compute_encryption_O_U( { if (V >= 5) { - throw std::logic_error( - "compute_encryption_O_U called for file with V >= 5"); + throw std::logic_error( + "compute_encryption_O_U called for file with V >= 5"); } EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata); @@ -1444,22 +1444,22 @@ QPDF::isEncrypted(int& R, int& P, int& V, { if (this->m->encp->encrypted) { - QPDFObjectHandle trailer = getTrailer(); - QPDFObjectHandle encrypt = trailer.getKey("/Encrypt"); - QPDFObjectHandle Pkey = encrypt.getKey("/P"); - QPDFObjectHandle Rkey = encrypt.getKey("/R"); + QPDFObjectHandle trailer = getTrailer(); + QPDFObjectHandle encrypt = trailer.getKey("/Encrypt"); + QPDFObjectHandle Pkey = encrypt.getKey("/P"); + QPDFObjectHandle Rkey = encrypt.getKey("/R"); QPDFObjectHandle Vkey = encrypt.getKey("/V"); - P = static_cast(Pkey.getIntValue()); - R = Rkey.getIntValueAsInt(); + P = static_cast(Pkey.getIntValue()); + R = Rkey.getIntValueAsInt(); V = Vkey.getIntValueAsInt(); stream_method = this->m->encp->cf_stream; string_method = this->m->encp->cf_string; file_method = this->m->encp->cf_file; - return true; + return true; } else { - return false; + return false; } } @@ -1490,14 +1490,14 @@ QPDF::allowAccessibility() bool status = true; if (isEncrypted(R, P)) { - if (R < 3) - { - status = is_bit_set(P, 5); - } - else - { - status = is_bit_set(P, 10); - } + if (R < 3) + { + status = is_bit_set(P, 5); + } + else + { + status = is_bit_set(P, 10); + } } return status; } @@ -1510,7 +1510,7 @@ QPDF::allowExtractAll() bool status = true; if (isEncrypted(R, P)) { - status = is_bit_set(P, 5); + status = is_bit_set(P, 5); } return status; } @@ -1523,7 +1523,7 @@ QPDF::allowPrintLowRes() bool status = true; if (isEncrypted(R, P)) { - status = is_bit_set(P, 3); + status = is_bit_set(P, 3); } return status; } @@ -1536,11 +1536,11 @@ QPDF::allowPrintHighRes() bool status = true; if (isEncrypted(R, P)) { - status = is_bit_set(P, 3); - if ((R >= 3) && (! is_bit_set(P, 12))) - { - status = false; - } + status = is_bit_set(P, 3); + if ((R >= 3) && (! is_bit_set(P, 12))) + { + status = false; + } } return status; } @@ -1553,14 +1553,14 @@ QPDF::allowModifyAssembly() bool status = true; if (isEncrypted(R, P)) { - if (R < 3) - { - status = is_bit_set(P, 4); - } - else - { - status = is_bit_set(P, 11); - } + if (R < 3) + { + status = is_bit_set(P, 4); + } + else + { + status = is_bit_set(P, 11); + } } return status; } @@ -1573,14 +1573,14 @@ QPDF::allowModifyForm() bool status = true; if (isEncrypted(R, P)) { - if (R < 3) - { - status = is_bit_set(P, 6); - } - else - { - status = is_bit_set(P, 9); - } + if (R < 3) + { + status = is_bit_set(P, 6); + } + else + { + status = is_bit_set(P, 9); + } } return status; } @@ -1593,7 +1593,7 @@ QPDF::allowModifyAnnotation() bool status = true; if (isEncrypted(R, P)) { - status = is_bit_set(P, 6); + status = is_bit_set(P, 6); } return status; } @@ -1606,7 +1606,7 @@ QPDF::allowModifyOther() bool status = true; if (isEncrypted(R, P)) { - status = is_bit_set(P, 4); + status = is_bit_set(P, 4); } return status; } @@ -1619,11 +1619,11 @@ QPDF::allowModifyAll() bool status = true; if (isEncrypted(R, P)) { - status = (is_bit_set(P, 4) && is_bit_set(P, 6)); - if (R >= 3) - { - status = status && (is_bit_set(P, 9) && is_bit_set(P, 11)); - } + status = (is_bit_set(P, 4) && is_bit_set(P, 6)); + if (R >= 3) + { + status = status && (is_bit_set(P, 9) && is_bit_set(P, 11)); + } } return status; } -- cgit v1.2.3-70-g09d2