Commit a8715c495b218c9b9388a2e20c8202a3fa73b2c1
1 parent
09175e45
add C API for R4 encryption
git-svn-id: svn+q:///qpdf/trunk@825 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing
11 changed files
with
107 additions
and
2 deletions
include/qpdf/QPDFWriter.hh
| ... | ... | @@ -110,6 +110,11 @@ class DLL_EXPORT QPDFWriter |
| 110 | 110 | // suites. |
| 111 | 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 | 118 | // Suppress inclusion of comments indicating original object IDs |
| 114 | 119 | // when writing QDF files. This can also be useful for testing, |
| 115 | 120 | // particularly when using comparison of two qdf files to | ... | ... |
include/qpdf/qpdf-c.h
| ... | ... | @@ -226,6 +226,12 @@ extern "C" { |
| 226 | 226 | DLL_EXPORT |
| 227 | 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 | 235 | DLL_EXPORT |
| 230 | 236 | void qpdf_set_suppress_original_object_IDs( |
| 231 | 237 | qpdf_data qpdf, QPDF_BOOL value); |
| ... | ... | @@ -259,6 +265,13 @@ extern "C" { |
| 259 | 265 | int print, int modify); |
| 260 | 266 | |
| 261 | 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 | 275 | void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); |
| 263 | 276 | |
| 264 | 277 | DLL_EXPORT | ... | ... |
libqpdf/Pl_AES_PDF.cc
| ... | ... | @@ -12,6 +12,8 @@ |
| 12 | 12 | # define srandom srand |
| 13 | 13 | #endif |
| 14 | 14 | |
| 15 | +bool Pl_AES_PDF::use_static_iv = false; | |
| 16 | + | |
| 15 | 17 | Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, |
| 16 | 18 | bool encrypt, unsigned char const key[key_size]) : |
| 17 | 19 | Pipeline(identifier, next), |
| ... | ... | @@ -52,6 +54,12 @@ Pl_AES_PDF::disableCBC() |
| 52 | 54 | } |
| 53 | 55 | |
| 54 | 56 | void |
| 57 | +Pl_AES_PDF::useStaticIV() | |
| 58 | +{ | |
| 59 | + use_static_iv = true; | |
| 60 | +} | |
| 61 | + | |
| 62 | +void | |
| 55 | 63 | Pl_AES_PDF::write(unsigned char* data, int len) |
| 56 | 64 | { |
| 57 | 65 | unsigned int bytes_left = len; |
| ... | ... | @@ -116,9 +124,19 @@ Pl_AES_PDF::initializeVector() |
| 116 | 124 | srandom((int)QUtil::get_current_time() ^ 0xcccc); |
| 117 | 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 | 140 | } |
| 141 | 141 | |
| 142 | 142 | void |
| 143 | +QPDFWriter::setStaticAesIV(bool val) | |
| 144 | +{ | |
| 145 | + if (val) | |
| 146 | + { | |
| 147 | + Pl_AES_PDF::useStaticIV(); | |
| 148 | + } | |
| 149 | +} | |
| 150 | + | |
| 151 | +void | |
| 143 | 152 | QPDFWriter::setSuppressOriginalObjectIDs(bool val) |
| 144 | 153 | { |
| 145 | 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 | 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 | 322 | void qpdf_set_suppress_original_object_IDs( |
| 317 | 323 | qpdf_data qpdf, QPDF_BOOL value) |
| 318 | 324 | { |
| ... | ... | @@ -356,6 +362,26 @@ void qpdf_set_r3_encryption_parameters( |
| 356 | 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 | 385 | void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) |
| 360 | 386 | { |
| 361 | 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 | 20 | |
| 21 | 21 | // For testing only; PDF always uses CBC |
| 22 | 22 | void disableCBC(); |
| 23 | + // For testing only: use a fixed initialization vector for CBC | |
| 24 | + static void useStaticIV(); | |
| 23 | 25 | |
| 24 | 26 | private: |
| 25 | 27 | void flush(bool discard_padding); |
| 26 | 28 | void initializeVector(); |
| 27 | 29 | |
| 28 | 30 | static unsigned int const buf_size = 16; |
| 31 | + static bool use_static_iv; | |
| 29 | 32 | |
| 30 | 33 | bool encrypt; |
| 31 | 34 | bool cbc_mode; | ... | ... |
qpdf/qpdf-ctest.c
| ... | ... | @@ -229,6 +229,22 @@ static void test14(char const* infile, |
| 229 | 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 | 248 | int main(int argc, char* argv[]) |
| 233 | 249 | { |
| 234 | 250 | char* whoami = 0; |
| ... | ... | @@ -278,6 +294,7 @@ int main(int argc, char* argv[]) |
| 278 | 294 | (n == 12) ? test12 : |
| 279 | 295 | (n == 13) ? test13 : |
| 280 | 296 | (n == 14) ? test14 : |
| 297 | + (n == 15) ? test15 : | |
| 281 | 298 | 0); |
| 282 | 299 | |
| 283 | 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 | 146 | automated test suites for software that uses the qpdf library.\n\ |
| 147 | 147 | \n\ |
| 148 | 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 | 151 | --no-original-object-ids suppress original object ID comments in qdf mode\n\ |
| 150 | 152 | --show-encryption quickly show encryption parameters\n\ |
| 151 | 153 | --check-linearization check file integrity and linearization status\n\ |
| ... | ... | @@ -604,6 +606,7 @@ int main(int argc, char* argv[]) |
| 604 | 606 | std::string force_version; |
| 605 | 607 | |
| 606 | 608 | bool static_id = false; |
| 609 | + bool static_aes_iv = false; | |
| 607 | 610 | bool suppress_original_object_id = false; |
| 608 | 611 | bool show_encryption = false; |
| 609 | 612 | bool check_linearization = false; |
| ... | ... | @@ -758,6 +761,10 @@ int main(int argc, char* argv[]) |
| 758 | 761 | { |
| 759 | 762 | static_id = true; |
| 760 | 763 | } |
| 764 | + else if (strcmp(arg, "static-aes-iv") == 0) | |
| 765 | + { | |
| 766 | + static_aes_iv = true; | |
| 767 | + } | |
| 761 | 768 | else if (strcmp(arg, "no-original-object-ids") == 0) |
| 762 | 769 | { |
| 763 | 770 | suppress_original_object_id = true; |
| ... | ... | @@ -1049,6 +1056,10 @@ int main(int argc, char* argv[]) |
| 1049 | 1056 | { |
| 1050 | 1057 | w.setStaticID(true); |
| 1051 | 1058 | } |
| 1059 | + if (static_aes_iv) | |
| 1060 | + { | |
| 1061 | + w.setStaticAesIV(true); | |
| 1062 | + } | |
| 1052 | 1063 | if (suppress_original_object_id) |
| 1053 | 1064 | { |
| 1054 | 1065 | w.setSuppressOriginalObjectIDs(true); | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -168,3 +168,5 @@ QPDF_encryption cleartext metadata 0 |
| 168 | 168 | QPDF_encryption aes decode stream 0 |
| 169 | 169 | QPDFWriter forcing object stream disable 0 |
| 170 | 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->runtest("invalid password", |
| 954 | 954 | my @cenc = ( |
| 955 | 955 | [11, 'hybrid-xref.pdf', "''", 'r2', ""], |
| 956 | 956 | [12, 'hybrid-xref.pdf', "''", 'r3', ""], |
| 957 | + [15, 'hybrid-xref.pdf', "''", 'r4', ""], | |
| 957 | 958 | [13, 'c-r2.pdf', 'user1', 'decrypt with user', |
| 958 | 959 | "user password: user1\n"], |
| 959 | 960 | [13, 'c-r3.pdf', 'owner2', 'decrypt with owner', | ... | ... |
qpdf/qtest/qpdf/c-r4.pdf
0 → 100644
No preview for this file type