| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- #include "hssl.h"
- #ifdef WITH_APPLETLS
- #include <Security/Security.h>
- #include <Security/SecureTransport.h>
- #include <CoreFoundation/CoreFoundation.h>
- const char* hssl_backend() {
- return "appletls";
- }
- typedef struct appletls_ctx {
- SecIdentityRef cert;
- hssl_ctx_init_param_t* param;
- } appletls_ctx_t;
- hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param) {
- appletls_ctx_t* ctx = (appletls_ctx_t*)malloc(sizeof(appletls_ctx_t));
- if (ctx == NULL) return NULL;
- ctx->cert = NULL;
- ctx->param = param;
- g_ssl_ctx = ctx;
- return ctx;
- }
- void hssl_ctx_cleanup(hssl_ctx_t ssl_ctx) {
- if (ssl_ctx == NULL) return;
- appletls_ctx_t* ctx = (appletls_ctx_t*)ssl_ctx;
- if (ctx->cert) {
- CFRelease(ctx->cert);
- ctx->cert = NULL;
- }
- free(ctx);
- }
- typedef struct appletls_s {
- SSLContextRef session;
- appletls_ctx_t* ctx;
- int fd;
- } appletls_t;
- hssl_t hssl_new(hssl_ctx_t ssl_ctx, int fd) {
- if (ssl_ctx == NULL) return NULL;
- appletls_t* appletls = (appletls_t*)malloc(sizeof(appletls_t));
- if (appletls == NULL) return NULL;
- appletls->session = NULL;
- appletls->ctx = (appletls_ctx_t*)ssl_ctx;
- appletls->fd = fd;
- return (hssl_t)appletls;
- }
- static OSStatus SocketRead(SSLConnectionRef conn, void* data, size_t* len) {
- // printf("SocketRead(%d)\n", (int)*len);
- appletls_t* appletls = (appletls_t*)conn;
- uint8_t* buffer = (uint8_t*)data;
- size_t remain = *len;
- *len = 0;
- while (remain) {
- // printf("read(%d)\n", (int)remain);
- ssize_t nread = read(appletls->fd, buffer, remain);
- // printf("nread=%d errno=%d\n", (int)nread, (int)errno);
- if (nread == 0) return errSSLClosedGraceful;
- if (nread < 0) {
- switch (errno) {
- case ENOENT: return errSSLClosedGraceful;
- case ECONNRESET:return errSSLClosedAbort;
- case EAGAIN: return errSSLWouldBlock;
- default: return errSSLClosedAbort;
- }
- }
- remain -= nread;
- buffer += nread;
- *len += nread;
- }
- return noErr;
- }
- static OSStatus SocketWrite(SSLConnectionRef conn, const void* data, size_t* len) {
- // printf("SocketWrite(%d)\n", (int)*len);
- appletls_t* appletls = (appletls_t*)conn;
- uint8_t* buffer = (uint8_t*)data;
- size_t remain = *len;
- *len = 0;
- while (remain) {
- // printf("write(%d)\n", (int)remain);
- ssize_t nwrite = write(appletls->fd, buffer, remain);
- // printf("nwrite=%d errno=%d\n", (int)nwrite, (int)errno);
- if (nwrite <= 0) {
- switch (errno) {
- case EAGAIN: return errSSLWouldBlock;
- default: return errSSLClosedAbort;
- }
- }
- remain -= nwrite;
- buffer += nwrite;
- *len += nwrite;
- }
- return noErr;
- }
- static int hssl_init(hssl_t ssl, int endpoint) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- OSStatus ret = noErr;
- if (appletls->session == NULL) {
- #if defined(__MAC_10_8)
- appletls->session = SSLCreateContext(NULL, endpoint == HSSL_SERVER ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
- #else
- SSLNewContext(endpoint == HSSL_SERVER, &(appletls->session));
- #endif
- }
- if (appletls->session == NULL) {
- fprintf(stderr, "SSLCreateContext failed!\n");
- return HSSL_ERROR;
- }
- ret = SSLSetProtocolVersionEnabled(appletls->session, kSSLProtocolAll, true);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetProtocolVersionEnabled failed!\n");
- return HSSL_ERROR;
- }
- bool verify_peer = false;
- if (appletls->ctx->param && appletls->ctx->param->verify_peer) {
- verify_peer = true;
- }
- #if defined(__MAC_10_8)
- ret = SSLSetSessionOption(appletls->session, kSSLSessionOptionBreakOnServerAuth, !verify_peer);
- #else
- ret = SSLSetEnableCertVerify(appletls->session, verify_peer);
- #endif
- if (ret != noErr) {
- fprintf(stderr, "SSLSetEnableCertVerify failed!\n");
- return HSSL_ERROR;
- }
- if (appletls->ctx->cert) {
- CFArrayRef certs = CFArrayCreate(NULL, (const void**)&appletls->ctx->cert, 1, NULL);
- if (!certs) {
- fprintf(stderr, "CFArrayCreate failed!\n");
- return HSSL_ERROR;
- }
- ret = SSLSetCertificate(appletls->session, certs);
- CFRelease(certs);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetCertificate failed!\n");
- return HSSL_ERROR;
- }
- }
- size_t all_ciphers_count = 0, allowed_ciphers_count = 0;
- SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
- ret = SSLGetNumberSupportedCiphers(appletls->session, &all_ciphers_count);
- if (ret != noErr) {
- fprintf(stderr, "SSLGetNumberSupportedCiphers failed!\n");
- goto error;
- }
- all_ciphers = (SSLCipherSuite*)malloc(all_ciphers_count * sizeof(SSLCipherSuite));
- allowed_ciphers = (SSLCipherSuite*)malloc(all_ciphers_count * sizeof(SSLCipherSuite));
- if (all_ciphers == NULL || allowed_ciphers == NULL) {
- fprintf(stderr, "malloc failed!\n");
- goto error;
- }
- ret = SSLGetSupportedCiphers(appletls->session, all_ciphers, &all_ciphers_count);
- if (ret != noErr) {
- fprintf(stderr, "SSLGetSupportedCiphers failed!\n");
- goto error;
- }
- for (size_t i = 0; i < all_ciphers_count; ++i) {
- /* Disclaimer: excerpted from curl */
- switch(all_ciphers[i]) {
- /* Disable NULL ciphersuites: */
- case SSL_NULL_WITH_NULL_NULL:
- case SSL_RSA_WITH_NULL_MD5:
- case SSL_RSA_WITH_NULL_SHA:
- case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
- case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
- case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
- case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
- case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
- case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
- case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
- case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
- case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
- case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
- case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
- case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
- case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
- /* Disable anonymous ciphersuites: */
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- case SSL_DH_anon_WITH_RC4_128_MD5:
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
- case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
- case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
- case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
- case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
- case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
- case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
- case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
- case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
- /* Disable weak key ciphersuites: */
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_RSA_WITH_DES_CBC_SHA:
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- /* Disable IDEA: */
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- /* Disable RC4: */
- case SSL_RSA_WITH_RC4_128_MD5:
- case SSL_RSA_WITH_RC4_128_SHA:
- case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
- case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
- case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
- case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
- case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
- case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
- case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
- }
- ret = SSLSetEnabledCiphers(appletls->session, allowed_ciphers, allowed_ciphers_count);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetEnabledCiphers failed!\n");
- goto error;
- }
- if (all_ciphers) {
- free(all_ciphers);
- all_ciphers = NULL;
- }
- if (allowed_ciphers) {
- free(allowed_ciphers);
- allowed_ciphers = NULL;
- }
- ret = SSLSetIOFuncs(appletls->session, SocketRead, SocketWrite);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetIOFuncs failed!\n");
- return HSSL_ERROR;
- }
- ret = SSLSetConnection(appletls->session, appletls);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetConnection failed!\n");
- return HSSL_ERROR;
- }
- /*
- char session_id[64] = {0};
- int session_id_len = snprintf(session_id, sizeof(session_id), "libhv:appletls:%p", appletls->session);
- ret = SSLSetPeerID(appletls->session, session_id, session_id_len);
- if (ret != noErr) {
- fprintf(stderr, "SSLSetPeerID failed!\n");
- return HSSL_ERROR;
- }
- */
- return HSSL_OK;
- error:
- if (all_ciphers) {
- free(all_ciphers);
- }
- if (allowed_ciphers) {
- free(allowed_ciphers);
- }
- return HSSL_ERROR;
- }
- void hssl_free(hssl_t ssl) {
- if (ssl == NULL) return;
- appletls_t* appletls = (appletls_t*)ssl;
- if (appletls->session) {
- #if defined(__MAC_10_8)
- CFRelease(appletls->session);
- #else
- SSLDisposeContext(appletls->session);
- #endif
- appletls->session = NULL;
- }
- free(appletls);
- }
- static int hssl_handshake(hssl_t ssl) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- OSStatus ret = SSLHandshake(appletls->session);
- // printf("SSLHandshake retval=%d\n", (int)ret);
- switch(ret) {
- case noErr:
- break;
- case errSSLWouldBlock:
- return HSSL_WANT_READ;
- case errSSLPeerAuthCompleted: /* peer cert is valid, or was ignored if verification disabled */
- return hssl_handshake(ssl);
- case errSSLBadConfiguration:
- return HSSL_WANT_READ;
- default:
- return HSSL_ERROR;
- }
- return HSSL_OK;
- }
- int hssl_accept(hssl_t ssl) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- if (appletls->session == NULL) {
- hssl_init(ssl, HSSL_SERVER);
- }
- return hssl_handshake(ssl);
- }
- int hssl_connect(hssl_t ssl) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- if (appletls->session == NULL) {
- hssl_init(ssl, HSSL_CLIENT);
- }
- return hssl_handshake(ssl);
- }
- int hssl_read(hssl_t ssl, void* buf, int len) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- size_t processed = 0;
- // printf("SSLRead(%d)\n", len);
- OSStatus ret = SSLRead(appletls->session, buf, len, &processed);
- // printf("SSLRead retval=%d processed=%d\n", (int)ret, (int)processed);
- switch (ret) {
- case noErr:
- return processed;
- case errSSLWouldBlock:
- return processed ? processed : HSSL_WOULD_BLOCK;
- case errSSLClosedGraceful:
- case errSSLClosedNoNotify:
- return 0;
- default:
- return HSSL_ERROR;
- }
- }
- int hssl_write(hssl_t ssl, const void* buf, int len) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- size_t processed = 0;
- // printf("SSLWrite(%d)\n", len);
- OSStatus ret = SSLWrite(appletls->session, buf, len, &processed);
- // printf("SSLWrite retval=%d processed=%d\n", (int)ret, (int)processed);
- switch (ret) {
- case noErr:
- return processed;
- case errSSLWouldBlock:
- return processed ? processed : HSSL_WOULD_BLOCK;
- case errSSLClosedGraceful:
- case errSSLClosedNoNotify:
- return 0;
- default:
- return HSSL_ERROR;
- }
- }
- int hssl_close(hssl_t ssl) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- SSLClose(appletls->session);
- return 0;
- }
- int hssl_set_sni_hostname(hssl_t ssl, const char* hostname) {
- if (ssl == NULL) return HSSL_ERROR;
- appletls_t* appletls = (appletls_t*)ssl;
- if (appletls->session == NULL) {
- hssl_init(ssl, HSSL_CLIENT);
- }
- SSLSetPeerDomainName(appletls->session, hostname, strlen(hostname));
- return 0;
- }
- #endif // WITH_APPLETLS
|