Commit a8715c495b218c9b9388a2e20c8202a3fa73b2c1

Authored by Jay Berkenbilt
1 parent 09175e45

add C API for R4 encryption

git-svn-id: svn+q:///qpdf/trunk@825 71b93d88-0707-0410-a8cf-f5a4172ac649
include/qpdf/QPDFWriter.hh
@@ -110,6 +110,11 @@ class DLL_EXPORT QPDFWriter @@ -110,6 +110,11 @@ class DLL_EXPORT QPDFWriter
110 // suites. 110 // suites.
111 void setStaticID(bool); 111 void setStaticID(bool);
112 112
  113 + // Use a fixed initialization vector for AES-CBC encryption. This
  114 + // is not secure. It should be used only in test suites for
  115 + // creating predictable encrypted output.
  116 + void setStaticAesIV(bool);
  117 +
113 // Suppress inclusion of comments indicating original object IDs 118 // Suppress inclusion of comments indicating original object IDs
114 // when writing QDF files. This can also be useful for testing, 119 // when writing QDF files. This can also be useful for testing,
115 // particularly when using comparison of two qdf files to 120 // particularly when using comparison of two qdf files to
include/qpdf/qpdf-c.h
@@ -226,6 +226,12 @@ extern "C" { @@ -226,6 +226,12 @@ extern "C" {
226 DLL_EXPORT 226 DLL_EXPORT
227 void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); 227 void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value);
228 228
  229 + /* Never use qpdf_set_static_aes_IV except in test suites to
  230 + * create predictable AES encrypted output.
  231 + */
  232 + DLL_EXPORT
  233 + void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);
  234 +
229 DLL_EXPORT 235 DLL_EXPORT
230 void qpdf_set_suppress_original_object_IDs( 236 void qpdf_set_suppress_original_object_IDs(
231 qpdf_data qpdf, QPDF_BOOL value); 237 qpdf_data qpdf, QPDF_BOOL value);
@@ -259,6 +265,13 @@ extern "C" { @@ -259,6 +265,13 @@ extern "C" {
259 int print, int modify); 265 int print, int modify);
260 266
261 DLL_EXPORT 267 DLL_EXPORT
  268 + void qpdf_set_r4_encryption_parameters(
  269 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  270 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  271 + int print, int modify,
  272 + QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
  273 +
  274 + DLL_EXPORT
262 void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); 275 void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value);
263 276
264 DLL_EXPORT 277 DLL_EXPORT
libqpdf/Pl_AES_PDF.cc
@@ -12,6 +12,8 @@ @@ -12,6 +12,8 @@
12 # define srandom srand 12 # define srandom srand
13 #endif 13 #endif
14 14
  15 +bool Pl_AES_PDF::use_static_iv = false;
  16 +
15 Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, 17 Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
16 bool encrypt, unsigned char const key[key_size]) : 18 bool encrypt, unsigned char const key[key_size]) :
17 Pipeline(identifier, next), 19 Pipeline(identifier, next),
@@ -52,6 +54,12 @@ Pl_AES_PDF::disableCBC() @@ -52,6 +54,12 @@ Pl_AES_PDF::disableCBC()
52 } 54 }
53 55
54 void 56 void
  57 +Pl_AES_PDF::useStaticIV()
  58 +{
  59 + use_static_iv = true;
  60 +}
  61 +
  62 +void
55 Pl_AES_PDF::write(unsigned char* data, int len) 63 Pl_AES_PDF::write(unsigned char* data, int len)
56 { 64 {
57 unsigned int bytes_left = len; 65 unsigned int bytes_left = len;
@@ -116,9 +124,19 @@ Pl_AES_PDF::initializeVector() @@ -116,9 +124,19 @@ Pl_AES_PDF::initializeVector()
116 srandom((int)QUtil::get_current_time() ^ 0xcccc); 124 srandom((int)QUtil::get_current_time() ^ 0xcccc);
117 seeded_random = true; 125 seeded_random = true;
118 } 126 }
119 - for (unsigned int i = 0; i < this->buf_size; ++i) 127 + if (use_static_iv)
  128 + {
  129 + for (unsigned int i = 0; i < this->buf_size; ++i)
  130 + {
  131 + this->cbc_block[i] = 14 * (1 + i);
  132 + }
  133 + }
  134 + else
120 { 135 {
121 - this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4); 136 + for (unsigned int i = 0; i < this->buf_size; ++i)
  137 + {
  138 + this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4);
  139 + }
122 } 140 }
123 } 141 }
124 142
libqpdf/QPDFWriter.cc
@@ -140,6 +140,15 @@ QPDFWriter::setStaticID(bool val) @@ -140,6 +140,15 @@ QPDFWriter::setStaticID(bool val)
140 } 140 }
141 141
142 void 142 void
  143 +QPDFWriter::setStaticAesIV(bool val)
  144 +{
  145 + if (val)
  146 + {
  147 + Pl_AES_PDF::useStaticIV();
  148 + }
  149 +}
  150 +
  151 +void
143 QPDFWriter::setSuppressOriginalObjectIDs(bool val) 152 QPDFWriter::setSuppressOriginalObjectIDs(bool val)
144 { 153 {
145 this->suppress_original_object_ids = val; 154 this->suppress_original_object_ids = val;
libqpdf/qpdf-c.cc
@@ -313,6 +313,12 @@ void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value) @@ -313,6 +313,12 @@ void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value)
313 qpdf->qpdf_writer->setStaticID(value); 313 qpdf->qpdf_writer->setStaticID(value);
314 } 314 }
315 315
  316 +void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value)
  317 +{
  318 + QTC::TC("qpdf", "qpdf-c called qpdf_set_static_aes_IV");
  319 + qpdf->qpdf_writer->setStaticAesIV(value);
  320 +}
  321 +
316 void qpdf_set_suppress_original_object_IDs( 322 void qpdf_set_suppress_original_object_IDs(
317 qpdf_data qpdf, QPDF_BOOL value) 323 qpdf_data qpdf, QPDF_BOOL value)
318 { 324 {
@@ -356,6 +362,26 @@ void qpdf_set_r3_encryption_parameters( @@ -356,6 +362,26 @@ void qpdf_set_r3_encryption_parameters(
356 QPDFWriter::r3m_all)); 362 QPDFWriter::r3m_all));
357 } 363 }
358 364
  365 +void qpdf_set_r4_encryption_parameters(
  366 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  367 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  368 + int print, int modify, QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
  369 +{
  370 + QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
  371 + qpdf->qpdf_writer->setR4EncryptionParameters(
  372 + user_password, owner_password,
  373 + allow_accessibility, allow_extract,
  374 + ((print == QPDF_R3_PRINT_LOW) ? QPDFWriter::r3p_low :
  375 + (print == QPDF_R3_PRINT_NONE) ? QPDFWriter::r3p_none :
  376 + QPDFWriter::r3p_full),
  377 + ((modify == QPDF_R3_MODIFY_ANNOTATE) ? QPDFWriter::r3m_annotate :
  378 + (modify == QPDF_R3_MODIFY_FORM) ? QPDFWriter::r3m_form :
  379 + (modify == QPDF_R3_MODIFY_ASSEMBLY) ? QPDFWriter::r3m_assembly :
  380 + (modify == QPDF_R3_MODIFY_NONE) ? QPDFWriter::r3m_none :
  381 + QPDFWriter::r3m_all),
  382 + encrypt_metadata, use_aes);
  383 +}
  384 +
359 void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) 385 void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value)
360 { 386 {
361 QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization"); 387 QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization");
libqpdf/qpdf/Pl_AES_PDF.hh
@@ -20,12 +20,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline @@ -20,12 +20,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline
20 20
21 // For testing only; PDF always uses CBC 21 // For testing only; PDF always uses CBC
22 void disableCBC(); 22 void disableCBC();
  23 + // For testing only: use a fixed initialization vector for CBC
  24 + static void useStaticIV();
23 25
24 private: 26 private:
25 void flush(bool discard_padding); 27 void flush(bool discard_padding);
26 void initializeVector(); 28 void initializeVector();
27 29
28 static unsigned int const buf_size = 16; 30 static unsigned int const buf_size = 16;
  31 + static bool use_static_iv;
29 32
30 bool encrypt; 33 bool encrypt;
31 bool cbc_mode; 34 bool cbc_mode;
qpdf/qpdf-ctest.c
@@ -229,6 +229,22 @@ static void test14(char const* infile, @@ -229,6 +229,22 @@ static void test14(char const* infile,
229 report_errors(); 229 report_errors();
230 } 230 }
231 231
  232 +static void test15(char const* infile,
  233 + char const* password,
  234 + char const* outfile,
  235 + char const* outfile2)
  236 +{
  237 + qpdf_read(qpdf, infile, password);
  238 + qpdf_init_write(qpdf, outfile);
  239 + qpdf_set_static_ID(qpdf, QPDF_TRUE);
  240 + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
  241 + qpdf_set_r4_encryption_parameters(
  242 + qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE,
  243 + QPDF_R3_PRINT_LOW, QPDF_R3_MODIFY_ALL, QPDF_TRUE, QPDF_TRUE);
  244 + qpdf_write(qpdf);
  245 + report_errors();
  246 +}
  247 +
232 int main(int argc, char* argv[]) 248 int main(int argc, char* argv[])
233 { 249 {
234 char* whoami = 0; 250 char* whoami = 0;
@@ -278,6 +294,7 @@ int main(int argc, char* argv[]) @@ -278,6 +294,7 @@ int main(int argc, char* argv[])
278 (n == 12) ? test12 : 294 (n == 12) ? test12 :
279 (n == 13) ? test13 : 295 (n == 13) ? test13 :
280 (n == 14) ? test14 : 296 (n == 14) ? test14 :
  297 + (n == 15) ? test15 :
281 0); 298 0);
282 299
283 if (fn == 0) 300 if (fn == 0)
qpdf/qpdf.cc
@@ -146,6 +146,8 @@ These options can be useful for digging into PDF files or for use in\n\ @@ -146,6 +146,8 @@ These options can be useful for digging into PDF files or for use in\n\
146 automated test suites for software that uses the qpdf library.\n\ 146 automated test suites for software that uses the qpdf library.\n\
147 \n\ 147 \n\
148 --static-id generate static /ID: FOR TESTING ONLY!\n\ 148 --static-id generate static /ID: FOR TESTING ONLY!\n\
  149 +--static-aes-iv use a static initialization vector for AES-CBC\n\
  150 + This is option is not secure! FOR TESTING ONLY!\n\
149 --no-original-object-ids suppress original object ID comments in qdf mode\n\ 151 --no-original-object-ids suppress original object ID comments in qdf mode\n\
150 --show-encryption quickly show encryption parameters\n\ 152 --show-encryption quickly show encryption parameters\n\
151 --check-linearization check file integrity and linearization status\n\ 153 --check-linearization check file integrity and linearization status\n\
@@ -604,6 +606,7 @@ int main(int argc, char* argv[]) @@ -604,6 +606,7 @@ int main(int argc, char* argv[])
604 std::string force_version; 606 std::string force_version;
605 607
606 bool static_id = false; 608 bool static_id = false;
  609 + bool static_aes_iv = false;
607 bool suppress_original_object_id = false; 610 bool suppress_original_object_id = false;
608 bool show_encryption = false; 611 bool show_encryption = false;
609 bool check_linearization = false; 612 bool check_linearization = false;
@@ -758,6 +761,10 @@ int main(int argc, char* argv[]) @@ -758,6 +761,10 @@ int main(int argc, char* argv[])
758 { 761 {
759 static_id = true; 762 static_id = true;
760 } 763 }
  764 + else if (strcmp(arg, "static-aes-iv") == 0)
  765 + {
  766 + static_aes_iv = true;
  767 + }
761 else if (strcmp(arg, "no-original-object-ids") == 0) 768 else if (strcmp(arg, "no-original-object-ids") == 0)
762 { 769 {
763 suppress_original_object_id = true; 770 suppress_original_object_id = true;
@@ -1049,6 +1056,10 @@ int main(int argc, char* argv[]) @@ -1049,6 +1056,10 @@ int main(int argc, char* argv[])
1049 { 1056 {
1050 w.setStaticID(true); 1057 w.setStaticID(true);
1051 } 1058 }
  1059 + if (static_aes_iv)
  1060 + {
  1061 + w.setStaticAesIV(true);
  1062 + }
1052 if (suppress_original_object_id) 1063 if (suppress_original_object_id)
1053 { 1064 {
1054 w.setSuppressOriginalObjectIDs(true); 1065 w.setSuppressOriginalObjectIDs(true);
qpdf/qpdf.testcov
@@ -168,3 +168,5 @@ QPDF_encryption cleartext metadata 0 @@ -168,3 +168,5 @@ QPDF_encryption cleartext metadata 0
168 QPDF_encryption aes decode stream 0 168 QPDF_encryption aes decode stream 0
169 QPDFWriter forcing object stream disable 0 169 QPDFWriter forcing object stream disable 0
170 QPDFWriter forced version disabled encryption 0 170 QPDFWriter forced version disabled encryption 0
  171 +qpdf-c called qpdf_set_r4_encryption_parameters 0
  172 +qpdf-c called qpdf_set_static_aes_IV 0
qpdf/qtest/qpdf.test
@@ -954,6 +954,7 @@ $td-&gt;runtest(&quot;invalid password&quot;, @@ -954,6 +954,7 @@ $td-&gt;runtest(&quot;invalid password&quot;,
954 my @cenc = ( 954 my @cenc = (
955 [11, 'hybrid-xref.pdf', "''", 'r2', ""], 955 [11, 'hybrid-xref.pdf', "''", 'r2', ""],
956 [12, 'hybrid-xref.pdf', "''", 'r3', ""], 956 [12, 'hybrid-xref.pdf', "''", 'r3', ""],
  957 + [15, 'hybrid-xref.pdf', "''", 'r4', ""],
957 [13, 'c-r2.pdf', 'user1', 'decrypt with user', 958 [13, 'c-r2.pdf', 'user1', 'decrypt with user',
958 "user password: user1\n"], 959 "user password: user1\n"],
959 [13, 'c-r3.pdf', 'owner2', 'decrypt with owner', 960 [13, 'c-r3.pdf', 'owner2', 'decrypt with owner',
qpdf/qtest/qpdf/c-r4.pdf 0 → 100644
No preview for this file type