From f35311bf61fa3cb0ce12549e29ac92eb9f30ade1 Mon Sep 17 00:00:00 2001 From: H0neyBadger Date: Fri, 15 May 2020 11:06:54 +0200 Subject: [PATCH] Add Nintendo Switch chiaki-lib support (#233) --- CMakeLists.txt | 27 +++++ cmake/switch.cmake | 99 ++++++++++++++++ lib/CMakeLists.txt | 14 ++- lib/include/chiaki/ecdh.h | 16 +++ lib/include/chiaki/stoppipe.h | 11 ++ lib/src/audio.c | 3 + lib/src/discovery.c | 6 +- lib/src/ecdh.c | 134 +++++++++++++++++++++- lib/src/gkcrypt.c | 105 ++++++++++++++++- lib/src/random.c | 37 +++++- lib/src/regist.c | 2 +- lib/src/rpcrypt.c | 95 +++++++++++++++ lib/src/stoppipe.c | 54 ++++++++- lib/src/takion.c | 7 +- lib/src/thread.c | 21 ++++ scripts/switch/Dockerfile | 81 +++++++++++++ scripts/switch/build.sh | 42 +++++++ scripts/switch/devkit_repo | 6 + scripts/switch/fake_ctest.nintendo.net.py | 31 +++++ 19 files changed, 771 insertions(+), 20 deletions(-) create mode 100644 cmake/switch.cmake create mode 100644 scripts/switch/Dockerfile create mode 100755 scripts/switch/build.sh create mode 100644 scripts/switch/devkit_repo create mode 100644 scripts/switch/fake_ctest.nintendo.net.py diff --git a/CMakeLists.txt b/CMakeLists.txt index e74e57c..9cffd0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,9 @@ option(CHIAKI_ENABLE_TESTS "Enable tests for Chiaki" ON) option(CHIAKI_ENABLE_CLI "Enable CLI for Chiaki" OFF) option(CHIAKI_ENABLE_GUI "Enable Qt GUI" ON) option(CHIAKI_ENABLE_ANDROID "Enable Android (Use only as part of the Gradle Project)" OFF) +option(CHIAKI_ENABLE_SWITCH "Enable Nintendo Switch (Requires devKitPro libnx)" OFF) option(CHIAKI_LIB_ENABLE_OPUS "Use Opus as part of Chiaki Lib" ON) +option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF) option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF) option(CHIAKI_GUI_ENABLE_QT_GAMEPAD "Use QtGamepad for Input" OFF) option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON) @@ -30,6 +32,22 @@ include(CPack) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +# configure nintendo switch toolchain +if(CHIAKI_ENABLE_SWITCH AND CHIAKI_ENABLE_SWITCH_LINUX) + # CHIAKI_ENABLE_SWITCH_LINUX is a special testing version + # the aim is to troubleshoot nitendo switch chiaki verison + # from a x86 linux os + add_definitions(-DCHIAKI_ENABLE_SWITCH_LINUX) + set(CMAKE_BUILD_TYPE Debug) +elseif(CHIAKI_ENABLE_SWITCH) + add_definitions(-D__SWITCH__) + # load switch.cmake toolchain form ./cmake folder + include(switch) + # TODO check if android ... or other versions are enabled + # force mbedtls as crypto lib + set(CHIAKI_LIB_ENABLE_MBEDTLS ON) +endif() + add_subdirectory(third-party) add_definitions(-DCHIAKI_VERSION_MAJOR=${CHIAKI_VERSION_MAJOR} -DCHIAKI_VERSION_MINOR=${CHIAKI_VERSION_MINOR} -DCHIAKI_VERSION_PATCH=${CHIAKI_VERSION_PATCH} -DCHIAKI_VERSION=\"${CHIAKI_VERSION}\") @@ -38,6 +56,10 @@ if(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT) include(OpenSSLExternalProject) endif() +if(CHIAKI_LIB_ENABLE_MBEDTLS) + add_definitions(-DCHIAKI_LIB_ENABLE_MBEDTLS) +endif() + add_subdirectory(lib) if(CHIAKI_ENABLE_CLI) @@ -56,3 +78,8 @@ endif() if(CHIAKI_ENABLE_ANDROID) add_subdirectory(android/app) endif() + +if(CHIAKI_ENABLE_SWITCH) + #TODO + #add_subdirectory(switch) +endif() diff --git a/cmake/switch.cmake b/cmake/switch.cmake new file mode 100644 index 0000000..5409422 --- /dev/null +++ b/cmake/switch.cmake @@ -0,0 +1,99 @@ +# https://github.com/nxengine/nxengine-evo + +# Find DEVKITPRO +if(NOT DEFINED ENV{DEVKITPRO}) + message(FATAL_ERROR "You must have defined DEVKITPRO before calling cmake.") +endif() + +set(DEVKITPRO $ENV{DEVKITPRO}) + +function(switchvar cmakevar var default) + # read or set env var + if(NOT DEFINED "ENV{$var}") + set("ENV{$var}" default) + endif() + set("$cmakevar" "ENV{$var}") +endfunction() + +# allow gcc -g to use +# aarch64-none-elf-addr2line -e build_switch/switch/chiaki -f -p -C -a 0xCCB5C +set(CMAKE_BUILD_TYPE Debug) + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_WIN32 ) + set( TOOL_OS_SUFFIX ".exe" ) +endif() + +set(CMAKE_SYSTEM_PROCESSOR "armv8-a") +set(CMAKE_C_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") +set(CMAKE_CXX_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") +set(CMAKE_ASM_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-as${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") +set(CMAKE_STRIP "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip") +set(CMAKE_AR "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive") +set(CMAKE_LINKER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker") +set(CMAKE_NM "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm") +set(CMAKE_OBJCOPY "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy") +set(CMAKE_OBJDUMP "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump") +set(CMAKE_RANLIB "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib") + +# custom /opt/devkitpro/switchvars.sh +switchvar(PORTLIBS_PREFIX PORTLIBS_PREFIX "${DEVKITPRO}/portlibs/switch") +switchvar(ARCH ARCH "-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec") +switchvar(CMAKE_C_FLAGS CFLAGS "${ARCH} -O2 -ffunction-sections -fdata-sections") +switchvar(CMAKE_CXX_FLAGS CXXFLAGS "${CMAKE_C_FLAGS}") +switchvar(CMAKE_CPP_FLAGS CPPFLAGS "-D__SWITCH__ -I${PORTLIBS_PREFIX}/include -isystem${DEVKITPRO}/libnx/include") +switchvar(CMAKE_LD_FLAGS LDFLAGS "${ARCH} -L${PORTLIBS_PREFIX}/lib -L${DEVKITPRO}/libnx/lib") +switchvar(LIBS LIBS "-lnx") + +# switchvar(CMAKE_CXX_FLAGS CXXFLAGS "${CMAKE_C_FLAGS} -fno-rtti") +include_directories(${DEVKITPRO}/libnx/include ${PORTLIBS_PREFIX}/include) + +# where is the target environment +set(CMAKE_FIND_ROOT_PATH + ${DEVKITPRO}/devkitA64 + ${DEVKITPRO}/libnx + ${DEVKITPRO}/portlibs/switch) + +# only search for libraries and includes in toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + +find_program(ELF2NRO elf2nro ${DEVKITPRO}/tools/bin) +if (ELF2NRO) + message(STATUS "elf2nro: ${ELF2NRO} - found") +else () + message(WARNING "elf2nro - not found") +endif () + +find_program(NACPTOOL nacptool ${DEVKITPRO}/tools/bin) +if (NACPTOOL) + message(STATUS "nacptool: ${NACPTOOL} - found") +else () + message(WARNING "nacptool - not found") +endif () + +function(__add_nacp target APP_TITLE APP_AUTHOR APP_VERSION) + set(__NACP_COMMAND ${NACPTOOL} --create ${APP_TITLE} ${APP_AUTHOR} ${APP_VERSION} ${CMAKE_CURRENT_BINARY_DIR}/${target}) + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target} + COMMAND ${__NACP_COMMAND} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + VERBATIM + ) +endfunction() + +function(add_nro_target target title author version icon romfs) + get_filename_component(target_we ${target} NAME_WE) + if (NOT ${target_we}.nacp) + __add_nacp(${target_we}.nacp ${title} ${author} ${version}) + endif () + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro + COMMAND ${ELF2NRO} $ ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro --icon=${icon} --nacp=${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nacp + # --romfsdir=${romfs} + DEPENDS ${target} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nacp + VERBATIM + ) + add_custom_target(${target_we}_nro ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro) +endfunction() + + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cfb2c04..c002ab8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -99,16 +99,26 @@ target_include_directories(chiaki-lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/includ find_package(Threads REQUIRED) target_link_libraries(chiaki-lib Threads::Threads) -if(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT) +if(CHIAKI_LIB_ENABLE_MBEDTLS) + # provided by mbedtls-static (mbedtls-devel) + # find_package(mbedcrypto REQUIRED) + target_link_libraries(chiaki-lib mbedtls mbedx509 mbedcrypto) +elseif(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT) target_link_libraries(chiaki-lib OpenSSL_Crypto) else() + # default find_package(OpenSSL REQUIRED) target_link_libraries(chiaki-lib OpenSSL::Crypto) endif() +if(CHIAKI_ENABLE_SWITCH AND NOT CHIAKI_ENABLE_SWITCH_LINUX) + # to provides csrngGetRandomBytes + target_link_libraries(chiaki-lib nx) +endif() + target_link_libraries(chiaki-lib protobuf-nanopb-static) target_link_libraries(chiaki-lib jerasure) if(CHIAKI_LIB_ENABLE_OPUS) target_link_libraries(chiaki-lib ${Opus_LIBRARIES}) -endif() \ No newline at end of file +endif() diff --git a/lib/include/chiaki/ecdh.h b/lib/include/chiaki/ecdh.h index 440fcb8..fed92c4 100644 --- a/lib/include/chiaki/ecdh.h +++ b/lib/include/chiaki/ecdh.h @@ -27,12 +27,28 @@ extern "C" { #endif +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +#include "mbedtls/ecdh.h" +#include "mbedtls/ctr_drbg.h" +#endif + + #define CHIAKI_ECDH_SECRET_SIZE 32 typedef struct chiaki_ecdh_t { +// the following lines may lead to memory corruption +// __SWITCH__ or CHIAKI_LIB_ENABLE_MBEDTLS must be defined +// globally (whole project) +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + // mbedtls ecdh context + mbedtls_ecdh_context ctx; + // deterministic random bit generator + mbedtls_ctr_drbg_context drbg; +#else struct ec_group_st *group; struct ec_key_st *key_local; +#endif } ChiakiECDH; CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh); diff --git a/lib/include/chiaki/stoppipe.h b/lib/include/chiaki/stoppipe.h index 229995e..1a1ab71 100644 --- a/lib/include/chiaki/stoppipe.h +++ b/lib/include/chiaki/stoppipe.h @@ -26,6 +26,8 @@ #ifdef _WIN32 #include +#else +#include #endif #ifdef __cplusplus @@ -36,6 +38,15 @@ typedef struct chiaki_stop_pipe_t { #ifdef _WIN32 WSAEVENT event; +#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + // due to a lack pipe/event/socketpair + // on switch env, we use a physical socket + // to send/trigger the cancel signal + struct sockaddr_in addr; + // local stop socket file descriptor + // this fd is audited by 'select' as + // fd_set *readfds + int fd; #else int fds[2]; #endif diff --git a/lib/src/audio.c b/lib/src/audio.c index c7a3512..2bd4168 100644 --- a/lib/src/audio.c +++ b/lib/src/audio.c @@ -23,6 +23,9 @@ #include #endif +#ifdef __SWITCH__ +#include +#endif void chiaki_audio_header_load(ChiakiAudioHeader *audio_header, const uint8_t *buf) { diff --git a/lib/src/discovery.c b/lib/src/discovery.c index e2d5205..e069aaa 100644 --- a/lib/src/discovery.c +++ b/lib/src/discovery.c @@ -127,7 +127,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, discovery->log = log; - discovery->socket = socket(AF_INET, SOCK_DGRAM, 0); + discovery->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(CHIAKI_SOCKET_IS_INVALID(discovery->socket)) { CHIAKI_LOGE(discovery->log, "Discovery failed to create socket"); @@ -138,9 +138,13 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, discovery->local_addr.sa_family = family; if(family == AF_INET6) { +#ifndef __SWITCH__ struct in6_addr anyaddr = IN6ADDR_ANY_INIT; +#endif struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&discovery->local_addr; +#ifndef __SWITCH__ addr->sin6_addr = anyaddr; +#endif addr->sin6_port = htons(0); } else // AF_INET diff --git a/lib/src/ecdh.c b/lib/src/ecdh.c index ad07515..056d69d 100644 --- a/lib/src/ecdh.c +++ b/lib/src/ecdh.c @@ -19,23 +19,58 @@ #include #include +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +#include "mbedtls/entropy.h" +#include "mbedtls/md.h" +#else #include #include #include #include #include +#endif +// memset #include #include - CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh) { memset(ecdh, 0, sizeof(ChiakiECDH)); +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +#define CHECK(err) if((err) != 0) { \ + chiaki_ecdh_fini(ecdh); \ + return CHIAKI_ERR_UNKNOWN; } + // mbedtls ecdh example: + // https://github.com/ARMmbed/mbedtls/blob/development/programs/pkey/ecdh_curve25519.c + const char pers[] = "ecdh"; + mbedtls_entropy_context entropy; + //init RNG Seed context + mbedtls_entropy_init(&entropy); + // init local key + //mbedtls_ecp_keypair_init(&ecdh->key_local); + mbedtls_ecdh_init(&ecdh->ctx); + // init ecdh group + // keep rng context in ecdh for later reuse + mbedtls_ctr_drbg_init(&ecdh->drbg); + // build RNG seed + CHECK(mbedtls_ctr_drbg_seed(&ecdh->drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, sizeof pers)); + + // build MBEDTLS_ECP_DP_SECP256K1 group + CHECK(mbedtls_ecp_group_load(&ecdh->ctx.grp, MBEDTLS_ECP_DP_SECP256K1)); + // build key + CHECK(mbedtls_ecdh_gen_public(&ecdh->ctx.grp, &ecdh->ctx.d, + &ecdh->ctx.Q, mbedtls_ctr_drbg_random, &ecdh->drbg)); + + // relese entropy ptr + mbedtls_entropy_free(&entropy); +#undef CHECK + +#else #define CHECK(a) if(!(a)) { chiaki_ecdh_fini(ecdh); return CHIAKI_ERR_UNKNOWN; } - CHECK(ecdh->group = EC_GROUP_new_by_curve_name(NID_secp256k1)); CHECK(ecdh->key_local = EC_KEY_new()); @@ -43,19 +78,53 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh) CHECK(EC_KEY_generate_key(ecdh->key_local)); #undef CHECK +#endif return CHIAKI_ERR_SUCCESS; } CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh) { +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + mbedtls_ecdh_free(&ecdh->ctx); + mbedtls_ctr_drbg_free(&ecdh->drbg); +#else EC_KEY_free(ecdh->key_local); EC_GROUP_free(ecdh->group); +#endif } CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_set_local_key(ChiakiECDH *ecdh, const uint8_t *private_key, size_t private_key_size, const uint8_t *public_key, size_t public_key_size) { +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + //https://tls.mbed.org/discussions/generic/publickey-binary-data-in-der + // Load keys from buffers (i.e: config file) + // TODO test + + // public + int r = 0; + r = mbedtls_ecp_point_read_binary(&ecdh->ctx.grp, &ecdh->ctx.Q, + public_key, public_key_size); + if(r != 0 ){ + return CHIAKI_ERR_UNKNOWN; + } + + // secret + r = mbedtls_mpi_read_binary(&ecdh->ctx.d, private_key, private_key_size); + if(r != 0 ){ + return CHIAKI_ERR_UNKNOWN; + } + + // regen key + r = mbedtls_ecdh_gen_public(&ecdh->ctx.grp, &ecdh->ctx.d, + &ecdh->ctx.Q, mbedtls_ctr_drbg_random, &ecdh->drbg); + if(r != 0 ){ + return CHIAKI_ERR_UNKNOWN; + } + + return CHIAKI_ERR_SUCCESS; +#else ChiakiErrorCode err = CHIAKI_ERR_SUCCESS; BIGNUM *private_key_bn = BN_bin2bn(private_key, (int)private_key_size, NULL); @@ -92,10 +161,40 @@ error_pub: error_priv: BN_free(private_key_bn); return err; +#endif } CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, uint8_t *key_out, size_t *key_out_size, const uint8_t *handshake_key, uint8_t *sig_out, size_t *sig_out_size) { +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + +#define GOTO_ERROR(err) do { \ + if((err) !=0){ \ + goto error; \ + }} while(0) + // extract pub key to build dh shared secret + // this key is sent to the remote server + GOTO_ERROR(mbedtls_ecp_point_write_binary( &ecdh->ctx.grp, &ecdh->ctx.Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, key_out_size, key_out, *key_out_size )); + + // https://tls.mbed.org/module-level-design-hashing + // HMAC + GOTO_ERROR(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) , 1)); + GOTO_ERROR(mbedtls_md_hmac_starts(&ctx, handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE)); + GOTO_ERROR(mbedtls_md_hmac_update(&ctx, key_out, *key_out_size)); + GOTO_ERROR(mbedtls_md_hmac_finish(&ctx, sig_out)); + // SHA256 = 8*32 + *sig_out_size = 32; +#undef GOTO_ERROR + mbedtls_md_free(&ctx); + return CHIAKI_ERR_SUCCESS; + +error: + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; +#else const EC_POINT *point = EC_KEY_get0_public_key(ecdh->key_local); if(!point) return CHIAKI_ERR_UNKNOWN; @@ -106,12 +205,40 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, ui if(!HMAC(EVP_sha256(), handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE, key_out, *key_out_size, sig_out, (unsigned int *)sig_out_size)) return CHIAKI_ERR_UNKNOWN; - return CHIAKI_ERR_SUCCESS; + +#endif } CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_derive_secret(ChiakiECDH *ecdh, uint8_t *secret_out, const uint8_t *remote_key, size_t remote_key_size, const uint8_t *handshake_key, const uint8_t *remote_sig, size_t remote_sig_size) { + //compute DH shared key +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + // https://github.com/ARMmbed/mbedtls/blob/development/programs/pkey/ecdh_curve25519.c#L151 +#define GOTO_ERROR(err) do { \ + if((err) !=0){ \ + goto error;} \ + } while(0) + + GOTO_ERROR(mbedtls_mpi_lset(&ecdh->ctx.Qp.Z, 1)); + // load Qp point form remote PK + GOTO_ERROR(mbedtls_ecp_point_read_binary(&ecdh->ctx.grp, + &ecdh->ctx.Qp, remote_key, remote_key_size)); + + // build shared secret (diffie-hellman) + GOTO_ERROR(mbedtls_ecdh_compute_shared(&ecdh->ctx.grp, + &ecdh->ctx.z, &ecdh->ctx.Qp, &ecdh->ctx.d, + mbedtls_ctr_drbg_random, &ecdh->drbg)); + + // export shared secret to data buffer + GOTO_ERROR(mbedtls_mpi_write_binary(&ecdh->ctx.z, + secret_out, CHIAKI_ECDH_SECRET_SIZE)); + + return CHIAKI_ERR_SUCCESS; +error: + return CHIAKI_ERR_UNKNOWN; + +#else EC_POINT *remote_public_key = EC_POINT_new(ecdh->group); if(!remote_public_key) return CHIAKI_ERR_UNKNOWN; @@ -130,4 +257,5 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_derive_secret(ChiakiECDH *ecdh, uint8_ return CHIAKI_ERR_UNKNOWN; return CHIAKI_ERR_SUCCESS; +#endif } diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c index f8be2c1..50678ea 100644 --- a/lib/src/gkcrypt.c +++ b/lib/src/gkcrypt.c @@ -21,9 +21,16 @@ #include #include +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +#include "mbedtls/aes.h" +#include "mbedtls/md.h" +#include "mbedtls/gcm.h" +#include "mbedtls/sha256.h" +#else #include #include #include +#endif #include "utils.h" @@ -69,7 +76,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_init(ChiakiGKCrypt *gkcrypt, Chiaki { gkcrypt->key_buf = NULL; } - err = gkcrypt_gen_key_iv(gkcrypt, index, handshake_key, ecdh_secret); if(err != CHIAKI_ERR_SUCCESS) { @@ -132,9 +138,37 @@ static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index, uint8_t hmac[CHIAKI_GKCRYPT_BLOCK_SIZE*2]; size_t hmac_size = sizeof(hmac); + #if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + + if(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) , 1) != 0){ + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; + } + + if(mbedtls_md_hmac_starts(&ctx, ecdh_secret, CHIAKI_ECDH_SECRET_SIZE) != 0){ + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; + } + + if(mbedtls_md_hmac_update(&ctx, data, sizeof(data)) != 0){ + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; + } + + if(mbedtls_md_hmac_finish(&ctx, hmac) != 0){ + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; + } + + mbedtls_md_free(&ctx); + + #else if(!HMAC(EVP_sha256(), ecdh_secret, CHIAKI_ECDH_SECRET_SIZE, data, sizeof(data), hmac, (unsigned int *)&hmac_size)) return CHIAKI_ERR_UNKNOWN; + #endif assert(hmac_size == sizeof(hmac)); memcpy(gkcrypt->key_base, hmac, CHIAKI_GKCRYPT_BLOCK_SIZE); @@ -164,7 +198,14 @@ CHIAKI_EXPORT void chiaki_gkcrypt_gen_gmac_key(uint64_t index, const uint8_t *ke memcpy(data, key_base, 0x10); counter_add(data + 0x10, iv, index * CHIAKI_GKCRYPT_GMAC_KEY_REFRESH_IV_OFFSET); uint8_t md[0x20]; +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + // last param + // is224 Determines which function to use. + // This must be either 0 for SHA-256, or 1 for SHA-224. + mbedtls_sha256_ret(data, sizeof(data), md, 0); +#else SHA256(data, 0x20, md); +#endif xor_bytes(md, md + 0x10, 0x10); memcpy(key_out, md, CHIAKI_GKCRYPT_BLOCK_SIZE); } @@ -189,6 +230,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry assert(key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE == 0); assert(buf_size % CHIAKI_GKCRYPT_BLOCK_SIZE == 0); +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + // build mbedtls aes context + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + + if(mbedtls_aes_setkey_enc(&ctx, gkcrypt->key_base, 128) != 0){ + mbedtls_aes_free(&ctx); + return CHIAKI_ERR_UNKNOWN; + } + +#else EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if(!ctx) return CHIAKI_ERR_UNKNOWN; @@ -204,12 +256,23 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry EVP_CIPHER_CTX_free(ctx); return CHIAKI_ERR_UNKNOWN; } - +#endif int counter_offset = (int)(key_pos / CHIAKI_GKCRYPT_BLOCK_SIZE); for(uint8_t *cur = buf, *end = buf + buf_size; cur < end; cur += CHIAKI_GKCRYPT_BLOCK_SIZE) counter_add(cur, gkcrypt->iv, counter_offset++); +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + for(int i=0; ilog, "GKCrypt %d thread starting", (int)gkcrypt->index); ChiakiErrorCode err = chiaki_mutex_lock(&gkcrypt->key_buf_mutex); assert(err == CHIAKI_ERR_SUCCESS); - while(1) { err = chiaki_cond_wait_pred(&gkcrypt->key_buf_cond, &gkcrypt->key_buf_mutex, key_buf_mutex_pred, gkcrypt); + if(gkcrypt->key_buf_thread_stop || err != CHIAKI_ERR_SUCCESS) break; @@ -438,7 +534,6 @@ static void *gkcrypt_thread_func(void *user) gkcrypt->key_buf_key_pos_min += KEY_BUF_CHUNK_SIZE; gkcrypt->key_buf_populated -= KEY_BUF_CHUNK_SIZE; } - err = gkcrypt_generate_next_chunk(gkcrypt); if(err != CHIAKI_ERR_SUCCESS) break; diff --git a/lib/src/random.c b/lib/src/random.c index beaf373..d28cb7d 100644 --- a/lib/src/random.c +++ b/lib/src/random.c @@ -17,17 +17,52 @@ #include +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +//#include +#include +#include +#else #include +#endif CHIAKI_EXPORT ChiakiErrorCode chiaki_random_bytes_crypt(uint8_t *buf, size_t buf_size) { +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) + // mbedtls_havege_state hs; + // mbedtls_havege_init(&hs); + // int r = mbedtls_havege_random( &hs, buf, sizeof( buf ) ); + // if(r != 0 ) + // return CHIAKI_ERR_UNKNOWN; + // return CHIAKI_ERR_SUCCESS; + + // https://github.com/ARMmbed/mbedtls/blob/development/programs/random/gen_random_ctr_drbg.c + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF); + if(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) "RANDOM_GEN", 10 ) != 0 ){ + return CHIAKI_ERR_UNKNOWN; + } + if(mbedtls_ctr_drbg_random(&ctr_drbg, buf, buf_size) != 0){ + return CHIAKI_ERR_UNKNOWN; + } + + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return CHIAKI_ERR_SUCCESS; + +#else int r = RAND_bytes(buf, (int)buf_size); if(!r) return CHIAKI_ERR_UNKNOWN; return CHIAKI_ERR_SUCCESS; +#endif } CHIAKI_EXPORT uint32_t chiaki_random_32() { return rand() % UINT32_MAX; -} \ No newline at end of file +} diff --git a/lib/src/regist.c b/lib/src/regist.c index 947b713..a50504e 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -404,7 +404,7 @@ static chiaki_socket_t regist_search_connect(ChiakiRegist *regist, struct addrin set_port(send_addr, htons(REGIST_PORT)); - sock = socket(ai->ai_family, SOCK_DGRAM, 0); + sock = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP); if(CHIAKI_SOCKET_IS_INVALID(sock)) { CHIAKI_LOGE(regist->log, "Regist failed to create socket for search"); diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c index 708947f..f2982b6 100644 --- a/lib/src/rpcrypt.c +++ b/lib/src/rpcrypt.c @@ -17,12 +17,18 @@ #include +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) +#include "mbedtls/aes.h" +#include "mbedtls/md.h" +#else #include #include +#endif #include #include + static const uint8_t echo_b[] = { 0xe1, 0xec, 0x9c, 0x3a, 0xdd, 0xbd, 0x08, 0x85, 0xfc, 0x0e, 0x1d, 0x78, 0x90, 0x32, 0xc0, 0x04 }; CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning) @@ -77,6 +83,7 @@ CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint rpcrypt->bright[3] ^= (uint8_t)((pin >> 0x00) & 0xff); } +#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS) CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter) { uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 }; @@ -92,6 +99,93 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, buf[CHIAKI_RPCRYPT_KEY_SIZE + 6] = (uint8_t)((counter >> 0x08) & 0xff); buf[CHIAKI_RPCRYPT_KEY_SIZE + 7] = (uint8_t)((counter >> 0x00) & 0xff); + uint8_t hmac[CHIAKI_RPCRYPT_KEY_SIZE]; + unsigned int hmac_len = 0; + + + mbedtls_md_context_t ctx; + mbedtls_md_type_t type = MBEDTLS_MD_SHA256; + + mbedtls_md_init(&ctx); + +#define GOTO_ERROR(err) do { \ + if((err) !=0){ \ + goto error;} \ + } while(0) + // https://tls.mbed.org/module-level-design-hashing + GOTO_ERROR(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(type) , 1)); + GOTO_ERROR(mbedtls_md_hmac_starts(&ctx, hmac_key, sizeof(hmac_key))); + GOTO_ERROR(mbedtls_md_hmac_update(&ctx, (const unsigned char *) buf, sizeof(buf))); + GOTO_ERROR(mbedtls_md_hmac_finish(&ctx, hmac)); +#undef GOTO_ERROR + memcpy(iv, hmac, CHIAKI_RPCRYPT_KEY_SIZE); + mbedtls_md_free(&ctx); + return CHIAKI_ERR_SUCCESS; +error: + mbedtls_md_free(&ctx); + return CHIAKI_ERR_UNKNOWN; +} + + +static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz, bool encrypt) +{ + +#define GOTO_ERROR(err) do { \ + if((err) !=0){ \ + goto error;} \ + } while(0) + + // https://github.com/ARMmbed/mbedtls/blob/development/programs/aes/aescrypt2.c + // build aes context + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + + // initialization vector + uint8_t iv[CHIAKI_RPCRYPT_KEY_SIZE]; + ChiakiErrorCode err = chiaki_rpcrypt_generate_iv(rpcrypt, iv, counter); + if(err != CHIAKI_ERR_SUCCESS) + return err; + + GOTO_ERROR(mbedtls_aes_setkey_enc(&ctx, rpcrypt->bright, 128)); + size_t iv_off = 0; + if(encrypt) + { + GOTO_ERROR(mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, sz, &iv_off, iv, in, out)); + } + else + { + // the aes_crypt_cfb128 does not seems to use the setkey_dec + // GOTO_ERROR(mbedtls_aes_setkey_dec(&ctx, rpcrypt->bright, 128)); + GOTO_ERROR(mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, sz, &iv_off, iv, in, out)); + } + +#undef GOTO_ERROR + mbedtls_aes_free(&ctx); + + return CHIAKI_ERR_SUCCESS; + +error: + mbedtls_aes_free(&ctx); + return CHIAKI_ERR_UNKNOWN; +} + +#else +CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter) +{ + uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 }; + + uint8_t buf[CHIAKI_RPCRYPT_KEY_SIZE + 8]; + memcpy(buf, rpcrypt->ambassador, CHIAKI_RPCRYPT_KEY_SIZE); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 0] = (uint8_t)((counter >> 0x38) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 1] = (uint8_t)((counter >> 0x30) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 2] = (uint8_t)((counter >> 0x28) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 3] = (uint8_t)((counter >> 0x20) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 4] = (uint8_t)((counter >> 0x18) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 5] = (uint8_t)((counter >> 0x10) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 6] = (uint8_t)((counter >> 0x08) & 0xff); + buf[CHIAKI_RPCRYPT_KEY_SIZE + 7] = (uint8_t)((counter >> 0x00) & 0xff); + + uint8_t hmac[32]; unsigned int hmac_len = 0; if(!HMAC(EVP_sha256(), hmac_key, CHIAKI_RPCRYPT_KEY_SIZE, buf, sizeof(buf), hmac, &hmac_len)) @@ -150,6 +244,7 @@ static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t cou EVP_CIPHER_CTX_free(ctx); return CHIAKI_ERR_SUCCESS; } +#endif CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz) { diff --git a/lib/src/stoppipe.c b/lib/src/stoppipe.c index cb90309..3262a98 100644 --- a/lib/src/stoppipe.c +++ b/lib/src/stoppipe.c @@ -34,11 +34,36 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe) stop_pipe->event = WSACreateEvent(); if(stop_pipe->event == WSA_INVALID_EVENT) return CHIAKI_ERR_UNKNOWN; +#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + // currently pipe or socketpare are not available on switch + // use a custom udp socket as pipe + + // struct sockaddr_in addr; + int addr_size = sizeof(stop_pipe->addr); + + stop_pipe->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(stop_pipe->fd < 0){ + return CHIAKI_ERR_UNKNOWN; + } + stop_pipe->addr.sin_family = AF_INET; + // bind to localhost + stop_pipe->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + // use a random port (dedicate one socket per object) + stop_pipe->addr.sin_port = htons(0); + // bind on localhost + bind(stop_pipe->fd, (struct sockaddr *) &stop_pipe->addr, addr_size); + // listen + getsockname(stop_pipe->fd, (struct sockaddr *) &stop_pipe->addr, &addr_size); + int r = fcntl(stop_pipe->fd, F_SETFL, O_NONBLOCK); + if(r == -1) + { + close(stop_pipe->fd); + return CHIAKI_ERR_UNKNOWN; + } #else int r = pipe(stop_pipe->fds); if(r < 0) return CHIAKI_ERR_UNKNOWN; - r = fcntl(stop_pipe->fds[0], F_SETFL, O_NONBLOCK); if(r == -1) { @@ -47,7 +72,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe) return CHIAKI_ERR_UNKNOWN; } #endif - return CHIAKI_ERR_SUCCESS; } @@ -55,6 +79,8 @@ CHIAKI_EXPORT void chiaki_stop_pipe_fini(ChiakiStopPipe *stop_pipe) { #ifdef _WIN32 WSACloseEvent(stop_pipe->event); +#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + close(stop_pipe->fd); #else close(stop_pipe->fds[0]); close(stop_pipe->fds[1]); @@ -65,6 +91,10 @@ CHIAKI_EXPORT void chiaki_stop_pipe_stop(ChiakiStopPipe *stop_pipe) { #ifdef _WIN32 WSASetEvent(stop_pipe->event); +#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + // send to local socket (FIXME MSG_CONFIRM) + sendto(stop_pipe->fd, "\x00", 1, 0, + (struct sockaddr*)&stop_pipe->addr, sizeof(struct sockaddr_in)); #else write(stop_pipe->fds[1], "\x00", 1); #endif @@ -105,12 +135,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto #else fd_set rfds; FD_ZERO(&rfds); - FD_SET(stop_pipe->fds[0], &rfds); +#if defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + // push udp local socket as fd + int stop_fd = stop_pipe->fd; +#else + int stop_fd = stop_pipe->fds[0]; +#endif + FD_SET(stop_fd, &rfds); + int nfds = stop_fd; fd_set wfds; FD_ZERO(&wfds); - - int nfds = stop_pipe->fds[0]; if(!CHIAKI_SOCKET_IS_INVALID(fd)) { FD_SET(fd, write ? &wfds : &rfds); @@ -129,10 +164,11 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto } int r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout); + if(r < 0) return CHIAKI_ERR_UNKNOWN; - if(FD_ISSET(stop_pipe->fds[0], &rfds)) + if(FD_ISSET(stop_fd, &rfds)) return CHIAKI_ERR_CANCELED; if(!CHIAKI_SOCKET_IS_INVALID(fd) && FD_ISSET(fd, write ? &wfds : &rfds)) @@ -223,6 +259,12 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe) #ifdef _WIN32 BOOL r = WSAResetEvent(stop_pipe->event); return r ? CHIAKI_ERR_SUCCESS : CHIAKI_ERR_UNKNOWN; +#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX) + //FIXME + uint8_t v; + int r; + while((r = read(stop_pipe->fd, &v, sizeof(v))) > 0); + return r < 0 ? CHIAKI_ERR_UNKNOWN : CHIAKI_ERR_SUCCESS; #else uint8_t v; int r; diff --git a/lib/src/takion.c b/lib/src/takion.c index 89dbfda..9964a1d 100644 --- a/lib/src/takion.c +++ b/lib/src/takion.c @@ -28,6 +28,11 @@ #ifdef _WIN32 #include +#elif defined(__SWITCH__) +#include +#include +#include +#include #else #include #include @@ -252,7 +257,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, Chiaki #if defined(_WIN32) const DWORD dontfragment_val = 1; r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAGMENT, (const void *)&dontfragment_val, sizeof(dontfragment_val)); -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__SWITCH__) const int dontfrag_val = 1; r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAG, (const void *)&dontfrag_val, sizeof(dontfrag_val)); #elif defined(IP_PMTUDISC_DO) diff --git a/lib/src/thread.c b/lib/src/thread.c index 27efd2f..563a140 100644 --- a/lib/src/thread.c +++ b/lib/src/thread.c @@ -24,6 +24,10 @@ #include #include +#ifdef __SWITCH__ +#include +#endif + #if _WIN32 static DWORD WINAPI win32_thread_func(LPVOID param) { @@ -33,6 +37,18 @@ static DWORD WINAPI win32_thread_func(LPVOID param) } #endif +#ifdef __SWITCH__ +int64_t get_thread_limit(){ + uint64_t resource_limit_handle_value = INVALID_HANDLE; + svcGetInfo(&resource_limit_handle_value, InfoType_ResourceLimit, INVALID_HANDLE, 0); + int64_t thread_cur_value = 0, thread_lim_value = 0; + svcGetResourceLimitCurrentValue(&thread_cur_value, resource_limit_handle_value, LimitableResource_Threads); + svcGetResourceLimitLimitValue(&thread_lim_value, resource_limit_handle_value, LimitableResource_Threads); + //printf("thread_cur_value: %lu, thread_lim_value: %lu\n", thread_cur_value, thread_lim_value); + return thread_lim_value - thread_cur_value; +} +#endif + CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg) { #if _WIN32 @@ -43,6 +59,11 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiT if(!thread->thread) return CHIAKI_ERR_THREAD; #else +#ifdef __SWITCH__ + if(get_thread_limit() <= 1){ + return CHIAKI_ERR_THREAD; + } +#endif int r = pthread_create(&thread->thread, NULL, func, arg); if(r != 0) return CHIAKI_ERR_THREAD; diff --git a/scripts/switch/Dockerfile b/scripts/switch/Dockerfile new file mode 100644 index 0000000..cd59827 --- /dev/null +++ b/scripts/switch/Dockerfile @@ -0,0 +1,81 @@ +FROM docker.io/archlinux/base + +ENV DEVKITPRO=/opt/devkitpro +ENV DEVKITARM=/opt/devkitpro/devkitARM +ENV DEVKITPPC=/opt/devkitpro/devkitPPC +ENV PATH="${PATH}:${DEVKITARM}/bin/:${DEVKITPPC}/bin/" + + +ENV WORKDIR="/build" +WORKDIR "${WORKDIR}" + +# Upgarde image +RUN pacman --noconfirm -Syu + +# Install requirements for libtransistor +RUN pacman --noconfirm -S \ + llvm \ + clang \ + lld \ + python \ + python-pip \ + python-virtualenv \ + squashfs-tools \ + base-devel \ + git \ + cmake \ + libx11 \ + vim + +RUN pacman-key --init +# Install devkitpro +# doc source : +# https://devkitpro.org/wiki/devkitPro_pacman + +# First import the key which is used to validate the packages +RUN pacman-key --recv F7FD5492264BB9D0 +RUN pacman-key --lsign F7FD5492264BB9D0 + +# Add the devkitPro repositories +ADD devkit_repo ./devkit_repo +RUN cat ./devkit_repo >> /etc/pacman.conf +# Install the keyring which adds more keys which may be used to verify the packages. +RUN pacman --noconfirm -U https://downloads.devkitpro.org/devkitpro-keyring-r1.787e015-2-any.pkg.tar.xz +# Now resync the database and update installed packages. +RUN pacman -Sy + +RUN pacman --noconfirm -Syu + +#RUN pacman --noconfirm -S $(pacman -Slq dkp-libs) + +RUN pacman --noconfirm -S \ + protobuf \ + python-protobuf \ + sfml \ + devkitARM \ + switch-pkg-config \ + devkitpro-pkgbuild-helpers \ + switch-dev \ + switch-zlib \ + switch-sdl2 \ + switch-freetype \ + switch-curl \ + switch-mesa \ + switch-glad \ + switch-glm \ + switch-libconfig \ + switch-sdl2_gfx \ + switch-sdl2_ttf \ + switch-sdl2_image \ + switch-libexpat \ + switch-bzip2 \ + switch-libopus \ + switch-ffmpeg \ + switch-mbedtls + +RUN pip3 install -U pip + +VOLUME ${WORKDIR} +# nxlink server port +EXPOSE 28771 +ENTRYPOINT ["/bin/bash"] diff --git a/scripts/switch/build.sh b/scripts/switch/build.sh new file mode 100755 index 0000000..fb8bf6f --- /dev/null +++ b/scripts/switch/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -xveo pipefail + +arg1=$1 +CHIAKI_ENABLE_SWITCH_LINUX="ON" +build="./build" +if [ "$arg1" != "linux" ]; then + CHIAKI_ENABLE_SWITCH_LINUX="OFF" + source /opt/devkitpro/switchvars.sh + toolchain=/opt/devkitpro/switch.cmake + + export CC=${TOOL_PREFIX}gcc + export CXX=${TOOL_PREFIX}g++ + build="./build_switch" +fi + +SCRIPTDIR=$(dirname "$0") +BASEDIR=$(realpath "${SCRIPTDIR}/../../") + +build_chiaki (){ + pushd "${BASEDIR}" + #rm -rf ./build + + cmake -B "${build}" -DCMAKE_TOOLCHAIN_FILE=${toolchain} \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ + -DCHIAKI_ENABLE_TESTS=OFF \ + -DCHIAKI_ENABLE_CLI=OFF \ + -DCHIAKI_ENABLE_GUI=OFF \ + -DCHIAKI_ENABLE_ANDROID=OFF \ + -DCHIAKI_ENABLE_SWITCH=ON \ + -DCHIAKI_ENABLE_SWITCH_LINUX="${CHIAKI_ENABLE_SWITCH_LINUX}" \ + -DCHIAKI_LIB_ENABLE_MBEDTLS=ON + + pushd "${BASEDIR}/${build}/switch/" + make + popd + popd +} + +build_chiaki + diff --git a/scripts/switch/devkit_repo b/scripts/switch/devkit_repo new file mode 100644 index 0000000..2646e2d --- /dev/null +++ b/scripts/switch/devkit_repo @@ -0,0 +1,6 @@ +[dkp-libs] +Server = http://downloads.devkitpro.org/packages + +[dkp-linux] +Server = http://downloads.devkitpro.org/packages/linux + diff --git a/scripts/switch/fake_ctest.nintendo.net.py b/scripts/switch/fake_ctest.nintendo.net.py new file mode 100644 index 0000000..b4cb83d --- /dev/null +++ b/scripts/switch/fake_ctest.nintendo.net.py @@ -0,0 +1,31 @@ +# simple python3 http server to emulate ctest.nintendo.net +# you have to redirect nintendo.net to your own host +# https://gitlab.com/a/90dns + +# the aim is to fake ctest.nintendo.net server +# to allow nintendo switch lan connection + +# The nintendo switch tries to join ctest to validate wifi settings +# without 200 OK from ctest.nintendo.net, the LAN connection is denied + +import http.server +import socketserver + +from http.server import HTTPServer, BaseHTTPRequestHandler + + +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_GET(self): + self.send_response(200) + self.send_header("Content-Type", "text/plain") + self.send_header("X-Organization", "Nintendo") + self.end_headers() + self.wfile.write(b'ok') + + +PORT = 80 + +httpd = HTTPServer(('0.0.0.0', PORT), SimpleHTTPRequestHandler) +httpd.serve_forever() +