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,25 +9,18 @@
9 9
10 bool Pl_AES_PDF::use_static_iv = false; 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 Pipeline(identifier, next), 13 Pipeline(identifier, next),
  14 + key(key),
19 crypto(QPDFCryptoProvider::getImpl()), 15 crypto(QPDFCryptoProvider::getImpl()),
20 - encrypt(encrypt),  
21 - key_bytes(key_bytes) 16 + encrypt(encrypt)
22 { 17 {
23 if (!next) { 18 if (!next) {
24 throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next"); 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 throw std::runtime_error("unsupported key length"); 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 std::memset(this->inbuf, 0, this->buf_size); 24 std::memset(this->inbuf, 0, this->buf_size);
32 std::memset(this->outbuf, 0, this->buf_size); 25 std::memset(this->outbuf, 0, this->buf_size);
33 std::memset(this->cbc_block, 0, this->buf_size); 26 std::memset(this->cbc_block, 0, this->buf_size);
@@ -170,7 +163,12 @@ Pl_AES_PDF::flush(bool strip_padding) @@ -170,7 +163,12 @@ Pl_AES_PDF::flush(bool strip_padding)
170 return_after_init = true; 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 if (return_after_init) { 172 if (return_after_init) {
175 return; 173 return;
176 } 174 }
libqpdf/Pl_RC4.cc
@@ -2,15 +2,10 @@ @@ -2,15 +2,10 @@
2 2
3 #include <qpdf/QUtil.hh> 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 Pipeline(identifier, next), 6 Pipeline(identifier, next),
12 out_bufsize(out_bufsize), 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 if (!next) { 10 if (!next) {
16 throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next"); 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,18 +1109,9 @@ QPDFWriter::write_encrypted(std::string_view str)
1109 if (!(m->encryption && !m->cur_data_key.empty())) { 1109 if (!(m->encryption && !m->cur_data_key.empty())) {
1110 write(str); 1110 write(str);
1111 } else if (m->encrypt_use_aes) { 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 } else { 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 return *this; 1117 return *this;
@@ -1654,12 +1645,7 @@ QPDFWriter::unparseObject( @@ -1654,12 +1645,7 @@ QPDFWriter::unparseObject(
1654 val = object.getStringValue(); 1645 val = object.getStringValue();
1655 if (m->encrypt_use_aes) { 1646 if (m->encrypt_use_aes) {
1656 Pl_Buffer bufpl("encrypted string"); 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 pl.writeString(val); 1649 pl.writeString(val);
1664 pl.finish(); 1650 pl.finish();
1665 val = QPDF_String(bufpl.getString()).unparse(true); 1651 val = QPDF_String(bufpl.getString()).unparse(true);
libqpdf/QPDF_encryption.cc
@@ -230,8 +230,7 @@ process_with_aes( @@ -230,8 +230,7 @@ process_with_aes(
230 size_t iv_length = 0) 230 size_t iv_length = 0)
231 { 231 {
232 Pl_Buffer buffer("buffer"); 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 if (iv) { 234 if (iv) {
236 aes.setIV(iv, iv_length); 235 aes.setIV(iv, iv_length);
237 } else { 236 } else {
@@ -902,12 +901,7 @@ QPDF::decryptString(std::string&amp; str, QPDFObjGen og) @@ -902,12 +901,7 @@ QPDF::decryptString(std::string&amp; str, QPDFObjGen og)
902 if (use_aes) { 901 if (use_aes) {
903 QTC::TC("qpdf", "QPDF_encryption aes decode string"); 902 QTC::TC("qpdf", "QPDF_encryption aes decode string");
904 Pl_Buffer bufpl("decrypted string"); 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 pl.writeString(str); 905 pl.writeString(str);
912 pl.finish(); 906 pl.finish();
913 str = bufpl.getString(); 907 str = bufpl.getString();
@@ -1028,19 +1022,11 @@ QPDF::decryptStream( @@ -1028,19 +1022,11 @@ QPDF::decryptStream(
1028 std::string key = getKeyForObject(encp, og, use_aes); 1022 std::string key = getKeyForObject(encp, og, use_aes);
1029 if (use_aes) { 1023 if (use_aes) {
1030 QTC::TC("qpdf", "QPDF_encryption aes decode stream"); 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 } else { 1027 } else {
1038 QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); 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 pipeline = decrypt_pipeline.get(); 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,12 +11,7 @@ class Pl_AES_PDF final: public Pipeline
11 { 11 {
12 public: 12 public:
13 // key should be a pointer to key_bytes bytes of data 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 ~Pl_AES_PDF() final = default; 15 ~Pl_AES_PDF() final = default;
21 16
22 void write(unsigned char const* data, size_t len) final; 17 void write(unsigned char const* data, size_t len) final;
@@ -42,13 +37,12 @@ class Pl_AES_PDF final: public Pipeline @@ -42,13 +37,12 @@ class Pl_AES_PDF final: public Pipeline
42 static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size; 37 static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size;
43 static bool use_static_iv; 38 static bool use_static_iv;
44 39
  40 + std::string key;
45 std::shared_ptr<QPDFCryptoImpl> crypto; 41 std::shared_ptr<QPDFCryptoImpl> crypto;
46 bool encrypt; 42 bool encrypt;
47 bool cbc_mode{true}; 43 bool cbc_mode{true};
48 bool first{true}; 44 bool first{true};
49 size_t offset{0}; // offset into memory buffer 45 size_t offset{0}; // offset into memory buffer
50 - std::unique_ptr<unsigned char[]> key;  
51 - size_t key_bytes{0};  
52 unsigned char inbuf[buf_size]; 46 unsigned char inbuf[buf_size];
53 unsigned char outbuf[buf_size]; 47 unsigned char outbuf[buf_size];
54 unsigned char cbc_block[buf_size]; 48 unsigned char cbc_block[buf_size];
libqpdf/qpdf/Pl_RC4.hh
@@ -12,11 +12,7 @@ class Pl_RC4 final: public Pipeline @@ -12,11 +12,7 @@ class Pl_RC4 final: public Pipeline
12 12
13 // key_len of -1 means treat key_data as a null-terminated string 13 // key_len of -1 means treat key_data as a null-terminated string
14 Pl_RC4( 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 ~Pl_RC4() final = default; 16 ~Pl_RC4() final = default;
21 17
22 void write(unsigned char const* data, size_t len) final; 18 void write(unsigned char const* data, size_t len) final;
libtests/aes.cc
@@ -84,8 +84,9 @@ main(int argc, char* argv[]) @@ -84,8 +84,9 @@ main(int argc, char* argv[])
84 key[i / 2] = static_cast<unsigned char>(val); 84 key[i / 2] = static_cast<unsigned char>(val);
85 } 85 }
86 86
  87 + std::string keystr(reinterpret_cast<char const*>(key), keylen);
87 auto* out = new Pl_StdioFile("stdout", outfile); 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 delete[] key; 90 delete[] key;
90 key = nullptr; 91 key = nullptr;
91 if (!cbc_mode) { 92 if (!cbc_mode) {
libtests/rc4.cc
@@ -58,7 +58,8 @@ main(int argc, char* argv[]) @@ -58,7 +58,8 @@ main(int argc, char* argv[])
58 FILE* outfile = QUtil::safe_fopen(outfilename, "wb"); 58 FILE* outfile = QUtil::safe_fopen(outfilename, "wb");
59 auto* out = new Pl_StdioFile("stdout", outfile); 59 auto* out = new Pl_StdioFile("stdout", outfile);
60 // Use a small buffer size (64) for testing 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 delete[] key; 63 delete[] key;
63 64
64 // 64 < buffer size < 512, buffer_size is not a power of 2 for testing 65 // 64 < buffer size < 512, buffer_size is not a power of 2 for testing