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

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

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,17 +17,52 @@
#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()
{
return rand() % UINT32_MAX;
}
}

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;