1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 07:45:07 +00:00
serenity/Userland/Libraries/LibPDF/Encryption.h
Nico Weber 281e3158c0 LibPDF: Some preparatory work for AESV3
This detects AESV3, and copies over the spec comments explaining what
needs to be done, but doesn't actually do it yet.

AESV3 is technically PDF 2.0-only, but
https://cipa.jp/std/documents/download_e.html?CIPA_DC-007-2021_E has a
1.7 PDF that uses it.

Previously we'd claim that we need a password to decrypt it.
Now, we cleanly crash with a TODO() \o/
2023-07-14 06:34:03 +02:00

89 lines
2.6 KiB
C++

/*
* Copyright (c) 2022, Matthew Olsson <mattco@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Span.h>
#include <LibPDF/ObjectDerivatives.h>
namespace Crypto::Cipher {
enum class Intent;
}
namespace PDF {
enum class CryptFilterMethod {
None,
V2, // RC4
AESV2,
AESV3,
};
class SecurityHandler : public RefCounted<SecurityHandler> {
public:
static PDFErrorOr<NonnullRefPtr<SecurityHandler>> create(Document*, NonnullRefPtr<DictObject> encryption_dict);
virtual ~SecurityHandler() = default;
virtual bool try_provide_user_password(StringView password) = 0;
virtual bool has_user_password() const = 0;
virtual void encrypt(NonnullRefPtr<Object>, Reference reference) const = 0;
virtual void decrypt(NonnullRefPtr<Object>, Reference reference) const = 0;
};
class StandardSecurityHandler : public SecurityHandler {
public:
static PDFErrorOr<NonnullRefPtr<StandardSecurityHandler>> create(Document*, NonnullRefPtr<DictObject> encryption_dict);
StandardSecurityHandler(Document*, size_t revision, DeprecatedString const& o_entry, DeprecatedString const& u_entry, u32 flags, bool encrypt_metadata, size_t length, CryptFilterMethod method);
~StandardSecurityHandler() override = default;
bool try_provide_user_password(StringView password_string) override;
bool has_user_password() const override { return m_encryption_key.has_value(); }
protected:
void encrypt(NonnullRefPtr<Object>, Reference reference) const override;
void decrypt(NonnullRefPtr<Object>, Reference reference) const override;
private:
void crypt(NonnullRefPtr<Object>, Reference reference, Crypto::Cipher::Intent) const;
ByteBuffer compute_user_password_value_r2(ByteBuffer password_string);
ByteBuffer compute_user_password_value_r3_to_r5(ByteBuffer password_string);
bool authenticate_user_password_r2_to_r5(StringView password_string);
bool authenticate_user_password_r6_and_later(StringView password_string);
ByteBuffer compute_encryption_key_r2_to_r5(ByteBuffer password_string);
ByteBuffer compute_encryption_key_r6_and_later(ByteBuffer password_string);
ByteBuffer computing_a_hash_r6_and_later(ByteBuffer password_string);
Document* m_document;
size_t m_revision;
Optional<ByteBuffer> m_encryption_key;
DeprecatedString m_o_entry;
DeprecatedString m_u_entry;
u32 m_flags;
bool m_encrypt_metadata;
size_t m_length;
CryptFilterMethod m_method;
};
class RC4 {
public:
RC4(ReadonlyBytes key);
void generate_bytes(ByteBuffer&);
ByteBuffer encrypt(ReadonlyBytes bytes);
private:
Array<size_t, 256> m_bytes;
};
}