appletls.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #include "hssl.h"
  2. #ifdef WITH_APPLETLS
  3. #include <Security/Security.h>
  4. #include <Security/SecureTransport.h>
  5. #include <CoreFoundation/CoreFoundation.h>
  6. const char* hssl_backend() {
  7. return "appletls";
  8. }
  9. typedef struct appletls_ctx {
  10. SecIdentityRef cert;
  11. hssl_ctx_init_param_t* param;
  12. } appletls_ctx_t;
  13. hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param) {
  14. appletls_ctx_t* ctx = (appletls_ctx_t*)malloc(sizeof(appletls_ctx_t));
  15. if (ctx == NULL) return NULL;
  16. ctx->cert = NULL;
  17. ctx->param = param;
  18. g_ssl_ctx = ctx;
  19. return ctx;
  20. }
  21. void hssl_ctx_cleanup(hssl_ctx_t ssl_ctx) {
  22. if (ssl_ctx == NULL) return;
  23. appletls_ctx_t* ctx = (appletls_ctx_t*)ssl_ctx;
  24. if (ctx->cert) {
  25. CFRelease(ctx->cert);
  26. ctx->cert = NULL;
  27. }
  28. free(ctx);
  29. }
  30. typedef struct appletls_s {
  31. SSLContextRef session;
  32. appletls_ctx_t* ctx;
  33. int fd;
  34. } appletls_t;
  35. hssl_t hssl_new(hssl_ctx_t ssl_ctx, int fd) {
  36. if (ssl_ctx == NULL) return NULL;
  37. appletls_t* appletls = (appletls_t*)malloc(sizeof(appletls_t));
  38. if (appletls == NULL) return NULL;
  39. appletls->session = NULL;
  40. appletls->ctx = (appletls_ctx_t*)ssl_ctx;
  41. appletls->fd = fd;
  42. return (hssl_t)appletls;
  43. }
  44. static OSStatus SocketRead(SSLConnectionRef conn, void* data, size_t* len) {
  45. // printf("SocketRead(%d)\n", (int)*len);
  46. appletls_t* appletls = (appletls_t*)conn;
  47. uint8_t* buffer = (uint8_t*)data;
  48. size_t remain = *len;
  49. *len = 0;
  50. while (remain) {
  51. // printf("read(%d)\n", (int)remain);
  52. ssize_t nread = read(appletls->fd, buffer, remain);
  53. // printf("nread=%d errno=%d\n", (int)nread, (int)errno);
  54. if (nread == 0) return errSSLClosedGraceful;
  55. if (nread < 0) {
  56. switch (errno) {
  57. case ENOENT: return errSSLClosedGraceful;
  58. case ECONNRESET:return errSSLClosedAbort;
  59. case EAGAIN: return errSSLWouldBlock;
  60. default: return errSSLClosedAbort;
  61. }
  62. }
  63. remain -= nread;
  64. buffer += nread;
  65. *len += nread;
  66. }
  67. return noErr;
  68. }
  69. static OSStatus SocketWrite(SSLConnectionRef conn, const void* data, size_t* len) {
  70. // printf("SocketWrite(%d)\n", (int)*len);
  71. appletls_t* appletls = (appletls_t*)conn;
  72. uint8_t* buffer = (uint8_t*)data;
  73. size_t remain = *len;
  74. *len = 0;
  75. while (remain) {
  76. // printf("write(%d)\n", (int)remain);
  77. ssize_t nwrite = write(appletls->fd, buffer, remain);
  78. // printf("nwrite=%d errno=%d\n", (int)nwrite, (int)errno);
  79. if (nwrite <= 0) {
  80. switch (errno) {
  81. case EAGAIN: return errSSLWouldBlock;
  82. default: return errSSLClosedAbort;
  83. }
  84. }
  85. remain -= nwrite;
  86. buffer += nwrite;
  87. *len += nwrite;
  88. }
  89. return noErr;
  90. }
  91. static int hssl_init(hssl_t ssl, int endpoint) {
  92. if (ssl == NULL) return HSSL_ERROR;
  93. appletls_t* appletls = (appletls_t*)ssl;
  94. OSStatus ret = noErr;
  95. if (appletls->session == NULL) {
  96. #if defined(__MAC_10_8)
  97. appletls->session = SSLCreateContext(NULL, endpoint == HSSL_SERVER ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
  98. #else
  99. SSLNewContext(endpoint == HSSL_SERVER, &(appletls->session));
  100. #endif
  101. }
  102. if (appletls->session == NULL) {
  103. fprintf(stderr, "SSLCreateContext failed!\n");
  104. return HSSL_ERROR;
  105. }
  106. ret = SSLSetProtocolVersionEnabled(appletls->session, kSSLProtocolAll, true);
  107. if (ret != noErr) {
  108. fprintf(stderr, "SSLSetProtocolVersionEnabled failed!\n");
  109. return HSSL_ERROR;
  110. }
  111. bool verify_peer = false;
  112. if (appletls->ctx->param && appletls->ctx->param->verify_peer) {
  113. verify_peer = true;
  114. }
  115. #if defined(__MAC_10_8)
  116. ret = SSLSetSessionOption(appletls->session, kSSLSessionOptionBreakOnServerAuth, !verify_peer);
  117. #else
  118. ret = SSLSetEnableCertVerify(appletls->session, verify_peer);
  119. #endif
  120. if (ret != noErr) {
  121. fprintf(stderr, "SSLSetEnableCertVerify failed!\n");
  122. return HSSL_ERROR;
  123. }
  124. if (appletls->ctx->cert) {
  125. CFArrayRef certs = CFArrayCreate(NULL, (const void**)&appletls->ctx->cert, 1, NULL);
  126. if (!certs) {
  127. fprintf(stderr, "CFArrayCreate failed!\n");
  128. return HSSL_ERROR;
  129. }
  130. ret = SSLSetCertificate(appletls->session, certs);
  131. CFRelease(certs);
  132. if (ret != noErr) {
  133. fprintf(stderr, "SSLSetCertificate failed!\n");
  134. return HSSL_ERROR;
  135. }
  136. }
  137. size_t all_ciphers_count = 0, allowed_ciphers_count = 0;
  138. SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
  139. ret = SSLGetNumberSupportedCiphers(appletls->session, &all_ciphers_count);
  140. if (ret != noErr) {
  141. fprintf(stderr, "SSLGetNumberSupportedCiphers failed!\n");
  142. goto error;
  143. }
  144. all_ciphers = (SSLCipherSuite*)malloc(all_ciphers_count * sizeof(SSLCipherSuite));
  145. allowed_ciphers = (SSLCipherSuite*)malloc(all_ciphers_count * sizeof(SSLCipherSuite));
  146. if (all_ciphers == NULL || allowed_ciphers == NULL) {
  147. fprintf(stderr, "malloc failed!\n");
  148. goto error;
  149. }
  150. ret = SSLGetSupportedCiphers(appletls->session, all_ciphers, &all_ciphers_count);
  151. if (ret != noErr) {
  152. fprintf(stderr, "SSLGetSupportedCiphers failed!\n");
  153. goto error;
  154. }
  155. for (size_t i = 0; i < all_ciphers_count; ++i) {
  156. /* Disclaimer: excerpted from curl */
  157. switch(all_ciphers[i]) {
  158. /* Disable NULL ciphersuites: */
  159. case SSL_NULL_WITH_NULL_NULL:
  160. case SSL_RSA_WITH_NULL_MD5:
  161. case SSL_RSA_WITH_NULL_SHA:
  162. case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
  163. case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
  164. case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
  165. case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
  166. case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
  167. case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
  168. case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
  169. case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
  170. case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
  171. case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
  172. case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
  173. case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
  174. case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
  175. case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
  176. case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
  177. /* Disable anonymous ciphersuites: */
  178. case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
  179. case SSL_DH_anon_WITH_RC4_128_MD5:
  180. case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
  181. case SSL_DH_anon_WITH_DES_CBC_SHA:
  182. case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
  183. case TLS_DH_anon_WITH_AES_128_CBC_SHA:
  184. case TLS_DH_anon_WITH_AES_256_CBC_SHA:
  185. case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
  186. case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
  187. case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
  188. case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
  189. case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
  190. case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
  191. case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
  192. case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
  193. case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
  194. /* Disable weak key ciphersuites: */
  195. case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
  196. case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
  197. case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
  198. case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
  199. case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
  200. case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
  201. case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
  202. case SSL_RSA_WITH_DES_CBC_SHA:
  203. case SSL_DH_DSS_WITH_DES_CBC_SHA:
  204. case SSL_DH_RSA_WITH_DES_CBC_SHA:
  205. case SSL_DHE_DSS_WITH_DES_CBC_SHA:
  206. case SSL_DHE_RSA_WITH_DES_CBC_SHA:
  207. /* Disable IDEA: */
  208. case SSL_RSA_WITH_IDEA_CBC_SHA:
  209. case SSL_RSA_WITH_IDEA_CBC_MD5:
  210. /* Disable RC4: */
  211. case SSL_RSA_WITH_RC4_128_MD5:
  212. case SSL_RSA_WITH_RC4_128_SHA:
  213. case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
  214. case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
  215. case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
  216. case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
  217. case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
  218. case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
  219. case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
  220. break;
  221. default: /* enable everything else */
  222. allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
  223. break;
  224. }
  225. }
  226. ret = SSLSetEnabledCiphers(appletls->session, allowed_ciphers, allowed_ciphers_count);
  227. if (ret != noErr) {
  228. fprintf(stderr, "SSLSetEnabledCiphers failed!\n");
  229. goto error;
  230. }
  231. if (all_ciphers) {
  232. free(all_ciphers);
  233. all_ciphers = NULL;
  234. }
  235. if (allowed_ciphers) {
  236. free(allowed_ciphers);
  237. allowed_ciphers = NULL;
  238. }
  239. ret = SSLSetIOFuncs(appletls->session, SocketRead, SocketWrite);
  240. if (ret != noErr) {
  241. fprintf(stderr, "SSLSetIOFuncs failed!\n");
  242. return HSSL_ERROR;
  243. }
  244. ret = SSLSetConnection(appletls->session, appletls);
  245. if (ret != noErr) {
  246. fprintf(stderr, "SSLSetConnection failed!\n");
  247. return HSSL_ERROR;
  248. }
  249. /*
  250. char session_id[64] = {0};
  251. int session_id_len = snprintf(session_id, sizeof(session_id), "libhv:appletls:%p", appletls->session);
  252. ret = SSLSetPeerID(appletls->session, session_id, session_id_len);
  253. if (ret != noErr) {
  254. fprintf(stderr, "SSLSetPeerID failed!\n");
  255. return HSSL_ERROR;
  256. }
  257. */
  258. return HSSL_OK;
  259. error:
  260. if (all_ciphers) {
  261. free(all_ciphers);
  262. }
  263. if (allowed_ciphers) {
  264. free(allowed_ciphers);
  265. }
  266. return HSSL_ERROR;
  267. }
  268. void hssl_free(hssl_t ssl) {
  269. if (ssl == NULL) return;
  270. appletls_t* appletls = (appletls_t*)ssl;
  271. if (appletls->session) {
  272. #if defined(__MAC_10_8)
  273. CFRelease(appletls->session);
  274. #else
  275. SSLDisposeContext(appletls->session);
  276. #endif
  277. appletls->session = NULL;
  278. }
  279. free(appletls);
  280. }
  281. static int hssl_handshake(hssl_t ssl) {
  282. if (ssl == NULL) return HSSL_ERROR;
  283. appletls_t* appletls = (appletls_t*)ssl;
  284. OSStatus ret = SSLHandshake(appletls->session);
  285. // printf("SSLHandshake retval=%d\n", (int)ret);
  286. switch(ret) {
  287. case noErr:
  288. break;
  289. case errSSLWouldBlock:
  290. return HSSL_WANT_READ;
  291. case errSSLPeerAuthCompleted: /* peer cert is valid, or was ignored if verification disabled */
  292. return hssl_handshake(ssl);
  293. case errSSLBadConfiguration:
  294. return HSSL_WANT_READ;
  295. default:
  296. return HSSL_ERROR;
  297. }
  298. return HSSL_OK;
  299. }
  300. int hssl_accept(hssl_t ssl) {
  301. if (ssl == NULL) return HSSL_ERROR;
  302. appletls_t* appletls = (appletls_t*)ssl;
  303. if (appletls->session == NULL) {
  304. hssl_init(ssl, HSSL_SERVER);
  305. }
  306. return hssl_handshake(ssl);
  307. }
  308. int hssl_connect(hssl_t ssl) {
  309. if (ssl == NULL) return HSSL_ERROR;
  310. appletls_t* appletls = (appletls_t*)ssl;
  311. if (appletls->session == NULL) {
  312. hssl_init(ssl, HSSL_CLIENT);
  313. }
  314. return hssl_handshake(ssl);
  315. }
  316. int hssl_read(hssl_t ssl, void* buf, int len) {
  317. if (ssl == NULL) return HSSL_ERROR;
  318. appletls_t* appletls = (appletls_t*)ssl;
  319. size_t processed = 0;
  320. // printf("SSLRead(%d)\n", len);
  321. OSStatus ret = SSLRead(appletls->session, buf, len, &processed);
  322. // printf("SSLRead retval=%d processed=%d\n", (int)ret, (int)processed);
  323. switch (ret) {
  324. case noErr:
  325. return processed;
  326. case errSSLWouldBlock:
  327. return processed ? processed : HSSL_WOULD_BLOCK;
  328. case errSSLClosedGraceful:
  329. case errSSLClosedNoNotify:
  330. return 0;
  331. default:
  332. return HSSL_ERROR;
  333. }
  334. }
  335. int hssl_write(hssl_t ssl, const void* buf, int len) {
  336. if (ssl == NULL) return HSSL_ERROR;
  337. appletls_t* appletls = (appletls_t*)ssl;
  338. size_t processed = 0;
  339. // printf("SSLWrite(%d)\n", len);
  340. OSStatus ret = SSLWrite(appletls->session, buf, len, &processed);
  341. // printf("SSLWrite retval=%d processed=%d\n", (int)ret, (int)processed);
  342. switch (ret) {
  343. case noErr:
  344. return processed;
  345. case errSSLWouldBlock:
  346. return processed ? processed : HSSL_WOULD_BLOCK;
  347. case errSSLClosedGraceful:
  348. case errSSLClosedNoNotify:
  349. return 0;
  350. default:
  351. return HSSL_ERROR;
  352. }
  353. }
  354. int hssl_close(hssl_t ssl) {
  355. if (ssl == NULL) return HSSL_ERROR;
  356. appletls_t* appletls = (appletls_t*)ssl;
  357. SSLClose(appletls->session);
  358. return 0;
  359. }
  360. int hssl_set_sni_hostname(hssl_t ssl, const char* hostname) {
  361. if (ssl == NULL) return HSSL_ERROR;
  362. appletls_t* appletls = (appletls_t*)ssl;
  363. if (appletls->session == NULL) {
  364. hssl_init(ssl, HSSL_CLIENT);
  365. }
  366. SSLSetPeerDomainName(appletls->session, hostname, strlen(hostname));
  367. return 0;
  368. }
  369. #endif // WITH_APPLETLS