#include #ifdef HX_WINDOWS # include # include #else # include # include # include typedef int SOCKET; #endif #include #include #if defined(NEKO_MAC) && !defined(IPHONE) && !defined(APPLETV) #include #endif typedef size_t socket_int; #define SOCKET_ERROR (-1) #define NRETRYS 20 #include "mbedtls/error.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/md.h" #include "mbedtls/pk.h" #include "mbedtls/oid.h" #include "mbedtls/x509_crt.h" #include "mbedtls/ssl.h" #include "mbedtls/debug.h" #define val_ssl(o) ((sslctx*)o.mPtr) #define val_conf(o) ((sslconf*)o.mPtr) #define val_cert(o) ((sslcert*)o.mPtr) #define val_pkey(o) ((sslpkey*)o.mPtr) struct SocketWrapper : public hx::Object { HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSocket }; SOCKET socket; }; struct sslctx : public hx::Object { HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSsl }; mbedtls_ssl_context *s; void create() { s = (mbedtls_ssl_context *)malloc(sizeof(mbedtls_ssl_context)); mbedtls_ssl_init(s); _hx_set_finalizer(this, finalize); } void destroy() { if( s ) { mbedtls_ssl_free( s ); free(s); s = 0; } } static void finalize(Dynamic obj) { ((sslctx *)(obj.mPtr))->destroy(); } String toString() { return HX_CSTRING("sslctx"); } }; struct sslconf : public hx::Object { HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslConf }; mbedtls_ssl_config *c; void create() { c = (mbedtls_ssl_config *)malloc(sizeof(mbedtls_ssl_config)); mbedtls_ssl_config_init(c); _hx_set_finalizer(this, finalize); } void destroy() { if( c ) { mbedtls_ssl_config_free( c ); free(c); c = 0; } } static void finalize(Dynamic obj) { ((sslconf *)(obj.mPtr))->destroy(); } String toString() { return HX_CSTRING("sslconfig"); } }; struct sslcert : public hx::Object { HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslCert }; mbedtls_x509_crt *c; bool head; void create(const mbedtls_x509_crt *inC) { if( inC ){ c = (mbedtls_x509_crt *)inC; head = false; }else{ c = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init(c); head = true; } _hx_set_finalizer(this, finalize); } void destroy() { if( c && head ) { mbedtls_x509_crt_free( c ); free(c); head = 0; } c = 0; } static void finalize(Dynamic obj) { ((sslcert *)(obj.mPtr))->destroy(); } String toString() { return HX_CSTRING("sslcert"); } }; struct sslpkey : public hx::Object { HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslKey }; mbedtls_pk_context *k; void create() { k = (mbedtls_pk_context *)malloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(k); _hx_set_finalizer(this, finalize); } void destroy() { if( k ) { mbedtls_pk_free(k); free(k); k = 0; } } static void finalize(Dynamic obj) { ((sslpkey *)(obj.mPtr))->destroy(); } String toString() { return HX_CSTRING("sslpkey"); } }; static mbedtls_entropy_context entropy; static mbedtls_ctr_drbg_context ctr_drbg; static bool is_ssl_blocking( int r ) { return r == MBEDTLS_ERR_SSL_WANT_READ || r == MBEDTLS_ERR_SSL_WANT_WRITE; } static bool is_block_error() { #ifdef NEKO_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY || err == WSAETIMEDOUT ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif return true; return false; } static void ssl_error( int ret ){ char buf[256]; mbedtls_strerror(ret, buf, sizeof(buf)); hx::Throw( String(buf) ); } Dynamic _hx_ssl_new( Dynamic hconf ) { int ret; sslctx *ssl = new sslctx(); ssl->create(); sslconf *conf = val_conf(hconf); if( ret = mbedtls_ssl_setup(ssl->s, conf->c) != 0 ){ ssl->destroy(); ssl_error(ret); } return ssl; } void _hx_ssl_close( Dynamic hssl ) { sslctx *ssl = val_ssl(hssl); ssl->destroy(); } void _hx_ssl_debug_set (int i) { mbedtls_debug_set_threshold(i); } void _hx_ssl_handshake( Dynamic hssl ) { int r; sslctx *ssl = val_ssl(hssl); POSIX_LABEL(handshake_again); r = mbedtls_ssl_handshake( ssl->s ); if ( is_ssl_blocking(r) ) { HANDLE_EINTR(handshake_again); hx::Throw(HX_CSTRING("Blocking")); }else if( r == SOCKET_ERROR ) { HANDLE_EINTR(handshake_again); hx::Throw(HX_CSTRING("ssl network error")); }else if( r != 0 ) ssl_error(r); } int net_read( void *fd, unsigned char *buf, size_t len ){ hx::EnterGCFreeZone(); int r = recv((SOCKET)(socket_int)fd, (char *)buf, len, 0); if( r == SOCKET_ERROR && is_block_error() ) r = MBEDTLS_ERR_SSL_WANT_READ; hx::ExitGCFreeZone(); return r; } int net_write( void *fd, const unsigned char *buf, size_t len ){ hx::EnterGCFreeZone(); int r = send((SOCKET)(socket_int)fd, (char *)buf, len, 0); if( r == SOCKET_ERROR && is_block_error() ) r = MBEDTLS_ERR_SSL_WANT_WRITE; hx::ExitGCFreeZone(); return r; } void _hx_ssl_set_socket( Dynamic hssl, Dynamic hsocket ) { sslctx *ssl = val_ssl(hssl); SocketWrapper *socket = (SocketWrapper *)hsocket.mPtr; mbedtls_ssl_set_bio( ssl->s, (void *)(socket_int)socket->socket, net_write, net_read, NULL ); } void _hx_ssl_set_hostname( Dynamic hssl, String hostname ){ int ret; sslctx *ssl = val_ssl(hssl); hx::strbuf buf; if( ret = mbedtls_ssl_set_hostname(ssl->s, hostname.utf8_str(&buf)) != 0 ) ssl_error(ret); } Dynamic _hx_ssl_get_peer_certificate( Dynamic hssl ){ sslctx *ssl = val_ssl(hssl); const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(ssl->s); if( crt == NULL ) return null(); sslcert *cert = new sslcert(); cert->create( crt ); return cert; } bool _hx_ssl_get_verify_result( Dynamic hssl ){ sslctx *ssl = val_ssl(hssl); int r = mbedtls_ssl_get_verify_result( ssl->s ); if( r == 0 ) return true; else if( r != -1 ) return false; hx::Throw( HX_CSTRING("not available") ); return false; } void _hx_ssl_send_char( Dynamic hssl, int c ) { if( c < 0 || c > 255 ) hx::Throw( HX_CSTRING("invalid char") ); sslctx *ssl = val_ssl(hssl); const unsigned char cc = c; mbedtls_ssl_write( ssl->s, &cc, 1 ); } int _hx_ssl_send( Dynamic hssl, Array buf, int p, int l ) { sslctx *ssl = val_ssl(hssl); int dlen = buf->length; if( p < 0 || l < 0 || p > dlen || p + l > dlen ) hx::Throw( HX_CSTRING("ssl_send") ); POSIX_LABEL(send_again); const unsigned char *base = (const unsigned char *)&buf[0]; dlen = mbedtls_ssl_write( ssl->s, base + p, l ); if ( is_ssl_blocking(dlen) ) { HANDLE_EINTR(send_again); hx::Throw(HX_CSTRING("Blocking")); }else if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); hx::Throw(HX_CSTRING("ssl network error")); } return dlen; } void _hx_ssl_write( Dynamic hssl, Array buf ) { sslctx *ssl = val_ssl(hssl); int len = buf->length; unsigned char *cdata = &buf[0]; while( len > 0 ) { POSIX_LABEL( write_again ); int slen = mbedtls_ssl_write( ssl->s, cdata, len ); if ( is_ssl_blocking(slen) ) { HANDLE_EINTR( write_again ); hx::Throw(HX_CSTRING("Blocking")); }else if( slen == SOCKET_ERROR ) { HANDLE_EINTR( write_again ); hx::Throw(HX_CSTRING("ssl network error")); } cdata += slen; len -= slen; } } int _hx_ssl_recv_char( Dynamic hssl ) { sslctx *ssl = val_ssl(hssl); unsigned char cc; int r = mbedtls_ssl_read( ssl->s, &cc, 1 ); if( r <= 0 ) hx::Throw( HX_CSTRING("ssl_recv_char") ); return (int)cc; } int _hx_ssl_recv( Dynamic hssl, Array buf, int p, int l ) { sslctx *ssl = val_ssl(hssl); int dlen = buf->length; if( p < 0 || l < 0 || p > dlen || p + l > dlen ) hx::Throw( HX_CSTRING("ssl_recv") ); unsigned char *base = &buf[0]; POSIX_LABEL(recv_again); dlen = mbedtls_ssl_read( ssl->s, base + p, l ); if ( is_ssl_blocking(dlen) ) { HANDLE_EINTR(recv_again); hx::Throw(HX_CSTRING("Blocking")); }else if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); hx::Throw(HX_CSTRING("ssl network error")); } 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") ); } return dlen; } Array _hx_ssl_read( Dynamic hssl ) { sslctx *ssl = val_ssl(hssl); Array result = Array_obj::__new(); unsigned char buf[256]; while( true ) { POSIX_LABEL(read_again); int len = mbedtls_ssl_read( ssl->s, buf, 256 ); if ( is_ssl_blocking(len) ) { HANDLE_EINTR(read_again); hx::Throw(HX_CSTRING("Blocking")); }else if( len == SOCKET_ERROR ) { HANDLE_EINTR(read_again); hx::Throw(HX_CSTRING("ssl network error")); } if( len == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { mbedtls_ssl_close_notify( ssl->s ); len = 0; } if( len == 0 ) break; result->memcpy(result->length, buf, len); } return result; } Dynamic _hx_ssl_conf_new( bool server ) { int ret; sslconf *conf = new sslconf(); conf->create(); if( ret = mbedtls_ssl_config_defaults( conf->c, server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, 0 ) != 0 ){ conf->destroy(); ssl_error( ret ); } mbedtls_ssl_conf_rng( conf->c, mbedtls_ctr_drbg_random, &ctr_drbg ); return conf; } void _hx_ssl_conf_close( Dynamic hconf ) { sslconf *conf = val_conf(hconf); conf->destroy(); } void _hx_ssl_conf_set_ca( Dynamic hconf, Dynamic hcert ) { sslconf *conf = val_conf(hconf); 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 ); } } void _hx_ssl_conf_set_verify( Dynamic hconf, int mode ) { sslconf *conf = val_conf(hconf); if( mode == 2 ) mbedtls_ssl_conf_authmode(conf->c, MBEDTLS_SSL_VERIFY_OPTIONAL); else if( mode == 1 ) mbedtls_ssl_conf_authmode(conf->c, MBEDTLS_SSL_VERIFY_REQUIRED); else mbedtls_ssl_conf_authmode(conf->c, MBEDTLS_SSL_VERIFY_NONE); } void _hx_ssl_conf_set_cert( Dynamic hconf, Dynamic hcert, Dynamic hpkey ) { int r; sslconf *conf = val_conf(hconf); sslcert *cert = val_cert(hcert); sslpkey *pkey = val_pkey(hpkey); if( r = mbedtls_ssl_conf_own_cert(conf->c, cert->c, pkey->k) != 0 ) ssl_error(r); } static int sni_callback( void *arg, mbedtls_ssl_context *ctx, const unsigned char *name, size_t len ){ if( name && arg ){ Dynamic cb = new Dynamic(); cb.mPtr = (hx::Object*)arg; const char *n = (const char *)name; Dynamic ret = cb->__run( String(n,strlen(n)) ); if( ret != null() ){ // TODO authmode and ca Dynamic hcert = ret->__Field(HX_CSTRING("cert"), hx::paccDynamic); Dynamic hpkey = ret->__Field(HX_CSTRING("key"), hx::paccDynamic); sslcert *cert = val_cert(hcert); sslpkey *pk = val_pkey(hpkey); return mbedtls_ssl_set_hs_own_cert( ctx, cert->c, pk->k ); } } return -1; } void _hx_ssl_conf_set_servername_callback( Dynamic hconf, Dynamic cb ){ sslconf *conf = val_conf(hconf); mbedtls_ssl_conf_sni( conf->c, sni_callback, (void *)cb.mPtr ); } Dynamic _hx_ssl_cert_load_defaults(){ #if defined(NEKO_WINDOWS) HCERTSTORE store; PCCERT_CONTEXT cert; sslcert *chain = NULL; if( store = CertOpenSystemStore(0, (LPCSTR)"Root") ){ cert = NULL; while( cert = CertEnumCertificatesInStore(store, cert) ){ if( chain == NULL ){ chain = new sslcert(); chain->create( NULL ); } mbedtls_x509_crt_parse_der( chain->c, (unsigned char *)cert->pbCertEncoded, cert->cbCertEncoded ); } CertCloseStore(store, 0); } if( chain != NULL ) return chain; #elif defined(NEKO_MAC) && !defined(IPHONE) && !defined(APPLETV) CFMutableDictionaryRef search; CFArrayRef result; SecKeychainRef keychain; SecCertificateRef item; CFDataRef dat; sslcert *chain = NULL; // Load keychain if( SecKeychainOpen("/System/Library/Keychains/SystemRootCertificates.keychain",&keychain) != errSecSuccess ) return null(); // Search for certificates search = CFDictionaryCreateMutable( NULL, 0, NULL, NULL ); CFDictionarySetValue( search, kSecClass, kSecClassCertificate ); CFDictionarySetValue( search, kSecMatchLimit, kSecMatchLimitAll ); CFDictionarySetValue( search, kSecReturnRef, kCFBooleanTrue ); CFDictionarySetValue( search, kSecMatchSearchList, CFArrayCreate(NULL, (const void **)&keychain, 1, NULL) ); if( SecItemCopyMatching( search, (CFTypeRef *)&result ) == errSecSuccess ){ CFIndex n = CFArrayGetCount( result ); for( CFIndex i = 0; i < n; i++ ){ item = (SecCertificateRef)CFArrayGetValueAtIndex( result, i ); // Get certificate in DER format dat = SecCertificateCopyData( item ); if( dat ){ if( chain == NULL ){ chain = new sslcert(); chain->create( NULL ); } mbedtls_x509_crt_parse_der( chain->c, (unsigned char *)CFDataGetBytePtr(dat), CFDataGetLength(dat) ); CFRelease( dat ); } } } CFRelease(keychain); if( chain != NULL ) return chain; #endif return null(); } Dynamic _hx_ssl_cert_load_file( String file ){ int r; sslcert *cert = new sslcert(); cert->create( NULL ); hx::strbuf buf; if( r = mbedtls_x509_crt_parse_file(cert->c, file.utf8_str(&buf)) != 0 ){ cert->destroy(); ssl_error(r); } return cert; } Dynamic _hx_ssl_cert_load_path( String path ){ int r; sslcert *cert = new sslcert(); cert->create( NULL ); hx::strbuf buf; if( r = mbedtls_x509_crt_parse_path(cert->c, path.utf8_str(&buf)) != 0 ){ cert->destroy(); ssl_error(r); } return cert; } static String asn1_buf_to_string( mbedtls_asn1_buf *dat ){ unsigned int i, c; HX_CHAR *result = hx::NewString( dat->len ); for( i = 0; i < dat->len; i++ ) { c = dat->p[i]; if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) result[i] = '?'; else result[i] = c; } result[i] = '\0'; return String(result,dat->len); } String _hx_ssl_cert_get_subject( Dynamic hcert, String objname ){ mbedtls_x509_name *obj; int r; const char *oname; sslcert *cert = val_cert(hcert); obj = &cert->c->subject; if( obj == NULL ) hx::Throw( HX_CSTRING("cert_get_subject") ); hx::strbuf buf; while( obj != NULL ){ r = mbedtls_oid_get_attr_short_name( &obj->oid, &oname ); if( r == 0 && strcmp( oname, objname.utf8_str(&buf) ) == 0 ) return asn1_buf_to_string( &obj->val ); obj = obj->next; } return String(); } String _hx_ssl_cert_get_issuer( Dynamic hcert, String objname ){ mbedtls_x509_name *obj; int r; const char *oname; sslcert *cert = val_cert(hcert); obj = &cert->c->issuer; if( obj == NULL ) hx::Throw( HX_CSTRING("cert_get_issuer") ); hx::strbuf buf; while( obj != NULL ){ r = mbedtls_oid_get_attr_short_name( &obj->oid, &oname ); if( r == 0 && strcmp( oname, objname.utf8_str(&buf) ) == 0 ) return asn1_buf_to_string( &obj->val ); obj = obj->next; } return String(); } Array _hx_ssl_cert_get_altnames( Dynamic hcert ){ sslcert *cert = val_cert(hcert); mbedtls_asn1_sequence *cur; Array result(0,1); if(mbedtls_x509_crt_has_ext_type(cert->c, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)){ cur = &cert->c->subject_alt_names; while( cur != NULL ){ result.Add( asn1_buf_to_string(&cur->buf) ); cur = cur->next; } } return result; } static Array x509_time_to_array( mbedtls_x509_time *t ){ if( !t ) hx::Throw( HX_CSTRING("x509_time_to_array") ); Array result(6,6); result[0] = t->year; result[1] = t->mon; result[2] = t->day; result[3] = t->hour; result[4] = t->min; result[5] = t->sec; return result; } Array _hx_ssl_cert_get_notbefore( Dynamic hcert ){ sslcert *cert = val_cert(hcert); if( !cert->c ) hx::Throw( HX_CSTRING("cert_get_notbefore") ); return x509_time_to_array( &cert->c->valid_from ); } Array _hx_ssl_cert_get_notafter( Dynamic hcert ){ sslcert *cert = val_cert(hcert); if( !cert->c ) hx::Throw( HX_CSTRING("cert_get_notafter") ); return x509_time_to_array( &cert->c->valid_to ); } Dynamic _hx_ssl_cert_get_next( Dynamic hcert ){ sslcert *cert = val_cert(hcert); mbedtls_x509_crt *crt = cert->c->next; if( crt == NULL ) return null(); cert = new sslcert(); cert->create(crt); return cert; } Dynamic _hx_ssl_cert_add_pem( Dynamic hcert, String data ){ #ifdef HX_SMART_STRINGS if (data.isUTF16Encoded()) hx::Throw( HX_CSTRING("Invalid data encoding") ); #endif sslcert *cert = val_cert(hcert); int r; bool isnew = 0; if( !cert ){ cert = new sslcert(); cert->create( NULL ); isnew = 1; } unsigned char *b = (unsigned char *)malloc((data.length+1) * sizeof(unsigned char)); memcpy(b,data.raw_ptr(),data.length); b[data.length] = '\0'; r = mbedtls_x509_crt_parse( cert->c, b, data.length+1 ); free(b); if( r < 0 ){ if( isnew ) cert->destroy(); ssl_error(r); } return cert; } Dynamic _hx_ssl_cert_add_der( Dynamic hcert, Array buf ){ sslcert *cert = val_cert(hcert); int r; bool isnew = 0; if( !cert ){ cert = new sslcert(); cert->create( NULL ); isnew = 1; } if( (r = mbedtls_x509_crt_parse_der( cert->c, &buf[0], buf->length)) < 0 ){ if( isnew ) cert->destroy(); ssl_error(r); } return cert; } Dynamic _hx_ssl_key_from_der( Array buf, bool pub ){ sslpkey *pk = new sslpkey(); pk->create(); int r; if( pub ) r = mbedtls_pk_parse_public_key( pk->k, &buf[0], buf->length ); else r = mbedtls_pk_parse_key( pk->k, &buf[0], buf->length, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg); if( r != 0 ){ pk->destroy(); ssl_error(r); } return pk; } Dynamic _hx_ssl_key_from_pem( String data, bool pub, String pass ){ #ifdef HX_SMART_STRINGS if (data.isUTF16Encoded()) hx::Throw( HX_CSTRING("Invalid data encoding") ); #endif sslpkey *pk = new sslpkey(); pk->create(); int r; unsigned char *b = (unsigned char *)malloc((data.length+1) * sizeof(unsigned char)); memcpy(b,data.raw_ptr(),data.length); b[data.length] = '\0'; if( pub ){ r = mbedtls_pk_parse_public_key( pk->k, b, data.length+1 ); }else if( pass == null() ){ r = mbedtls_pk_parse_key( pk->k, b, data.length+1, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg); }else{ Array pbytes(0,0); __hxcpp_bytes_of_string(pbytes,pass); r = mbedtls_pk_parse_key( pk->k, b, data.length+1, (const unsigned char *)pbytes->GetBase(), pbytes->length, mbedtls_ctr_drbg_random, &ctr_drbg); } free(b); if( r != 0 ){ pk->destroy(); ssl_error(r); } return pk; } Array _hx_ssl_dgst_make( Array buf, String alg ){ hx::strbuf ubuf; const mbedtls_md_info_t *md = mbedtls_md_info_from_string(alg.utf8_str(&ubuf)); if( md == NULL ) hx::Throw( HX_CSTRING("Invalid hash algorithm") ); int size = mbedtls_md_get_size(md); Array out = Array_obj::__new(size,size); int r = -1; if( r = mbedtls_md( md, &buf[0], buf->length, &out[0] ) != 0 ) ssl_error(r); return out; } Array _hx_ssl_dgst_sign( Array buf, Dynamic hpkey, String alg ){ int r = -1; size_t olen = 0; unsigned char hash[32]; sslpkey *pk = val_pkey(hpkey); hx::strbuf ubuf; const mbedtls_md_info_t *md = mbedtls_md_info_from_string( alg.utf8_str(&ubuf) ); if( md == NULL ) hx::Throw( HX_CSTRING("Invalid hash algorithm") ); if( r = mbedtls_md( md, &buf[0], buf->length, hash ) != 0 ) ssl_error(r); Array result = Array_obj::__new(MBEDTLS_MPI_MAX_SIZE,MBEDTLS_MPI_MAX_SIZE); if( r = mbedtls_pk_sign( pk->k, mbedtls_md_get_type(md), hash, 0, &result[0], MBEDTLS_MPI_MAX_SIZE, &olen, mbedtls_ctr_drbg_random, &ctr_drbg ) != 0 ) ssl_error(r); result[olen] = 0; result->__SetSize(olen); return result; } bool _hx_ssl_dgst_verify( Array buf, Array sign, Dynamic hpkey, String alg ){ const mbedtls_md_info_t *md; int r = -1; unsigned char hash[32]; sslpkey *pk = val_pkey(hpkey); hx::strbuf ubuf; md = mbedtls_md_info_from_string( alg.utf8_str(&ubuf) ); if( md == NULL ) hx::Throw( HX_CSTRING("Invalid hash algorithm") ); if( r = mbedtls_md( md, &buf[0], buf->length, hash ) != 0 ) ssl_error(r); if( r = mbedtls_pk_verify( pk->k, mbedtls_md_get_type(md), hash, 0, &sign[0], sign->length ) != 0 ) return false; return true; } #if (_MSC_VER || defined(WIN32)) static void threading_mutex_init_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL ) return; InitializeCriticalSection( &mutex->cs ); mutex->is_valid = 1; } static void threading_mutex_free_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return; DeleteCriticalSection( &mutex->cs ); mutex->is_valid = 0; } static int threading_mutex_lock_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); EnterCriticalSection( &mutex->cs ); return( 0 ); } static int threading_mutex_unlock_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); LeaveCriticalSection( &mutex->cs ); return( 0 ); } #endif static bool _hx_ssl_inited = false; void _hx_ssl_init() { if (_hx_ssl_inited) return; _hx_ssl_inited = true; #if (_MSC_VER || defined(WIN32)) mbedtls_threading_set_alt( threading_mutex_init_alt, threading_mutex_free_alt, threading_mutex_lock_alt, threading_mutex_unlock_alt ); #endif psa_crypto_init(); // Init RNG mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 ); }