From dea704f0ab7f625e1e7b3f9a1110b45b63157317 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 26 Aug 2017 21:10:07 -0400 Subject: Pad keys to avoid memory errors (fixes #147) --- libqpdf/QPDF_encryption.cc | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 81325591..a2445b61 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -479,6 +479,8 @@ compute_O_value(std::string const& user_password, char upass[key_bytes]; pad_or_truncate_password_V4(user_password, upass); + std::string k1(reinterpret_cast(O_key), OU_key_bytes_V4); + pad_short_parameter(k1, data.getLengthBytes()); iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes, O_key, data.getLengthBytes(), (data.getR() >= 3) ? 20 : 1, false); @@ -495,6 +497,7 @@ compute_U_value_R2(std::string const& user_password, std::string k1 = QPDF::compute_encryption_key(user_password, data); char udata[key_bytes]; pad_or_truncate_password_V4("", udata); + pad_short_parameter(k1, data.getLengthBytes()); iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes, QUtil::unsigned_char_pointer(k1), data.getLengthBytes(), 1, false); @@ -516,6 +519,7 @@ compute_U_value_R3(std::string const& user_password, data.getId1().length()); MD5::Digest digest; md5.digest(digest); + pad_short_parameter(k1, data.getLengthBytes()); iterate_rc4(digest, sizeof(MD5::Digest), QUtil::unsigned_char_pointer(k1), data.getLengthBytes(), 20, false); @@ -591,7 +595,10 @@ check_owner_password_V4(std::string& user_password, compute_O_rc4_key(user_password, owner_password, data, key); unsigned char O_data[key_bytes]; memcpy(O_data, QUtil::unsigned_char_pointer(data.getO()), key_bytes); - iterate_rc4(O_data, key_bytes, key, data.getLengthBytes(), + std::string k1(reinterpret_cast(key), OU_key_bytes_V4); + pad_short_parameter(k1, data.getLengthBytes()); + iterate_rc4(O_data, key_bytes, QUtil::unsigned_char_pointer(k1), + data.getLengthBytes(), (data.getR() >= 3) ? 20 : 1, true); std::string new_user_password = std::string(reinterpret_cast(O_data), key_bytes); @@ -886,6 +893,7 @@ QPDF::initializeEncryption() if (V < 5) { + // These must be exactly the right number of bytes. pad_short_parameter(O, key_bytes); pad_short_parameter(U, key_bytes); if (! ((O.length() == key_bytes) && (U.length() == key_bytes))) @@ -913,24 +921,12 @@ QPDF::initializeEncryption() UE = encryption_dict.getKey("/UE").getStringValue(); Perms = encryption_dict.getKey("/Perms").getStringValue(); + // These may be longer than the minimum number of bytes. pad_short_parameter(O, OU_key_bytes_V5); pad_short_parameter(U, OU_key_bytes_V5); pad_short_parameter(OE, OUE_key_bytes_V5); pad_short_parameter(UE, OUE_key_bytes_V5); pad_short_parameter(Perms, Perms_key_bytes_V5); - if ((O.length() < OU_key_bytes_V5) || - (U.length() < OU_key_bytes_V5) || - (OE.length() < OUE_key_bytes_V5) || - (UE.length() < OUE_key_bytes_V5) || - (Perms.length() < Perms_key_bytes_V5)) - { - throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), - "encryption dictionary", - this->m->file->getLastOffset(), - "incorrect length for some of" - " /O, /U, /OE, /UE, or /Perms in" - " encryption dictionary"); - } } int Length = 40; -- cgit v1.2.3-54-g00ecf