Coverage Report

Created: 2025-06-22 06:27

/src/qpdf/libqpdf/QPDF_encryption.cc
Line
Count
Source (jump to first uncovered line)
1
// This file implements methods from the QPDF class that involve
2
// encryption.
3
4
#include <qpdf/assert_debug.h>
5
6
#include <qpdf/QPDF_private.hh>
7
8
#include <qpdf/QPDFExc.hh>
9
10
#include <qpdf/MD5.hh>
11
#include <qpdf/Pl_AES_PDF.hh>
12
#include <qpdf/Pl_Buffer.hh>
13
#include <qpdf/Pl_RC4.hh>
14
#include <qpdf/Pl_SHA2.hh>
15
#include <qpdf/QTC.hh>
16
#include <qpdf/QUtil.hh>
17
#include <qpdf/RC4.hh>
18
19
#include <algorithm>
20
#include <cstring>
21
22
static unsigned char const padding_string[] = {
23
    0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
24
    0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a};
25
26
static unsigned int const key_bytes = 32;
27
28
// V4 key lengths apply to V <= 4
29
static unsigned int const OU_key_bytes_V4 = sizeof(MD5::Digest);
30
31
static unsigned int const OU_key_bytes_V5 = 48;
32
static unsigned int const OUE_key_bytes_V5 = 32;
33
static unsigned int const Perms_key_bytes_V5 = 16;
34
35
int
36
QPDF::EncryptionData::getV() const
37
3.29k
{
38
3.29k
    return this->V;
39
3.29k
}
40
41
int
42
QPDF::EncryptionData::getR() const
43
5.66k
{
44
5.66k
    return this->R;
45
5.66k
}
46
47
int
48
QPDF::EncryptionData::getLengthBytes() const
49
2.29k
{
50
2.29k
    return this->Length_bytes;
51
2.29k
}
52
53
int
54
QPDF::EncryptionData::getP() const
55
1.09k
{
56
1.09k
    return this->P;
57
1.09k
}
58
59
std::string const&
60
QPDF::EncryptionData::getO() const
61
3.52k
{
62
3.52k
    return this->O;
63
3.52k
}
64
65
std::string const&
66
QPDF::EncryptionData::getU() const
67
4.64k
{
68
4.64k
    return this->U;
69
4.64k
}
70
71
std::string const&
72
QPDF::EncryptionData::getOE() const
73
59
{
74
59
    return this->OE;
75
59
}
76
77
std::string const&
78
QPDF::EncryptionData::getUE() const
79
380
{
80
380
    return this->UE;
81
380
}
82
83
std::string const&
84
QPDF::EncryptionData::getPerms() const
85
439
{
86
439
    return this->Perms;
87
439
}
88
89
std::string const&
90
QPDF::EncryptionData::getId1() const
91
2.18k
{
92
2.18k
    return this->id1;
93
2.18k
}
94
95
bool
96
QPDF::EncryptionData::getEncryptMetadata() const
97
1.06k
{
98
1.06k
    return this->encrypt_metadata;
99
1.06k
}
100
101
void
102
QPDF::EncryptionData::setO(std::string const& O)
103
0
{
104
0
    this->O = O;
105
0
}
106
107
void
108
QPDF::EncryptionData::setU(std::string const& U)
109
0
{
110
0
    this->U = U;
111
0
}
112
113
void
114
QPDF::EncryptionData::setV5EncryptionParameters(
115
    std::string const& O,
116
    std::string const& OE,
117
    std::string const& U,
118
    std::string const& UE,
119
    std::string const& Perms)
120
0
{
121
0
    this->O = O;
122
0
    this->OE = OE;
123
0
    this->U = U;
124
0
    this->UE = UE;
125
0
    this->Perms = Perms;
126
0
}
127
128
static void
129
pad_or_truncate_password_V4(std::string const& password, char k1[key_bytes])
130
1.35k
{
131
1.35k
    size_t password_bytes = std::min(QIntC::to_size(key_bytes), password.length());
132
1.35k
    size_t pad_bytes = key_bytes - password_bytes;
133
1.35k
    memcpy(k1, password.c_str(), password_bytes);
134
1.35k
    memcpy(k1 + password_bytes, padding_string, pad_bytes);
135
1.35k
}
136
137
void
138
QPDF::trim_user_password(std::string& user_password)
139
16
{
140
    // Although unnecessary, this routine trims the padding string from the end of a user password.
141
    // Its only purpose is for recovery of user passwords which is done in the test suite.
142
16
    char const* cstr = user_password.c_str();
143
16
    size_t len = user_password.length();
144
16
    if (len < key_bytes) {
145
0
        return;
146
0
    }
147
148
16
    char const* p1 = cstr;
149
16
    char const* p2 = nullptr;
150
17
    while ((p2 = strchr(p1, '\x28')) != nullptr) {
151
1
        size_t idx = toS(p2 - cstr);
152
1
        if (memcmp(p2, padding_string, len - idx) == 0) {
153
0
            user_password = user_password.substr(0, idx);
154
0
            return;
155
1
        } else {
156
1
            QTC::TC("qpdf", "QPDF_encryption skip 0x28");
157
1
            p1 = p2 + 1;
158
1
        }
159
1
    }
160
16
}
161
162
static std::string
163
pad_or_truncate_password_V4(std::string const& password)
164
1.33k
{
165
1.33k
    char k1[key_bytes];
166
1.33k
    pad_or_truncate_password_V4(password, k1);
167
1.33k
    return {k1, key_bytes};
168
1.33k
}
169
170
static std::string
171
truncate_password_V5(std::string const& password)
172
2.95k
{
173
2.95k
    return password.substr(0, std::min(static_cast<size_t>(127), password.length()));
174
2.95k
}
175
176
static void
177
iterate_md5_digest(MD5& md5, MD5::Digest& digest, int iterations, int key_len)
178
895
{
179
895
    md5.digest(digest);
180
181
43.6k
    for (int i = 0; i < iterations; ++i) {
182
42.7k
        MD5 m;
183
42.7k
        m.encodeDataIncrementally(reinterpret_cast<char*>(digest), QIntC::to_size(key_len));
184
42.7k
        m.digest(digest);
185
42.7k
    }
186
895
}
187
188
static void
189
iterate_rc4(
190
    unsigned char* data,
191
    size_t data_len,
192
    unsigned char* okey,
193
    int key_len,
194
    int iterations,
195
    bool reverse)
196
701
{
197
701
    auto key_ph = std::make_unique<unsigned char[]>(QIntC::to_size(key_len));
198
701
    unsigned char* key = key_ph.get();
199
13.9k
    for (int i = 0; i < iterations; ++i) {
200
13.2k
        int const xor_value = (reverse ? iterations - 1 - i : i);
201
148k
        for (int j = 0; j < key_len; ++j) {
202
134k
            key[j] = static_cast<unsigned char>(okey[j] ^ xor_value);
203
134k
        }
204
13.2k
        RC4 rc4(key, QIntC::to_int(key_len));
205
13.2k
        rc4.process(data, data_len, data);
206
13.2k
    }
207
701
}
208
209
static std::string
210
process_with_aes(
211
    std::string const& key,
212
    bool encrypt,
213
    std::string const& data,
214
    size_t outlength = 0,
215
    unsigned int repetitions = 1,
216
    unsigned char const* iv = nullptr,
217
    size_t iv_length = 0)
218
181k
{
219
181k
    Pl_Buffer buffer("buffer");
220
181k
    Pl_AES_PDF aes(
221
181k
        "aes", &buffer, encrypt, QUtil::unsigned_char_pointer(key), QIntC::to_uint(key.length()));
222
181k
    if (iv) {
223
180k
        aes.setIV(iv, iv_length);
224
180k
    } else {
225
878
        aes.useZeroIV();
226
878
    }
227
181k
    aes.disablePadding();
228
11.7M
    for (unsigned int i = 0; i < repetitions; ++i) {
229
11.5M
        aes.writeString(data);
230
11.5M
    }
231
181k
    aes.finish();
232
181k
    if (outlength == 0) {
233
180k
        return buffer.getString();
234
180k
    } else {
235
439
        return buffer.getString().substr(0, outlength);
236
439
    }
237
181k
}
238
239
static std::string
240
hash_V5(
241
    std::string const& password,
242
    std::string const& salt,
243
    std::string const& udata,
244
    QPDF::EncryptionData const& data)
245
2.95k
{
246
2.95k
    Pl_SHA2 hash(256);
247
2.95k
    hash.writeString(password);
248
2.95k
    hash.writeString(salt);
249
2.95k
    hash.writeString(udata);
250
2.95k
    hash.finish();
251
2.95k
    std::string K = hash.getRawDigest();
252
253
2.95k
    std::string result;
254
2.95k
    if (data.getR() < 6) {
255
340
        result = K;
256
2.61k
    } else {
257
        // Algorithm 2.B from ISO 32000-1 chapter 7: Computing a hash
258
259
2.61k
        int round_number = 0;
260
2.61k
        bool done = false;
261
182k
        while (!done) {
262
            // The hash algorithm has us setting K initially to the R5 value and then repeating a
263
            // series of steps 64 times before starting with the termination case testing.  The
264
            // wording of the specification is very unclear as to the exact number of times it
265
            // should be run since the wording about whether the initial setup counts as round 0 or
266
            // not is ambiguous.  This code counts the initial setup (R5) value as round 0, which
267
            // appears to be correct.  This was determined to be correct by increasing or decreasing
268
            // the number of rounds by 1 or 2 from this value and generating 20 test files.  In this
269
            // interpretation, all the test files worked with Adobe Reader X.  In the other
270
            // configurations, many of the files did not work, and we were accurately able to
271
            // predict which files didn't work by looking at the conditions under which we
272
            // terminated repetition.
273
274
180k
            ++round_number;
275
180k
            std::string K1 = password + K + udata;
276
180k
            qpdf_assert_debug(K.length() >= 32);
277
180k
            std::string E = process_with_aes(
278
180k
                K.substr(0, 16),
279
180k
                true,
280
180k
                K1,
281
180k
                0,
282
180k
                64,
283
180k
                QUtil::unsigned_char_pointer(K.substr(16, 16)),
284
180k
                16);
285
286
            // E_mod_3 is supposed to be mod 3 of the first 16 bytes of E taken as as a (128-bit)
287
            // big-endian number.  Since (xy mod n) is equal to ((x mod n) + (y mod n)) mod n and
288
            // since 256 mod n is 1, we can just take the sums of the the mod 3s of each byte to get
289
            // the same result.
290
180k
            int E_mod_3 = 0;
291
3.06M
            for (unsigned int i = 0; i < 16; ++i) {
292
2.88M
                E_mod_3 += static_cast<unsigned char>(E.at(i));
293
2.88M
            }
294
180k
            E_mod_3 %= 3;
295
180k
            int next_hash = ((E_mod_3 == 0) ? 256 : (E_mod_3 == 1) ? 384 : 512);
296
180k
            Pl_SHA2 sha2(next_hash);
297
180k
            sha2.writeString(E);
298
180k
            sha2.finish();
299
180k
            K = sha2.getRawDigest();
300
301
180k
            if (round_number >= 64) {
302
15.6k
                unsigned int ch = static_cast<unsigned char>(*(E.rbegin()));
303
304
15.6k
                if (ch <= QIntC::to_uint(round_number - 32)) {
305
2.61k
                    done = true;
306
2.61k
                }
307
15.6k
            }
308
180k
        }
309
2.61k
        result = K.substr(0, 32);
310
2.61k
    }
311
312
2.95k
    return result;
313
2.95k
}
314
315
static void
316
pad_short_parameter(std::string& param, size_t max_len)
317
5.45k
{
318
5.45k
    if (param.length() < max_len) {
319
2.19k
        QTC::TC("qpdf", "QPDF_encryption pad short parameter");
320
2.19k
        param.append(max_len - param.length(), '\0');
321
2.19k
    }
322
5.45k
}
323
324
std::string
325
QPDF::compute_data_key(
326
    std::string const& encryption_key,
327
    int objid,
328
    int generation,
329
    bool use_aes,
330
    int encryption_V,
331
    int encryption_R)
332
2.99k
{
333
    // Algorithm 3.1 from the PDF 1.7 Reference Manual
334
335
2.99k
    std::string result = encryption_key;
336
337
2.99k
    if (encryption_V >= 5) {
338
        // Algorithm 3.1a (PDF 1.7 extension level 3): just use encryption key straight.
339
806
        return result;
340
806
    }
341
342
    // Append low three bytes of object ID and low two bytes of generation
343
2.19k
    result.append(1, static_cast<char>(objid & 0xff));
344
2.19k
    result.append(1, static_cast<char>((objid >> 8) & 0xff));
345
2.19k
    result.append(1, static_cast<char>((objid >> 16) & 0xff));
346
2.19k
    result.append(1, static_cast<char>(generation & 0xff));
347
2.19k
    result.append(1, static_cast<char>((generation >> 8) & 0xff));
348
2.19k
    if (use_aes) {
349
361
        result += "sAlT";
350
361
    }
351
352
2.19k
    MD5 md5;
353
2.19k
    md5.encodeDataIncrementally(result.c_str(), result.length());
354
2.19k
    MD5::Digest digest;
355
2.19k
    md5.digest(digest);
356
2.19k
    return {reinterpret_cast<char*>(digest), std::min(result.length(), toS(16))};
357
2.99k
}
358
359
std::string
360
QPDF::compute_encryption_key(std::string const& password, EncryptionData const& data)
361
656
{
362
656
    if (data.getV() >= 5) {
363
        // For V >= 5, the encryption key is generated and stored in the file, encrypted separately
364
        // with both user and owner passwords.
365
0
        return recover_encryption_key_with_password(password, data);
366
656
    } else {
367
        // For V < 5, the encryption key is derived from the user
368
        // password.
369
656
        return compute_encryption_key_from_password(password, data);
370
656
    }
371
656
}
372
373
std::string
374
QPDF::compute_encryption_key_from_password(std::string const& password, EncryptionData const& data)
375
656
{
376
    // Algorithm 3.2 from the PDF 1.7 Reference Manual
377
378
    // This code does not properly handle Unicode passwords. Passwords are supposed to be converted
379
    // from OS codepage characters to PDFDocEncoding.  Unicode passwords are supposed to be
380
    // converted to OS codepage before converting to PDFDocEncoding.  We instead require the
381
    // password to be presented in its final form.
382
383
656
    MD5 md5;
384
656
    md5.encodeDataIncrementally(pad_or_truncate_password_V4(password).c_str(), key_bytes);
385
656
    md5.encodeDataIncrementally(data.getO().c_str(), key_bytes);
386
656
    char pbytes[4];
387
656
    int P = data.getP();
388
656
    pbytes[0] = static_cast<char>(P & 0xff);
389
656
    pbytes[1] = static_cast<char>((P >> 8) & 0xff);
390
656
    pbytes[2] = static_cast<char>((P >> 16) & 0xff);
391
656
    pbytes[3] = static_cast<char>((P >> 24) & 0xff);
392
656
    md5.encodeDataIncrementally(pbytes, 4);
393
656
    md5.encodeDataIncrementally(data.getId1().c_str(), data.getId1().length());
394
656
    if ((data.getR() >= 4) && (!data.getEncryptMetadata())) {
395
2
        char bytes[4];
396
2
        memset(bytes, 0xff, 4);
397
2
        md5.encodeDataIncrementally(bytes, 4);
398
2
    }
399
656
    MD5::Digest digest;
400
656
    int key_len = std::min(toI(sizeof(digest)), data.getLengthBytes());
401
656
    iterate_md5_digest(md5, digest, ((data.getR() >= 3) ? 50 : 0), key_len);
402
656
    return {reinterpret_cast<char*>(digest), toS(key_len)};
403
656
}
404
405
static void
406
compute_O_rc4_key(
407
    std::string const& user_password,
408
    std::string const& owner_password,
409
    QPDF::EncryptionData const& data,
410
    unsigned char key[OU_key_bytes_V4])
411
239
{
412
239
    if (data.getV() >= 5) {
413
0
        throw std::logic_error("compute_O_rc4_key called for file with V >= 5");
414
0
    }
415
239
    std::string password = owner_password;
416
239
    if (password.empty()) {
417
239
        password = user_password;
418
239
    }
419
239
    MD5 md5;
420
239
    md5.encodeDataIncrementally(pad_or_truncate_password_V4(password).c_str(), key_bytes);
421
239
    MD5::Digest digest;
422
239
    int key_len = std::min(QIntC::to_int(sizeof(digest)), data.getLengthBytes());
423
239
    iterate_md5_digest(md5, digest, ((data.getR() >= 3) ? 50 : 0), key_len);
424
239
    memcpy(key, digest, OU_key_bytes_V4);
425
239
}
426
427
static std::string
428
compute_O_value(
429
    std::string const& user_password,
430
    std::string const& owner_password,
431
    QPDF::EncryptionData const& data)
432
0
{
433
    // Algorithm 3.3 from the PDF 1.7 Reference Manual
434
435
0
    unsigned char O_key[OU_key_bytes_V4];
436
0
    compute_O_rc4_key(user_password, owner_password, data, O_key);
437
438
0
    char upass[key_bytes];
439
0
    pad_or_truncate_password_V4(user_password, upass);
440
0
    std::string k1(reinterpret_cast<char*>(O_key), OU_key_bytes_V4);
441
0
    pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
442
0
    iterate_rc4(
443
0
        QUtil::unsigned_char_pointer(upass),
444
0
        key_bytes,
445
0
        O_key,
446
0
        data.getLengthBytes(),
447
0
        (data.getR() >= 3) ? 20 : 1,
448
0
        false);
449
0
    return {upass, key_bytes};
450
0
}
451
452
static std::string
453
compute_U_value_R2(std::string const& user_password, QPDF::EncryptionData const& data)
454
26
{
455
    // Algorithm 3.4 from the PDF 1.7 Reference Manual
456
457
26
    std::string k1 = QPDF::compute_encryption_key(user_password, data);
458
26
    char udata[key_bytes];
459
26
    pad_or_truncate_password_V4("", udata);
460
26
    pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
461
26
    iterate_rc4(
462
26
        QUtil::unsigned_char_pointer(udata),
463
26
        key_bytes,
464
26
        QUtil::unsigned_char_pointer(k1),
465
26
        data.getLengthBytes(),
466
26
        1,
467
26
        false);
468
26
    return {udata, key_bytes};
469
26
}
470
471
static std::string
472
compute_U_value_R3(std::string const& user_password, QPDF::EncryptionData const& data)
473
436
{
474
    // Algorithm 3.5 from the PDF 1.7 Reference Manual
475
476
436
    std::string k1 = QPDF::compute_encryption_key(user_password, data);
477
436
    MD5 md5;
478
436
    md5.encodeDataIncrementally(pad_or_truncate_password_V4("").c_str(), key_bytes);
479
436
    md5.encodeDataIncrementally(data.getId1().c_str(), data.getId1().length());
480
436
    MD5::Digest digest;
481
436
    md5.digest(digest);
482
436
    pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
483
436
    iterate_rc4(
484
436
        digest,
485
436
        sizeof(MD5::Digest),
486
436
        QUtil::unsigned_char_pointer(k1),
487
436
        data.getLengthBytes(),
488
436
        20,
489
436
        false);
490
436
    char result[key_bytes];
491
436
    memcpy(result, digest, sizeof(MD5::Digest));
492
    // pad with arbitrary data -- make it consistent for the sake of
493
    // testing
494
7.41k
    for (unsigned int i = sizeof(MD5::Digest); i < key_bytes; ++i) {
495
6.97k
        result[i] = static_cast<char>((i * i) % 0xff);
496
6.97k
    }
497
436
    return {result, key_bytes};
498
436
}
499
500
static std::string
501
compute_U_value(std::string const& user_password, QPDF::EncryptionData const& data)
502
462
{
503
462
    if (data.getR() >= 3) {
504
436
        return compute_U_value_R3(user_password, data);
505
436
    }
506
507
26
    return compute_U_value_R2(user_password, data);
508
462
}
509
510
static bool
511
check_user_password_V4(std::string const& user_password, QPDF::EncryptionData const& data)
512
462
{
513
    // Algorithm 3.6 from the PDF 1.7 Reference Manual
514
515
462
    std::string u_value = compute_U_value(user_password, data);
516
462
    size_t to_compare = ((data.getR() >= 3) ? sizeof(MD5::Digest) : key_bytes);
517
462
    return (memcmp(data.getU().c_str(), u_value.c_str(), to_compare) == 0);
518
462
}
519
520
static bool
521
check_user_password_V5(std::string const& user_password, QPDF::EncryptionData const& data)
522
1.22k
{
523
    // Algorithm 3.11 from the PDF 1.7 extension level 3
524
525
1.22k
    std::string user_data = data.getU().substr(0, 32);
526
1.22k
    std::string validation_salt = data.getU().substr(32, 8);
527
1.22k
    std::string password = truncate_password_V5(user_password);
528
1.22k
    return (hash_V5(password, validation_salt, "", data) == user_data);
529
1.22k
}
530
531
static bool
532
check_user_password(std::string const& user_password, QPDF::EncryptionData const& data)
533
1.31k
{
534
1.31k
    if (data.getV() < 5) {
535
462
        return check_user_password_V4(user_password, data);
536
848
    } else {
537
848
        return check_user_password_V5(user_password, data);
538
848
    }
539
1.31k
}
540
541
static bool
542
check_owner_password_V4(
543
    std::string& user_password, std::string const& owner_password, QPDF::EncryptionData const& data)
544
239
{
545
    // Algorithm 3.7 from the PDF 1.7 Reference Manual
546
547
239
    unsigned char key[OU_key_bytes_V4];
548
239
    compute_O_rc4_key(user_password, owner_password, data, key);
549
239
    unsigned char O_data[key_bytes];
550
239
    memcpy(O_data, QUtil::unsigned_char_pointer(data.getO()), key_bytes);
551
239
    std::string k1(reinterpret_cast<char*>(key), OU_key_bytes_V4);
552
239
    pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
553
239
    iterate_rc4(
554
239
        O_data,
555
239
        key_bytes,
556
239
        QUtil::unsigned_char_pointer(k1),
557
239
        data.getLengthBytes(),
558
239
        (data.getR() >= 3) ? 20 : 1,
559
239
        true);
560
239
    std::string new_user_password = std::string(reinterpret_cast<char*>(O_data), key_bytes);
561
239
    bool result = false;
562
239
    if (check_user_password(new_user_password, data)) {
563
16
        result = true;
564
16
        user_password = new_user_password;
565
16
    }
566
239
    return result;
567
239
}
568
569
static bool
570
check_owner_password_V5(std::string const& owner_password, QPDF::EncryptionData const& data)
571
1.28k
{
572
    // Algorithm 3.12 from the PDF 1.7 extension level 3
573
574
1.28k
    std::string user_data = data.getU().substr(0, 48);
575
1.28k
    std::string owner_data = data.getO().substr(0, 32);
576
1.28k
    std::string validation_salt = data.getO().substr(32, 8);
577
1.28k
    std::string password = truncate_password_V5(owner_password);
578
1.28k
    return (hash_V5(password, validation_salt, user_data, data) == owner_data);
579
1.28k
}
580
581
static bool
582
check_owner_password(
583
    std::string& user_password, std::string const& owner_password, QPDF::EncryptionData const& data)
584
1.08k
{
585
1.08k
    if (data.getV() < 5) {
586
239
        return check_owner_password_V4(user_password, owner_password, data);
587
848
    } else {
588
848
        return check_owner_password_V5(owner_password, data);
589
848
    }
590
1.08k
}
591
592
std::string
593
QPDF::recover_encryption_key_with_password(std::string const& password, EncryptionData const& data)
594
0
{
595
    // Disregard whether Perms is valid.
596
0
    bool disregard;
597
0
    return recover_encryption_key_with_password(password, data, disregard);
598
0
}
599
600
static void
601
compute_U_UE_value_V5(
602
    std::string const& user_password,
603
    std::string const& encryption_key,
604
    QPDF::EncryptionData const& data,
605
    std::string& U,
606
    std::string& UE)
607
0
{
608
    // Algorithm 3.8 from the PDF 1.7 extension level 3
609
0
    char k[16];
610
0
    QUtil::initializeWithRandomBytes(reinterpret_cast<unsigned char*>(k), sizeof(k));
611
0
    std::string validation_salt(k, 8);
612
0
    std::string key_salt(k + 8, 8);
613
0
    U = hash_V5(user_password, validation_salt, "", data) + validation_salt + key_salt;
614
0
    std::string intermediate_key = hash_V5(user_password, key_salt, "", data);
615
0
    UE = process_with_aes(intermediate_key, true, encryption_key);
616
0
}
617
618
static void
619
compute_O_OE_value_V5(
620
    std::string const& owner_password,
621
    std::string const& encryption_key,
622
    QPDF::EncryptionData const& data,
623
    std::string const& U,
624
    std::string& O,
625
    std::string& OE)
626
0
{
627
    // Algorithm 3.9 from the PDF 1.7 extension level 3
628
0
    char k[16];
629
0
    QUtil::initializeWithRandomBytes(reinterpret_cast<unsigned char*>(k), sizeof(k));
630
0
    std::string validation_salt(k, 8);
631
0
    std::string key_salt(k + 8, 8);
632
0
    O = hash_V5(owner_password, validation_salt, U, data) + validation_salt + key_salt;
633
0
    std::string intermediate_key = hash_V5(owner_password, key_salt, U, data);
634
0
    OE = process_with_aes(intermediate_key, true, encryption_key);
635
0
}
636
637
void
638
compute_Perms_value_V5_clear(
639
    std::string const& encryption_key, QPDF::EncryptionData const& data, unsigned char k[16])
640
439
{
641
    // From algorithm 3.10 from the PDF 1.7 extension level 3
642
439
    unsigned long long extended_perms =
643
439
        0xffffffff00000000LL | static_cast<unsigned long long>(data.getP());
644
3.95k
    for (int i = 0; i < 8; ++i) {
645
3.51k
        k[i] = static_cast<unsigned char>(extended_perms & 0xff);
646
3.51k
        extended_perms >>= 8;
647
3.51k
    }
648
439
    k[8] = data.getEncryptMetadata() ? 'T' : 'F';
649
439
    k[9] = 'a';
650
439
    k[10] = 'd';
651
439
    k[11] = 'b';
652
439
    QUtil::initializeWithRandomBytes(k + 12, 4);
653
439
}
654
655
static std::string
656
compute_Perms_value_V5(std::string const& encryption_key, QPDF::EncryptionData const& data)
657
0
{
658
    // Algorithm 3.10 from the PDF 1.7 extension level 3
659
0
    unsigned char k[16];
660
0
    compute_Perms_value_V5_clear(encryption_key, data, k);
661
0
    return process_with_aes(
662
0
        encryption_key, true, std::string(reinterpret_cast<char*>(k), sizeof(k)));
663
0
}
664
665
std::string
666
QPDF::recover_encryption_key_with_password(
667
    std::string const& password, EncryptionData const& data, bool& perms_valid)
668
439
{
669
    // Algorithm 3.2a from the PDF 1.7 extension level 3
670
671
    // This code does not handle Unicode passwords correctly. Empirical evidence suggests that most
672
    // viewers don't.  We are supposed to process the input string with the SASLprep (RFC 4013)
673
    // profile of stringprep (RFC 3454) and then convert the result to UTF-8.
674
675
439
    perms_valid = false;
676
439
    std::string key_password = truncate_password_V5(password);
677
439
    std::string key_salt;
678
439
    std::string user_data;
679
439
    std::string encrypted_file_key;
680
439
    if (check_owner_password_V5(key_password, data)) {
681
59
        key_salt = data.getO().substr(40, 8);
682
59
        user_data = data.getU().substr(0, 48);
683
59
        encrypted_file_key = data.getOE().substr(0, 32);
684
380
    } else if (check_user_password_V5(key_password, data)) {
685
380
        key_salt = data.getU().substr(40, 8);
686
380
        encrypted_file_key = data.getUE().substr(0, 32);
687
380
    }
688
439
    std::string intermediate_key = hash_V5(key_password, key_salt, user_data, data);
689
439
    std::string file_key = process_with_aes(intermediate_key, false, encrypted_file_key);
690
691
    // Decrypt Perms and check against expected value
692
439
    std::string perms_check = process_with_aes(file_key, false, data.getPerms(), 12);
693
439
    unsigned char k[16];
694
439
    compute_Perms_value_V5_clear(file_key, data, k);
695
439
    perms_valid = (memcmp(perms_check.c_str(), k, 12) == 0);
696
697
439
    return file_key;
698
439
}
699
700
QPDF::encryption_method_e
701
QPDF::interpretCF(std::shared_ptr<EncryptionParameters> encp, QPDFObjectHandle cf)
702
1.90k
{
703
1.90k
    if (cf.isName()) {
704
1.31k
        std::string filter = cf.getName();
705
1.31k
        auto it = encp->crypt_filters.find(filter);
706
1.31k
        if (it != encp->crypt_filters.end()) {
707
500
            return it->second;
708
500
        }
709
819
        if (filter == "/Identity") {
710
2
            return e_none;
711
2
        }
712
817
        return e_unknown;
713
819
    }
714
    // Default: /Identity
715
585
    return e_none;
716
1.90k
}
717
718
void
719
QPDF::initializeEncryption()
720
2.89k
{
721
2.89k
    if (m->encp->encryption_initialized) {
722
6
        return;
723
6
    }
724
2.88k
    m->encp->encryption_initialized = true;
725
726
    // After we initialize encryption parameters, we must use stored key information and never look
727
    // at /Encrypt again.  Otherwise, things could go wrong if someone mutates the encryption
728
    // dictionary.
729
730
2.88k
    if (!m->trailer.hasKey("/Encrypt")) {
731
1.69k
        return;
732
1.69k
    }
733
734
    // Go ahead and set m->encrypted here.  That way, isEncrypted will return true even if there
735
    // were errors reading the encryption dictionary.
736
1.19k
    m->encp->encrypted = true;
737
738
1.19k
    std::string id1;
739
1.19k
    QPDFObjectHandle id_obj = m->trailer.getKey("/ID");
740
1.19k
    if ((id_obj.isArray() && (id_obj.getArrayNItems() == 2) && id_obj.getArrayItem(0).isString())) {
741
296
        id1 = id_obj.getArrayItem(0).getStringValue();
742
899
    } else {
743
        // Treating a missing ID as the empty string enables qpdf to decrypt some invalid encrypted
744
        // files with no /ID that poppler can read but Adobe Reader can't.
745
899
        warn(damagedPDF("trailer", "invalid /ID in trailer dictionary"));
746
899
    }
747
748
1.19k
    QPDFObjectHandle encryption_dict = m->trailer.getKey("/Encrypt");
749
1.19k
    if (!encryption_dict.isDictionary()) {
750
4
        throw damagedPDF("/Encrypt in trailer dictionary is not a dictionary");
751
4
    }
752
753
1.19k
    if (!(encryption_dict.getKey("/Filter").isName() &&
754
1.19k
          (encryption_dict.getKey("/Filter").getName() == "/Standard"))) {
755
11
        throw QPDFExc(
756
11
            qpdf_e_unsupported,
757
11
            m->file->getName(),
758
11
            "encryption dictionary",
759
11
            m->file->getLastOffset(),
760
11
            "unsupported encryption filter");
761
11
    }
762
1.18k
    if (!encryption_dict.getKey("/SubFilter").isNull()) {
763
1
        warn(
764
1
            qpdf_e_unsupported,
765
1
            "encryption dictionary",
766
1
            m->file->getLastOffset(),
767
1
            "file uses encryption SubFilters, which qpdf does not support");
768
1
    }
769
770
1.18k
    if (!(encryption_dict.getKey("/V").isInteger() && encryption_dict.getKey("/R").isInteger() &&
771
1.18k
          encryption_dict.getKey("/O").isString() && encryption_dict.getKey("/U").isString() &&
772
1.18k
          encryption_dict.getKey("/P").isInteger())) {
773
8
        throw damagedPDF(
774
8
            "encryption dictionary",
775
8
            "some encryption dictionary parameters are missing or the wrong "
776
8
            "type");
777
8
    }
778
779
1.17k
    int V = encryption_dict.getKey("/V").getIntValueAsInt();
780
1.17k
    int R = encryption_dict.getKey("/R").getIntValueAsInt();
781
1.17k
    std::string O = encryption_dict.getKey("/O").getStringValue();
782
1.17k
    std::string U = encryption_dict.getKey("/U").getStringValue();
783
1.17k
    int P = static_cast<int>(encryption_dict.getKey("/P").getIntValue());
784
785
    // If supporting new encryption R/V values, remember to update error message inside this if
786
    // statement.
787
1.17k
    if (!(((R >= 2) && (R <= 6)) && ((V == 1) || (V == 2) || (V == 4) || (V == 5)))) {
788
63
        throw QPDFExc(
789
63
            qpdf_e_unsupported,
790
63
            m->file->getName(),
791
63
            "encryption dictionary",
792
63
            m->file->getLastOffset(),
793
63
            "Unsupported /R or /V in encryption dictionary; R = " + std::to_string(R) +
794
63
                " (max 6), V = " + std::to_string(V) + " (max 5)");
795
63
    }
796
797
1.10k
    m->encp->encryption_V = V;
798
1.10k
    m->encp->encryption_R = R;
799
800
    // OE, UE, and Perms are only present if V >= 5.
801
1.10k
    std::string OE;
802
1.10k
    std::string UE;
803
1.10k
    std::string Perms;
804
805
1.10k
    if (V < 5) {
806
        // These must be exactly the right number of bytes.
807
251
        pad_short_parameter(O, key_bytes);
808
251
        pad_short_parameter(U, key_bytes);
809
251
        if (!((O.length() == key_bytes) && (U.length() == key_bytes))) {
810
12
            throw damagedPDF(
811
12
                "encryption dictionary",
812
12
                "incorrect length for /O and/or /U in encryption dictionary");
813
12
        }
814
858
    } else {
815
858
        if (!(encryption_dict.getKey("/OE").isString() &&
816
858
              encryption_dict.getKey("/UE").isString() &&
817
858
              encryption_dict.getKey("/Perms").isString())) {
818
4
            throw damagedPDF(
819
4
                "encryption dictionary",
820
4
                "some V=5 encryption dictionary parameters are missing or the "
821
4
                "wrong type");
822
4
        }
823
854
        OE = encryption_dict.getKey("/OE").getStringValue();
824
854
        UE = encryption_dict.getKey("/UE").getStringValue();
825
854
        Perms = encryption_dict.getKey("/Perms").getStringValue();
826
827
        // These may be longer than the minimum number of bytes.
828
854
        pad_short_parameter(O, OU_key_bytes_V5);
829
854
        pad_short_parameter(U, OU_key_bytes_V5);
830
854
        pad_short_parameter(OE, OUE_key_bytes_V5);
831
854
        pad_short_parameter(UE, OUE_key_bytes_V5);
832
854
        pad_short_parameter(Perms, Perms_key_bytes_V5);
833
854
    }
834
835
1.09k
    int Length = 0;
836
1.09k
    if (V <= 1) {
837
119
        Length = 40;
838
974
    } else if (V == 4) {
839
81
        Length = 128;
840
893
    } else if (V == 5) {
841
850
        Length = 256;
842
850
    } else {
843
43
        if (encryption_dict.getKey("/Length").isInteger()) {
844
17
            Length = encryption_dict.getKey("/Length").getIntValueAsInt();
845
17
            if ((Length % 8) || (Length < 40) || (Length > 128)) {
846
12
                Length = 0;
847
12
            }
848
17
        }
849
43
    }
850
1.09k
    if (Length == 0) {
851
        // Still no Length? Just take a guess.
852
34
        Length = 128;
853
34
    }
854
855
1.09k
    m->encp->encrypt_metadata = true;
856
1.09k
    if ((V >= 4) && (encryption_dict.getKey("/EncryptMetadata").isBool())) {
857
1
        m->encp->encrypt_metadata = encryption_dict.getKey("/EncryptMetadata").getBoolValue();
858
1
    }
859
860
1.09k
    if ((V == 4) || (V == 5)) {
861
931
        QPDFObjectHandle CF = encryption_dict.getKey("/CF");
862
6.09k
        for (auto const& filter: CF.getKeys()) {
863
6.09k
            QPDFObjectHandle cdict = CF.getKey(filter);
864
6.09k
            if (cdict.isDictionary()) {
865
2.73k
                encryption_method_e method = e_none;
866
2.73k
                if (cdict.getKey("/CFM").isName()) {
867
1.99k
                    std::string method_name = cdict.getKey("/CFM").getName();
868
1.99k
                    if (method_name == "/V2") {
869
107
                        QTC::TC("qpdf", "QPDF_encryption CFM V2");
870
107
                        method = e_rc4;
871
1.89k
                    } else if (method_name == "/AESV2") {
872
177
                        QTC::TC("qpdf", "QPDF_encryption CFM AESV2");
873
177
                        method = e_aes;
874
1.71k
                    } else if (method_name == "/AESV3") {
875
240
                        QTC::TC("qpdf", "QPDF_encryption CFM AESV3");
876
240
                        method = e_aesv3;
877
1.47k
                    } else {
878
                        // Don't complain now -- maybe we won't need to reference this type.
879
1.47k
                        method = e_unknown;
880
1.47k
                    }
881
1.99k
                }
882
2.73k
                m->encp->crypt_filters[filter] = method;
883
2.73k
            }
884
6.09k
        }
885
886
931
        QPDFObjectHandle StmF = encryption_dict.getKey("/StmF");
887
931
        QPDFObjectHandle StrF = encryption_dict.getKey("/StrF");
888
931
        QPDFObjectHandle EFF = encryption_dict.getKey("/EFF");
889
931
        m->encp->cf_stream = interpretCF(m->encp, StmF);
890
931
        m->encp->cf_string = interpretCF(m->encp, StrF);
891
931
        if (EFF.isName()) {
892
            // qpdf does not use this for anything other than informational purposes. This is
893
            // intended to instruct conforming writers on which crypt filter should be used when new
894
            // file attachments are added to a PDF file, but qpdf never generates encrypted files
895
            // with non-default crypt filters. Prior to 10.2, I was under the mistaken impression
896
            // that this was supposed to be used for decrypting attachments, but the code was wrong
897
            // in a way that turns out not to have mattered because no writers were generating files
898
            // the way I was imagining. Still, providing this information could be useful when
899
            // looking at a file generated by something else, such as Acrobat when specifying that
900
            // only attachments should be encrypted.
901
46
            m->encp->cf_file = interpretCF(m->encp, EFF);
902
885
        } else {
903
885
            m->encp->cf_file = m->encp->cf_stream;
904
885
        }
905
931
    }
906
907
1.09k
    EncryptionData data(V, R, Length / 8, P, O, U, OE, UE, Perms, id1, m->encp->encrypt_metadata);
908
1.09k
    if (m->provided_password_is_hex_key) {
909
        // ignore passwords in file
910
1.09k
    } else {
911
1.09k
        m->encp->owner_password_matched =
912
1.09k
            check_owner_password(m->encp->user_password, m->encp->provided_password, data);
913
1.09k
        if (m->encp->owner_password_matched && (V < 5)) {
914
            // password supplied was owner password; user_password has been initialized for V < 5
915
16
            if (getTrimmedUserPassword() == m->encp->provided_password) {
916
0
                m->encp->user_password_matched = true;
917
0
                QTC::TC("qpdf", "QPDF_encryption user matches owner V < 5");
918
0
            }
919
1.07k
        } else {
920
1.07k
            m->encp->user_password_matched = check_user_password(m->encp->provided_password, data);
921
1.07k
            if (m->encp->user_password_matched) {
922
563
                m->encp->user_password = m->encp->provided_password;
923
563
            }
924
1.07k
        }
925
1.09k
        if (m->encp->user_password_matched && m->encp->owner_password_matched) {
926
5
            QTC::TC("qpdf", "QPDF_encryption same password", (V < 5) ? 0 : 1);
927
5
        }
928
1.09k
        if (!(m->encp->owner_password_matched || m->encp->user_password_matched)) {
929
454
            throw QPDFExc(qpdf_e_password, m->file->getName(), "", 0, "invalid password");
930
454
        }
931
1.09k
    }
932
933
639
    if (m->provided_password_is_hex_key) {
934
0
        m->encp->encryption_key = QUtil::hex_decode(m->encp->provided_password);
935
639
    } else if (V < 5) {
936
        // For V < 5, the user password is encrypted with the owner password, and the user password
937
        // is always used for computing the encryption key.
938
194
        m->encp->encryption_key = compute_encryption_key(m->encp->user_password, data);
939
445
    } else {
940
        // For V >= 5, either password can be used independently to compute the encryption key, and
941
        // neither password can be used to recover the other.
942
445
        bool perms_valid;
943
445
        m->encp->encryption_key =
944
445
            recover_encryption_key_with_password(m->encp->provided_password, data, perms_valid);
945
445
        if (!perms_valid) {
946
407
            warn(damagedPDF(
947
407
                "encryption dictionary",
948
407
                "/Perms field in encryption dictionary doesn't match expected "
949
407
                "value"));
950
407
        }
951
445
    }
952
639
}
953
954
std::string
955
QPDF::getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen og, bool use_aes)
956
35.5k
{
957
35.5k
    if (!encp->encrypted) {
958
0
        throw std::logic_error("request for encryption key in non-encrypted PDF");
959
0
    }
960
961
35.5k
    if (og != encp->cached_key_og) {
962
2.99k
        encp->cached_object_encryption_key = compute_data_key(
963
2.99k
            encp->encryption_key,
964
2.99k
            og.getObj(),
965
2.99k
            og.getGen(),
966
2.99k
            use_aes,
967
2.99k
            encp->encryption_V,
968
2.99k
            encp->encryption_R);
969
2.99k
        encp->cached_key_og = og;
970
2.99k
    }
971
972
35.5k
    return encp->cached_object_encryption_key;
973
35.5k
}
974
975
void
976
QPDF::decryptString(std::string& str, QPDFObjGen og)
977
36.5k
{
978
36.5k
    if (!og.isIndirect()) {
979
0
        return;
980
0
    }
981
36.5k
    bool use_aes = false;
982
36.5k
    if (m->encp->encryption_V >= 4) {
983
13.9k
        switch (m->encp->cf_string) {
984
1.25k
        case e_none:
985
1.25k
            return;
986
987
11.5k
        case e_aes:
988
11.5k
            use_aes = true;
989
11.5k
            break;
990
991
611
        case e_aesv3:
992
611
            use_aes = true;
993
611
            break;
994
995
461
        case e_rc4:
996
461
            break;
997
998
127
        default:
999
127
            warn(damagedPDF(
1000
127
                "unknown encryption filter for strings (check /StrF in "
1001
127
                "/Encrypt dictionary); strings may be decrypted improperly"));
1002
            // To avoid repeated warnings, reset cf_string.  Assume we'd want to use AES if V == 4.
1003
127
            m->encp->cf_string = e_aes;
1004
127
            use_aes = true;
1005
127
            break;
1006
13.9k
        }
1007
13.9k
    }
1008
1009
35.3k
    std::string key = getKeyForObject(m->encp, og, use_aes);
1010
35.3k
    try {
1011
35.3k
        if (use_aes) {
1012
12.2k
            QTC::TC("qpdf", "QPDF_encryption aes decode string");
1013
12.2k
            Pl_Buffer bufpl("decrypted string");
1014
12.2k
            Pl_AES_PDF pl(
1015
12.2k
                "aes decrypt string",
1016
12.2k
                &bufpl,
1017
12.2k
                false,
1018
12.2k
                QUtil::unsigned_char_pointer(key),
1019
12.2k
                key.length());
1020
12.2k
            pl.writeString(str);
1021
12.2k
            pl.finish();
1022
12.2k
            str = bufpl.getString();
1023
23.0k
        } else {
1024
23.0k
            QTC::TC("qpdf", "QPDF_encryption rc4 decode string");
1025
23.0k
            size_t vlen = str.length();
1026
            // Using std::shared_ptr guarantees that tmp will be freed even if rc4.process throws an
1027
            // exception.
1028
23.0k
            auto tmp = QUtil::make_unique_cstr(str);
1029
23.0k
            RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
1030
23.0k
            auto data = QUtil::unsigned_char_pointer(tmp.get());
1031
23.0k
            rc4.process(data, vlen, data);
1032
23.0k
            str = std::string(tmp.get(), vlen);
1033
23.0k
        }
1034
35.3k
    } catch (QPDFExc&) {
1035
0
        throw;
1036
0
    } catch (std::runtime_error& e) {
1037
0
        throw damagedPDF("error decrypting string for object " + og.unparse() + ": " + e.what());
1038
0
    }
1039
35.3k
}
1040
1041
// Prepend a decryption pipeline to 'pipeline'. The decryption pipeline (returned as
1042
// 'decrypt_pipeline' must be owned by the caller to ensure that it stays alive while the pipeline
1043
// is in use.
1044
void
1045
QPDF::decryptStream(
1046
    std::shared_ptr<EncryptionParameters> encp,
1047
    std::shared_ptr<InputSource> file,
1048
    QPDF& qpdf_for_warning,
1049
    Pipeline*& pipeline,
1050
    QPDFObjGen og,
1051
    QPDFObjectHandle& stream_dict,
1052
    bool is_root_metadata,
1053
    std::unique_ptr<Pipeline>& decrypt_pipeline)
1054
259
{
1055
259
    std::string type;
1056
259
    if (stream_dict.getKey("/Type").isName()) {
1057
228
        type = stream_dict.getKey("/Type").getName();
1058
228
    }
1059
259
    if (type == "/XRef") {
1060
1
        QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file");
1061
1
        return;
1062
1
    }
1063
258
    bool use_aes = false;
1064
258
    if (encp->encryption_V >= 4) {
1065
256
        encryption_method_e method = e_unknown;
1066
256
        std::string method_source = "/StmF from /Encrypt dictionary";
1067
1068
256
        if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) {
1069
3
            if (stream_dict.getKey("/DecodeParms").isDictionary()) {
1070
0
                QPDFObjectHandle decode_parms = stream_dict.getKey("/DecodeParms");
1071
0
                if (decode_parms.isDictionaryOfType("/CryptFilterDecodeParms")) {
1072
0
                    QTC::TC("qpdf", "QPDF_encryption stream crypt filter");
1073
0
                    method = interpretCF(encp, decode_parms.getKey("/Name"));
1074
0
                    method_source = "stream's Crypt decode parameters";
1075
0
                }
1076
3
            } else if (
1077
3
                stream_dict.getKey("/DecodeParms").isArray() &&
1078
3
                stream_dict.getKey("/Filter").isArray()) {
1079
0
                QPDFObjectHandle filter = stream_dict.getKey("/Filter");
1080
0
                QPDFObjectHandle decode = stream_dict.getKey("/DecodeParms");
1081
0
                if (filter.getArrayNItems() == decode.getArrayNItems()) {
1082
0
                    for (int i = 0; i < filter.getArrayNItems(); ++i) {
1083
0
                        if (filter.getArrayItem(i).isNameAndEquals("/Crypt")) {
1084
0
                            QPDFObjectHandle crypt_params = decode.getArrayItem(i);
1085
0
                            if (crypt_params.isDictionary() &&
1086
0
                                crypt_params.getKey("/Name").isName()) {
1087
0
                                QTC::TC("qpdf", "QPDF_encrypt crypt array");
1088
0
                                method = interpretCF(encp, crypt_params.getKey("/Name"));
1089
0
                                method_source = "stream's Crypt decode parameters (array)";
1090
0
                            }
1091
0
                        }
1092
0
                    }
1093
0
                }
1094
0
            }
1095
3
        }
1096
1097
256
        if (method == e_unknown) {
1098
256
            if ((!encp->encrypt_metadata) && is_root_metadata) {
1099
0
                QTC::TC("qpdf", "QPDF_encryption cleartext metadata");
1100
0
                method = e_none;
1101
256
            } else {
1102
256
                method = encp->cf_stream;
1103
256
            }
1104
256
        }
1105
256
        use_aes = false;
1106
256
        switch (method) {
1107
46
        case e_none:
1108
46
            return;
1109
0
            break;
1110
1111
21
        case e_aes:
1112
21
            use_aes = true;
1113
21
            break;
1114
1115
45
        case e_aesv3:
1116
45
            use_aes = true;
1117
45
            break;
1118
1119
71
        case e_rc4:
1120
71
            break;
1121
1122
73
        default:
1123
            // filter local to this stream.
1124
73
            qpdf_for_warning.warn(QPDFExc(
1125
73
                qpdf_e_damaged_pdf,
1126
73
                file->getName(),
1127
73
                "",
1128
73
                file->getLastOffset(),
1129
73
                "unknown encryption filter for streams (check " + method_source +
1130
73
                    "); streams may be decrypted improperly"));
1131
            // To avoid repeated warnings, reset cf_stream.  Assume we'd want to use AES if V == 4.
1132
73
            encp->cf_stream = e_aes;
1133
73
            use_aes = true;
1134
73
            break;
1135
256
        }
1136
256
    }
1137
211
    std::string key = getKeyForObject(encp, og, use_aes);
1138
211
    if (use_aes) {
1139
138
        QTC::TC("qpdf", "QPDF_encryption aes decode stream");
1140
138
        decrypt_pipeline = std::make_unique<Pl_AES_PDF>(
1141
138
            "AES stream decryption",
1142
138
            pipeline,
1143
138
            false,
1144
138
            QUtil::unsigned_char_pointer(key),
1145
138
            key.length());
1146
138
    } else {
1147
73
        QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
1148
73
        decrypt_pipeline = std::make_unique<Pl_RC4>(
1149
73
            "RC4 stream decryption",
1150
73
            pipeline,
1151
73
            QUtil::unsigned_char_pointer(key),
1152
73
            toI(key.length()));
1153
73
    }
1154
211
    pipeline = decrypt_pipeline.get();
1155
211
}
1156
1157
void
1158
QPDF::compute_encryption_O_U(
1159
    char const* user_password,
1160
    char const* owner_password,
1161
    int V,
1162
    int R,
1163
    int key_len,
1164
    int P,
1165
    bool encrypt_metadata,
1166
    std::string const& id1,
1167
    std::string& O,
1168
    std::string& U)
1169
0
{
1170
0
    if (V >= 5) {
1171
0
        throw std::logic_error("compute_encryption_O_U called for file with V >= 5");
1172
0
    }
1173
0
    EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata);
1174
0
    data.setO(compute_O_value(user_password, owner_password, data));
1175
0
    O = data.getO();
1176
0
    data.setU(compute_U_value(user_password, data));
1177
0
    U = data.getU();
1178
0
}
1179
1180
void
1181
QPDF::compute_encryption_parameters_V5(
1182
    char const* user_password,
1183
    char const* owner_password,
1184
    int V,
1185
    int R,
1186
    int key_len,
1187
    int P,
1188
    bool encrypt_metadata,
1189
    std::string const& id1,
1190
    std::string& encryption_key,
1191
    std::string& O,
1192
    std::string& U,
1193
    std::string& OE,
1194
    std::string& UE,
1195
    std::string& Perms)
1196
0
{
1197
0
    EncryptionData data(V, R, key_len, P, "", "", "", "", "", id1, encrypt_metadata);
1198
0
    unsigned char k[key_bytes];
1199
0
    QUtil::initializeWithRandomBytes(k, key_bytes);
1200
0
    encryption_key = std::string(reinterpret_cast<char*>(k), key_bytes);
1201
0
    compute_U_UE_value_V5(user_password, encryption_key, data, U, UE);
1202
0
    compute_O_OE_value_V5(owner_password, encryption_key, data, U, O, OE);
1203
0
    Perms = compute_Perms_value_V5(encryption_key, data);
1204
0
    data.setV5EncryptionParameters(O, OE, U, UE, Perms);
1205
0
}
1206
1207
std::string const&
1208
QPDF::getPaddedUserPassword() const
1209
0
{
1210
0
    return m->encp->user_password;
1211
0
}
1212
1213
std::string
1214
QPDF::getTrimmedUserPassword() const
1215
16
{
1216
16
    std::string result = m->encp->user_password;
1217
16
    trim_user_password(result);
1218
16
    return result;
1219
16
}
1220
1221
std::string
1222
QPDF::getEncryptionKey() const
1223
0
{
1224
0
    return m->encp->encryption_key;
1225
0
}
1226
1227
bool
1228
QPDF::isEncrypted() const
1229
0
{
1230
0
    return m->encp->encrypted;
1231
0
}
1232
1233
bool
1234
QPDF::isEncrypted(int& R, int& P)
1235
0
{
1236
0
    int V;
1237
0
    encryption_method_e stream, string, file;
1238
0
    return isEncrypted(R, P, V, stream, string, file);
1239
0
}
1240
1241
bool
1242
QPDF::isEncrypted(
1243
    int& R,
1244
    int& P,
1245
    int& V,
1246
    encryption_method_e& stream_method,
1247
    encryption_method_e& string_method,
1248
    encryption_method_e& file_method)
1249
0
{
1250
0
    if (m->encp->encrypted) {
1251
0
        QPDFObjectHandle trailer = getTrailer();
1252
0
        QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
1253
0
        QPDFObjectHandle Pkey = encrypt.getKey("/P");
1254
0
        QPDFObjectHandle Rkey = encrypt.getKey("/R");
1255
0
        QPDFObjectHandle Vkey = encrypt.getKey("/V");
1256
0
        P = static_cast<int>(Pkey.getIntValue());
1257
0
        R = Rkey.getIntValueAsInt();
1258
0
        V = Vkey.getIntValueAsInt();
1259
0
        stream_method = m->encp->cf_stream;
1260
0
        string_method = m->encp->cf_string;
1261
0
        file_method = m->encp->cf_file;
1262
0
        return true;
1263
0
    } else {
1264
0
        return false;
1265
0
    }
1266
0
}
1267
1268
bool
1269
QPDF::ownerPasswordMatched() const
1270
0
{
1271
0
    return m->encp->owner_password_matched;
1272
0
}
1273
1274
bool
1275
QPDF::userPasswordMatched() const
1276
0
{
1277
0
    return m->encp->user_password_matched;
1278
0
}
1279
1280
static bool
1281
is_bit_set(int P, int bit)
1282
0
{
1283
    // Bits in P are numbered from 1 in the spec
1284
0
    return ((P & (1 << (bit - 1))) != 0);
1285
0
}
1286
1287
bool
1288
QPDF::allowAccessibility()
1289
0
{
1290
0
    int R = 0;
1291
0
    int P = 0;
1292
0
    bool status = true;
1293
0
    if (isEncrypted(R, P)) {
1294
0
        if (R < 3) {
1295
0
            status = is_bit_set(P, 5);
1296
0
        } else {
1297
0
            status = is_bit_set(P, 10);
1298
0
        }
1299
0
    }
1300
0
    return status;
1301
0
}
1302
1303
bool
1304
QPDF::allowExtractAll()
1305
0
{
1306
0
    int R = 0;
1307
0
    int P = 0;
1308
0
    bool status = true;
1309
0
    if (isEncrypted(R, P)) {
1310
0
        status = is_bit_set(P, 5);
1311
0
    }
1312
0
    return status;
1313
0
}
1314
1315
bool
1316
QPDF::allowPrintLowRes()
1317
0
{
1318
0
    int R = 0;
1319
0
    int P = 0;
1320
0
    bool status = true;
1321
0
    if (isEncrypted(R, P)) {
1322
0
        status = is_bit_set(P, 3);
1323
0
    }
1324
0
    return status;
1325
0
}
1326
1327
bool
1328
QPDF::allowPrintHighRes()
1329
0
{
1330
0
    int R = 0;
1331
0
    int P = 0;
1332
0
    bool status = true;
1333
0
    if (isEncrypted(R, P)) {
1334
0
        status = is_bit_set(P, 3);
1335
0
        if ((R >= 3) && (!is_bit_set(P, 12))) {
1336
0
            status = false;
1337
0
        }
1338
0
    }
1339
0
    return status;
1340
0
}
1341
1342
bool
1343
QPDF::allowModifyAssembly()
1344
0
{
1345
0
    int R = 0;
1346
0
    int P = 0;
1347
0
    bool status = true;
1348
0
    if (isEncrypted(R, P)) {
1349
0
        if (R < 3) {
1350
0
            status = is_bit_set(P, 4);
1351
0
        } else {
1352
0
            status = is_bit_set(P, 11);
1353
0
        }
1354
0
    }
1355
0
    return status;
1356
0
}
1357
1358
bool
1359
QPDF::allowModifyForm()
1360
0
{
1361
0
    int R = 0;
1362
0
    int P = 0;
1363
0
    bool status = true;
1364
0
    if (isEncrypted(R, P)) {
1365
0
        if (R < 3) {
1366
0
            status = is_bit_set(P, 6);
1367
0
        } else {
1368
0
            status = is_bit_set(P, 9);
1369
0
        }
1370
0
    }
1371
0
    return status;
1372
0
}
1373
1374
bool
1375
QPDF::allowModifyAnnotation()
1376
0
{
1377
0
    int R = 0;
1378
0
    int P = 0;
1379
0
    bool status = true;
1380
0
    if (isEncrypted(R, P)) {
1381
0
        status = is_bit_set(P, 6);
1382
0
    }
1383
0
    return status;
1384
0
}
1385
1386
bool
1387
QPDF::allowModifyOther()
1388
0
{
1389
0
    int R = 0;
1390
0
    int P = 0;
1391
0
    bool status = true;
1392
0
    if (isEncrypted(R, P)) {
1393
0
        status = is_bit_set(P, 4);
1394
0
    }
1395
0
    return status;
1396
0
}
1397
1398
bool
1399
QPDF::allowModifyAll()
1400
0
{
1401
0
    int R = 0;
1402
0
    int P = 0;
1403
0
    bool status = true;
1404
0
    if (isEncrypted(R, P)) {
1405
0
        status = (is_bit_set(P, 4) && is_bit_set(P, 6));
1406
0
        if (R >= 3) {
1407
0
            status = status && (is_bit_set(P, 9) && is_bit_set(P, 11));
1408
0
        }
1409
0
    }
1410
0
    return status;
1411
0
}