@@ -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
2124typedef 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+
466502void _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
476522void _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