Commit dea704f0ab7f625e1e7b3f9a1110b45b63157317

Authored by Jay Berkenbilt
1 parent 021c2293

Pad keys to avoid memory errors (fixes #147)

Showing 1 changed file with 10 additions and 14 deletions
libqpdf/QPDF_encryption.cc
@@ -479,6 +479,8 @@ compute_O_value(std::string const& user_password, @@ -479,6 +479,8 @@ compute_O_value(std::string const& user_password,
479 479
480 char upass[key_bytes]; 480 char upass[key_bytes];
481 pad_or_truncate_password_V4(user_password, upass); 481 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());
482 iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes, 484 iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes,
483 O_key, data.getLengthBytes(), 485 O_key, data.getLengthBytes(),
484 (data.getR() >= 3) ? 20 : 1, false); 486 (data.getR() >= 3) ? 20 : 1, false);
@@ -495,6 +497,7 @@ compute_U_value_R2(std::string const&amp; user_password, @@ -495,6 +497,7 @@ compute_U_value_R2(std::string const&amp; user_password,
495 std::string k1 = QPDF::compute_encryption_key(user_password, data); 497 std::string k1 = QPDF::compute_encryption_key(user_password, data);
496 char udata[key_bytes]; 498 char udata[key_bytes];
497 pad_or_truncate_password_V4("", udata); 499 pad_or_truncate_password_V4("", udata);
  500 + pad_short_parameter(k1, data.getLengthBytes());
498 iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes, 501 iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes,
499 QUtil::unsigned_char_pointer(k1), 502 QUtil::unsigned_char_pointer(k1),
500 data.getLengthBytes(), 1, false); 503 data.getLengthBytes(), 1, false);
@@ -516,6 +519,7 @@ compute_U_value_R3(std::string const&amp; user_password, @@ -516,6 +519,7 @@ compute_U_value_R3(std::string const&amp; user_password,
516 data.getId1().length()); 519 data.getId1().length());
517 MD5::Digest digest; 520 MD5::Digest digest;
518 md5.digest(digest); 521 md5.digest(digest);
  522 + pad_short_parameter(k1, data.getLengthBytes());
519 iterate_rc4(digest, sizeof(MD5::Digest), 523 iterate_rc4(digest, sizeof(MD5::Digest),
520 QUtil::unsigned_char_pointer(k1), 524 QUtil::unsigned_char_pointer(k1),
521 data.getLengthBytes(), 20, false); 525 data.getLengthBytes(), 20, false);
@@ -591,7 +595,10 @@ check_owner_password_V4(std::string&amp; user_password, @@ -591,7 +595,10 @@ check_owner_password_V4(std::string&amp; user_password,
591 compute_O_rc4_key(user_password, owner_password, data, key); 595 compute_O_rc4_key(user_password, owner_password, data, key);
592 unsigned char O_data[key_bytes]; 596 unsigned char O_data[key_bytes];
593 memcpy(O_data, QUtil::unsigned_char_pointer(data.getO()), key_bytes); 597 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(),
595 (data.getR() >= 3) ? 20 : 1, true); 602 (data.getR() >= 3) ? 20 : 1, true);
596 std::string new_user_password = 603 std::string new_user_password =
597 std::string(reinterpret_cast<char*>(O_data), key_bytes); 604 std::string(reinterpret_cast<char*>(O_data), key_bytes);
@@ -886,6 +893,7 @@ QPDF::initializeEncryption() @@ -886,6 +893,7 @@ QPDF::initializeEncryption()
886 893
887 if (V < 5) 894 if (V < 5)
888 { 895 {
  896 + // These must be exactly the right number of bytes.
889 pad_short_parameter(O, key_bytes); 897 pad_short_parameter(O, key_bytes);
890 pad_short_parameter(U, key_bytes); 898 pad_short_parameter(U, key_bytes);
891 if (! ((O.length() == key_bytes) && (U.length() == key_bytes))) 899 if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
@@ -913,24 +921,12 @@ QPDF::initializeEncryption() @@ -913,24 +921,12 @@ QPDF::initializeEncryption()
913 UE = encryption_dict.getKey("/UE").getStringValue(); 921 UE = encryption_dict.getKey("/UE").getStringValue();
914 Perms = encryption_dict.getKey("/Perms").getStringValue(); 922 Perms = encryption_dict.getKey("/Perms").getStringValue();
915 923
  924 + // These may be longer than the minimum number of bytes.
916 pad_short_parameter(O, OU_key_bytes_V5); 925 pad_short_parameter(O, OU_key_bytes_V5);
917 pad_short_parameter(U, OU_key_bytes_V5); 926 pad_short_parameter(U, OU_key_bytes_V5);
918 pad_short_parameter(OE, OUE_key_bytes_V5); 927 pad_short_parameter(OE, OUE_key_bytes_V5);
919 pad_short_parameter(UE, OUE_key_bytes_V5); 928 pad_short_parameter(UE, OUE_key_bytes_V5);
920 pad_short_parameter(Perms, Perms_key_bytes_V5); 929 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 - }  
934 } 930 }
935 931
936 int Length = 40; 932 int Length = 40;