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