Add Nintendo Switch chiaki-lib support (#233)

This commit is contained in:
H0neyBadger 2020-05-15 11:06:54 +02:00 committed by GitHub
commit f35311bf61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 771 additions and 20 deletions

View file

@ -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()

99
cmake/switch.cmake Normal file
View file

@ -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} $<TARGET_FILE:${target}> ${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()

View file

@ -99,13 +99,23 @@ 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)

View file

@ -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);

View file

@ -26,6 +26,8 @@
#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#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

View file

@ -23,6 +23,9 @@
#include <netinet/in.h>
#endif
#ifdef __SWITCH__
#include <arpa/inet.h>
#endif
void chiaki_audio_header_load(ChiakiAudioHeader *audio_header, const uint8_t *buf)
{

View file

@ -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

View file

@ -19,23 +19,58 @@
#include <chiaki/ecdh.h>
#include <chiaki/base64.h>
#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
#include "mbedtls/entropy.h"
#include "mbedtls/md.h"
#else
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/hmac.h>
#include <openssl/bn.h>
#include <openssl/ecdh.h>
#endif
// memset
#include <string.h>
#include <stdio.h>
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
}

View file

@ -21,9 +21,16 @@
#include <string.h>
#include <assert.h>
#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 <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#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; i<buf_size; i=i+16){
// loop over all blocks of 16 bytes (128 bits)
if(mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, buf+i, buf+i) != 0){
mbedtls_aes_free(&ctx);
return CHIAKI_ERR_UNKNOWN;
}
}
mbedtls_aes_free(&ctx);
#else
int outl;
EVP_EncryptUpdate(ctx, buf, &outl, buf, (int)buf_size);
if(outl != buf_size)
@ -219,6 +282,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry
}
EVP_CIPHER_CTX_free(ctx);
#endif
return CHIAKI_ERR_SUCCESS;
}
@ -310,6 +374,38 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gmac(ChiakiGKCrypt *gkcrypt, size_t
gmac_key = gmac_key_tmp;
}
#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
// build mbedtls gcm context AES_128_GCM
// Encryption
mbedtls_gcm_context actx;
mbedtls_gcm_init(&actx);
// set gmac_key 128 bits key
if(mbedtls_gcm_setkey(&actx, MBEDTLS_CIPHER_ID_AES, gmac_key, CHIAKI_GKCRYPT_BLOCK_SIZE*8) != 0){
mbedtls_gcm_free(&actx);
return CHIAKI_ERR_UNKNOWN;
}
// encrypt without additional data
if(mbedtls_gcm_starts(&actx, MBEDTLS_GCM_ENCRYPT, iv, CHIAKI_GKCRYPT_BLOCK_SIZE, NULL, 0) != 0){
mbedtls_gcm_free(&actx);
return CHIAKI_ERR_UNKNOWN;
}
// set "additional data" only whitout input nor output
// to get the same result as:
// EVP_EncryptUpdate(ctx, NULL, &len, buf, (int)buf_size)
if(mbedtls_gcm_crypt_and_tag(&actx, MBEDTLS_GCM_ENCRYPT,
0, iv, CHIAKI_GKCRYPT_BLOCK_SIZE,
buf, buf_size, NULL, NULL,
CHIAKI_GKCRYPT_GMAC_SIZE, gmac_out) != 0){
mbedtls_gcm_free(&actx);
return CHIAKI_ERR_UNKNOWN;
}
mbedtls_gcm_free(&actx);
return CHIAKI_ERR_SUCCESS;
#else
ChiakiErrorCode ret = CHIAKI_ERR_SUCCESS;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
@ -360,6 +456,7 @@ fail_cipher:
EVP_CIPHER_CTX_free(ctx);
fail:
return ret;
#endif
}
static bool key_buf_mutex_pred(void *user)
@ -401,15 +498,14 @@ static ChiakiErrorCode gkcrypt_generate_next_chunk(ChiakiGKCrypt *gkcrypt)
static void *gkcrypt_thread_func(void *user)
{
ChiakiGKCrypt *gkcrypt = user;
CHIAKI_LOGV(gkcrypt->log, "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;

View file

@ -17,14 +17,49 @@
#include <chiaki/random.h>
#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
//#include <mbedtls/havege.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#else
#include <openssl/rand.h>
#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()

View file

@ -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");

View file

@ -17,12 +17,18 @@
#include <chiaki/rpcrypt.h>
#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
#else
#include <openssl/hmac.h>
#include <openssl/evp.h>
#endif
#include <string.h>
#include <stdbool.h>
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)
{

View file

@ -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;

View file

@ -28,6 +28,11 @@
#ifdef _WIN32
#include <ws2tcpip.h>
#elif defined(__SWITCH__)
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#include <unistd.h>
#include <netinet/in.h>
@ -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)

View file

@ -24,6 +24,10 @@
#include <stdlib.h>
#include <errno.h>
#ifdef __SWITCH__
#include <switch.h>
#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;

81
scripts/switch/Dockerfile Normal file
View file

@ -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"]

42
scripts/switch/build.sh Executable file
View file

@ -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

View file

@ -0,0 +1,6 @@
[dkp-libs]
Server = http://downloads.devkitpro.org/packages
[dkp-linux]
Server = http://downloads.devkitpro.org/packages/linux

View file

@ -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()