Commit 9faffb7441bcadbaec21089c7d1d629ffaf0328d

Authored by m-holger
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.
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&amp; 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
... ...