Merge pull request #211 from wiidev/master

Update wolfSSL and improve formatting
This commit is contained in:
Fledge68 2020-10-19 08:41:57 -05:00 committed by GitHub
commit da479654ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 736 additions and 600 deletions

View File

@ -9,7 +9,7 @@
#include "memory/memory.h"
#include "identify.h"
static inline bool apply_patch(char *name, const u8 *old, const u8 *patch, u32 size)
static inline bool apply_patch(__attribute__((unused)) char *name, const u8 *old, const u8 *patch, u32 size)
{
u8 i;
u32 found = 0;

View File

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

Binary file not shown.

View File

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

View File

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

View File

@ -62,6 +62,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#include <libwolfssl/wolfcrypt/port/st/stm32.h>
#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 */
};

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <libwolfssl/wolfcrypt/settings.h>
#ifdef USE_FAST_MATH
#include <libwolfssl/wolfcrypt/tfm.h>
#elif defined WOLFSSL_SP_MATH
#include <libwolfssl/wolfcrypt/sp_int.h>
#else
#include <libwolfssl/wolfcrypt/integer.h>
#endif
#include <libwolfssl/wolfcrypt/aes.h>
#include <libwolfssl/wolfcrypt/error-crypt.h>
#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

View File

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

View File

@ -72,6 +72,9 @@
#ifdef WOLFSSL_ESP32WROOM32_CRYPT
#include <libwolfssl/wolfcrypt/port/Espressif/esp32-crypt.h>
#endif
#ifdef WOLFSSL_IMXRT_DCP
#include <libwolfssl/wolfcrypt/port/nxp/dcp_port.h>
#endif
#if !defined(NO_OLD_SHA_NAMES)
#define SHA WC_SHA

View File

@ -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 <libwolfssl/wolfcrypt/port/nxp/dcp_port.h>
#else
/* wc_Sha256 digest */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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