Skip to content

Commit

Permalink
Patches pck signing to work with pck pactches
Browse files Browse the repository at this point in the history
  • Loading branch information
debian build committed Sep 28, 2024
1 parent 646fe82 commit c4c6570
Show file tree
Hide file tree
Showing 25 changed files with 1,551 additions and 205 deletions.
73 changes: 59 additions & 14 deletions core/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Import("env")

import os

import base64
import core_builders

import methods
Expand Down Expand Up @@ -217,35 +218,79 @@ gen_hash = env.CommandNoCache(
env.add_source_files(env.core_sources, gen_hash)


# Generate AES256 script encryption key
def encryption_key_builder(target, source, env):
# Generate encryption and signing keys
def encryption_key_h_builder(target, source, env):
with methods.generated_wrapper(target) as file:
file.write(
f"""\
extern uint8_t pck_encryption_key[32];
extern uint8_t pck_sign_pub_key[{source[0]}];
size_t pck_sign_pub_key_len={source[0]};"""
)

def encryption_key_cpp_builder(target, source, env):
with methods.generated_wrapper(target) as file:
file.write(
f"""\
#include "core/config/project_settings.h"
uint8_t script_encryption_key[32] = {{
{source[0]}
uint8_t pck_encryption_key[32] = {{
{source[0]}
}};
uint8_t pck_sign_pub_key[{source[1]}] = {{
{source[2]}
}};"""
)

gdkey = "0" * 64
ec_valid = True
if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ) or ("PCK_AES256_ENCRYPTION_KEY" in os.environ):
if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ:
gdkey = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"]
elif "PCK_AES256_ENCRYPTION_KEY" in os.environ:
gdkey = os.environ["PCK_AES256_ENCRYPTION_KEY"]
ec_valid = len(gdkey) == 64
if ec_valid:
try:
gdkey = ",".join([str(int(f"{a}{b}", 16)) for a, b in zip(gdkey[0::2], gdkey[1::2])])
except Exception:
ec_valid = False

pubkey = "0"
pubkey_len = 1
if "PCK_SIGNING_PUBLIC_KEY" in os.environ:
raw_key = base64.b64decode(os.environ["PCK_SIGNING_PUBLIC_KEY"]).hex()
if len(raw_key) >= 64:
pubkey = ""
pubkey_len = len(raw_key) >> 1
for i in range(pubkey_len):
if i > 0:
pubkey += ","
pubkey += "0x" + raw_key[i * 2 : i * 2 + 2]
env.Append(CPPDEFINES=["PCK_SIGNING_ENABLED"])

gdkey = os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY", "0" * 64)
ec_valid = len(gdkey) == 64
if ec_valid:
try:
gdkey = ", ".join([str(int(f"{a}{b}", 16)) for a, b in zip(gdkey[0::2], gdkey[1::2])])
except Exception:
ec_valid = False
if not ec_valid:
methods.print_error(
f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{gdkey}".\n'
"Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment "
"Unset `PCK_AES256_ENCRYPTION_KEY` in your environment "
"or make sure that it contains exactly 64 hexadecimal characters."
)
Exit(255)
gen_encrypt = env.CommandNoCache("script_encryption_key.gen.cpp", env.Value(gdkey), env.Run(encryption_key_builder))
env.add_source_files(env.core_sources, gen_encrypt)

env.Depends(
"#core/script_encryption_key.gen.h",
[env.Value(pubkey_len)],
)
env.CommandNoCache("#core/script_encryption_key.gen.h", env.Value(pubkey_len), env.Run(encryption_key_h_builder))
env.Depends(
"#core/script_encryption_key.gen.cpp",
[env.Value(gdkey), env.Value(pubkey_len), env.Value(pubkey)],
)
gen_encrypt_cpp = env.CommandNoCache("#core/script_encryption_key.gen.cpp", [env.Value(gdkey), env.Value(pubkey_len), env.Value(pubkey)], env.Run(encryption_key_cpp_builder))
env.add_source_files(env.core_sources, gen_encrypt_cpp)

if env["module_mbedtls_enabled"] or env.editor_build or "PCK_SIGNING_PUBLIC_KEY" in os.environ:
env.Append(CPPDEFINES=["ECDSA_ENABLED"])


# Certificates
Expand Down
29 changes: 27 additions & 2 deletions core/crypto/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ from misc.utility.scons_hints import *

Import("env")

import os

env_crypto = env.Clone()

is_builtin = env["builtin_mbedtls"]
Expand All @@ -22,9 +24,14 @@ if is_builtin or not has_module:
# to make a "light" build with only the necessary mbedtls files.
if not has_module:
# Minimal mbedTLS config file
config_path = "thirdparty/mbedtls/include/godot_core_mbedtls_config.h"
if env.editor_build or "PCK_SIGNING_PUBLIC_KEY" in os.environ:
config_path = "thirdparty/mbedtls/include/godot_core_ecdsa_mbedtls_config.h"
else:
config_path = "thirdparty/mbedtls/include/godot_core_mbedtls_config.h"

config_path = f"<{config_path}>" if env_crypto["ninja"] and env_crypto.msvc else f'\\"{config_path}\\"'
env_crypto.Append(CPPDEFINES=[("MBEDTLS_CONFIG_FILE", config_path)])

# Build minimal mbedTLS library (MD5/SHA/Base64/AES).
env_thirdparty = env_crypto.Clone()
env_thirdparty.disable_warnings()
Expand All @@ -41,10 +48,28 @@ if not has_module:
"sha256.c",
"godot_core_mbedtls_platform.c",
]
if env.editor_build or "PCK_SIGNING_PUBLIC_KEY" in os.environ:
# PCK siginig is enabled or with editor.
thirdparty_mbedtls_sources += [
"asn1parse.c",
"asn1write.c",
"bignum.c",
"ecdsa.c",
"ecp.c",
"ecp_curves.c",
"hmac_drbg.c",
"md.c",
"platform.c",
"platform_util.c",
"threading.c",
]
env_thirdparty.Depends(thirdparty_obj, "#thirdparty/mbedtls/include/godot_core_ecdsa_mbedtls_config.h")
else:
env_thirdparty.Depends(thirdparty_obj, "#thirdparty/mbedtls/include/godot_core_mbedtls_config.h")

thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources]
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_mbedtls_sources)
# Needed to force rebuilding the library when the configuration file is updated.
env_thirdparty.Depends(thirdparty_obj, "#thirdparty/mbedtls/include/godot_core_mbedtls_config.h")
env.core_sources += thirdparty_obj
elif is_builtin:
# Module mbedTLS config file
Expand Down
107 changes: 107 additions & 0 deletions core/crypto/crypto_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "core/os/os.h"

#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#include <mbedtls/aes.h>
#include <mbedtls/base64.h>
#include <mbedtls/ctr_drbg.h>
Expand All @@ -43,6 +44,9 @@
#include <mbedtls/compat-2.x.h>
#endif

#include <mbedtls/ecdsa.h>
#include <mbedtls/ecp.h>

// RandomGenerator
CryptoCore::RandomGenerator::RandomGenerator() {
entropy = memalloc(sizeof(mbedtls_entropy_context));
Expand Down Expand Up @@ -249,3 +253,106 @@ Error CryptoCore::sha256(const uint8_t *p_src, int p_src_len, unsigned char r_ha
int ret = mbedtls_sha256_ret(p_src, p_src_len, r_hash, 0);
return ret ? FAILED : OK;
}

#ifdef ECDSA_ENABLED

#define CHECK_COND_V(m_cond, m_retval) \
if (unlikely(m_cond)) { \
if (silent) { \
return m_retval; \
} else { \
ERR_FAIL_COND_V(m_cond, m_retval); \
} \
}

CryptoCore::ECDSAContext::ECDSAContext(CryptoCore::ECDSAContext::CurveType p_curve) {
curve_type = p_curve;
entropy = memalloc(sizeof(mbedtls_entropy_context));
mbedtls_entropy_init((mbedtls_entropy_context *)entropy);

ctr_drbg = memalloc(sizeof(mbedtls_ctr_drbg_context));
mbedtls_ctr_drbg_init((mbedtls_ctr_drbg_context *)ctr_drbg);
mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctr_drbg, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0);

ctx = memalloc(sizeof(mbedtls_ecdsa_context));
mbedtls_ecdsa_init((mbedtls_ecdsa_context *)ctx);

keypair = memalloc(sizeof(mbedtls_ecp_keypair));
mbedtls_ecp_keypair_init((mbedtls_ecp_keypair *)keypair);
}

CryptoCore::ECDSAContext::~ECDSAContext() {
mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *)keypair);
mbedtls_ecdsa_free((mbedtls_ecdsa_context *)ctx);
mbedtls_entropy_free((mbedtls_entropy_context *)entropy);
mbedtls_ctr_drbg_free((mbedtls_ctr_drbg_context *)ctr_drbg);
}

void CryptoCore::ECDSAContext::set_silent(bool p_silent) {
silent = p_silent;
}

Error CryptoCore::ECDSAContext::validate_private_key(const uint8_t *p_priv_key, size_t p_priv_len) {
mbedtls_ecp_keypair keypair_val;
mbedtls_ecp_keypair_init(&keypair_val);

int priv_ok = mbedtls_ecp_read_key((mbedtls_ecp_group_id)curve_type, &keypair_val, (const unsigned char *)p_priv_key, p_priv_len);
if (priv_ok == 0) {
priv_ok = mbedtls_ecp_check_privkey(&(keypair_val.grp), &(keypair_val.d));
}
mbedtls_ecp_keypair_free(&keypair_val);

return (priv_ok == 0) ? OK : FAILED;
}

Error CryptoCore::ECDSAContext::validate_public_key(const uint8_t *p_pub_key, size_t p_pub_len) {
mbedtls_ecp_keypair keypair_val;
mbedtls_ecp_keypair_init(&keypair_val);
mbedtls_ecp_group_load(&(keypair_val.grp), (mbedtls_ecp_group_id)curve_type);

int pub_ok = mbedtls_ecp_point_read_binary(&(keypair_val.grp), &(keypair_val.Q), (const unsigned char *)p_pub_key, p_pub_len);
if (pub_ok == 0) {
pub_ok = mbedtls_ecp_check_pubkey(&(keypair_val.grp), &(keypair_val.Q));
}
mbedtls_ecp_keypair_free(&keypair_val);

return (pub_ok == 0) ? OK : FAILED;
}

Error CryptoCore::ECDSAContext::generate_key_pair(uint8_t *p_priv_key, size_t p_priv_len, size_t *r_priv_len, uint8_t *p_pub_key, size_t p_pub_len, size_t *r_pub_len) {
CHECK_COND_V(mbedtls_ecp_gen_key((mbedtls_ecp_group_id)curve_type, (mbedtls_ecp_keypair *)keypair, mbedtls_ctr_drbg_random, (mbedtls_ctr_drbg_context *)ctr_drbg) != 0, FAILED);
CHECK_COND_V(mbedtls_ecdsa_from_keypair((mbedtls_ecdsa_context *)ctx, (mbedtls_ecp_keypair *)keypair) != 0, FAILED);
size_t len = MIN(size_t((((mbedtls_ecp_keypair *)keypair)->grp.pbits + 7) / 8), p_priv_len);
size_t key_length = 0;
CHECK_COND_V(mbedtls_ecp_write_key_ext((mbedtls_ecp_keypair *)keypair, &key_length, (unsigned char *)p_priv_key, len) != 0, FAILED);
*r_priv_len = key_length;
CHECK_COND_V(mbedtls_ecp_point_write_binary(&(((mbedtls_ecp_keypair *)keypair)->grp), &(((mbedtls_ecp_keypair *)keypair)->Q), MBEDTLS_ECP_PF_UNCOMPRESSED, r_pub_len, (unsigned char *)p_pub_key, p_pub_len) != 0, FAILED);
return OK;
}

Error CryptoCore::ECDSAContext::set_public_key(const uint8_t *p_key, size_t p_len) {
mbedtls_ecp_group_load(&(((mbedtls_ecp_keypair *)keypair)->grp), (mbedtls_ecp_group_id)curve_type);
CHECK_COND_V(mbedtls_ecp_point_read_binary(&(((mbedtls_ecp_keypair *)keypair)->grp), &(((mbedtls_ecp_keypair *)keypair)->Q), (const unsigned char *)p_key, p_len) != 0, FAILED);
CHECK_COND_V(mbedtls_ecdsa_from_keypair((mbedtls_ecdsa_context *)ctx, (mbedtls_ecp_keypair *)keypair) != 0, FAILED);
return OK;
}

Error CryptoCore::ECDSAContext::set_private_key(const uint8_t *p_key, size_t p_len) {
CHECK_COND_V(mbedtls_ecp_read_key((mbedtls_ecp_group_id)curve_type, (mbedtls_ecp_keypair *)keypair, (const unsigned char *)p_key, p_len) != 0, FAILED);
CHECK_COND_V(mbedtls_ecdsa_from_keypair((mbedtls_ecdsa_context *)ctx, (mbedtls_ecp_keypair *)keypair) != 0, FAILED);
return OK;
}

Error CryptoCore::ECDSAContext::sign(const unsigned char *p_hash_sha256, uint8_t *r_signature, size_t *r_signature_len) {
CHECK_COND_V(mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *)ctx, MBEDTLS_MD_SHA256, p_hash_sha256, 32, r_signature, *r_signature_len, r_signature_len, mbedtls_ctr_drbg_random, (mbedtls_ctr_drbg_context *)ctr_drbg) != 0, FAILED);
return OK;
}

Error CryptoCore::ECDSAContext::verify(const unsigned char *p_hash_sha256, uint8_t *p_signature, size_t p_signature_len) {
CHECK_COND_V(mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *)ctx, p_hash_sha256, 32, p_signature, p_signature_len) != 0, FAILED);
return OK;
}

#undef CHECK_COND_V

#endif //ECDSA_ENABLED
49 changes: 49 additions & 0 deletions core/crypto/crypto_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,55 @@ class CryptoCore {
static Error md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]);
static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]);
static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]);

#ifdef ECDSA_ENABLED

class ECDSAContext {
public:
enum CurveType {
ECP_DP_NONE,
ECP_DP_SECP192R1,
ECP_DP_SECP224R1,
ECP_DP_SECP256R1,
ECP_DP_SECP384R1,
ECP_DP_SECP521R1,
ECP_DP_BP256R1,
ECP_DP_BP384R1,
ECP_DP_BP512R1,
ECP_DP_CURVE25519,
ECP_DP_SECP192K1,
ECP_DP_SECP224K1,
ECP_DP_SECP256K1,
ECP_DP_CURVE448,
};

private:
CurveType curve_type = ECP_DP_SECP256R1;
void *entropy = nullptr;
void *ctr_drbg = nullptr;
void *ctx = nullptr;
void *keypair = nullptr;
bool silent = false;

public:
ECDSAContext(CurveType p_curve = ECP_DP_BP256R1);
~ECDSAContext();

void set_silent(bool p_silent);

Error validate_private_key(const uint8_t *p_priv_key, size_t p_priv_len);
Error validate_public_key(const uint8_t *p_pub_key, size_t p_pub_len);

Error generate_key_pair(uint8_t *p_priv_key, size_t p_priv_len, size_t *r_priv_len, uint8_t *p_pub_key, size_t p_pub_len, size_t *r_pub_len);

Error set_public_key(const uint8_t *p_key, size_t p_len);
Error set_private_key(const uint8_t *p_key, size_t p_len);

Error sign(const unsigned char *p_hash_sha256, uint8_t *r_signature, size_t *r_signature_len);
Error verify(const unsigned char *p_hash_sha256, uint8_t *p_signature, size_t p_signature_len);
};

#endif
};

#endif // CRYPTO_CORE_H
Loading

0 comments on commit c4c6570

Please sign in to comment.