Update wolfSSL and improve formatting

This commit is contained in:
wiidev 2020-10-17 18:29:03 +01:00
parent d506c49d4f
commit 0a53dbb34f
20 changed files with 735 additions and 599 deletions

View File

@ -1634,14 +1634,14 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
#ifdef WOLFSSL_SESSION_EXPORT #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); word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
word32 sz); word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl,
byte* buf, word32 sz); byte* buf, word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, 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); WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
#endif #endif
#endif #endif
@ -4167,6 +4167,8 @@ struct WOLFSSL {
#endif /* HAVE_TLS_EXTENSIONS */ #endif /* HAVE_TLS_EXTENSIONS */
#ifdef HAVE_OCSP #ifdef HAVE_OCSP
void* ocspIOCtx; void* ocspIOCtx;
byte ocspProducedDate[MAX_DATE_SZ];
int ocspProducedDateFormat;
#ifdef OPENSSL_EXTRA #ifdef OPENSSL_EXTRA
byte* ocspResp; byte* ocspResp;
int ocspRespSz; int ocspRespSz;

Binary file not shown.

View File

@ -354,10 +354,12 @@ struct WOLFSSL_EVP_CIPHER_CTX {
#define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV #define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
int ivSz; int ivSz;
#ifdef HAVE_AESGCM #ifdef HAVE_AESGCM
byte* gcmDecryptBuffer; byte* gcmBuffer;
int gcmDecryptBufferLen; int gcmBufferLen;
ALIGN16 unsigned char authTag[AES_BLOCK_SIZE]; ALIGN16 unsigned char authTag[AES_BLOCK_SIZE];
int authTagSz; int authTagSz;
byte* gcmAuthIn;
int gcmAuthInSz;
#endif #endif
#endif #endif
}; };

View File

@ -743,7 +743,7 @@ typedef int (*wc_dtls_export)(WOLFSSL* ssl,
#define WOLFSSL_DTLS_EXPORT_TYPES #define WOLFSSL_DTLS_EXPORT_TYPES
#endif /* 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); unsigned int sz);
WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
wc_dtls_export func); 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); WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void);
#endif #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) \ #if defined(OPENSSL_ALL) \
|| defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_NGINX) \
|| defined(WOLFSSL_HAPROXY) \ || 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> #include <libwolfssl/wolfcrypt/port/st/stm32.h>
#endif #endif
#ifdef WOLFSSL_IMXRT_DCP
#include "fsl_dcp.h"
#endif
#ifdef WOLFSSL_XILINX_CRYPT #ifdef WOLFSSL_XILINX_CRYPT
#include "xsecure_aes.h" #include "xsecure_aes.h"
@ -225,6 +228,9 @@ struct Aes {
#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT) defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT)
TSIP_AES_CTX ctx; TSIP_AES_CTX ctx;
#endif
#if defined(WOLFSSL_IMXRT_DCP)
dcp_handle_t handle;
#endif #endif
void* heap; /* memory hint to use */ void* heap; /* memory hint to use */
}; };

View File

@ -538,7 +538,9 @@ enum Extensions_Sum {
POLICY_CONST_OID = 150, POLICY_CONST_OID = 150,
ISSUE_ALT_NAMES_OID = 132, ISSUE_ALT_NAMES_OID = 132,
TLS_FEATURE_OID = 92, /* id-pe 24 */ 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 { enum CertificatePolicy_Sum {
@ -909,6 +911,9 @@ struct DecodedCert {
byte weOwnAltNames : 1; /* altNames haven't been given to copy */ byte weOwnAltNames : 1; /* altNames haven't been given to copy */
byte extKeyUsageSet : 1; byte extKeyUsageSet : 1;
byte extExtKeyUsageSet : 1; /* Extended Key Usage set */ byte extExtKeyUsageSet : 1; /* Extended Key Usage set */
#ifdef HAVE_OCSP
byte ocspNoCheckSet : 1; /* id-pkix-ocsp-nocheck set */
#endif
byte extCRLdistSet : 1; byte extCRLdistSet : 1;
byte extAuthInfoSet : 1; byte extAuthInfoSet : 1;
byte extBasicConstSet : 1; byte extBasicConstSet : 1;

View File

@ -79,7 +79,7 @@ typedef struct ChaCha {
byte extra[12]; byte extra[12];
#endif #endif
word32 left; /* number of bytes leftover */ 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]; word32 over[CHACHA_CHUNK_WORDS];
#endif #endif
} ChaCha; } 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, ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a,
mp_int* modulus, mp_digit mp); 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 #endif
WOLFSSL_API 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_zero (mp_int * a);
MP_API void mp_clamp (mp_int * a); MP_API void mp_clamp (mp_int * a);
MP_API void mp_exch (mp_int * a, mp_int * b); 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_rshd (mp_int * a, int b);
MP_API void mp_rshb (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); 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 */ /* random seed */
#define NO_OLD_RNGNAME #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 #define FREESCALE_KSDK_2_0_TRNG
#elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0) #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0)
#ifdef FREESCALE_KSDK_1_3 #ifdef FREESCALE_KSDK_1_3
@ -1621,6 +1623,12 @@ extern void uITRON4_free(void *p) ;
#endif #endif
#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) && \ #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
!defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \
!defined(XMALLOC_OVERRIDE) !defined(XMALLOC_OVERRIDE)
@ -2124,10 +2132,18 @@ extern void uITRON4_free(void *p) ;
#define SIZEOF_LONG 8 #define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8 #define SIZEOF_LONG_LONG 8
#define CHAR_BIT 8 #define CHAR_BIT 8
#define WOLFSSL_SP_DIV_64 #ifndef WOLFSSL_SP_DIV_64
#define WOLFSSL_SP_DIV_WORD_HALF #define WOLFSSL_SP_DIV_64
#define SP_HALF_SIZE 32 #endif
#define SP_HALF_MAX 4294967295U #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 #endif

View File

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

View File

@ -128,6 +128,8 @@ enum {
#include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h"
#elif defined(WOLFSSL_PSOC6_CRYPTO) #elif defined(WOLFSSL_PSOC6_CRYPTO)
#include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h" #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h"
#elif defined(WOLFSSL_IMXRT_DCP)
#include <libwolfssl/wolfcrypt/port/nxp/dcp_port.h>
#else #else
/* wc_Sha256 digest */ /* 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_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
MP_API int mp_exch(mp_int *a, mp_int *b); MP_API int mp_exch(mp_int *a, mp_int *b);
#endif /* WOLFSSL_KEY_GEN */ #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_cnt_lsb(fp_int *a);
MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); 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 */ #else /* ! WOLFSSL_LINUXKM */
#ifdef BUILDING_WOLFSSL #ifdef BUILDING_WOLFSSL
#define SAVE_VECTOR_REGISTERS() ({}) #define SAVE_VECTOR_REGISTERS() do{}while(0)
#define RESTORE_VECTOR_REGISTERS() ({}) #define RESTORE_VECTOR_REGISTERS() do{}while(0)
#endif #endif
#endif /* WOLFSSL_LINUXKM */ #endif /* WOLFSSL_LINUXKM */
@ -836,11 +836,12 @@ WOLFSSL_API int wolfCrypt_Cleanup(void);
#endif #endif
#endif #endif
#if !defined(XGMTIME) && !defined(TIME_OVERRIDES) #if !defined(XGMTIME) && !defined(TIME_OVERRIDES)
#if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) /* Always use gmtime_r if available. */
#define XGMTIME(c, t) gmtime((c)) #if defined(HAVE_GMTIME_R)
#else
#define XGMTIME(c, t) gmtime_r((c), (t)) #define XGMTIME(c, t) gmtime_r((c), (t))
#define NEED_TMP_TIME #define NEED_TMP_TIME
#else
#define XGMTIME(c, t) gmtime((c))
#endif #endif
#endif #endif
#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE) #if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE)

View File

@ -70,104 +70,104 @@ static const unsigned char unb64[]={
// (you must pass pointer flen). // (you must pass pointer flen).
char *base64(const void *binaryData, int len, int *flen) char *base64(const void *binaryData, int len, int *flen)
{ {
const unsigned char *bin = (const unsigned char *)binaryData; const unsigned char *bin = (const unsigned char *)binaryData;
char *res; char *res;
int rc = 0; // result counter int rc = 0; // result counter
int byteNo; // I need this after the loop int byteNo; // I need this after the loop
int modulusLen = len % 3; int modulusLen = len % 3;
int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0. int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
*flen = 4 * (len + pad) / 3; *flen = 4 * (len + pad) / 3;
res = (char *)MEM2_alloc(*flen + 1); // and one for the null res = (char *)MEM2_alloc(*flen + 1); // and one for the null
if (!res) if (!res)
return 0; return 0;
for (byteNo = 0; byteNo <= len - 3; byteNo += 3) for (byteNo = 0; byteNo <= len - 3; byteNo += 3)
{ {
unsigned char BYTE0 = bin[byteNo]; unsigned char BYTE0 = bin[byteNo];
unsigned char BYTE1 = bin[byteNo + 1]; unsigned char BYTE1 = bin[byteNo + 1];
unsigned char BYTE2 = bin[byteNo + 2]; unsigned char BYTE2 = bin[byteNo + 2];
res[rc++] = b64[BYTE0 >> 2]; res[rc++] = b64[BYTE0 >> 2];
res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)]; res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)]; res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
res[rc++] = b64[0x3f & BYTE2]; res[rc++] = b64[0x3f & BYTE2];
} }
if (pad == 2) if (pad == 2)
{ {
res[rc++] = b64[bin[byteNo] >> 2]; res[rc++] = b64[bin[byteNo] >> 2];
res[rc++] = b64[(0x3 & bin[byteNo]) << 4]; res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
res[rc++] = '='; res[rc++] = '=';
res[rc++] = '='; res[rc++] = '=';
} }
else if (pad == 1) else if (pad == 1)
{ {
res[rc++] = b64[bin[byteNo] >> 2]; res[rc++] = b64[bin[byteNo] >> 2];
res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)]; res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2]; res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
res[rc++] = '='; res[rc++] = '=';
} }
res[rc] = 0; // NULL TERMINATOR!;) res[rc] = 0; // NULL TERMINATOR!;)
return res; return res;
} }
unsigned char *unbase64(const char *ascii, int len, int *flen) unsigned char *unbase64(const char *ascii, int len, int *flen)
{ {
const unsigned char *safeAsciiPtr = (const unsigned char *)ascii; const unsigned char *safeAsciiPtr = (const unsigned char *)ascii;
unsigned char *bin; unsigned char *bin;
int cb = 0; int cb = 0;
int charNo; int charNo;
int pad = 0; int pad = 0;
if ((len <= 0) || (len % 4 != 0)) if ((len <= 0) || (len % 4 != 0))
{ // 2 accesses below would be OOB. { // 2 accesses below would be OOB.
// catch empty string or incorrect padding size, return NULL as result. // catch empty string or incorrect padding size, return NULL as result.
*flen = 0; *flen = 0;
return 0; return 0;
} }
if (safeAsciiPtr[len - 1] == '=') if (safeAsciiPtr[len - 1] == '=')
++pad; ++pad;
if (safeAsciiPtr[len - 2] == '=') if (safeAsciiPtr[len - 2] == '=')
++pad; ++pad;
*flen = 3 * len / 4 - pad; *flen = 3 * len / 4 - pad;
bin = (unsigned char *)MEM2_alloc(*flen); bin = (unsigned char *)MEM2_alloc(*flen);
if (!bin) if (!bin)
return 0; return 0;
for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) for (charNo = 0; charNo <= len - 4 - pad; charNo += 4)
{ {
int A = unb64[safeAsciiPtr[charNo]]; int A = unb64[safeAsciiPtr[charNo]];
int B = unb64[safeAsciiPtr[charNo + 1]]; int B = unb64[safeAsciiPtr[charNo + 1]];
int C = unb64[safeAsciiPtr[charNo + 2]]; int C = unb64[safeAsciiPtr[charNo + 2]];
int D = unb64[safeAsciiPtr[charNo + 3]]; int D = unb64[safeAsciiPtr[charNo + 3]];
bin[cb++] = (A << 2) | (B >> 4); bin[cb++] = (A << 2) | (B >> 4);
bin[cb++] = (B << 4) | (C >> 2); bin[cb++] = (B << 4) | (C >> 2);
bin[cb++] = (C << 6) | (D); bin[cb++] = (C << 6) | (D);
} }
if (pad == 1) if (pad == 1)
{ {
int A = unb64[safeAsciiPtr[charNo]]; int A = unb64[safeAsciiPtr[charNo]];
int B = unb64[safeAsciiPtr[charNo + 1]]; int B = unb64[safeAsciiPtr[charNo + 1]];
int C = unb64[safeAsciiPtr[charNo + 2]]; int C = unb64[safeAsciiPtr[charNo + 2]];
bin[cb++] = (A << 2) | (B >> 4); bin[cb++] = (A << 2) | (B >> 4);
bin[cb++] = (B << 4) | (C >> 2); bin[cb++] = (B << 4) | (C >> 2);
} }
else if (pad == 2) else if (pad == 2)
{ {
int A = unb64[safeAsciiPtr[charNo]]; int A = unb64[safeAsciiPtr[charNo]];
int B = unb64[safeAsciiPtr[charNo + 1]]; int B = unb64[safeAsciiPtr[charNo + 1]];
bin[cb++] = (A << 2) | (B >> 4); bin[cb++] = (A << 2) | (B >> 4);
} }
return bin; return bin;
} }
#endif #endif

View File

@ -16,559 +16,565 @@ WOLFSSL_SESSION *session;
int https_write(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy) int https_write(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy)
{ {
int ret, pos = 0; int ret, pos = 0;
int rlen = len > BLOCK_SIZE ? BLOCK_SIZE : len; int rlen = len > BLOCK_SIZE ? BLOCK_SIZE : len;
u64 time = gettime(); u64 time = gettime();
while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT)
{ {
if (httpinfo->use_https && !proxy) if (httpinfo->use_https && !proxy)
ret = wolfSSL_write(httpinfo->ssl, &buffer[pos], rlen); ret = wolfSSL_write(httpinfo->ssl, &buffer[pos], rlen);
else else
ret = net_write(httpinfo->sock, &buffer[pos], rlen); ret = net_write(httpinfo->sock, &buffer[pos], rlen);
if (ret > 0) if (ret > 0)
{ {
pos += ret; pos += ret;
rlen = len - pos > BLOCK_SIZE ? BLOCK_SIZE : len - pos; rlen = len - pos > BLOCK_SIZE ? BLOCK_SIZE : len - pos;
if (pos >= len) if (pos >= len)
return pos; return pos;
time = gettime(); time = gettime();
} }
usleep(10000); usleep(10000);
} }
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("The connection timed out (write)\n"); gprintf("The connection timed out (write)\n");
#endif #endif
return -ETIMEDOUT; return -ETIMEDOUT;
} }
int https_read(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy) int https_read(HTTP_INFO *httpinfo, char *buffer, int len, bool proxy)
{ {
int ret = -ETIMEDOUT; int ret = -ETIMEDOUT;
u64 time = gettime(); u64 time = gettime();
if (len > BLOCK_SIZE) if (len > BLOCK_SIZE)
len = BLOCK_SIZE; len = BLOCK_SIZE;
while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT) while (ticks_to_millisecs(diff_ticks(time, gettime())) < READ_WRITE_TIMEOUT)
{ {
if (httpinfo->use_https && !proxy) if (httpinfo->use_https && !proxy)
ret = wolfSSL_read(httpinfo->ssl, buffer, len); ret = wolfSSL_read(httpinfo->ssl, buffer, len);
else else
ret = net_read(httpinfo->sock, buffer, len); ret = net_read(httpinfo->sock, buffer, len);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
usleep(10000); usleep(10000);
} }
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("The connection timed out (read)\n"); gprintf("The connection timed out (read)\n");
#endif #endif
return -ETIMEDOUT; return -ETIMEDOUT;
} }
int send_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx) int send_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx)
{ {
int sent = net_write(*(int *)ctx, buf, sz); int sent = net_write(*(int *)ctx, buf, sz);
if (sent < 0) if (sent < 0)
{ {
if (sent == -EAGAIN) if (sent == -EAGAIN)
return WOLFSSL_CBIO_ERR_WANT_WRITE; return WOLFSSL_CBIO_ERR_WANT_WRITE;
else if (sent == -ECONNRESET) else if (sent == -ECONNRESET)
return WOLFSSL_CBIO_ERR_CONN_RST; return WOLFSSL_CBIO_ERR_CONN_RST;
else if (sent == -EINTR) else if (sent == -EINTR)
return WOLFSSL_CBIO_ERR_ISR; return WOLFSSL_CBIO_ERR_ISR;
else if (sent == -EPIPE) else if (sent == -EPIPE)
return WOLFSSL_CBIO_ERR_CONN_CLOSE; return WOLFSSL_CBIO_ERR_CONN_CLOSE;
else else
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
} }
return sent; return sent;
} }
int recv_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx) int recv_callback(__attribute__((unused)) WOLFSSL *ssl, char *buf, int sz, void *ctx)
{ {
int recvd = net_read(*(int *)ctx, buf, sz); int recvd = net_read(*(int *)ctx, buf, sz);
if (recvd < 0) if (recvd < 0)
{ {
if (recvd == -EAGAIN) if (recvd == -EAGAIN)
return WOLFSSL_CBIO_ERR_WANT_READ; return WOLFSSL_CBIO_ERR_WANT_READ;
else if (recvd == -ECONNRESET) else if (recvd == -ECONNRESET)
return WOLFSSL_CBIO_ERR_CONN_RST; return WOLFSSL_CBIO_ERR_CONN_RST;
else if (recvd == -EINTR) else if (recvd == -EINTR)
return WOLFSSL_CBIO_ERR_ISR; return WOLFSSL_CBIO_ERR_ISR;
else if (recvd == -ECONNABORTED) else if (recvd == -ECONNABORTED)
return WOLFSSL_CBIO_ERR_CONN_CLOSE; return WOLFSSL_CBIO_ERR_CONN_CLOSE;
else else
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
} }
else if (recvd == 0) else if (recvd == 0)
return WOLFSSL_CBIO_ERR_CONN_CLOSE; return WOLFSSL_CBIO_ERR_CONN_CLOSE;
return recvd; return recvd;
} }
void https_close(HTTP_INFO *httpinfo) void https_close(HTTP_INFO *httpinfo)
{ {
if (httpinfo->use_https) if (httpinfo->use_https)
{ {
wolfSSL_shutdown(httpinfo->ssl); wolfSSL_shutdown(httpinfo->ssl);
wolfSSL_free(httpinfo->ssl); wolfSSL_free(httpinfo->ssl);
wolfSSL_CTX_free(httpinfo->ctx); wolfSSL_CTX_free(httpinfo->ctx);
} }
net_close(httpinfo->sock); net_close(httpinfo->sock);
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Closed socket and cleaned up\n"); gprintf("Closed socket and cleaned up\n");
#endif #endif
} }
bool get_header_value(struct phr_header *headers, size_t num_headers, char *dst, char *header) 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) for (size_t i = 0; i != num_headers; ++i)
{ {
if (strncasecmp(header, headers[i].name, headers[i].name_len) == 0) if (strncasecmp(header, headers[i].name, headers[i].name_len) == 0)
{ {
strlcpy(dst, headers[i].value, headers[i].value_len + 1); strlcpy(dst, headers[i].value, headers[i].value_len + 1);
return true; return true;
} }
} }
return false; return false;
} }
u64 get_header_value_int(struct phr_header *headers, size_t num_headers, char *header) u64 get_header_value_int(struct phr_header *headers, size_t num_headers, char *header)
{ {
char header_value[30]; char header_value[30];
if (!get_header_value(headers, num_headers, header_value, header)) if (!get_header_value(headers, num_headers, header_value, header))
return 0; return 0;
return strtoull(header_value, NULL, 0); return strtoull(header_value, NULL, 0);
} }
bool is_chunked(struct phr_header *headers, size_t num_headers) bool is_chunked(struct phr_header *headers, size_t num_headers)
{ {
char encoding[9]; char encoding[9];
if (!get_header_value(headers, num_headers, encoding, "transfer-encoding")) if (!get_header_value(headers, num_headers, encoding, "transfer-encoding"))
return false; return false;
return (strcasecmp(encoding, "chunked") == 0); return (strcasecmp(encoding, "chunked") == 0);
} }
bool read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) bool read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos)
{ {
struct phr_chunked_decoder decoder = {0}; struct phr_chunked_decoder decoder = {0};
size_t rsize, capacity = 4096; size_t rsize, capacity = 4096;
ssize_t pret; ssize_t pret;
int ret; int ret;
decoder.consume_trailer = true; decoder.consume_trailer = true;
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Data is chunked\n"); gprintf("Data is chunked\n");
#endif #endif
do do
{ {
if (start_pos == capacity) if (start_pos == capacity)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Increased buffer size\n"); gprintf("Increased buffer size\n");
#endif #endif
capacity *= 2; capacity *= 2;
buffer->data = MEM2_realloc(buffer->data, capacity); buffer->data = MEM2_realloc(buffer->data, capacity);
} }
if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) < 1) if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) < 1)
return false; return false;
rsize = ret; rsize = ret;
pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize); pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize);
if (pret == -1) if (pret == -1)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Parse error\n"); gprintf("Parse error\n");
#endif #endif
return false; return false;
} }
start_pos += rsize; start_pos += rsize;
} while (pret == -2); } while (pret == -2);
buffer->size = start_pos; buffer->size = start_pos;
buffer->data = MEM2_realloc(buffer->data, buffer->size); buffer->data = MEM2_realloc(buffer->data, buffer->size);
return true; return true;
} }
bool read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) bool read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos)
{ {
size_t capacity = 4096; size_t capacity = 4096;
int ret; int ret;
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Data is not chunked\n"); gprintf("Data is not chunked\n");
#endif #endif
while (true) while (true)
{ {
if (start_pos == capacity) if (start_pos == capacity)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Increased buffer size\n"); gprintf("Increased buffer size\n");
#endif #endif
capacity *= 2; capacity *= 2;
buffer->data = MEM2_realloc(buffer->data, capacity); buffer->data = MEM2_realloc(buffer->data, capacity);
} }
if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) == 0) if ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos, false)) == 0)
break; break;
if (ret < 0) if (ret < 0)
return false; return false;
start_pos += ret; start_pos += ret;
}; };
buffer->size = start_pos; buffer->size = start_pos;
buffer->data = MEM2_realloc(buffer->data, buffer->size); buffer->data = MEM2_realloc(buffer->data, buffer->size);
return (buffer->content_length > 0 && buffer->content_length == start_pos); return (buffer->content_length > 0 && buffer->content_length == start_pos);
} }
bool get_response(HTTP_INFO *httpinfo, HTTP_RESPONSE *resp, bool proxy) bool get_response(HTTP_INFO *httpinfo, HTTP_RESPONSE *resp, bool proxy)
{ {
int rret, minor_version; int rret, minor_version;
size_t msg_len, prevbuflen; size_t msg_len, prevbuflen;
const char *msg; const char *msg;
while (true) while (true)
{ {
if ((rret = https_read(httpinfo, &resp->data[resp->buflen], 1, proxy)) < 1) if ((rret = https_read(httpinfo, &resp->data[resp->buflen], 1, proxy)) < 1)
return false; return false;
prevbuflen = resp->buflen; prevbuflen = resp->buflen;
resp->buflen += rret; resp->buflen += rret;
// Parse the response // Parse the response
resp->num_headers = sizeof(resp->headers) / sizeof(resp->headers[0]); 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) if ((resp->pret = phr_parse_response(resp->data, resp->buflen, &minor_version, &resp->status, &msg, &msg_len,
return true; resp->headers, &resp->num_headers, prevbuflen)) > 0)
else if (resp->pret == -1) return true;
{ else if (resp->pret == -1)
{
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("pret error %i\n", resp->pret); gprintf("pret error %i\n", resp->pret);
#endif #endif
return false; return false;
} }
if (resp->buflen == sizeof(resp->data)) if (resp->buflen == sizeof(resp->data))
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("buflen error %lu\n", (unsigned long)resp->buflen); gprintf("buflen error %lu\n", (unsigned long)resp->buflen);
#endif #endif
return false; return false;
} }
} }
return false; return false;
} }
bool check_ip(char *str) bool check_ip(char *str)
{ {
int partA, partB, partC, partD; int partA, partB, partC, partD;
char extra; char extra;
// We avoid using regex because it increases the file size // We avoid using regex because it increases the file size
return (sscanf(str, "%d.%d.%d.%d%c", &partA, &partB, &partC, &partD, &extra) == 4); 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) bool connect_proxy(HTTP_INFO *httpinfo, char *host, char *username, char *password)
{ {
HTTP_RESPONSE response = {0}; HTTP_RESPONSE response = {0};
char request[500]; char request[500];
char credentials[66]; char credentials[66];
char *auth; char *auth;
int len; int len;
if (username && password) if (username && password)
{ {
if (!snprintf(credentials, sizeof(credentials), "%s:%s", username, password)) if (!snprintf(credentials, sizeof(credentials), "%s:%s", username, password))
return false; return false;
if (!(auth = base64(credentials, strlen(credentials), &len))) if (!(auth = base64(credentials, strlen(credentials), &len)))
return false; 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); len = snprintf(request, sizeof(request),
MEM2_free(auth); "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);
else MEM2_free(auth);
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) else
return false; len = snprintf(request, sizeof(request),
if (get_response(httpinfo, &response, true)) "CONNECT %s:%i HTTP/1.1\r\nUser-Agent: curl/7.55.1\r\n\r\n",
{ host, httpinfo->use_https ? 443 : 80);
if (response.status == 200) if (len > 0 && https_write(httpinfo, request, len, true) != len)
return true; return false;
} if (get_response(httpinfo, &response, true))
return false; {
if (response.status == 200)
return true;
}
return false;
} }
int connect(char *host, u16 port) int connect(char *host, u16 port)
{ {
struct sockaddr_in sin; struct sockaddr_in sin;
s32 sock, ret; s32 sock, ret;
u32 ipaddress; u32 ipaddress;
u64 time; u64 time;
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Connecting to %s", host); gprintf("Connecting to %s", host);
#endif #endif
if ((ipaddress = check_ip(host) ? inet_addr(host) : getipbynamecached(host)) == 0) if ((ipaddress = check_ip(host) ? inet_addr(host) : getipbynamecached(host)) == 0)
return -EFAULT; return -EFAULT;
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = htons(port); sin.sin_port = htons(port);
sin.sin_addr.s_addr = ipaddress; sin.sin_addr.s_addr = ipaddress;
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
if (!check_ip(host)) if (!check_ip(host))
gprintf(" (%s)", inet_ntoa(sin.sin_addr)); gprintf(" (%s)", inet_ntoa(sin.sin_addr));
#endif #endif
if ((sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) if ((sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
return sock; return sock;
net_fcntl(sock, F_SETFL, 4); net_fcntl(sock, F_SETFL, 4);
time = gettime(); time = gettime();
while (ticks_to_millisecs(diff_ticks(time, gettime())) < CONNECT_TIMEOUT) while (ticks_to_millisecs(diff_ticks(time, gettime())) < CONNECT_TIMEOUT)
{ {
if ((ret = net_connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0) if ((ret = net_connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0)
{ {
if (ret == -EISCONN) if (ret == -EISCONN)
return sock; return sock;
if (ret == -EINPROGRESS || ret == -EALREADY) if (ret == -EINPROGRESS || ret == -EALREADY)
{ {
usleep(10000); usleep(10000);
continue; continue;
} }
net_close(sock); net_close(sock);
return ret; return ret;
} }
} }
net_close(sock); net_close(sock);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
void downloadfile(const char *url, struct download *buffer) void downloadfile(const char *url, struct download *buffer)
{ {
HTTP_INFO httpinfo = {0}; HTTP_INFO httpinfo = {0};
// Always reset the size due to the image downloader looping // Always reset the size due to the image downloader looping
buffer->size = 0; buffer->size = 0;
// Check if we're using HTTPS and set the path // Check if we're using HTTPS and set the path
char *path; char *path;
if (strncmp(url, "https://", 8) == 0) if (strncmp(url, "https://", 8) == 0)
{ {
httpinfo.use_https = 1; httpinfo.use_https = 1;
path = strchr(url + 8, '/'); path = strchr(url + 8, '/');
} }
else if (strncmp(url, "http://", 7) == 0) else if (strncmp(url, "http://", 7) == 0)
{ {
httpinfo.use_https = 0; httpinfo.use_https = 0;
path = strchr(url + 7, '/'); path = strchr(url + 7, '/');
} }
else else
return; return;
if (path == NULL) if (path == NULL)
return; return;
// Get the host // Get the host
int domainlength = path - url - 7 - httpinfo.use_https; int domainlength = path - url - 7 - httpinfo.use_https;
char host[domainlength + 1]; char host[domainlength + 1];
strlcpy(host, url + 7 + httpinfo.use_https, domainlength + 1); strlcpy(host, url + 7 + httpinfo.use_https, domainlength + 1);
// Start connecting // Start connecting
if (getProxyAddress() && getProxyPort() > 0) if (getProxyAddress() && getProxyPort() > 0)
httpinfo.sock = connect(getProxyAddress(), getProxyPort()); httpinfo.sock = connect(getProxyAddress(), getProxyPort());
else else
httpinfo.sock = connect(host, httpinfo.use_https ? 443 : 80); httpinfo.sock = connect(host, httpinfo.use_https ? 443 : 80);
if (httpinfo.sock < 0) if (httpinfo.sock < 0)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
if (httpinfo.sock == -ETIMEDOUT) if (httpinfo.sock == -ETIMEDOUT)
gprintf("\nFailed to connect (timed out)\n"); gprintf("\nFailed to connect (timed out)\n");
else else
gprintf("\nFailed to connect (%i)\n", httpinfo.sock); gprintf("\nFailed to connect (%i)\n", httpinfo.sock);
#endif #endif
return; return;
} }
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("\nConnected\n"); gprintf("\nConnected\n");
#endif #endif
// Connect to a web proxy // Connect to a web proxy
if (getProxyAddress() && getProxyPort() > 0) if (getProxyAddress() && getProxyPort() > 0)
{ {
if (!connect_proxy(&httpinfo, host, getProxyUsername(), getProxyPassword())) if (!connect_proxy(&httpinfo, host, getProxyUsername(), getProxyPassword()))
{ {
#ifdef DEBUG_NETWORK #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 #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
session = NULL; // Resume doesn't work with a proxy session = NULL; // Resume doesn't work with a proxy
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Proxy is ready to receive\n"); gprintf("Proxy is ready to receive\n");
#endif #endif
} }
// Setup for HTTPS if it's necessary // Setup for HTTPS if it's necessary
if (httpinfo.use_https) if (httpinfo.use_https)
{ {
// Create a new SSL context // Create a new SSL context
// wolfSSLv23_client_method() works but TLS 1.2 is slightly faster on Wii // wolfSSLv23_client_method() works but TLS 1.2 is slightly faster on Wii
if ((httpinfo.ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) if ((httpinfo.ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Failed to create WOLFSSL_CTX\n"); gprintf("Failed to create WOLFSSL_CTX\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Don't verify certificates // Don't verify certificates
wolfSSL_CTX_set_verify(httpinfo.ctx, WOLFSSL_VERIFY_NONE, 0); wolfSSL_CTX_set_verify(httpinfo.ctx, WOLFSSL_VERIFY_NONE, 0);
// Enable SNI // Enable SNI
if (wolfSSL_CTX_UseSNI(httpinfo.ctx, 0, host, strlen(host)) != WOLFSSL_SUCCESS) if (wolfSSL_CTX_UseSNI(httpinfo.ctx, 0, host, strlen(host)) != WOLFSSL_SUCCESS)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Failed to set SNI\n"); gprintf("Failed to set SNI\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Custom I/O is essential due to how libogc handles errors // Custom I/O is essential due to how libogc handles errors
wolfSSL_SetIOSend(httpinfo.ctx, send_callback); wolfSSL_SetIOSend(httpinfo.ctx, send_callback);
wolfSSL_SetIORecv(httpinfo.ctx, recv_callback); wolfSSL_SetIORecv(httpinfo.ctx, recv_callback);
// Create a new wolfSSL session // Create a new wolfSSL session
if ((httpinfo.ssl = wolfSSL_new(httpinfo.ctx)) == NULL) if ((httpinfo.ssl = wolfSSL_new(httpinfo.ctx)) == NULL)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("SSL session creation failed\n"); gprintf("SSL session creation failed\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Set the file descriptor // Set the file descriptor
if (wolfSSL_set_fd(httpinfo.ssl, httpinfo.sock) != SSL_SUCCESS) if (wolfSSL_set_fd(httpinfo.ssl, httpinfo.sock) != SSL_SUCCESS)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Failed to set SSL file descriptor\n"); gprintf("Failed to set SSL file descriptor\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Attempt to resume the session // Attempt to resume the session
if (session != NULL && wolfSSL_set_session(httpinfo.ssl, session) != SSL_SUCCESS) if (session != NULL && wolfSSL_set_session(httpinfo.ssl, session) != SSL_SUCCESS)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Failed to set session (session timed out?)\n"); gprintf("Failed to set session (session timed out?)\n");
#endif #endif
session = NULL; session = NULL;
} }
// Initiate a handshake // Initiate a handshake
u64 time = gettime(); u64 time = gettime();
while (true) while (true)
{ {
if (ticks_to_millisecs(diff_ticks(time, gettime())) > CONNECT_TIMEOUT) if (ticks_to_millisecs(diff_ticks(time, gettime())) > CONNECT_TIMEOUT)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("SSL handshake failed\n"); gprintf("SSL handshake failed\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
if (wolfSSL_connect(httpinfo.ssl) == SSL_SUCCESS) if (wolfSSL_connect(httpinfo.ssl) == SSL_SUCCESS)
break; break;
usleep(10000); usleep(10000);
} }
// Check if we resumed successfully // Check if we resumed successfully
if (session != NULL && !wolfSSL_session_reused(httpinfo.ssl)) if (session != NULL && !wolfSSL_session_reused(httpinfo.ssl))
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Failed to resume session\n"); gprintf("Failed to resume session\n");
#endif #endif
session = NULL; session = NULL;
} }
// Cipher info // Cipher info
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
/*char ciphers[4096]; /*char ciphers[4096];
wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
gprintf("All supported ciphers: %s\n", ciphers);*/ gprintf("All supported ciphers: %s\n", ciphers);*/
WOLFSSL_CIPHER *cipher = wolfSSL_get_current_cipher(httpinfo.ssl); WOLFSSL_CIPHER *cipher = wolfSSL_get_current_cipher(httpinfo.ssl);
gprintf("Using: %s - %s\n", wolfSSL_get_version(httpinfo.ssl), wolfSSL_CIPHER_get_name(cipher)); gprintf("Using: %s - %s\n", wolfSSL_get_version(httpinfo.ssl), wolfSSL_CIPHER_get_name(cipher));
#endif #endif
} }
// Send our request // Send our request
char request[2300]; char request[2300];
int ret, len; int ret, len;
len = snprintf(request, sizeof(request), len = snprintf(request, sizeof(request),
"GET %s HTTP/1.1\r\n" "GET %s HTTP/1.1\r\n"
"Host: %s\r\n" "Host: %s\r\n"
"User-Agent: WiiFlow-Lite\r\n" "User-Agent: WiiFlow-Lite\r\n"
"Connection: close\r\n" "Connection: close\r\n"
"Pragma: no-cache\r\n" "Pragma: no-cache\r\n"
"Cache-Control: no-cache\r\n\r\n", "Cache-Control: no-cache\r\n\r\n",
path, host); path, host);
if ((ret = https_write(&httpinfo, request, len, false)) != len) if ((ret = https_write(&httpinfo, request, len, false)) != len)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("https_write error: %i\n", ret); gprintf("https_write error: %i\n", ret);
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Check if we want a response // Check if we want a response
if (buffer->skip_response) if (buffer->skip_response)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Sent request to %s and skipping response\n", host); gprintf("Sent request to %s and skipping response\n", host);
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Get the response // Get the response
HTTP_RESPONSE response = {0}; HTTP_RESPONSE response = {0};
if (!get_response(&httpinfo, &response, false)) if (!get_response(&httpinfo, &response, false))
{ {
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// The website wants to redirect us // The website wants to redirect us
if (response.status == 301 || response.status == 302) if (response.status == 301 || response.status == 302)
{ {
https_close(&httpinfo); https_close(&httpinfo);
if (loop == REDIRECT_LIMIT) if (loop == REDIRECT_LIMIT)
{ {
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Reached redirect limit\n"); gprintf("Reached redirect limit\n");
#endif #endif
return; return;
} }
loop++; loop++;
char location[2049]; char location[2049];
if (!get_header_value(response.headers, response.num_headers, location, "location")) if (!get_header_value(response.headers, response.num_headers, location, "location"))
return; return;
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Redirect #%i - %s\n", loop, location); gprintf("Redirect #%i - %s\n", loop, location);
#endif #endif
downloadfile(location, buffer); downloadfile(location, buffer);
return; return;
} }
// It's not 301 or 302, so reset the loop // It's not 301 or 302, so reset the loop
loop = 0; loop = 0;
// We got what we wanted // We got what we wanted
if (response.status == 200) if (response.status == 200)
{ {
buffer->data = MEM2_alloc(4096); buffer->data = MEM2_alloc(4096);
memcpy(buffer->data, &response.data[response.pret], response.buflen - response.pret); memcpy(buffer->data, &response.data[response.pret], response.buflen - response.pret);
// Determine how to read the data // Determine how to read the data
bool dl_valid; bool dl_valid;
if (is_chunked(response.headers, response.num_headers)) if (is_chunked(response.headers, response.num_headers))
dl_valid = read_chunked(&httpinfo, buffer, response.buflen - response.pret); dl_valid = read_chunked(&httpinfo, buffer, response.buflen - response.pret);
else else
{ {
buffer->content_length = get_header_value_int(response.headers, response.num_headers, "content-length"); buffer->content_length = get_header_value_int(response.headers, response.num_headers, "content-length");
dl_valid = read_all(&httpinfo, buffer, response.buflen - response.pret); dl_valid = read_all(&httpinfo, buffer, response.buflen - response.pret);
} }
// Check if the download is incomplete // Check if the download is incomplete
if (!dl_valid || buffer->size < 1) if (!dl_valid || buffer->size < 1)
{ {
buffer->size = 0; buffer->size = 0;
MEM2_free(buffer->data); MEM2_free(buffer->data);
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Removed incomplete download\n"); gprintf("Removed incomplete download\n");
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
return; return;
} }
// Save the session // Save the session
if (httpinfo.use_https) if (httpinfo.use_https)
session = wolfSSL_get_session(httpinfo.ssl); session = wolfSSL_get_session(httpinfo.ssl);
// Finished // Finished
https_close(&httpinfo); https_close(&httpinfo);
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Download size: %llu\n", (long long)buffer->size); gprintf("Download size: %llu\n", (long long)buffer->size);
gprintf("------------- HEADERS -------------\n"); gprintf("------------- HEADERS -------------\n");
for (size_t i = 0; i != response.num_headers; ++i) 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("%.*s: %.*s\n", (int)response.headers[i].name_len, response.headers[i].name,
gprintf("------------ COMPLETED ------------\n"); (int)response.headers[i].value_len, response.headers[i].value);
gprintf("------------ COMPLETED ------------\n");
#endif #endif
return; return;
} }
// Close on all other status codes // Close on all other status codes
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Status code: %i - %s\n", response.status, url); gprintf("Status code: %i - %s\n", response.status, url);
#endif #endif
https_close(&httpinfo); https_close(&httpinfo);
} }

View File

@ -21,34 +21,34 @@ extern "C"
#define READ_WRITE_TIMEOUT 20000 #define READ_WRITE_TIMEOUT 20000
#define BLOCK_SIZE 8192 #define BLOCK_SIZE 8192
struct download struct download
{ {
bool skip_response; // Used by WiinnerTag bool skip_response; // Used by WiinnerTag
u64 content_length; u64 content_length;
u64 size; u64 size;
char *data; char *data;
}; };
typedef struct typedef struct
{ {
int status; int status;
int pret; int pret;
size_t num_headers; size_t num_headers;
size_t buflen; size_t buflen;
struct phr_header headers[100]; struct phr_header headers[100];
char data[4096]; char data[4096];
} HTTP_RESPONSE; } HTTP_RESPONSE;
typedef struct typedef struct
{ {
u8 use_https; u8 use_https;
s32 sock; s32 sock;
WOLFSSL *ssl; WOLFSSL *ssl;
WOLFSSL_CTX *ctx; WOLFSSL_CTX *ctx;
} HTTP_INFO; } HTTP_INFO;
void downloadfile(const char *url, struct download *buffer); void downloadfile(const char *url, struct download *buffer);
int wolfSSL_CTX_UseSNI(WOLFSSL_CTX *ctx, unsigned char type, const void *data, unsigned short size); int wolfSSL_CTX_UseSNI(WOLFSSL_CTX *ctx, unsigned char type, const void *data, unsigned short size);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -17,59 +17,59 @@ char proxy_password[33];
void getProxyInfo() void getProxyInfo()
{ {
char *buffer; char *buffer;
int fd = ISFS_Open("/shared2/sys/net/02/config.dat", ISFS_OPEN_READ); int fd = ISFS_Open("/shared2/sys/net/02/config.dat", ISFS_OPEN_READ);
if (fd >= 0) if (fd >= 0)
{ {
fstats stats ATTRIBUTE_ALIGN(32); fstats stats ATTRIBUTE_ALIGN(32);
if(ISFS_GetFileStats(fd, &stats) >= 0) if (ISFS_GetFileStats(fd, &stats) >= 0)
{ {
if (stats.file_length == 7004) if (stats.file_length == 7004)
{ {
buffer = (char *)MEM2_alloc(ALIGN32(stats.file_length)); buffer = (char *)MEM2_alloc(ALIGN32(stats.file_length));
if (buffer) if (buffer)
{ {
if (ISFS_Read(fd, buffer, stats.file_length) == 7004) if (ISFS_Read(fd, buffer, stats.file_length) == 7004)
{ {
proxy_enabled = buffer[44]; proxy_enabled = buffer[44];
proxy_creds_enabled = buffer[45]; proxy_creds_enabled = buffer[45];
strncpy(proxy_address, buffer + 48, sizeof(proxy_address) - 1); strncpy(proxy_address, buffer + 48, sizeof(proxy_address) - 1);
proxy_port = ((buffer[304] & 0xFF) << 8) | (buffer[305] & 0xFF); proxy_port = ((buffer[304] & 0xFF) << 8) | (buffer[305] & 0xFF);
strncpy(proxy_username, buffer + 306, sizeof(proxy_username) - 1); strncpy(proxy_username, buffer + 306, sizeof(proxy_username) - 1);
strncpy(proxy_password, buffer + 338, sizeof(proxy_password) - 1); strncpy(proxy_password, buffer + 338, sizeof(proxy_password) - 1);
} }
} }
MEM2_free(buffer); MEM2_free(buffer);
} }
} }
ISFS_Close(fd); ISFS_Close(fd);
} }
} }
char *getProxyAddress() char *getProxyAddress()
{ {
if (mainMenu.proxyUseSystem) if (mainMenu.proxyUseSystem)
return proxy_enabled ? proxy_address : NULL; return proxy_enabled ? proxy_address : NULL;
return (strlen(mainMenu.proxyAddress) > 6) ? mainMenu.proxyAddress : NULL; return (strlen(mainMenu.proxyAddress) > 6) ? mainMenu.proxyAddress : NULL;
} }
u16 getProxyPort() u16 getProxyPort()
{ {
if (mainMenu.proxyUseSystem) if (mainMenu.proxyUseSystem)
return proxy_enabled ? proxy_port : 0; return proxy_enabled ? proxy_port : 0;
return mainMenu.proxyPort; return mainMenu.proxyPort;
} }
char *getProxyUsername() char *getProxyUsername()
{ {
if (mainMenu.proxyUseSystem) if (mainMenu.proxyUseSystem)
return proxy_enabled && proxy_creds_enabled ? proxy_username : NULL; return proxy_enabled && proxy_creds_enabled ? proxy_username : NULL;
return (strlen(mainMenu.proxyUsername) > 0) ? mainMenu.proxyUsername : NULL; return (strlen(mainMenu.proxyUsername) > 0) ? mainMenu.proxyUsername : NULL;
} }
char *getProxyPassword() char *getProxyPassword()
{ {
if (mainMenu.proxyUseSystem) if (mainMenu.proxyUseSystem)
return proxy_enabled && proxy_creds_enabled ? proxy_password : NULL; return proxy_enabled && proxy_creds_enabled ? proxy_password : NULL;
return (strlen(mainMenu.proxyPassword) > 0) ? mainMenu.proxyPassword : NULL; return (strlen(mainMenu.proxyPassword) > 0) ? mainMenu.proxyPassword : NULL;
} }

View File

@ -6,11 +6,11 @@
extern "C" extern "C"
{ {
#endif #endif
void getProxyInfo(); void getProxyInfo();
char *getProxyAddress(); char *getProxyAddress();
u16 getProxyPort(); u16 getProxyPort();
char *getProxyUsername(); char *getProxyUsername();
char *getProxyPassword(); char *getProxyPassword();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif