Coverage Report

Created: 2025-09-05 06:52

/src/serenity/Userland/Libraries/LibPDF/Encryption.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2022, Matthew Olsson <mattco@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Span.h>
10
#include <LibPDF/ObjectDerivatives.h>
11
12
namespace Crypto::Cipher {
13
enum class Intent;
14
}
15
16
namespace PDF {
17
18
enum class CryptFilterMethod {
19
    None,
20
    V2, // RC4
21
    AESV2,
22
    AESV3,
23
};
24
25
class SecurityHandler : public RefCounted<SecurityHandler> {
26
public:
27
    static PDFErrorOr<NonnullRefPtr<SecurityHandler>> create(Document*, NonnullRefPtr<DictObject> encryption_dict);
28
29
0
    virtual ~SecurityHandler() = default;
30
31
    virtual bool try_provide_user_password(StringView password) = 0;
32
    virtual bool has_user_password() const = 0;
33
34
    virtual void encrypt(NonnullRefPtr<Object>, Reference reference) const = 0;
35
    virtual void decrypt(NonnullRefPtr<Object>, Reference reference) const = 0;
36
};
37
38
class StandardSecurityHandler : public SecurityHandler {
39
public:
40
    static PDFErrorOr<NonnullRefPtr<StandardSecurityHandler>> create(Document*, NonnullRefPtr<DictObject> encryption_dict);
41
42
    StandardSecurityHandler(Document*, size_t revision, ByteString const& o_entry, ByteString const& oe_entry, ByteString const& u_entry, ByteString const& ue_entry, ByteString const& perms, u32 flags, bool encrypt_metadata, size_t length, CryptFilterMethod method);
43
44
0
    ~StandardSecurityHandler() override = default;
45
46
    bool try_provide_user_password(StringView password_string) override;
47
48
0
    bool has_user_password() const override { return m_encryption_key.has_value(); }
49
50
protected:
51
    void encrypt(NonnullRefPtr<Object>, Reference reference) const override;
52
    void decrypt(NonnullRefPtr<Object>, Reference reference) const override;
53
54
private:
55
    void crypt(NonnullRefPtr<Object>, Reference reference, Crypto::Cipher::Intent) const;
56
57
    ByteBuffer compute_user_password_value_r2(ByteBuffer password_string);
58
    ByteBuffer compute_user_password_value_r3_to_r5(ByteBuffer password_string);
59
60
    bool authenticate_user_password_r2_to_r5(StringView password_string);
61
    bool authenticate_user_password_r6_and_later(StringView password_string);
62
    bool authenticate_owner_password_r6_and_later(StringView password_string);
63
64
    ByteBuffer compute_encryption_key_r2_to_r5(ByteBuffer password_string);
65
    bool compute_encryption_key_r6_and_later(ByteBuffer password_string);
66
67
    enum class HashKind {
68
        Owner,
69
        User,
70
    };
71
    ByteBuffer computing_a_hash_r6_and_later(ByteBuffer input, StringView input_password, HashKind);
72
73
    Document* m_document;
74
    size_t m_revision;
75
    Optional<ByteBuffer> m_encryption_key;
76
    ByteString m_o_entry;
77
    ByteString m_oe_entry;
78
    ByteString m_u_entry;
79
    ByteString m_ue_entry;
80
    ByteString m_perms_entry;
81
    u32 m_flags;
82
    bool m_encrypt_metadata;
83
    size_t m_length;
84
    CryptFilterMethod m_method;
85
};
86
87
class RC4 {
88
public:
89
    RC4(ReadonlyBytes key);
90
91
    void generate_bytes(ByteBuffer&);
92
    ByteBuffer encrypt(ReadonlyBytes bytes);
93
94
private:
95
    Array<size_t, 256> m_bytes;
96
};
97
98
}