diff --git a/src/hx/libs/ssl/Build.xml b/src/hx/libs/ssl/Build.xml
index 2240f564a..af1f3cbc9 100644
--- a/src/hx/libs/ssl/Build.xml
+++ b/src/hx/libs/ssl/Build.xml
@@ -23,8 +23,13 @@
-
-
+
diff --git a/src/hx/libs/ssl/SSL.cpp b/src/hx/libs/ssl/SSL.cpp
index 36d3897ed..35f17dff6 100644
--- a/src/hx/libs/ssl/SSL.cpp
+++ b/src/hx/libs/ssl/SSL.cpp
@@ -14,9 +14,12 @@ typedef int SOCKET;
#include
#include
-#if defined(NEKO_MAC) && !defined(IPHONE) && !defined(APPLETV)
+#if defined(NEKO_MAC) || defined(IPHONE) || defined(APPLETV)
#include
#endif
+#if defined(IPHONE) || defined(APPLETV)
+#include
+#endif
typedef size_t socket_int;
@@ -361,12 +364,12 @@ int _hx_ssl_recv( Dynamic hssl, Array buf, int p, int l ) {
HANDLE_EINTR(recv_again);
hx::Throw(HX_CSTRING("ssl network error"));
}
- if( dlen < 0 ) {
+ if( dlen < 0 ) {
if( dlen == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) {
mbedtls_ssl_close_notify( ssl->s );
return 0;
}
- hx::Throw( HX_CSTRING("ssl_recv") );
+ hx::Throw( HX_CSTRING("ssl_recv") );
}
return dlen;
}
@@ -463,14 +466,57 @@ void _hx_ssl_conf_close( Dynamic hconf ) {
conf->destroy();
}
+#if defined(IPHONE) || defined(APPLETV)
+static int apple_verify_cb(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
+ // use mbedtls validate the chain structure and we validate with the iOS system trust store to replace the missing CA bundle
+ if (depth != 0) {
+ *flags = 0;
+ return 0;
+ }
+
+ CFDataRef derData = CFDataCreate(NULL, crt->raw.p, crt->raw.len);
+ if (!derData) return 0;
+
+ SecCertificateRef secCert = SecCertificateCreateWithData(NULL, derData);
+ CFRelease(derData);
+ if (!secCert) return 0;
+
+ SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
+ CFArrayRef certs = CFArrayCreate(NULL, (const void **)&secCert, 1, &kCFTypeArrayCallBacks);
+ SecTrustRef trust = NULL;
+ SecTrustCreateWithCertificates(certs, policy, &trust);
+ CFRelease(certs);
+ CFRelease(policy);
+ CFRelease(secCert);
+
+ CFErrorRef err = NULL;
+ bool trusted = SecTrustEvaluateWithError(trust, &err);
+ CFRelease(trust);
+ if (err) CFRelease(err);
+
+ if (trusted) *flags = 0;
+ return 0;
+}
+#endif
+
void _hx_ssl_conf_set_ca( Dynamic hconf, Dynamic hcert ) {
sslconf *conf = val_conf(hconf);
+#if defined(IPHONE) || defined(APPLETV)
+ // always attach Apple system verification callback
+ mbedtls_ssl_conf_verify(conf->c, apple_verify_cb, NULL);
+
+ sslcert *cert = val_cert(hcert);
+ // make sure the ca chain is set even if null
+ mbedtls_ssl_conf_ca_chain(conf->c, cert ? cert->c : NULL, NULL);
+
+#else
if( hconf.mPtr ){
sslcert *cert = val_cert(hcert);
mbedtls_ssl_conf_ca_chain( conf->c, cert->c, NULL );
}else{
mbedtls_ssl_conf_ca_chain( conf->c, NULL, NULL );
}
+#endif
}
void _hx_ssl_conf_set_verify( Dynamic hconf, int mode ) {
@@ -583,6 +629,10 @@ Dynamic _hx_ssl_cert_load_defaults(){
CFRelease(keychain);
if( chain != NULL )
return chain;
+#elif defined(IPHONE) || defined(APPLETV) // SystemRootCertificates.keychain doesn't exist on iOS and tvOS so i use a cool workaround
+ sslcert *chain = new sslcert();
+ chain->create(NULL); // creates a ssl cert with only the default ones that iOS or tvOS trust in the os
+ return chain;
#endif
return null();
}