Skip to content

Commit 380e6cb

Browse files
FuroYTMAJigsaw77
authored andcommitted
Fixed SSL CA chain on iOS and tvOS
1 parent 5a8ec55 commit 380e6cb

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

src/hx/libs/ssl/Build.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
<lib name="crypt32.lib" if="windows" unless="static_link" />
2424
<lib name="ws2_32.lib" if="windows" unless="static_link" />
2525

26-
<flag value="-framework" if="macos"/>
27-
<flag value="Security" if="macos"/>
26+
<flag value="-framework" if="macos || ios || tvos"/>
27+
<flag value="Security" if="macos || ios || tvos"/>
28+
29+
<flag value="-framework" if="ios || tvos"/>
30+
<flag value="CoreFoundation" if="ios || tvos"/>
2831
</target>
2932

3033
</xml>

src/hx/libs/ssl/SSL.cpp

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ typedef int SOCKET;
1414
#include <hxcpp.h>
1515
#include <hx/OS.h>
1616

17-
#if defined(NEKO_MAC) && !defined(IPHONE) && !defined(APPLETV)
17+
#if defined(NEKO_MAC) || defined(IPHONE) || defined(APPLETV)
1818
#include <Security/Security.h>
1919
#endif
20+
#if defined(IPHONE) || defined(APPLETV)
21+
#include <CoreFoundation/CoreFoundation.h>
22+
#endif
2023

2124
typedef size_t socket_int;
2225

@@ -361,12 +364,12 @@ int _hx_ssl_recv( Dynamic hssl, Array<unsigned char> buf, int p, int l ) {
361364
HANDLE_EINTR(recv_again);
362365
hx::Throw(HX_CSTRING("ssl network error"));
363366
}
364-
if( dlen < 0 ) {
367+
if( dlen < 0 ) {
365368
if( dlen == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) {
366369
mbedtls_ssl_close_notify( ssl->s );
367370
return 0;
368371
}
369-
hx::Throw( HX_CSTRING("ssl_recv") );
372+
hx::Throw( HX_CSTRING("ssl_recv") );
370373
}
371374
return dlen;
372375
}
@@ -463,14 +466,57 @@ void _hx_ssl_conf_close( Dynamic hconf ) {
463466
conf->destroy();
464467
}
465468

469+
#if defined(IPHONE) || defined(APPLETV)
470+
static int apple_verify_cb(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
471+
// use mbedtls validate the chain structure and we validate with the iOS system trust store to replace the missing CA bundle
472+
if (depth != 0) {
473+
*flags = 0;
474+
return 0;
475+
}
476+
477+
CFDataRef derData = CFDataCreate(NULL, crt->raw.p, crt->raw.len);
478+
if (!derData) return 0;
479+
480+
SecCertificateRef secCert = SecCertificateCreateWithData(NULL, derData);
481+
CFRelease(derData);
482+
if (!secCert) return 0;
483+
484+
SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
485+
CFArrayRef certs = CFArrayCreate(NULL, (const void **)&secCert, 1, &kCFTypeArrayCallBacks);
486+
SecTrustRef trust = NULL;
487+
SecTrustCreateWithCertificates(certs, policy, &trust);
488+
CFRelease(certs);
489+
CFRelease(policy);
490+
CFRelease(secCert);
491+
492+
CFErrorRef err = NULL;
493+
bool trusted = SecTrustEvaluateWithError(trust, &err);
494+
CFRelease(trust);
495+
if (err) CFRelease(err);
496+
497+
if (trusted) *flags = 0;
498+
return 0;
499+
}
500+
#endif
501+
466502
void _hx_ssl_conf_set_ca( Dynamic hconf, Dynamic hcert ) {
467503
sslconf *conf = val_conf(hconf);
504+
#if defined(IPHONE) || defined(APPLETV)
505+
// always attach Apple system verification callback
506+
mbedtls_ssl_conf_verify(conf->c, apple_verify_cb, NULL);
507+
508+
sslcert *cert = val_cert(hcert);
509+
// make sure the ca chain is set even if null
510+
mbedtls_ssl_conf_ca_chain(conf->c, cert ? cert->c : NULL, NULL);
511+
512+
#else
468513
if( hconf.mPtr ){
469514
sslcert *cert = val_cert(hcert);
470515
mbedtls_ssl_conf_ca_chain( conf->c, cert->c, NULL );
471516
}else{
472517
mbedtls_ssl_conf_ca_chain( conf->c, NULL, NULL );
473518
}
519+
#endif
474520
}
475521

476522
void _hx_ssl_conf_set_verify( Dynamic hconf, int mode ) {
@@ -583,6 +629,10 @@ Dynamic _hx_ssl_cert_load_defaults(){
583629
CFRelease(keychain);
584630
if( chain != NULL )
585631
return chain;
632+
#elif defined(IPHONE) || defined(APPLETV) // SystemRootCertificates.keychain doesn't exist on iOS and tvOS so i use a cool workaround
633+
sslcert *chain = new sslcert();
634+
chain->create(NULL); // creates a ssl cert with only the default ones that iOS or tvOS trust in the os
635+
return chain;
586636
#endif
587637
return null();
588638
}

0 commit comments

Comments
 (0)