Commit 9faffb7441bcadbaec21089c7d1d629ffaf0328d
1 parent
4278a557
Refactor `Pl_AES_PDF` and `Pl_RC4` constructors to simplify key handling
Replaced raw key pointer and length parameters with a `std::string` in `Pl_AES_PDF` and `Pl_RC4` constructors for improved safety and clarity. Updated all usage sites accordingly, reducing reliance on manual memory management and redundant conversions.
Showing
8 changed files
with
27 additions
and
70 deletions
libqpdf/Pl_AES_PDF.cc
| ... | ... | @@ -9,25 +9,18 @@ |
| 9 | 9 | |
| 10 | 10 | bool Pl_AES_PDF::use_static_iv = false; |
| 11 | 11 | |
| 12 | -Pl_AES_PDF::Pl_AES_PDF( | |
| 13 | - char const* identifier, | |
| 14 | - Pipeline* next, | |
| 15 | - bool encrypt, | |
| 16 | - unsigned char const* key, | |
| 17 | - size_t key_bytes) : | |
| 12 | +Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, bool encrypt, std::string key) : | |
| 18 | 13 | Pipeline(identifier, next), |
| 14 | + key(key), | |
| 19 | 15 | crypto(QPDFCryptoProvider::getImpl()), |
| 20 | - encrypt(encrypt), | |
| 21 | - key_bytes(key_bytes) | |
| 16 | + encrypt(encrypt) | |
| 22 | 17 | { |
| 23 | 18 | if (!next) { |
| 24 | 19 | throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next"); |
| 25 | 20 | } |
| 26 | - if (!(key_bytes == 32 || key_bytes == 16)) { | |
| 21 | + if (!(key.size() == 32 || key.size() == 16)) { | |
| 27 | 22 | throw std::runtime_error("unsupported key length"); |
| 28 | 23 | } |
| 29 | - this->key = std::make_unique<unsigned char[]>(key_bytes); | |
| 30 | - std::memcpy(this->key.get(), key, key_bytes); | |
| 31 | 24 | std::memset(this->inbuf, 0, this->buf_size); |
| 32 | 25 | std::memset(this->outbuf, 0, this->buf_size); |
| 33 | 26 | std::memset(this->cbc_block, 0, this->buf_size); |
| ... | ... | @@ -170,7 +163,12 @@ Pl_AES_PDF::flush(bool strip_padding) |
| 170 | 163 | return_after_init = true; |
| 171 | 164 | } |
| 172 | 165 | } |
| 173 | - crypto->rijndael_init(encrypt, key.get(), key_bytes, cbc_mode, cbc_block); | |
| 166 | + crypto->rijndael_init( | |
| 167 | + encrypt, | |
| 168 | + reinterpret_cast<const unsigned char*>(key.data()), | |
| 169 | + key.size(), | |
| 170 | + cbc_mode, | |
| 171 | + cbc_block); | |
| 174 | 172 | if (return_after_init) { |
| 175 | 173 | return; |
| 176 | 174 | } | ... | ... |
libqpdf/Pl_RC4.cc
| ... | ... | @@ -2,15 +2,10 @@ |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QUtil.hh> |
| 4 | 4 | |
| 5 | -Pl_RC4::Pl_RC4( | |
| 6 | - char const* identifier, | |
| 7 | - Pipeline* next, | |
| 8 | - unsigned char const* key_data, | |
| 9 | - int key_len, | |
| 10 | - size_t out_bufsize) : | |
| 5 | +Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next, std::string key, size_t out_bufsize) : | |
| 11 | 6 | Pipeline(identifier, next), |
| 12 | 7 | out_bufsize(out_bufsize), |
| 13 | - rc4(key_data, key_len) | |
| 8 | + rc4(reinterpret_cast<unsigned char const*>(key.data()), static_cast<int>(key.size())) | |
| 14 | 9 | { |
| 15 | 10 | if (!next) { |
| 16 | 11 | throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next"); | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -1109,18 +1109,9 @@ QPDFWriter::write_encrypted(std::string_view str) |
| 1109 | 1109 | if (!(m->encryption && !m->cur_data_key.empty())) { |
| 1110 | 1110 | write(str); |
| 1111 | 1111 | } else if (m->encrypt_use_aes) { |
| 1112 | - write( | |
| 1113 | - pl::pipe<Pl_AES_PDF>( | |
| 1114 | - str, | |
| 1115 | - true, | |
| 1116 | - QUtil::unsigned_char_pointer(m->cur_data_key), | |
| 1117 | - m->cur_data_key.length())); | |
| 1112 | + write(pl::pipe<Pl_AES_PDF>(str, true, m->cur_data_key)); | |
| 1118 | 1113 | } else { |
| 1119 | - write( | |
| 1120 | - pl::pipe<Pl_RC4>( | |
| 1121 | - str, | |
| 1122 | - QUtil::unsigned_char_pointer(m->cur_data_key), | |
| 1123 | - QIntC::to_int(m->cur_data_key.length()))); | |
| 1114 | + write(pl::pipe<Pl_RC4>(str, m->cur_data_key)); | |
| 1124 | 1115 | } |
| 1125 | 1116 | |
| 1126 | 1117 | return *this; |
| ... | ... | @@ -1654,12 +1645,7 @@ QPDFWriter::unparseObject( |
| 1654 | 1645 | val = object.getStringValue(); |
| 1655 | 1646 | if (m->encrypt_use_aes) { |
| 1656 | 1647 | Pl_Buffer bufpl("encrypted string"); |
| 1657 | - Pl_AES_PDF pl( | |
| 1658 | - "aes encrypt string", | |
| 1659 | - &bufpl, | |
| 1660 | - true, | |
| 1661 | - QUtil::unsigned_char_pointer(m->cur_data_key), | |
| 1662 | - m->cur_data_key.length()); | |
| 1648 | + Pl_AES_PDF pl("aes encrypt string", &bufpl, true, m->cur_data_key); | |
| 1663 | 1649 | pl.writeString(val); |
| 1664 | 1650 | pl.finish(); |
| 1665 | 1651 | val = QPDF_String(bufpl.getString()).unparse(true); | ... | ... |
libqpdf/QPDF_encryption.cc
| ... | ... | @@ -230,8 +230,7 @@ process_with_aes( |
| 230 | 230 | size_t iv_length = 0) |
| 231 | 231 | { |
| 232 | 232 | Pl_Buffer buffer("buffer"); |
| 233 | - Pl_AES_PDF aes( | |
| 234 | - "aes", &buffer, encrypt, QUtil::unsigned_char_pointer(key), QIntC::to_uint(key.length())); | |
| 233 | + Pl_AES_PDF aes("aes", &buffer, encrypt, key); | |
| 235 | 234 | if (iv) { |
| 236 | 235 | aes.setIV(iv, iv_length); |
| 237 | 236 | } else { |
| ... | ... | @@ -902,12 +901,7 @@ QPDF::decryptString(std::string& str, QPDFObjGen og) |
| 902 | 901 | if (use_aes) { |
| 903 | 902 | QTC::TC("qpdf", "QPDF_encryption aes decode string"); |
| 904 | 903 | Pl_Buffer bufpl("decrypted string"); |
| 905 | - Pl_AES_PDF pl( | |
| 906 | - "aes decrypt string", | |
| 907 | - &bufpl, | |
| 908 | - false, | |
| 909 | - QUtil::unsigned_char_pointer(key), | |
| 910 | - key.length()); | |
| 904 | + Pl_AES_PDF pl("aes decrypt string", &bufpl, false, key); | |
| 911 | 905 | pl.writeString(str); |
| 912 | 906 | pl.finish(); |
| 913 | 907 | str = bufpl.getString(); |
| ... | ... | @@ -1028,19 +1022,11 @@ QPDF::decryptStream( |
| 1028 | 1022 | std::string key = getKeyForObject(encp, og, use_aes); |
| 1029 | 1023 | if (use_aes) { |
| 1030 | 1024 | QTC::TC("qpdf", "QPDF_encryption aes decode stream"); |
| 1031 | - decrypt_pipeline = std::make_unique<Pl_AES_PDF>( | |
| 1032 | - "AES stream decryption", | |
| 1033 | - pipeline, | |
| 1034 | - false, | |
| 1035 | - QUtil::unsigned_char_pointer(key), | |
| 1036 | - key.length()); | |
| 1025 | + decrypt_pipeline = | |
| 1026 | + std::make_unique<Pl_AES_PDF>("AES stream decryption", pipeline, false, key); | |
| 1037 | 1027 | } else { |
| 1038 | 1028 | QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); |
| 1039 | - decrypt_pipeline = std::make_unique<Pl_RC4>( | |
| 1040 | - "RC4 stream decryption", | |
| 1041 | - pipeline, | |
| 1042 | - QUtil::unsigned_char_pointer(key), | |
| 1043 | - toI(key.length())); | |
| 1029 | + decrypt_pipeline = std::make_unique<Pl_RC4>("RC4 stream decryption", pipeline, key); | |
| 1044 | 1030 | } |
| 1045 | 1031 | pipeline = decrypt_pipeline.get(); |
| 1046 | 1032 | } | ... | ... |
libqpdf/qpdf/Pl_AES_PDF.hh
| ... | ... | @@ -11,12 +11,7 @@ class Pl_AES_PDF final: public Pipeline |
| 11 | 11 | { |
| 12 | 12 | public: |
| 13 | 13 | // key should be a pointer to key_bytes bytes of data |
| 14 | - Pl_AES_PDF( | |
| 15 | - char const* identifier, | |
| 16 | - Pipeline* next, | |
| 17 | - bool encrypt, | |
| 18 | - unsigned char const* key, | |
| 19 | - size_t key_bytes); | |
| 14 | + Pl_AES_PDF(char const* identifier, Pipeline* next, bool encrypt, std::string key); | |
| 20 | 15 | ~Pl_AES_PDF() final = default; |
| 21 | 16 | |
| 22 | 17 | void write(unsigned char const* data, size_t len) final; |
| ... | ... | @@ -42,13 +37,12 @@ class Pl_AES_PDF final: public Pipeline |
| 42 | 37 | static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size; |
| 43 | 38 | static bool use_static_iv; |
| 44 | 39 | |
| 40 | + std::string key; | |
| 45 | 41 | std::shared_ptr<QPDFCryptoImpl> crypto; |
| 46 | 42 | bool encrypt; |
| 47 | 43 | bool cbc_mode{true}; |
| 48 | 44 | bool first{true}; |
| 49 | 45 | size_t offset{0}; // offset into memory buffer |
| 50 | - std::unique_ptr<unsigned char[]> key; | |
| 51 | - size_t key_bytes{0}; | |
| 52 | 46 | unsigned char inbuf[buf_size]; |
| 53 | 47 | unsigned char outbuf[buf_size]; |
| 54 | 48 | unsigned char cbc_block[buf_size]; | ... | ... |
libqpdf/qpdf/Pl_RC4.hh
| ... | ... | @@ -12,11 +12,7 @@ class Pl_RC4 final: public Pipeline |
| 12 | 12 | |
| 13 | 13 | // key_len of -1 means treat key_data as a null-terminated string |
| 14 | 14 | Pl_RC4( |
| 15 | - char const* identifier, | |
| 16 | - Pipeline* next, | |
| 17 | - unsigned char const* key_data, | |
| 18 | - int key_len = -1, | |
| 19 | - size_t out_bufsize = def_bufsize); | |
| 15 | + char const* identifier, Pipeline* next, std::string key, size_t out_bufsize = def_bufsize); | |
| 20 | 16 | ~Pl_RC4() final = default; |
| 21 | 17 | |
| 22 | 18 | void write(unsigned char const* data, size_t len) final; | ... | ... |
libtests/aes.cc
| ... | ... | @@ -84,8 +84,9 @@ main(int argc, char* argv[]) |
| 84 | 84 | key[i / 2] = static_cast<unsigned char>(val); |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | + std::string keystr(reinterpret_cast<char const*>(key), keylen); | |
| 87 | 88 | auto* out = new Pl_StdioFile("stdout", outfile); |
| 88 | - auto* aes = new Pl_AES_PDF("aes_128_cbc", out, encrypt, key, keylen); | |
| 89 | + auto* aes = new Pl_AES_PDF("aes_128_cbc", out, encrypt, keystr); | |
| 89 | 90 | delete[] key; |
| 90 | 91 | key = nullptr; |
| 91 | 92 | if (!cbc_mode) { | ... | ... |
libtests/rc4.cc
| ... | ... | @@ -58,7 +58,8 @@ main(int argc, char* argv[]) |
| 58 | 58 | FILE* outfile = QUtil::safe_fopen(outfilename, "wb"); |
| 59 | 59 | auto* out = new Pl_StdioFile("stdout", outfile); |
| 60 | 60 | // Use a small buffer size (64) for testing |
| 61 | - auto* rc4 = new Pl_RC4("rc4", out, key, QIntC::to_int(keylen), 64U); | |
| 61 | + std::string keystr(reinterpret_cast<char const*>(key), keylen); | |
| 62 | + auto* rc4 = new Pl_RC4("rc4", out, keystr, 64U); | |
| 62 | 63 | delete[] key; |
| 63 | 64 | |
| 64 | 65 | // 64 < buffer size < 512, buffer_size is not a power of 2 for testing | ... | ... |