Skip to content

Commit 76f7dc3

Browse files
committed
Stub in new SSL implemenation for Apple OS
Use native SSL on Apple OS instead of mbedtls. Especially needed on iOS where the root CA store cannot be read.
1 parent a428509 commit 76f7dc3

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed

src/hx/libs/ssl/SSL.cpp

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,223 @@
1+
#if defined(HX_MACOS) || defined(IPHONE) || defined(APPLETV)
2+
3+
#include <Security/Security.h>
4+
#include <Security/SecureTransport.h>
5+
#include <CoreFoundation/CoreFoundation.h>
6+
#include <unistd.h>
7+
#include <sys/socket.h>
8+
#include <errno.h>
9+
10+
#include <hxcpp.h>
11+
12+
#define val_ssl(o) ((sslctx*)o.mPtr)
13+
#define val_conf(o) ((sslconf*)o.mPtr)
14+
#define val_socket(o) ((SocketWrapper*)o.mPtr)
15+
#define val_cert(o) ((sslcert*)o.mPtr)
16+
#define val_pkey(o) ((sslpkey*)o.mPtr)
17+
18+
struct SocketWrapper : public hx::Object {
19+
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSocket };
20+
int socket;
21+
};
22+
23+
struct sslcert : public hx::Object {
24+
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslCert };
25+
void create() { _hx_set_finalizer(this, finalize); }
26+
void destroy() {}
27+
static void finalize(Dynamic obj) { ((sslcert*)obj.mPtr)->destroy(); }
28+
String toString() { return HX_CSTRING("sslcert"); }
29+
};
30+
31+
struct sslpkey : public hx::Object {
32+
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslKey };
33+
void create() { _hx_set_finalizer(this, finalize); }
34+
void destroy() {}
35+
static void finalize(Dynamic obj) { ((sslpkey*)obj.mPtr)->destroy(); }
36+
String toString() { return HX_CSTRING("sslpkey"); }
37+
};
38+
39+
struct sslctx : public hx::Object {
40+
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSsl };
41+
SSLContextRef sslCtx = nullptr;
42+
void create(bool isServer = false) {
43+
sslCtx = SSLCreateContext(kCFAllocatorDefault, isServer ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
44+
if (!sslCtx) hx::Throw(HX_CSTRING("Failed to create SSL context"));
45+
_hx_set_finalizer(this, finalize);
46+
}
47+
void destroy() {
48+
if (sslCtx) { CFRelease(sslCtx); sslCtx = nullptr; }
49+
}
50+
static void finalize(Dynamic obj) {
51+
((sslctx*)obj.mPtr)->destroy();
52+
}
53+
String toString() { return HX_CSTRING("sslctx_native"); }
54+
};
55+
56+
struct sslconf : public hx::Object {
57+
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdSslConf };
58+
bool isServer;
59+
void create(bool server) { isServer = server; _hx_set_finalizer(this, finalize); }
60+
void destroy() {}
61+
static void finalize(Dynamic obj) { ((sslconf*)obj.mPtr)->destroy(); }
62+
String toString() { return HX_CSTRING("sslconf"); }
63+
};
64+
65+
Dynamic _hx_ssl_conf_new(bool isServer) {
66+
sslconf* conf = new sslconf(); conf->create(isServer);
67+
return conf;
68+
}
69+
70+
void _hx_ssl_conf_close(Dynamic hconf) {
71+
val_conf(hconf)->destroy();
72+
}
73+
74+
void _hx_ssl_conf_set_ca(Dynamic hconf, Dynamic hcert) {
75+
// Using system trust by default
76+
}
77+
78+
void _hx_ssl_conf_set_verify(Dynamic hconf, int mode) {
79+
// TODO
80+
}
81+
82+
void _hx_ssl_conf_set_cert(Dynamic hconf, Dynamic hcert, Dynamic hpkey) {
83+
// TODO
84+
}
85+
86+
void _hx_ssl_conf_set_servername_callback(Dynamic hconf, Dynamic cb) {
87+
// TODO
88+
}
89+
90+
Dynamic _hx_ssl_cert_load_file(String file) {
91+
hx::Throw(HX_CSTRING("ssl_cert_load_file not supported"));
92+
return null();
93+
}
94+
95+
Dynamic _hx_ssl_cert_load_path(String path) {
96+
hx::Throw(HX_CSTRING("ssl_cert_load_path not supported"));
97+
return null();
98+
}
99+
100+
Dynamic _hx_ssl_new(Dynamic hconf) {
101+
sslctx* ctx = new sslctx();
102+
ctx->create(val_conf(hconf)->isServer);
103+
return ctx;
104+
}
105+
106+
void _hx_ssl_close(Dynamic hssl) {
107+
val_ssl(hssl)->destroy();
108+
}
109+
110+
static OSStatus socket_read(SSLConnectionRef conn, void *data, size_t *len) {
111+
int fd = (int)(intptr_t)conn;
112+
ssize_t ret = recv(fd, data, *len, 0);
113+
if (ret > 0) { *len = ret; return noErr; }
114+
if (ret == 0) return errSSLClosedGraceful;
115+
if (errno == EAGAIN || errno == EWOULDBLOCK) return errSSLWouldBlock;
116+
return errSecIO;
117+
}
118+
static OSStatus socket_write(SSLConnectionRef conn, const void *data, size_t *len) {
119+
int fd = (int)(intptr_t)conn;
120+
ssize_t ret = send(fd, data, *len, 0);
121+
if (ret > 0) { *len = ret; return noErr; }
122+
if (errno == EAGAIN || errno == EWOULDBLOCK) return errSSLWouldBlock;
123+
return errSecIO;
124+
}
125+
126+
void _hx_ssl_set_socket(Dynamic hssl, Dynamic hsocket) {
127+
sslctx* ctx = val_ssl(hssl);
128+
SocketWrapper* sock = val_socket(hsocket);
129+
SSLSetConnection(ctx->sslCtx, (SSLConnectionRef)(intptr_t)sock->socket);
130+
SSLSetIOFuncs(ctx->sslCtx, socket_read, socket_write);
131+
SSLSetProtocolVersionMin(ctx->sslCtx, kTLSProtocol1);
132+
SSLSetProtocolVersionMax(ctx->sslCtx, kTLSProtocol13);
133+
}
134+
135+
void _hx_ssl_set_hostname(Dynamic hssl, String hostname) {
136+
sslctx* ctx = val_ssl(hssl);
137+
hx::strbuf buf;
138+
SSLSetPeerDomainName(ctx->sslCtx, hostname.utf8_str(&buf), hostname.length);
139+
}
140+
141+
void _hx_ssl_handshake(Dynamic hssl) {
142+
sslctx* ctx = val_ssl(hssl);
143+
OSStatus s = SSLHandshake(ctx->sslCtx);
144+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
145+
if (s != noErr) hx::Throw(HX_CSTRING("SSL handshake error"));
146+
}
147+
148+
int _hx_ssl_send(Dynamic hssl, Array<unsigned char> buf, int p, int l) {
149+
sslctx* ctx = val_ssl(hssl);
150+
const void* data = &buf[0] + p;
151+
size_t len = l;
152+
OSStatus s = SSLWrite(ctx->sslCtx, data, len, &len);
153+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
154+
if (s != noErr) hx::Throw(HX_CSTRING("SSL write error"));
155+
return (int)len;
156+
}
157+
158+
int _hx_ssl_recv(Dynamic hssl, Array<unsigned char> buf, int p, int l) {
159+
sslctx* ctx = val_ssl(hssl);
160+
void* data = &buf[0] + p;
161+
size_t len = l;
162+
OSStatus s = SSLRead(ctx->sslCtx, data, len, &len);
163+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
164+
if (s == errSSLClosedGraceful || s == errSSLClosedAbort) return 0;
165+
if (s != noErr) hx::Throw(HX_CSTRING("SSL read error"));
166+
return (int)len;
167+
}
168+
169+
void _hx_ssl_send_char(Dynamic hssl, int c) {
170+
sslctx* ctx = val_ssl(hssl);
171+
UInt8 byte = (UInt8)c;
172+
size_t processed = 0;
173+
OSStatus s = SSLWrite(ctx->sslCtx, &byte, 1, &processed);
174+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
175+
if (s != noErr || processed != 1) hx::Throw(HX_CSTRING("SSL write error"));
176+
}
177+
178+
int _hx_ssl_recv_char(Dynamic hssl) {
179+
sslctx* ctx = val_ssl(hssl);
180+
UInt8 byte;
181+
size_t processed = 0;
182+
OSStatus s = SSLRead(ctx->sslCtx, &byte, 1, &processed);
183+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
184+
if (s != noErr || processed == 0) hx::Throw(HX_CSTRING("ssl_recv_char"));
185+
return (int)byte;
186+
}
187+
188+
void _hx_ssl_write(Dynamic hssl, Array<unsigned char> buf) {
189+
int total = buf->length;
190+
int offset = 0;
191+
while (total > 0) {
192+
int sent = _hx_ssl_send(hssl, buf, offset, total);
193+
offset += sent;
194+
total -= sent;
195+
}
196+
}
197+
198+
Array<unsigned char> _hx_ssl_read(Dynamic hssl) {
199+
Array<unsigned char> res = Array_obj<unsigned char>::__new();
200+
unsigned char buffer[256];
201+
while (true) {
202+
size_t processed = 0;
203+
OSStatus s = SSLRead(val_ssl(hssl)->sslCtx, buffer, sizeof(buffer), &processed);
204+
if (s == errSSLWouldBlock) hx::Throw(HX_CSTRING("Blocking"));
205+
if (s == errSSLClosedGraceful || s == errSSLClosedAbort) break;
206+
if (s != noErr) hx::Throw(HX_CSTRING("SSL read error"));
207+
if (processed == 0) break;
208+
res->memcpy(res->length, buffer, processed);
209+
}
210+
return res;
211+
}
212+
213+
void _hx_ssl_init() {}
214+
215+
Dynamic _hx_ssl_cert_load_defaults() {
216+
return null();
217+
}
218+
219+
#else
220+
1221
#include <string.h>
2222

3223
#ifdef HX_WINDOWS
@@ -896,3 +1116,5 @@ void _hx_ssl_init() {
8961116
mbedtls_ctr_drbg_init( &ctr_drbg );
8971117
mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 );
8981118
}
1119+
1120+
#endif

0 commit comments

Comments
 (0)