Skip to content

Commit dea704f

Browse files
committed
Pad keys to avoid memory errors (fixes #147)
1 parent 021c229 commit dea704f

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

Diff for: libqpdf/QPDF_encryption.cc

+10-14
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ compute_O_value(std::string const& user_password,
479479

480480
char upass[key_bytes];
481481
pad_or_truncate_password_V4(user_password, upass);
482+
std::string k1(reinterpret_cast<char*>(O_key), OU_key_bytes_V4);
483+
pad_short_parameter(k1, data.getLengthBytes());
482484
iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes,
483485
O_key, data.getLengthBytes(),
484486
(data.getR() >= 3) ? 20 : 1, false);
@@ -495,6 +497,7 @@ compute_U_value_R2(std::string const& user_password,
495497
std::string k1 = QPDF::compute_encryption_key(user_password, data);
496498
char udata[key_bytes];
497499
pad_or_truncate_password_V4("", udata);
500+
pad_short_parameter(k1, data.getLengthBytes());
498501
iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes,
499502
QUtil::unsigned_char_pointer(k1),
500503
data.getLengthBytes(), 1, false);
@@ -516,6 +519,7 @@ compute_U_value_R3(std::string const& user_password,
516519
data.getId1().length());
517520
MD5::Digest digest;
518521
md5.digest(digest);
522+
pad_short_parameter(k1, data.getLengthBytes());
519523
iterate_rc4(digest, sizeof(MD5::Digest),
520524
QUtil::unsigned_char_pointer(k1),
521525
data.getLengthBytes(), 20, false);
@@ -591,7 +595,10 @@ check_owner_password_V4(std::string& user_password,
591595
compute_O_rc4_key(user_password, owner_password, data, key);
592596
unsigned char O_data[key_bytes];
593597
memcpy(O_data, QUtil::unsigned_char_pointer(data.getO()), key_bytes);
594-
iterate_rc4(O_data, key_bytes, key, data.getLengthBytes(),
598+
std::string k1(reinterpret_cast<char*>(key), OU_key_bytes_V4);
599+
pad_short_parameter(k1, data.getLengthBytes());
600+
iterate_rc4(O_data, key_bytes, QUtil::unsigned_char_pointer(k1),
601+
data.getLengthBytes(),
595602
(data.getR() >= 3) ? 20 : 1, true);
596603
std::string new_user_password =
597604
std::string(reinterpret_cast<char*>(O_data), key_bytes);
@@ -886,6 +893,7 @@ QPDF::initializeEncryption()
886893

887894
if (V < 5)
888895
{
896+
// These must be exactly the right number of bytes.
889897
pad_short_parameter(O, key_bytes);
890898
pad_short_parameter(U, key_bytes);
891899
if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
@@ -913,24 +921,12 @@ QPDF::initializeEncryption()
913921
UE = encryption_dict.getKey("/UE").getStringValue();
914922
Perms = encryption_dict.getKey("/Perms").getStringValue();
915923

924+
// These may be longer than the minimum number of bytes.
916925
pad_short_parameter(O, OU_key_bytes_V5);
917926
pad_short_parameter(U, OU_key_bytes_V5);
918927
pad_short_parameter(OE, OUE_key_bytes_V5);
919928
pad_short_parameter(UE, OUE_key_bytes_V5);
920929
pad_short_parameter(Perms, Perms_key_bytes_V5);
921-
if ((O.length() < OU_key_bytes_V5) ||
922-
(U.length() < OU_key_bytes_V5) ||
923-
(OE.length() < OUE_key_bytes_V5) ||
924-
(UE.length() < OUE_key_bytes_V5) ||
925-
(Perms.length() < Perms_key_bytes_V5))
926-
{
927-
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
928-
"encryption dictionary",
929-
this->m->file->getLastOffset(),
930-
"incorrect length for some of"
931-
" /O, /U, /OE, /UE, or /Perms in"
932-
" encryption dictionary");
933-
}
934930
}
935931

936932
int Length = 40;

0 commit comments

Comments
 (0)