diff --git a/source/libwolfssl/internal.h b/source/libwolfssl/internal.h index ef2c4bf0..7a425fb5 100644 --- a/source/libwolfssl/internal.h +++ b/source/libwolfssl/internal.h @@ -1634,14 +1634,14 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); #ifdef WOLFSSL_SESSION_EXPORT - WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, + WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, const byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, - byte* buf, word32 sz); + const byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl); #endif #endif @@ -4167,6 +4167,8 @@ struct WOLFSSL { #endif /* HAVE_TLS_EXTENSIONS */ #ifdef HAVE_OCSP void* ocspIOCtx; + byte ocspProducedDate[MAX_DATE_SZ]; + int ocspProducedDateFormat; #ifdef OPENSSL_EXTRA byte* ocspResp; int ocspRespSz; diff --git a/source/libwolfssl/libwolfssl.a b/source/libwolfssl/libwolfssl.a index b36fabce..e98409f4 100644 Binary files a/source/libwolfssl/libwolfssl.a and b/source/libwolfssl/libwolfssl.a differ diff --git a/source/libwolfssl/openssl/evp.h b/source/libwolfssl/openssl/evp.h index c7ae6488..89cb26cf 100644 --- a/source/libwolfssl/openssl/evp.h +++ b/source/libwolfssl/openssl/evp.h @@ -354,10 +354,12 @@ struct WOLFSSL_EVP_CIPHER_CTX { #define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV int ivSz; #ifdef HAVE_AESGCM - byte* gcmDecryptBuffer; - int gcmDecryptBufferLen; + byte* gcmBuffer; + int gcmBufferLen; ALIGN16 unsigned char authTag[AES_BLOCK_SIZE]; int authTagSz; + byte* gcmAuthIn; + int gcmAuthInSz; #endif #endif }; diff --git a/source/libwolfssl/ssl.h b/source/libwolfssl/ssl.h index b160b824..0f89d508 100644 --- a/source/libwolfssl/ssl.h +++ b/source/libwolfssl/ssl.h @@ -743,7 +743,7 @@ typedef int (*wc_dtls_export)(WOLFSSL* ssl, #define WOLFSSL_DTLS_EXPORT_TYPES #endif /* WOLFSSL_DTLS_EXPORT_TYPES */ -WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, +WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz); WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func); @@ -3735,6 +3735,16 @@ WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); #endif +#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME) + WOLFSSL_API int wolfSSL_get_ocsp_producedDate( + WOLFSSL *ssl, + byte *producedDate, + size_t producedDate_space, + int *producedDateFormat); + WOLFSSL_API int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, + struct tm *produced_tm); +#endif + #if defined(OPENSSL_ALL) \ || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) \ diff --git a/source/libwolfssl/wolfcrypt/aes.h b/source/libwolfssl/wolfcrypt/aes.h index 9e60768c..b45ad78b 100644 --- a/source/libwolfssl/wolfcrypt/aes.h +++ b/source/libwolfssl/wolfcrypt/aes.h @@ -62,6 +62,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif +#ifdef WOLFSSL_IMXRT_DCP + #include "fsl_dcp.h" +#endif #ifdef WOLFSSL_XILINX_CRYPT #include "xsecure_aes.h" @@ -225,6 +228,9 @@ struct Aes { #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT) TSIP_AES_CTX ctx; +#endif +#if defined(WOLFSSL_IMXRT_DCP) + dcp_handle_t handle; #endif void* heap; /* memory hint to use */ }; diff --git a/source/libwolfssl/wolfcrypt/asn.h b/source/libwolfssl/wolfcrypt/asn.h index 8a05e48e..0266cc79 100644 --- a/source/libwolfssl/wolfcrypt/asn.h +++ b/source/libwolfssl/wolfcrypt/asn.h @@ -538,7 +538,9 @@ enum Extensions_Sum { POLICY_CONST_OID = 150, ISSUE_ALT_NAMES_OID = 132, TLS_FEATURE_OID = 92, /* id-pe 24 */ - NETSCAPE_CT_OID = 753 /* 2.16.840.1.113730.1.1 */ + NETSCAPE_CT_OID = 753, /* 2.16.840.1.113730.1.1 */ + OCSP_NOCHECK_OID = 121 /* 1.3.6.1.5.5.7.48.1.5 + id-pkix-ocsp-nocheck */ }; enum CertificatePolicy_Sum { @@ -909,6 +911,9 @@ struct DecodedCert { byte weOwnAltNames : 1; /* altNames haven't been given to copy */ byte extKeyUsageSet : 1; byte extExtKeyUsageSet : 1; /* Extended Key Usage set */ +#ifdef HAVE_OCSP + byte ocspNoCheckSet : 1; /* id-pkix-ocsp-nocheck set */ +#endif byte extCRLdistSet : 1; byte extAuthInfoSet : 1; byte extBasicConstSet : 1; diff --git a/source/libwolfssl/wolfcrypt/chacha.h b/source/libwolfssl/wolfcrypt/chacha.h index 2582678f..40468e3c 100644 --- a/source/libwolfssl/wolfcrypt/chacha.h +++ b/source/libwolfssl/wolfcrypt/chacha.h @@ -79,7 +79,7 @@ typedef struct ChaCha { byte extra[12]; #endif word32 left; /* number of bytes leftover */ -#ifdef USE_INTEL_CHACHA_SPEEDUP +#if defined(USE_INTEL_CHACHA_SPEEDUP) || defined(WOLFSSL_ARMASM) word32 over[CHACHA_CHUNK_WORDS]; #endif } ChaCha; diff --git a/source/libwolfssl/wolfcrypt/ecc.h b/source/libwolfssl/wolfcrypt/ecc.h index d45ef3fa..9ed42d76 100644 --- a/source/libwolfssl/wolfcrypt/ecc.h +++ b/source/libwolfssl/wolfcrypt/ecc.h @@ -471,6 +471,10 @@ ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp); +WOLFSSL_LOCAL +int ecc_projective_add_point_safe(ecc_point* A, ecc_point* B, ecc_point* R, + mp_int* a, mp_int* modulus, mp_digit mp, int* infinity); + #endif WOLFSSL_API diff --git a/source/libwolfssl/wolfcrypt/integer.h b/source/libwolfssl/wolfcrypt/integer.h index 1406ab7e..d62c54c2 100644 --- a/source/libwolfssl/wolfcrypt/integer.h +++ b/source/libwolfssl/wolfcrypt/integer.h @@ -305,6 +305,7 @@ MP_API int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); MP_API void mp_zero (mp_int * a); MP_API void mp_clamp (mp_int * a); MP_API void mp_exch (mp_int * a, mp_int * b); +MP_API int mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m); MP_API void mp_rshd (mp_int * a, int b); MP_API void mp_rshb (mp_int * a, int b); MP_API int mp_mod_2d (mp_int * a, int b, mp_int * c); diff --git a/source/libwolfssl/wolfcrypt/port/nxp/dcp_port.h b/source/libwolfssl/wolfcrypt/port/nxp/dcp_port.h new file mode 100644 index 00000000..87099da8 --- /dev/null +++ b/source/libwolfssl/wolfcrypt/port/nxp/dcp_port.h @@ -0,0 +1,77 @@ +/* dcp_port.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifndef _DCP_PORT_H_ +#define _DCP_PORT_H_ + +#include +#ifdef USE_FAST_MATH + #include +#elif defined WOLFSSL_SP_MATH + #include +#else + #include +#endif + +#include +#include +#include "fsl_device_registers.h" +#include "fsl_debug_console.h" +#include "fsl_dcp.h" + +int wc_dcp_init(void); + +#ifndef NO_AES +int DCPAesInit(Aes* aes); +void DCPAesFree(Aes *aes); + +int DCPAesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir); +int DCPAesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); +int DCPAesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); +#endif + +#ifdef HAVE_AES_ECB +int DCPAesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); +int DCPAesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); +#endif + +#ifndef NO_SHA256 +typedef struct wc_Sha256_DCP { + dcp_handle_t handle; + dcp_hash_ctx_t ctx; +} wc_Sha256; +#define WC_SHA256_TYPE_DEFINED + +void DCPSha256Free(wc_Sha256 *sha256); + +#endif + +#ifndef NO_SHA +typedef struct wc_Sha_DCP { + dcp_handle_t handle; + dcp_hash_ctx_t ctx; +} wc_Sha; +#define WC_SHA_TYPE_DEFINED + +void DCPShaFree(wc_Sha *sha); +#endif + +#endif diff --git a/source/libwolfssl/wolfcrypt/settings.h b/source/libwolfssl/wolfcrypt/settings.h index 5efa1afb..a305cec7 100644 --- a/source/libwolfssl/wolfcrypt/settings.h +++ b/source/libwolfssl/wolfcrypt/settings.h @@ -1091,7 +1091,9 @@ extern void uITRON4_free(void *p) ; /* random seed */ #define NO_OLD_RNGNAME - #if defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0) + #if defined(FREESCALE_NO_RNG) + /* nothing to define */ + #elif defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0) #define FREESCALE_KSDK_2_0_TRNG #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0) #ifdef FREESCALE_KSDK_1_3 @@ -1621,6 +1623,12 @@ extern void uITRON4_free(void *p) ; #endif #endif +/* If DCP is used without SINGLE_THREADED, enforce WOLFSSL_CRYPT_HW_MUTEX */ +#if defined(WOLFSSL_IMXRT_DCP) && !defined(SINGLE_THREADED) + #undef WOLFSSL_CRYPT_HW_MUTEX + #define WOLFSSL_CRYPT_HW_MUTEX 1 +#endif + #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \ !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ !defined(XMALLOC_OVERRIDE) @@ -2124,10 +2132,18 @@ extern void uITRON4_free(void *p) ; #define SIZEOF_LONG 8 #define SIZEOF_LONG_LONG 8 #define CHAR_BIT 8 - #define WOLFSSL_SP_DIV_64 - #define WOLFSSL_SP_DIV_WORD_HALF - #define SP_HALF_SIZE 32 - #define SP_HALF_MAX 4294967295U + #ifndef WOLFSSL_SP_DIV_64 + #define WOLFSSL_SP_DIV_64 + #endif + #ifndef WOLFSSL_SP_DIV_WORD_HALF + #define WOLFSSL_SP_DIV_WORD_HALF + #endif + #ifndef SP_HALF_SIZE + #define SP_HALF_SIZE 32 + #endif + #ifndef SP_HALF_MAX + #define SP_HALF_MAX 4294967295U + #endif #endif diff --git a/source/libwolfssl/wolfcrypt/sha.h b/source/libwolfssl/wolfcrypt/sha.h index 428599c1..61267b63 100644 --- a/source/libwolfssl/wolfcrypt/sha.h +++ b/source/libwolfssl/wolfcrypt/sha.h @@ -72,6 +72,9 @@ #ifdef WOLFSSL_ESP32WROOM32_CRYPT #include #endif +#ifdef WOLFSSL_IMXRT_DCP + #include +#endif #if !defined(NO_OLD_SHA_NAMES) #define SHA WC_SHA diff --git a/source/libwolfssl/wolfcrypt/sha256.h b/source/libwolfssl/wolfcrypt/sha256.h index e6964d30..ee460d19 100644 --- a/source/libwolfssl/wolfcrypt/sha256.h +++ b/source/libwolfssl/wolfcrypt/sha256.h @@ -128,6 +128,8 @@ enum { #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" #elif defined(WOLFSSL_PSOC6_CRYPTO) #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h" +#elif defined(WOLFSSL_IMXRT_DCP) + #include #else /* wc_Sha256 digest */ diff --git a/source/libwolfssl/wolfcrypt/tfm.h b/source/libwolfssl/wolfcrypt/tfm.h index 10af218a..f328f24b 100644 --- a/source/libwolfssl/wolfcrypt/tfm.h +++ b/source/libwolfssl/wolfcrypt/tfm.h @@ -832,6 +832,7 @@ MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c); MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); MP_API int mp_exch(mp_int *a, mp_int *b); #endif /* WOLFSSL_KEY_GEN */ +MP_API int mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m); MP_API int mp_cnt_lsb(fp_int *a); MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); diff --git a/source/libwolfssl/wolfcrypt/wc_port.h b/source/libwolfssl/wolfcrypt/wc_port.h index 9ef56da4..d5225309 100644 --- a/source/libwolfssl/wolfcrypt/wc_port.h +++ b/source/libwolfssl/wolfcrypt/wc_port.h @@ -158,8 +158,8 @@ #else /* ! WOLFSSL_LINUXKM */ #ifdef BUILDING_WOLFSSL - #define SAVE_VECTOR_REGISTERS() ({}) - #define RESTORE_VECTOR_REGISTERS() ({}) + #define SAVE_VECTOR_REGISTERS() do{}while(0) + #define RESTORE_VECTOR_REGISTERS() do{}while(0) #endif #endif /* WOLFSSL_LINUXKM */ @@ -836,11 +836,12 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif #endif #if !defined(XGMTIME) && !defined(TIME_OVERRIDES) - #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) - #define XGMTIME(c, t) gmtime((c)) - #else + /* Always use gmtime_r if available. */ + #if defined(HAVE_GMTIME_R) #define XGMTIME(c, t) gmtime_r((c), (t)) #define NEED_TMP_TIME + #else + #define XGMTIME(c, t) gmtime((c)) #endif #endif #if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE) diff --git a/source/network/base64.h b/source/network/base64.h index 388c945b..5b5c10a1 100644 --- a/source/network/base64.h +++ b/source/network/base64.h @@ -70,104 +70,104 @@ static const unsigned char unb64[]={ // (you must pass pointer flen). char *base64(const void *binaryData, int len, int *flen) { - const unsigned char *bin = (const unsigned char *)binaryData; - char *res; + const unsigned char *bin = (const unsigned char *)binaryData; + char *res; - int rc = 0; // result counter - int byteNo; // I need this after the loop + int rc = 0; // result counter + int byteNo; // I need this after the loop - int modulusLen = len % 3; - int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0. + int modulusLen = len % 3; + int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0. - *flen = 4 * (len + pad) / 3; - res = (char *)MEM2_alloc(*flen + 1); // and one for the null - if (!res) - return 0; + *flen = 4 * (len + pad) / 3; + res = (char *)MEM2_alloc(*flen + 1); // and one for the null + if (!res) + return 0; - for (byteNo = 0; byteNo <= len - 3; byteNo += 3) - { - unsigned char BYTE0 = bin[byteNo]; - unsigned char BYTE1 = bin[byteNo + 1]; - unsigned char BYTE2 = bin[byteNo + 2]; - res[rc++] = b64[BYTE0 >> 2]; - res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)]; - res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)]; - res[rc++] = b64[0x3f & BYTE2]; - } + for (byteNo = 0; byteNo <= len - 3; byteNo += 3) + { + unsigned char BYTE0 = bin[byteNo]; + unsigned char BYTE1 = bin[byteNo + 1]; + unsigned char BYTE2 = bin[byteNo + 2]; + res[rc++] = b64[BYTE0 >> 2]; + res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)]; + res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)]; + res[rc++] = b64[0x3f & BYTE2]; + } - if (pad == 2) - { - res[rc++] = b64[bin[byteNo] >> 2]; - res[rc++] = b64[(0x3 & bin[byteNo]) << 4]; - res[rc++] = '='; - res[rc++] = '='; - } - else if (pad == 1) - { - res[rc++] = b64[bin[byteNo] >> 2]; - res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)]; - res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2]; - res[rc++] = '='; - } + if (pad == 2) + { + res[rc++] = b64[bin[byteNo] >> 2]; + res[rc++] = b64[(0x3 & bin[byteNo]) << 4]; + res[rc++] = '='; + res[rc++] = '='; + } + else if (pad == 1) + { + res[rc++] = b64[bin[byteNo] >> 2]; + res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)]; + res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2]; + res[rc++] = '='; + } - res[rc] = 0; // NULL TERMINATOR!;) - return res; + res[rc] = 0; // NULL TERMINATOR!;) + return res; } unsigned char *unbase64(const char *ascii, int len, int *flen) { - const unsigned char *safeAsciiPtr = (const unsigned char *)ascii; - unsigned char *bin; - int cb = 0; - int charNo; - int pad = 0; + const unsigned char *safeAsciiPtr = (const unsigned char *)ascii; + unsigned char *bin; + int cb = 0; + int charNo; + int pad = 0; - if ((len <= 0) || (len % 4 != 0)) - { // 2 accesses below would be OOB. - // catch empty string or incorrect padding size, return NULL as result. - *flen = 0; - return 0; - } - if (safeAsciiPtr[len - 1] == '=') - ++pad; - if (safeAsciiPtr[len - 2] == '=') - ++pad; + if ((len <= 0) || (len % 4 != 0)) + { // 2 accesses below would be OOB. + // catch empty string or incorrect padding size, return NULL as result. + *flen = 0; + return 0; + } + if (safeAsciiPtr[len - 1] == '=') + ++pad; + if (safeAsciiPtr[len - 2] == '=') + ++pad; - *flen = 3 * len / 4 - pad; - bin = (unsigned char *)MEM2_alloc(*flen); - if (!bin) - return 0; + *flen = 3 * len / 4 - pad; + bin = (unsigned char *)MEM2_alloc(*flen); + if (!bin) + return 0; - for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) - { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; - int C = unb64[safeAsciiPtr[charNo + 2]]; - int D = unb64[safeAsciiPtr[charNo + 3]]; + for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) + { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; + int C = unb64[safeAsciiPtr[charNo + 2]]; + int D = unb64[safeAsciiPtr[charNo + 3]]; - bin[cb++] = (A << 2) | (B >> 4); - bin[cb++] = (B << 4) | (C >> 2); - bin[cb++] = (C << 6) | (D); - } + bin[cb++] = (A << 2) | (B >> 4); + bin[cb++] = (B << 4) | (C >> 2); + bin[cb++] = (C << 6) | (D); + } - if (pad == 1) - { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; - int C = unb64[safeAsciiPtr[charNo + 2]]; + if (pad == 1) + { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; + int C = unb64[safeAsciiPtr[charNo + 2]]; - bin[cb++] = (A << 2) | (B >> 4); - bin[cb++] = (B << 4) | (C >> 2); - } - else if (pad == 2) - { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; + bin[cb++] = (A << 2) | (B >> 4); + bin[cb++] = (B << 4) | (C >> 2); + } + else if (pad == 2) + { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; - bin[cb++] = (A << 2) | (B >> 4); - } + bin[cb++] = (A << 2) | (B >> 4); + } - return bin; + return bin; } #endif diff --git a/source/network/https.c b/source/network/https.c index e07c1bb7..84cc5147 100644 --- a/source/network/https.c +++ b/source/network/https.c @@ -16,559 +16,565 @@ WOLFSSL_SESSION *session; int https_write(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy) { - int ret, pos = 0; - int rlen = len > BLOCK_SIZE ? BLOCK_SIZE : len; - u64 time = gettime(); - while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) - { - if (httpinfo->use_https && !proxy) - ret = wolfSSL_write(httpinfo->ssl, &buffer[pos], rlen); - else - ret = net_write(httpinfo->sock, &buffer[pos], rlen); - if (ret > 0) - { - pos += ret; - rlen = len - pos > BLOCK_SIZE ? BLOCK_SIZE : len - pos; - if (pos >= len) - return pos; - time = gettime(); - } - usleep(10000); - } + int ret, pos = 0; + int rlen = len > BLOCK_SIZE ? BLOCK_SIZE : len; + u64 time = gettime(); + while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) + { + if (httpinfo->use_https && !proxy) + ret = wolfSSL_write(httpinfo->ssl, &buffer[pos], rlen); + else + ret = net_write(httpinfo->sock, &buffer[pos], rlen); + if (ret > 0) + { + pos += ret; + rlen = len - pos > BLOCK_SIZE ? BLOCK_SIZE : len - pos; + if (pos >= len) + return pos; + time = gettime(); + } + usleep(10000); + } #ifdef DEBUG_NETWORK - gprintf("The connection timed out (write)\n"); + gprintf("The connection timed out (write)\n"); #endif - return -ETIMEDOUT; + return -ETIMEDOUT; } int https_read(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy) { - int ret = -ETIMEDOUT; - u64 time = gettime(); - if (len > BLOCK_SIZE) - len = BLOCK_SIZE; - while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) - { - if (httpinfo->use_https && !proxy) - ret = wolfSSL_read(httpinfo->ssl, buffer, len); - else - ret = net_read(httpinfo->sock, buffer, len); - if (ret >= 0) - return ret; - usleep(10000); - } + int ret = -ETIMEDOUT; + u64 time = gettime(); + if (len > BLOCK_SIZE) + len = BLOCK_SIZE; + while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) + { + if (httpinfo->use_https && !proxy) + ret = wolfSSL_read(httpinfo->ssl, buffer, len); + else + ret = net_read(httpinfo->sock, buffer, len); + if (ret >= 0) + return ret; + usleep(10000); + } #ifdef DEBUG_NETWORK - gprintf("The connection timed out (read)\n"); + gprintf("The connection timed out (read)\n"); #endif - return -ETIMEDOUT; + return -ETIMEDOUT; } int send_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx) { - int sent = net_write(*(int *)ctx, buf, sz); - if (sent < 0) - { - if (sent == -EAGAIN) - return WOLFSSL_CBIO_ERR_WANT_WRITE; - else if (sent == -ECONNRESET) - return WOLFSSL_CBIO_ERR_CONN_RST; - else if (sent == -EINTR) - return WOLFSSL_CBIO_ERR_ISR; - else if (sent == -EPIPE) - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - else - return WOLFSSL_CBIO_ERR_GENERAL; - } - return sent; + int sent = net_write(*(int *)ctx, buf, sz); + if (sent < 0) + { + if (sent == -EAGAIN) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + else if (sent == -ECONNRESET) + return WOLFSSL_CBIO_ERR_CONN_RST; + else if (sent == -EINTR) + return WOLFSSL_CBIO_ERR_ISR; + else if (sent == -EPIPE) + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + else + return WOLFSSL_CBIO_ERR_GENERAL; + } + return sent; } int recv_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx) { - int recvd = net_read(*(int *)ctx, buf, sz); - if (recvd < 0) - { - if (recvd == -EAGAIN) - return WOLFSSL_CBIO_ERR_WANT_READ; - else if (recvd == -ECONNRESET) - return WOLFSSL_CBIO_ERR_CONN_RST; - else if (recvd == -EINTR) - return WOLFSSL_CBIO_ERR_ISR; - else if (recvd == -ECONNABORTED) - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - else - return WOLFSSL_CBIO_ERR_GENERAL; - } - else if (recvd == 0) - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - return recvd; + int recvd = net_read(*(int *)ctx, buf, sz); + if (recvd < 0) + { + if (recvd == -EAGAIN) + return WOLFSSL_CBIO_ERR_WANT_READ; + else if (recvd == -ECONNRESET) + return WOLFSSL_CBIO_ERR_CONN_RST; + else if (recvd == -EINTR) + return WOLFSSL_CBIO_ERR_ISR; + else if (recvd == -ECONNABORTED) + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + else + return WOLFSSL_CBIO_ERR_GENERAL; + } + else if (recvd == 0) + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + return recvd; } void https_close(HTTP_INFO *httpinfo) { - if (httpinfo->use_https) - { - wolfSSL_shutdown(httpinfo->ssl); - wolfSSL_free(httpinfo->ssl); - wolfSSL_CTX_free(httpinfo->ctx); - } - net_close(httpinfo->sock); + if (httpinfo->use_https) + { + wolfSSL_shutdown(httpinfo->ssl); + wolfSSL_free(httpinfo->ssl); + wolfSSL_CTX_free(httpinfo->ctx); + } + net_close(httpinfo->sock); #ifdef DEBUG_NETWORK - gprintf("Closed socket and cleaned up\n"); + gprintf("Closed socket and cleaned up\n"); #endif } bool get_header_value(struct phr_header *headers, size_t num_headers, char *dst, char *header) { - for (size_t i = 0; i != num_headers; ++i) - { - if (strncasecmp(header, headers[i].name, headers[i].name_len) == 0) - { - strlcpy(dst, headers[i].value, headers[i].value_len + 1); - return true; - } - } - return false; + for (size_t i = 0; i != num_headers; ++i) + { + if (strncasecmp(header, headers[i].name, headers[i].name_len) == 0) + { + strlcpy(dst, headers[i].value, headers[i].value_len + 1); + return true; + } + } + return false; } u64 get_header_value_int(struct phr_header *headers, size_t num_headers, char *header) { - char header_value[30]; - if (!get_header_value(headers, num_headers, header_value, header)) - return 0; - return strtoull(header_value, NULL, 0); + char header_value[30]; + if (!get_header_value(headers, num_headers, header_value, header)) + return 0; + return strtoull(header_value, NULL, 0); } bool is_chunked(struct phr_header *headers, size_t num_headers) { - char encoding[9]; - if (!get_header_value(headers, num_headers, encoding, "transfer-encoding")) - return false; - return (strcasecmp(encoding, "chunked") == 0); + char encoding[9]; + if (!get_header_value(headers, num_headers, encoding, "transfer-encoding")) + return false; + return (strcasecmp(encoding, "chunked") == 0); } bool read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) { - struct phr_chunked_decoder decoder = {0}; - size_t rsize, capacity = 4096; - ssize_t pret; - int ret; - decoder.consume_trailer = true; + struct phr_chunked_decoder decoder = {0}; + size_t rsize, capacity = 4096; + ssize_t pret; + int ret; + decoder.consume_trailer = true; #ifdef DEBUG_NETWORK - gprintf("Data is chunked\n"); + gprintf("Data is chunked\n"); #endif - do - { - if (start_pos == capacity) - { + do + { + if (start_pos == capacity) + { #ifdef DEBUG_NETWORK - gprintf("Increased buffer size\n"); + gprintf("Increased buffer size\n"); #endif - capacity *= 2; - buffer->data = MEM2_realloc(buffer->data, capacity); - } - if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) < 1) - return false; - rsize = ret; - pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize); - if (pret == -1) - { + capacity *= 2; + buffer->data = MEM2_realloc(buffer->data, capacity); + } + if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) < 1) + return false; + rsize = ret; + pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize); + if (pret == -1) + { #ifdef DEBUG_NETWORK - gprintf("Parse error\n"); + gprintf("Parse error\n"); #endif - return false; - } - start_pos += rsize; - } while (pret == -2); - buffer->size = start_pos; - buffer->data = MEM2_realloc(buffer->data, buffer->size); - return true; + return false; + } + start_pos += rsize; + } while (pret == -2); + buffer->size = start_pos; + buffer->data = MEM2_realloc(buffer->data, buffer->size); + return true; } bool read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) { - size_t capacity = 4096; - int ret; + size_t capacity = 4096; + int ret; #ifdef DEBUG_NETWORK - gprintf("Data is not chunked\n"); + gprintf("Data is not chunked\n"); #endif - while (true) - { - if (start_pos == capacity) - { + while (true) + { + if (start_pos == capacity) + { #ifdef DEBUG_NETWORK - gprintf("Increased buffer size\n"); + gprintf("Increased buffer size\n"); #endif - capacity *= 2; - buffer->data = MEM2_realloc(buffer->data, capacity); - } - if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) == 0) - break; - if (ret < 0) - return false; - start_pos += ret; - }; - buffer->size = start_pos; - buffer->data = MEM2_realloc(buffer->data, buffer->size); - return (buffer->content_length > 0 && buffer->content_length == start_pos); + capacity *= 2; + buffer->data = MEM2_realloc(buffer->data, capacity); + } + if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) == 0) + break; + if (ret < 0) + return false; + start_pos += ret; + }; + buffer->size = start_pos; + buffer->data = MEM2_realloc(buffer->data, buffer->size); + return (buffer->content_length > 0 && buffer->content_length == start_pos); } bool get_response(HTTP_INFO *httpinfo, HTTP_RESPONSE *resp, bool proxy) { - int rret, minor_version; - size_t msg_len, prevbuflen; - const char *msg; + int rret, minor_version; + size_t msg_len, prevbuflen; + const char *msg; - while (true) - { - if ((rret = https_read(httpinfo, &resp->data[resp->buflen], 1, proxy)) < 1) - return false; - prevbuflen = resp->buflen; - resp->buflen += rret; - // Parse the response - resp->num_headers = sizeof(resp->headers) / sizeof(resp->headers[0]); - if ((resp->pret = phr_parse_response(resp->data, resp->buflen, &minor_version, &resp->status, &msg, &msg_len, resp->headers, &resp->num_headers, prevbuflen)) > 0) - return true; - else if (resp->pret == -1) - { + while (true) + { + if ((rret = https_read(httpinfo, &resp->data[resp->buflen], 1, proxy)) < 1) + return false; + prevbuflen = resp->buflen; + resp->buflen += rret; + // Parse the response + resp->num_headers = sizeof(resp->headers) / sizeof(resp->headers[0]); + if ((resp->pret = phr_parse_response(resp->data, resp->buflen, &minor_version, &resp->status, &msg, &msg_len, + resp->headers, &resp->num_headers, prevbuflen)) > 0) + return true; + else if (resp->pret == -1) + { #ifdef DEBUG_NETWORK - gprintf("pret error %i\n", resp->pret); + gprintf("pret error %i\n", resp->pret); #endif - return false; - } - if (resp->buflen == sizeof(resp->data)) - { + return false; + } + if (resp->buflen == sizeof(resp->data)) + { #ifdef DEBUG_NETWORK - gprintf("buflen error %lu\n", (unsigned long)resp->buflen); + gprintf("buflen error %lu\n", (unsigned long)resp->buflen); #endif - return false; - } - } - return false; + return false; + } + } + return false; } bool check_ip(char *str) { - int partA, partB, partC, partD; - char extra; - // We avoid using regex because it increases the file size - return (sscanf(str, "%d.%d.%d.%d%c", &partA, &partB, &partC, &partD, &extra) == 4); + int partA, partB, partC, partD; + char extra; + // We avoid using regex because it increases the file size + return (sscanf(str, "%d.%d.%d.%d%c", &partA, &partB, &partC, &partD, &extra) == 4); } bool connect_proxy(HTTP_INFO *httpinfo, char *host, char *username, char *password) { - HTTP_RESPONSE response = {0}; - char request[500]; - char credentials[66]; - char *auth; - int len; - if (username && password) - { - if (!snprintf(credentials, sizeof(credentials), "%s:%s", username, password)) - return false; - if (!(auth = base64(credentials, strlen(credentials), &len))) - return false; - len = snprintf(request, sizeof(request), "CONNECT %s:%i HTTP/1.1\r\nProxy-Authorization: Basic %s\r\nUser-Agent: curl/7.55.1\r\n\r\n", host, httpinfo->use_https ? 443 : 80, auth); - MEM2_free(auth); - } - else - len = snprintf(request, sizeof(request), "CONNECT %s:%i HTTP/1.1\r\nUser-Agent: curl/7.55.1\r\n\r\n", host, httpinfo->use_https ? 443 : 80); - if (len > 0 && https_write(httpinfo, request, len, true) != len) - return false; - if (get_response(httpinfo, &response, true)) - { - if (response.status == 200) - return true; - } - return false; + HTTP_RESPONSE response = {0}; + char request[500]; + char credentials[66]; + char *auth; + int len; + if (username && password) + { + if (!snprintf(credentials, sizeof(credentials), "%s:%s", username, password)) + return false; + if (!(auth = base64(credentials, strlen(credentials), &len))) + return false; + len = snprintf(request, sizeof(request), + "CONNECT %s:%i HTTP/1.1\r\nProxy-Authorization: Basic %s\r\nUser-Agent: curl/7.55.1\r\n\r\n", + host, httpinfo->use_https ? 443 : 80, auth); + MEM2_free(auth); + } + else + len = snprintf(request, sizeof(request), + "CONNECT %s:%i HTTP/1.1\r\nUser-Agent: curl/7.55.1\r\n\r\n", + host, httpinfo->use_https ? 443 : 80); + if (len > 0 && https_write(httpinfo, request, len, true) != len) + return false; + if (get_response(httpinfo, &response, true)) + { + if (response.status == 200) + return true; + } + return false; } int connect(char *host, u16 port) { - struct sockaddr_in sin; - s32 sock, ret; - u32 ipaddress; - u64 time; + struct sockaddr_in sin; + s32 sock, ret; + u32 ipaddress; + u64 time; #ifdef DEBUG_NETWORK - gprintf("Connecting to %s", host); + gprintf("Connecting to %s", host); #endif - if ((ipaddress = check_ip(host) ? inet_addr(host) : getipbynamecached(host)) == 0) - return -EFAULT; - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = ipaddress; + if ((ipaddress = check_ip(host) ? inet_addr(host) : getipbynamecached(host)) == 0) + return -EFAULT; + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = ipaddress; #ifdef DEBUG_NETWORK - if (!check_ip(host)) - gprintf(" (%s)", inet_ntoa(sin.sin_addr)); + if (!check_ip(host)) + gprintf(" (%s)", inet_ntoa(sin.sin_addr)); #endif - if ((sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) - return sock; - net_fcntl(sock, F_SETFL, 4); - time = gettime(); - while (ticks_to_millisecs(diff_ticks(time, gettime())) < CONNECT_TIMEOUT) - { - if ((ret = net_connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0) - { - if (ret == -EISCONN) - return sock; - if (ret == -EINPROGRESS || ret == -EALREADY) - { - usleep(10000); - continue; - } - net_close(sock); - return ret; - } - } - net_close(sock); - return -ETIMEDOUT; + if ((sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) + return sock; + net_fcntl(sock, F_SETFL, 4); + time = gettime(); + while (ticks_to_millisecs(diff_ticks(time, gettime())) < CONNECT_TIMEOUT) + { + if ((ret = net_connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0) + { + if (ret == -EISCONN) + return sock; + if (ret == -EINPROGRESS || ret == -EALREADY) + { + usleep(10000); + continue; + } + net_close(sock); + return ret; + } + } + net_close(sock); + return -ETIMEDOUT; } void downloadfile(const char *url, struct download *buffer) { - HTTP_INFO httpinfo = {0}; - // Always reset the size due to the image downloader looping - buffer->size = 0; - // Check if we're using HTTPS and set the path - char *path; - if (strncmp(url, "https://", 8) == 0) - { - httpinfo.use_https = 1; - path = strchr(url + 8, '/'); - } - else if (strncmp(url, "http://", 7) == 0) - { - httpinfo.use_https = 0; - path = strchr(url + 7, '/'); - } - else - return; - if (path == NULL) - return; - // Get the host - int domainlength = path - url - 7 - httpinfo.use_https; - char host[domainlength + 1]; - strlcpy(host, url + 7 + httpinfo.use_https, domainlength + 1); - // Start connecting - if (getProxyAddress() && getProxyPort() > 0) - httpinfo.sock = connect(getProxyAddress(), getProxyPort()); - else - httpinfo.sock = connect(host, httpinfo.use_https ? 443 : 80); + HTTP_INFO httpinfo = {0}; + // Always reset the size due to the image downloader looping + buffer->size = 0; + // Check if we're using HTTPS and set the path + char *path; + if (strncmp(url, "https://", 8) == 0) + { + httpinfo.use_https = 1; + path = strchr(url + 8, '/'); + } + else if (strncmp(url, "http://", 7) == 0) + { + httpinfo.use_https = 0; + path = strchr(url + 7, '/'); + } + else + return; + if (path == NULL) + return; + // Get the host + int domainlength = path - url - 7 - httpinfo.use_https; + char host[domainlength + 1]; + strlcpy(host, url + 7 + httpinfo.use_https, domainlength + 1); + // Start connecting + if (getProxyAddress() && getProxyPort() > 0) + httpinfo.sock = connect(getProxyAddress(), getProxyPort()); + else + httpinfo.sock = connect(host, httpinfo.use_https ? 443 : 80); - if (httpinfo.sock < 0) - { + if (httpinfo.sock < 0) + { #ifdef DEBUG_NETWORK - if (httpinfo.sock == -ETIMEDOUT) - gprintf("\nFailed to connect (timed out)\n"); - else - gprintf("\nFailed to connect (%i)\n", httpinfo.sock); + if (httpinfo.sock == -ETIMEDOUT) + gprintf("\nFailed to connect (timed out)\n"); + else + gprintf("\nFailed to connect (%i)\n", httpinfo.sock); #endif - return; - } + return; + } #ifdef DEBUG_NETWORK - gprintf("\nConnected\n"); + gprintf("\nConnected\n"); #endif - // Connect to a web proxy - if (getProxyAddress() && getProxyPort() > 0) - { - if (!connect_proxy(&httpinfo, host, getProxyUsername(), getProxyPassword())) - { + // Connect to a web proxy + if (getProxyAddress() && getProxyPort() > 0) + { + if (!connect_proxy(&httpinfo, host, getProxyUsername(), getProxyPassword())) + { #ifdef DEBUG_NETWORK - gprintf("Failed to connect to proxy (%s:%i)\n", getProxyAddress(), getProxyPort()); + gprintf("Failed to connect to proxy (%s:%i)\n", getProxyAddress(), getProxyPort()); #endif - https_close(&httpinfo); - return; - } - session = NULL; // Resume doesn't work with a proxy + https_close(&httpinfo); + return; + } + session = NULL; // Resume doesn't work with a proxy #ifdef DEBUG_NETWORK - gprintf("Proxy is ready to receive\n"); + gprintf("Proxy is ready to receive\n"); #endif - } - // Setup for HTTPS if it's necessary - if (httpinfo.use_https) - { - // Create a new SSL context - // wolfSSLv23_client_method() works but TLS 1.2 is slightly faster on Wii - if ((httpinfo.ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) - { + } + // Setup for HTTPS if it's necessary + if (httpinfo.use_https) + { + // Create a new SSL context + // wolfSSLv23_client_method() works but TLS 1.2 is slightly faster on Wii + if ((httpinfo.ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) + { #ifdef DEBUG_NETWORK - gprintf("Failed to create WOLFSSL_CTX\n"); + gprintf("Failed to create WOLFSSL_CTX\n"); #endif - https_close(&httpinfo); - return; - } - // Don't verify certificates - wolfSSL_CTX_set_verify(httpinfo.ctx, WOLFSSL_VERIFY_NONE, 0); - // Enable SNI - if (wolfSSL_CTX_UseSNI(httpinfo.ctx, 0, host, strlen(host)) != WOLFSSL_SUCCESS) - { + https_close(&httpinfo); + return; + } + // Don't verify certificates + wolfSSL_CTX_set_verify(httpinfo.ctx, WOLFSSL_VERIFY_NONE, 0); + // Enable SNI + if (wolfSSL_CTX_UseSNI(httpinfo.ctx, 0, host, strlen(host)) != WOLFSSL_SUCCESS) + { #ifdef DEBUG_NETWORK - gprintf("Failed to set SNI\n"); + gprintf("Failed to set SNI\n"); #endif - https_close(&httpinfo); - return; - } - // Custom I/O is essential due to how libogc handles errors - wolfSSL_SetIOSend(httpinfo.ctx, send_callback); - wolfSSL_SetIORecv(httpinfo.ctx, recv_callback); - // Create a new wolfSSL session - if ((httpinfo.ssl = wolfSSL_new(httpinfo.ctx)) == NULL) - { + https_close(&httpinfo); + return; + } + // Custom I/O is essential due to how libogc handles errors + wolfSSL_SetIOSend(httpinfo.ctx, send_callback); + wolfSSL_SetIORecv(httpinfo.ctx, recv_callback); + // Create a new wolfSSL session + if ((httpinfo.ssl = wolfSSL_new(httpinfo.ctx)) == NULL) + { #ifdef DEBUG_NETWORK - gprintf("SSL session creation failed\n"); + gprintf("SSL session creation failed\n"); #endif - https_close(&httpinfo); - return; - } - // Set the file descriptor - if (wolfSSL_set_fd(httpinfo.ssl, httpinfo.sock) != SSL_SUCCESS) - { + https_close(&httpinfo); + return; + } + // Set the file descriptor + if (wolfSSL_set_fd(httpinfo.ssl, httpinfo.sock) != SSL_SUCCESS) + { #ifdef DEBUG_NETWORK - gprintf("Failed to set SSL file descriptor\n"); + gprintf("Failed to set SSL file descriptor\n"); #endif - https_close(&httpinfo); - return; - } - // Attempt to resume the session - if (session != NULL && wolfSSL_set_session(httpinfo.ssl, session) != SSL_SUCCESS) - { + https_close(&httpinfo); + return; + } + // Attempt to resume the session + if (session != NULL && wolfSSL_set_session(httpinfo.ssl, session) != SSL_SUCCESS) + { #ifdef DEBUG_NETWORK - gprintf("Failed to set session (session timed out?)\n"); + gprintf("Failed to set session (session timed out?)\n"); #endif - session = NULL; - } - // Initiate a handshake - u64 time = gettime(); - while (true) - { - if (ticks_to_millisecs(diff_ticks(time, gettime())) > CONNECT_TIMEOUT) - { + session = NULL; + } + // Initiate a handshake + u64 time = gettime(); + while (true) + { + if (ticks_to_millisecs(diff_ticks(time, gettime())) > CONNECT_TIMEOUT) + { #ifdef DEBUG_NETWORK - gprintf("SSL handshake failed\n"); + gprintf("SSL handshake failed\n"); #endif - https_close(&httpinfo); - return; - } - if (wolfSSL_connect(httpinfo.ssl) == SSL_SUCCESS) - break; - usleep(10000); - } - // Check if we resumed successfully - if (session != NULL && !wolfSSL_session_reused(httpinfo.ssl)) - { + https_close(&httpinfo); + return; + } + if (wolfSSL_connect(httpinfo.ssl) == SSL_SUCCESS) + break; + usleep(10000); + } + // Check if we resumed successfully + if (session != NULL && !wolfSSL_session_reused(httpinfo.ssl)) + { #ifdef DEBUG_NETWORK - gprintf("Failed to resume session\n"); + gprintf("Failed to resume session\n"); #endif - session = NULL; - } - // Cipher info + session = NULL; + } + // Cipher info #ifdef DEBUG_NETWORK - /*char ciphers[4096]; + /*char ciphers[4096]; wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); gprintf("All supported ciphers: %s\n", ciphers);*/ - WOLFSSL_CIPHER *cipher = wolfSSL_get_current_cipher(httpinfo.ssl); - gprintf("Using: %s - %s\n", wolfSSL_get_version(httpinfo.ssl), wolfSSL_CIPHER_get_name(cipher)); + WOLFSSL_CIPHER *cipher = wolfSSL_get_current_cipher(httpinfo.ssl); + gprintf("Using: %s - %s\n", wolfSSL_get_version(httpinfo.ssl), wolfSSL_CIPHER_get_name(cipher)); #endif - } - // Send our request - char request[2300]; - int ret, len; - len = snprintf(request, sizeof(request), - "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: WiiFlow-Lite\r\n" - "Connection: close\r\n" - "Pragma: no-cache\r\n" - "Cache-Control: no-cache\r\n\r\n", - path, host); - if ((ret = https_write(&httpinfo, request, len, false)) != len) - { + } + // Send our request + char request[2300]; + int ret, len; + len = snprintf(request, sizeof(request), + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: WiiFlow-Lite\r\n" + "Connection: close\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n\r\n", + path, host); + if ((ret = https_write(&httpinfo, request, len, false)) != len) + { #ifdef DEBUG_NETWORK - gprintf("https_write error: %i\n", ret); + gprintf("https_write error: %i\n", ret); #endif - https_close(&httpinfo); - return; - } - // Check if we want a response - if (buffer->skip_response) - { + https_close(&httpinfo); + return; + } + // Check if we want a response + if (buffer->skip_response) + { #ifdef DEBUG_NETWORK - gprintf("Sent request to %s and skipping response\n", host); + gprintf("Sent request to %s and skipping response\n", host); #endif - https_close(&httpinfo); - return; - } - // Get the response - HTTP_RESPONSE response = {0}; - if (!get_response(&httpinfo, &response, false)) - { - https_close(&httpinfo); - return; - } - // The website wants to redirect us - if (response.status == 301 || response.status == 302) - { - https_close(&httpinfo); - if (loop == REDIRECT_LIMIT) - { + https_close(&httpinfo); + return; + } + // Get the response + HTTP_RESPONSE response = {0}; + if (!get_response(&httpinfo, &response, false)) + { + https_close(&httpinfo); + return; + } + // The website wants to redirect us + if (response.status == 301 || response.status == 302) + { + https_close(&httpinfo); + if (loop == REDIRECT_LIMIT) + { #ifdef DEBUG_NETWORK - gprintf("Reached redirect limit\n"); + gprintf("Reached redirect limit\n"); #endif - return; - } - loop++; - char location[2049]; - if (!get_header_value(response.headers, response.num_headers, location, "location")) - return; + return; + } + loop++; + char location[2049]; + if (!get_header_value(response.headers, response.num_headers, location, "location")) + return; #ifdef DEBUG_NETWORK - gprintf("Redirect #%i - %s\n", loop, location); + gprintf("Redirect #%i - %s\n", loop, location); #endif - downloadfile(location, buffer); - return; - } - // It's not 301 or 302, so reset the loop - loop = 0; - // We got what we wanted - if (response.status == 200) - { - buffer->data = MEM2_alloc(4096); - memcpy(buffer->data, &response.data[response.pret], response.buflen - response.pret); - // Determine how to read the data - bool dl_valid; - if (is_chunked(response.headers, response.num_headers)) - dl_valid = read_chunked(&httpinfo, buffer, response.buflen - response.pret); - else - { - buffer->content_length = get_header_value_int(response.headers, response.num_headers, "content-length"); - dl_valid = read_all(&httpinfo, buffer, response.buflen - response.pret); - } - // Check if the download is incomplete - if (!dl_valid || buffer->size < 1) - { - buffer->size = 0; - MEM2_free(buffer->data); + downloadfile(location, buffer); + return; + } + // It's not 301 or 302, so reset the loop + loop = 0; + // We got what we wanted + if (response.status == 200) + { + buffer->data = MEM2_alloc(4096); + memcpy(buffer->data, &response.data[response.pret], response.buflen - response.pret); + // Determine how to read the data + bool dl_valid; + if (is_chunked(response.headers, response.num_headers)) + dl_valid = read_chunked(&httpinfo, buffer, response.buflen - response.pret); + else + { + buffer->content_length = get_header_value_int(response.headers, response.num_headers, "content-length"); + dl_valid = read_all(&httpinfo, buffer, response.buflen - response.pret); + } + // Check if the download is incomplete + if (!dl_valid || buffer->size < 1) + { + buffer->size = 0; + MEM2_free(buffer->data); #ifdef DEBUG_NETWORK - gprintf("Removed incomplete download\n"); + gprintf("Removed incomplete download\n"); #endif - https_close(&httpinfo); - return; - } - // Save the session - if (httpinfo.use_https) - session = wolfSSL_get_session(httpinfo.ssl); - // Finished - https_close(&httpinfo); + https_close(&httpinfo); + return; + } + // Save the session + if (httpinfo.use_https) + session = wolfSSL_get_session(httpinfo.ssl); + // Finished + https_close(&httpinfo); #ifdef DEBUG_NETWORK - gprintf("Download size: %llu\n", (long long)buffer->size); - gprintf("------------- HEADERS -------------\n"); - for (size_t i = 0; i != response.num_headers; ++i) - gprintf("%.*s: %.*s\n", (int)response.headers[i].name_len, response.headers[i].name, (int)response.headers[i].value_len, response.headers[i].value); - gprintf("------------ COMPLETED ------------\n"); + gprintf("Download size: %llu\n", (long long)buffer->size); + gprintf("------------- HEADERS -------------\n"); + for (size_t i = 0; i != response.num_headers; ++i) + gprintf("%.*s: %.*s\n", (int)response.headers[i].name_len, response.headers[i].name, + (int)response.headers[i].value_len, response.headers[i].value); + gprintf("------------ COMPLETED ------------\n"); #endif - return; - } - // Close on all other status codes + return; + } + // Close on all other status codes #ifdef DEBUG_NETWORK - gprintf("Status code: %i - %s\n", response.status, url); + gprintf("Status code: %i - %s\n", response.status, url); #endif - https_close(&httpinfo); + https_close(&httpinfo); } diff --git a/source/network/https.h b/source/network/https.h index 7b602ce1..1886e423 100644 --- a/source/network/https.h +++ b/source/network/https.h @@ -21,34 +21,34 @@ extern "C" #define READ_WRITE_TIMEOUT 20000 #define BLOCK_SIZE 8192 - struct download - { - bool skip_response; // Used by WiinnerTag - u64 content_length; - u64 size; - char *data; - }; + struct download + { + bool skip_response; // Used by WiinnerTag + u64 content_length; + u64 size; + char *data; + }; - typedef struct - { - int status; - int pret; - size_t num_headers; - size_t buflen; - struct phr_header headers[100]; - char data[4096]; - } HTTP_RESPONSE; + typedef struct + { + int status; + int pret; + size_t num_headers; + size_t buflen; + struct phr_header headers[100]; + char data[4096]; + } HTTP_RESPONSE; - typedef struct - { - u8 use_https; - s32 sock; - WOLFSSL *ssl; - WOLFSSL_CTX *ctx; - } HTTP_INFO; + typedef struct + { + u8 use_https; + s32 sock; + WOLFSSL *ssl; + WOLFSSL_CTX *ctx; + } HTTP_INFO; - void downloadfile(const char *url, struct download *buffer); - int wolfSSL_CTX_UseSNI(WOLFSSL_CTX *ctx, unsigned char type, const void *data, unsigned short size); + void downloadfile(const char *url, struct download *buffer); + int wolfSSL_CTX_UseSNI(WOLFSSL_CTX *ctx, unsigned char type, const void *data, unsigned short size); #ifdef __cplusplus } diff --git a/source/network/proxysettings.cpp b/source/network/proxysettings.cpp index d0aca3c6..e9122a90 100644 --- a/source/network/proxysettings.cpp +++ b/source/network/proxysettings.cpp @@ -17,59 +17,59 @@ char proxy_password[33]; void getProxyInfo() { - char *buffer; - int fd = ISFS_Open("/shared2/sys/net/02/config.dat", ISFS_OPEN_READ); - if (fd >= 0) - { - fstats stats ATTRIBUTE_ALIGN(32); - if(ISFS_GetFileStats(fd, &stats) >= 0) - { - if (stats.file_length == 7004) - { - buffer = (char *)MEM2_alloc(ALIGN32(stats.file_length)); - if (buffer) - { - if (ISFS_Read(fd, buffer, stats.file_length) == 7004) - { - proxy_enabled = buffer[44]; - proxy_creds_enabled = buffer[45]; - strncpy(proxy_address, buffer + 48, sizeof(proxy_address) - 1); - proxy_port = ((buffer[304] & 0xFF) << 8) | (buffer[305] & 0xFF); - strncpy(proxy_username, buffer + 306, sizeof(proxy_username) - 1); - strncpy(proxy_password, buffer + 338, sizeof(proxy_password) - 1); - } - } - MEM2_free(buffer); - } - } - ISFS_Close(fd); - } + char *buffer; + int fd = ISFS_Open("/shared2/sys/net/02/config.dat", ISFS_OPEN_READ); + if (fd >= 0) + { + fstats stats ATTRIBUTE_ALIGN(32); + if (ISFS_GetFileStats(fd, &stats) >= 0) + { + if (stats.file_length == 7004) + { + buffer = (char *)MEM2_alloc(ALIGN32(stats.file_length)); + if (buffer) + { + if (ISFS_Read(fd, buffer, stats.file_length) == 7004) + { + proxy_enabled = buffer[44]; + proxy_creds_enabled = buffer[45]; + strncpy(proxy_address, buffer + 48, sizeof(proxy_address) - 1); + proxy_port = ((buffer[304] & 0xFF) << 8) | (buffer[305] & 0xFF); + strncpy(proxy_username, buffer + 306, sizeof(proxy_username) - 1); + strncpy(proxy_password, buffer + 338, sizeof(proxy_password) - 1); + } + } + MEM2_free(buffer); + } + } + ISFS_Close(fd); + } } char *getProxyAddress() { - if (mainMenu.proxyUseSystem) - return proxy_enabled ? proxy_address : NULL; - return (strlen(mainMenu.proxyAddress) > 6) ? mainMenu.proxyAddress : NULL; + if (mainMenu.proxyUseSystem) + return proxy_enabled ? proxy_address : NULL; + return (strlen(mainMenu.proxyAddress) > 6) ? mainMenu.proxyAddress : NULL; } u16 getProxyPort() { - if (mainMenu.proxyUseSystem) - return proxy_enabled ? proxy_port : 0; - return mainMenu.proxyPort; + if (mainMenu.proxyUseSystem) + return proxy_enabled ? proxy_port : 0; + return mainMenu.proxyPort; } char *getProxyUsername() { - if (mainMenu.proxyUseSystem) - return proxy_enabled && proxy_creds_enabled ? proxy_username : NULL; - return (strlen(mainMenu.proxyUsername) > 0) ? mainMenu.proxyUsername : NULL; + if (mainMenu.proxyUseSystem) + return proxy_enabled && proxy_creds_enabled ? proxy_username : NULL; + return (strlen(mainMenu.proxyUsername) > 0) ? mainMenu.proxyUsername : NULL; } char *getProxyPassword() { - if (mainMenu.proxyUseSystem) - return proxy_enabled && proxy_creds_enabled ? proxy_password : NULL; - return (strlen(mainMenu.proxyPassword) > 0) ? mainMenu.proxyPassword : NULL; + if (mainMenu.proxyUseSystem) + return proxy_enabled && proxy_creds_enabled ? proxy_password : NULL; + return (strlen(mainMenu.proxyPassword) > 0) ? mainMenu.proxyPassword : NULL; } diff --git a/source/network/proxysettings.h b/source/network/proxysettings.h index 892d7d64..7e874d78 100644 --- a/source/network/proxysettings.h +++ b/source/network/proxysettings.h @@ -6,11 +6,11 @@ extern "C" { #endif - void getProxyInfo(); - char *getProxyAddress(); - u16 getProxyPort(); - char *getProxyUsername(); - char *getProxyPassword(); + void getProxyInfo(); + char *getProxyAddress(); + u16 getProxyPort(); + char *getProxyUsername(); + char *getProxyPassword(); #ifdef __cplusplus } #endif