Commit 8fe0b06cd879f503d0e5be63f706d3adda3b8203

Authored by Jay Berkenbilt
1 parent 0c99cf87

Pad encryption parameters that are too short (fixes #96)

ChangeLog
  1 +2017-08-11 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Handle encrypted files whose encryption parameters are too
  4 + short. Fixes #96.
  5 +
1 2017-08-10 Jay Berkenbilt <ejb@ql.org> 6 2017-08-10 Jay Berkenbilt <ejb@ql.org>
2 7
3 * Remove dependency on libpcre. 8 * Remove dependency on libpcre.
libqpdf/QPDF_encryption.cc
@@ -340,6 +340,16 @@ hash_V5(std::string const&amp; password, @@ -340,6 +340,16 @@ hash_V5(std::string const&amp; password,
340 return result; 340 return result;
341 } 341 }
342 342
  343 +static
  344 +void pad_short_parameter(std::string& param, unsigned int max_len)
  345 +{
  346 + if (param.length() < max_len)
  347 + {
  348 + QTC::TC("qpdf", "QPDF_encryption pad short parameter");
  349 + param.append(max_len - param.length(), '\0');
  350 + }
  351 +}
  352 +
343 std::string 353 std::string
344 QPDF::compute_data_key(std::string const& encryption_key, 354 QPDF::compute_data_key(std::string const& encryption_key,
345 int objid, int generation, bool use_aes, 355 int objid, int generation, bool use_aes,
@@ -876,6 +886,8 @@ QPDF::initializeEncryption() @@ -876,6 +886,8 @@ QPDF::initializeEncryption()
876 886
877 if (V < 5) 887 if (V < 5)
878 { 888 {
  889 + pad_short_parameter(O, key_bytes);
  890 + pad_short_parameter(U, key_bytes);
879 if (! ((O.length() == key_bytes) && (U.length() == key_bytes))) 891 if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
880 { 892 {
881 throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), 893 throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
@@ -899,6 +911,11 @@ QPDF::initializeEncryption() @@ -899,6 +911,11 @@ QPDF::initializeEncryption()
899 UE = encryption_dict.getKey("/UE").getStringValue(); 911 UE = encryption_dict.getKey("/UE").getStringValue();
900 Perms = encryption_dict.getKey("/Perms").getStringValue(); 912 Perms = encryption_dict.getKey("/Perms").getStringValue();
901 913
  914 + pad_short_parameter(O, OU_key_bytes_V5);
  915 + pad_short_parameter(U, OU_key_bytes_V5);
  916 + pad_short_parameter(OE, OUE_key_bytes_V5);
  917 + pad_short_parameter(UE, OUE_key_bytes_V5);
  918 + pad_short_parameter(Perms, Perms_key_bytes_V5);
902 if ((O.length() < OU_key_bytes_V5) || 919 if ((O.length() < OU_key_bytes_V5) ||
903 (U.length() < OU_key_bytes_V5) || 920 (U.length() < OU_key_bytes_V5) ||
904 (OE.length() < OUE_key_bytes_V5) || 921 (OE.length() < OUE_key_bytes_V5) ||
qpdf/qpdf.testcov
@@ -293,3 +293,4 @@ QPDF ignore first space in xref entry 0 @@ -293,3 +293,4 @@ QPDF ignore first space in xref entry 0
293 QPDF ignore first extra space in xref entry 0 293 QPDF ignore first extra space in xref entry 0
294 QPDF ignore second extra space in xref entry 0 294 QPDF ignore second extra space in xref entry 0
295 QPDF ignore length error xref entry 0 295 QPDF ignore length error xref entry 0
  296 +QPDF_encryption pad short parameter 0
qpdf/qtest/qpdf.test
@@ -232,7 +232,7 @@ foreach my $d (@bug_tests) @@ -232,7 +232,7 @@ foreach my $d (@bug_tests)
232 show_ntests(); 232 show_ntests();
233 # ---------- 233 # ----------
234 $td->notify("--- Miscellaneous Tests ---"); 234 $td->notify("--- Miscellaneous Tests ---");
235 -$n_tests += 87; 235 +$n_tests += 88;
236 236
237 $td->runtest("qpdf version", 237 $td->runtest("qpdf version",
238 {$td->COMMAND => "qpdf --version"}, 238 {$td->COMMAND => "qpdf --version"},
@@ -676,6 +676,16 @@ $td-&gt;runtest(&quot;recoverable xref errors&quot;, @@ -676,6 +676,16 @@ $td-&gt;runtest(&quot;recoverable xref errors&quot;,
676 $td->EXIT_STATUS => 3}, 676 $td->EXIT_STATUS => 3},
677 $td->NORMALIZE_NEWLINES); 677 $td->NORMALIZE_NEWLINES);
678 678
  679 +# A file was emailed privately with issue 96. short-O-U.pdf was
  680 +# created by copying encryption parameters from that file. It exhibits
  681 +# the same behavior as the original file.
  682 +$td->runtest("short /O or /U",
  683 + {$td->COMMAND =>
  684 + "qpdf --password=19723102477 --check short-O-U.pdf"},
  685 + {$td->FILE => "short-O-U.out",
  686 + $td->EXIT_STATUS => 0},
  687 + $td->NORMALIZE_NEWLINES);
  688 +
679 show_ntests(); 689 show_ntests();
680 # ---------- 690 # ----------
681 $td->notify("--- Single Page ---"); 691 $td->notify("--- Single Page ---");
qpdf/qtest/qpdf/short-O-U.out 0 → 100644
  1 +checking short-O-U.pdf
  2 +PDF Version: 1.6
  3 +R = 4
  4 +P = -4
  5 +User password = 19723102477
  6 +extract for accessibility: allowed
  7 +extract for any purpose: allowed
  8 +print low resolution: allowed
  9 +print high resolution: allowed
  10 +modify document assembly: allowed
  11 +modify forms: allowed
  12 +modify annotations: allowed
  13 +modify other: allowed
  14 +modify anything: allowed
  15 +stream encryption method: AESv2
  16 +string encryption method: AESv2
  17 +file encryption method: AESv2
  18 +File is not linearized
  19 +No syntax or stream encoding errors found; the file may still contain
  20 +errors that qpdf cannot detect
qpdf/qtest/qpdf/short-O-U.pdf 0 → 100644
No preview for this file type