aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2017-08-27 03:10:07 +0200
committerJay Berkenbilt <ejb@ql.org>2017-08-27 03:35:59 +0200
commitdea704f0ab7f625e1e7b3f9a1110b45b63157317 (patch)
treeb57e4ec9bccee38c578b8ac8f5bf5dcf8cbb171b /libqpdf
parent021c229331444aae507186c7b4a54bb1692b5846 (diff)
downloadqpdf-dea704f0ab7f625e1e7b3f9a1110b45b63157317.tar.zst
Pad keys to avoid memory errors (fixes #147)
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/QPDF_encryption.cc24
1 files changed, 10 insertions, 14 deletions
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<char*>(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<char*>(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<char*>(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;