Skip to content

Commit 1627912

Browse files
committed
Merge pull request godotengine#98918 from bruvzg/pck_enc_iv
Allow setting custom initialization vector for FileAccessEncrypted. Add export setting to set static seed for PCK encryption initialization vectors.
2 parents ddb2073 + 45593d4 commit 1627912

18 files changed

+200
-52
lines changed

core/io/file_access.compat.inc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**************************************************************************/
2+
/* file_access.compat.inc */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#ifndef DISABLE_DEPRECATED
32+
33+
Ref<FileAccess> FileAccess::_open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
34+
return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>());
35+
}
36+
37+
void FileAccess::_bind_compatibility_methods() {
38+
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
39+
}
40+
41+
#endif // DISABLE_DEPRECATED

core/io/file_access.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/**************************************************************************/
3030

3131
#include "file_access.h"
32+
#include "file_access.compat.inc"
3233

3334
#include "core/config/project_settings.h"
3435
#include "core/crypto/crypto_core.h"
@@ -124,15 +125,15 @@ Ref<FileAccess> FileAccess::_open(const String &p_path, ModeFlags p_mode_flags)
124125
return fa;
125126
}
126127

127-
Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
128+
Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv) {
128129
Ref<FileAccess> fa = _open(p_path, p_mode_flags);
129130
if (fa.is_null()) {
130131
return fa;
131132
}
132133

133134
Ref<FileAccessEncrypted> fae;
134135
fae.instantiate();
135-
Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
136+
Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ, true, p_iv);
136137
last_file_open_error = err;
137138
if (err) {
138139
return Ref<FileAccess>();
@@ -806,7 +807,7 @@ String FileAccess::get_sha256(const String &p_file) {
806807

807808
void FileAccess::_bind_methods() {
808809
ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open);
809-
ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::open_encrypted);
810+
ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key", "iv"), &FileAccess::open_encrypted, DEFVAL(Vector<uint8_t>()));
810811
ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &FileAccess::open_encrypted_pass);
811812
ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0));
812813
ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error);

core/io/file_access.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ class FileAccess : public RefCounted {
109109

110110
static FileCloseFailNotify close_fail_notify;
111111

112+
#ifndef DISABLE_DEPRECATED
113+
static Ref<FileAccess> _open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key);
114+
115+
static void _bind_compatibility_methods();
116+
#endif
117+
112118
private:
113119
static bool backup_save;
114120
thread_local static Error last_file_open_error;
@@ -199,7 +205,7 @@ class FileAccess : public RefCounted {
199205
static Ref<FileAccess> create_for_path(const String &p_path);
200206
static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
201207

202-
static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key);
208+
static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv = Vector<uint8_t>());
203209
static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass);
204210
static Ref<FileAccess> open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ);
205211
static Error get_open_error();

core/io/file_access_encrypted.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
#include <stdio.h>
3838

39-
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
39+
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic, const Vector<uint8_t> &p_iv) {
4040
ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute()));
4141
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
4242

@@ -49,6 +49,16 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u
4949
writing = true;
5050
file = p_base;
5151
key = p_key;
52+
if (p_iv.is_empty()) {
53+
iv.resize(16);
54+
CryptoCore::RandomGenerator rng;
55+
ERR_FAIL_COND_V_MSG(rng.init(), FAILED, "Failed to initialize random number generator.");
56+
Error err = rng.get_random_bytes(iv.ptrw(), 16);
57+
ERR_FAIL_COND_V(err != OK, err);
58+
} else {
59+
ERR_FAIL_COND_V(p_iv.size() != 16, ERR_INVALID_PARAMETER);
60+
iv = p_iv;
61+
}
5262

5363
} else if (p_mode == MODE_READ) {
5464
writing = false;
@@ -63,10 +73,8 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u
6373
p_base->get_buffer(md5d, 16);
6474
length = p_base->get_64();
6575

66-
unsigned char iv[16];
67-
for (int i = 0; i < 16; i++) {
68-
iv[i] = p_base->get_8();
69-
}
76+
iv.resize(16);
77+
p_base->get_buffer(iv.ptrw(), 16);
7078

7179
base = p_base->get_position();
7280
ERR_FAIL_COND_V(p_base->get_length() < base + length, ERR_FILE_CORRUPT);
@@ -83,7 +91,7 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u
8391
CryptoCore::AESContext ctx;
8492

8593
ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption!
86-
ctx.decrypt_cfb(ds, iv, data.ptrw(), data.ptrw());
94+
ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw());
8795
}
8896

8997
data.resize(length);
@@ -145,14 +153,9 @@ void FileAccessEncrypted::_close() {
145153

146154
file->store_buffer(hash, 16);
147155
file->store_64(data.size());
156+
file->store_buffer(iv.ptr(), 16);
148157

149-
unsigned char iv[16];
150-
for (int i = 0; i < 16; i++) {
151-
iv[i] = Math::rand() % 256;
152-
file->store_8(iv[i]);
153-
}
154-
155-
ctx.encrypt_cfb(len, iv, compressed.ptrw(), compressed.ptrw());
158+
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw());
156159

157160
file->store_buffer(compressed.ptr(), compressed.size());
158161
data.clear();

core/io/file_access_encrypted.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class FileAccessEncrypted : public FileAccess {
4444
};
4545

4646
private:
47+
Vector<uint8_t> iv;
4748
Vector<uint8_t> key;
4849
bool writing = false;
4950
Ref<FileAccess> file;
@@ -57,9 +58,11 @@ class FileAccessEncrypted : public FileAccess {
5758
void _close();
5859

5960
public:
60-
Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
61+
Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true, const Vector<uint8_t> &p_iv = Vector<uint8_t>());
6162
Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
6263

64+
Vector<uint8_t> get_iv() const { return iv; }
65+
6366
virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
6467
virtual bool is_open() const override; ///< true when file is open
6568

doc/classes/FileAccess.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@
308308
<param index="0" name="path" type="String" />
309309
<param index="1" name="mode_flags" type="int" enum="FileAccess.ModeFlags" />
310310
<param index="2" name="key" type="PackedByteArray" />
311+
<param index="3" name="iv" type="PackedByteArray" default="PackedByteArray()" />
311312
<description>
312313
Creates a new [FileAccess] object and opens an encrypted file in write or read mode. You need to pass a binary key to encrypt/decrypt it.
313314
[b]Note:[/b] The provided key must be 32 bytes long.

editor/export/editor_export.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ void EditorExport::_save() {
8787

8888
config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter());
8989
config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
90+
config->set_value(section, "seed", preset->get_seed());
91+
9092
config->set_value(section, "encrypt_pck", preset->get_enc_pck());
9193
config->set_value(section, "encrypt_directory", preset->get_enc_directory());
9294
config->set_value(section, "script_export_mode", preset->get_script_export_mode());
@@ -307,6 +309,9 @@ void EditorExport::load_config() {
307309
preset->set_script_export_mode(config->get_value(section, "script_export_mode", EditorExportPreset::MODE_SCRIPT_BINARY_TOKENS_COMPRESSED));
308310
preset->set_patches(config->get_value(section, "patches", Vector<String>()));
309311

312+
if (config->has_section_key(section, "seed")) {
313+
preset->set_seed(config->get_value(section, "seed"));
314+
}
310315
if (config->has_section_key(section, "encrypt_pck")) {
311316
preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
312317
}

0 commit comments

Comments
 (0)