summaryrefslogtreecommitdiffstats
path: root/src/idevice.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2011-09-14 18:55:59 +0200
committerGravatar Martin Szulecki2012-03-19 01:43:29 +0100
commit8b1af4cf80eff619d3465925dce7fe572fc09224 (patch)
tree1fc167114f574c2ff3470c97d6ce74938778f9db /src/idevice.c
parent294cf69b256419e407b1eac04634752412ee7756 (diff)
downloadlibimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.gz
libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.bz2
Add OpenSSL support
Diffstat (limited to 'src/idevice.c')
-rw-r--r--src/idevice.c155
1 files changed, 154 insertions, 1 deletions
diff --git a/src/idevice.c b/src/idevice.c
index af87e61..d2769de 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -20,16 +20,28 @@
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */ 21 */
22 22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
23#include <stdlib.h> 27#include <stdlib.h>
24#include <string.h> 28#include <string.h>
25#include <errno.h> 29#include <errno.h>
26 30
27#include <usbmuxd.h> 31#include <usbmuxd.h>
32#ifdef HAVE_OPENSSL
33#include <openssl/ssl.h>
34#else
28#include <gnutls/gnutls.h> 35#include <gnutls/gnutls.h>
36#endif
29#include "idevice.h" 37#include "idevice.h"
30#include "userpref.h" 38#include "userpref.h"
31#include "debug.h" 39#include "debug.h"
32 40
41#ifdef HAVE_OPENSSL
42static int openssl_init_done = 0;
43#endif
44
33static idevice_event_cb_t event_cb = NULL; 45static idevice_event_cb_t event_cb = NULL;
34 46
35static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data) 47static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
@@ -303,7 +315,12 @@ idevice_error_t idevice_connection_send(idevice_connection_t connection, const c
303 } 315 }
304 316
305 if (connection->ssl_data) { 317 if (connection->ssl_data) {
318#ifdef HAVE_OPENSSL
319 int sent = SSL_write(connection->ssl_data->session, (const void*)data, (int)len);
320 debug_info("SSL_write %d, sent %d", len, sent);
321#else
306 ssize_t sent = gnutls_record_send(connection->ssl_data->session, (void*)data, (size_t)len); 322 ssize_t sent = gnutls_record_send(connection->ssl_data->session, (void*)data, (size_t)len);
323#endif
307 if ((uint32_t)sent == (uint32_t)len) { 324 if ((uint32_t)sent == (uint32_t)len) {
308 *sent_bytes = sent; 325 *sent_bytes = sent;
309 return IDEVICE_E_SUCCESS; 326 return IDEVICE_E_SUCCESS;
@@ -359,7 +376,12 @@ idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connecti
359 } 376 }
360 377
361 if (connection->ssl_data) { 378 if (connection->ssl_data) {
379#ifdef HAVE_OPENSSL
380 int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len);
381 debug_info("SSL_read %d, received %d", len, received);
382#else
362 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); 383 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len);
384#endif
363 if (received > 0) { 385 if (received > 0) {
364 *recv_bytes = received; 386 *recv_bytes = received;
365 return IDEVICE_E_SUCCESS; 387 return IDEVICE_E_SUCCESS;
@@ -413,7 +435,12 @@ idevice_error_t idevice_connection_receive(idevice_connection_t connection, char
413 } 435 }
414 436
415 if (connection->ssl_data) { 437 if (connection->ssl_data) {
438#ifdef HAVE_OPENSSL
439 int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len);
440 debug_info("SSL_read %d, received %d", len, received);
441#else
416 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); 442 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len);
443#endif
417 if (received > 0) { 444 if (received > 0) {
418 *recv_bytes = received; 445 *recv_bytes = received;
419 return IDEVICE_E_SUCCESS; 446 return IDEVICE_E_SUCCESS;
@@ -453,6 +480,7 @@ idevice_error_t idevice_get_uuid(idevice_t device, char **uuid)
453 return IDEVICE_E_SUCCESS; 480 return IDEVICE_E_SUCCESS;
454} 481}
455 482
483#ifndef HAVE_OPENSSL
456/** 484/**
457 * Internally used gnutls callback function for receiving encrypted data. 485 * Internally used gnutls callback function for receiving encrypted data.
458 */ 486 */
@@ -514,6 +542,7 @@ static ssize_t internal_ssl_write(gnutls_transport_ptr_t transport, char *buffer
514 debug_info("post-send sent %i bytes", bytes); 542 debug_info("post-send sent %i bytes", bytes);
515 return bytes; 543 return bytes;
516} 544}
545#endif
517 546
518/** 547/**
519 * Internally used function for cleaning up SSL stuff. 548 * Internally used function for cleaning up SSL stuff.
@@ -523,6 +552,14 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
523 if (!ssl_data) 552 if (!ssl_data)
524 return; 553 return;
525 554
555#ifdef HAVE_OPENSSL
556 if (ssl_data->session) {
557 SSL_free(ssl_data->session);
558 }
559 if (ssl_data->ctx) {
560 SSL_CTX_free(ssl_data->ctx);
561 }
562#else
526 if (ssl_data->session) { 563 if (ssl_data->session) {
527 gnutls_deinit(ssl_data->session); 564 gnutls_deinit(ssl_data->session);
528 } 565 }
@@ -541,8 +578,45 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
541 if (ssl_data->host_privkey) { 578 if (ssl_data->host_privkey) {
542 gnutls_x509_privkey_deinit(ssl_data->host_privkey); 579 gnutls_x509_privkey_deinit(ssl_data->host_privkey);
543 } 580 }
581#endif
582}
583
584#ifdef HAVE_OPENSSL
585static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx)
586{
587 return 1;
588}
589
590#ifndef STRIP_DEBUG_CODE
591static const char *errorstring(int e)
592{
593 switch(e) {
594 case SSL_ERROR_NONE:
595 return "SSL_ERROR_NONE";
596 case SSL_ERROR_SSL:
597 return "SSL_ERROR_SSL";
598 case SSL_ERROR_WANT_READ:
599 return "SSL_ERROR_WANT_READ";
600 case SSL_ERROR_WANT_WRITE:
601 return "SSL_ERROR_WANT_WRITE";
602 case SSL_ERROR_WANT_X509_LOOKUP:
603 return "SSL_ERROR_WANT_X509_LOOKUP";
604 case SSL_ERROR_SYSCALL:
605 return "SSL_ERROR_SYSCALL";
606 case SSL_ERROR_ZERO_RETURN:
607 return "SSL_ERROR_ZERO_RETURN";
608 case SSL_ERROR_WANT_CONNECT:
609 return "SSL_ERROR_WANT_CONNECT";
610 case SSL_ERROR_WANT_ACCEPT:
611 return "SSL_ERROR_WANT_ACCEPT";
612 default:
613 return "UNKOWN_ERROR_VALUE";
614 }
544} 615}
616#endif
617#endif
545 618
619#ifndef HAVE_OPENSSL
546/** 620/**
547 * Internally used gnutls callback function that gets called during handshake. 621 * Internally used gnutls callback function that gets called during handshake.
548 */ 622 */
@@ -564,6 +638,7 @@ static int internal_cert_callback (gnutls_session_t session, const gnutls_datum_
564 } 638 }
565 return res; 639 return res;
566} 640}
641#endif
567 642
568/** 643/**
569 * Enables SSL for the given connection. 644 * Enables SSL for the given connection.
@@ -582,6 +657,76 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
582 idevice_error_t ret = IDEVICE_E_SSL_ERROR; 657 idevice_error_t ret = IDEVICE_E_SSL_ERROR;
583 uint32_t return_me = 0; 658 uint32_t return_me = 0;
584 659
660#ifdef HAVE_OPENSSL
661 key_data_t root_cert = { NULL, 0 };
662 key_data_t root_privkey = { NULL, 0 };
663
664 userpref_error_t uerr = userpref_get_keys_and_certs(&root_privkey, &root_cert, NULL, NULL);
665 if (uerr != USERPREF_E_SUCCESS) {
666 debug_info("Error %d when loading keys and certificates! %d", uerr);
667 }
668
669 /* Set up OpenSSL */
670 BIO *ssl_bio = BIO_new(BIO_s_socket());
671 if (!ssl_bio) {
672 debug_info("ERROR: Could not create SSL bio.");
673 return ret;
674 }
675 BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE);
676
677 if (openssl_init_done == 0) {
678 SSL_library_init();
679 openssl_init_done = 1;
680 }
681 SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method());
682
683 BIO* membp;
684 X509* rootCert = NULL;
685 membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
686 PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
687 BIO_free(membp);
688 if (SSL_CTX_use_certificate(ssl_ctx, rootCert) != 1) {
689 debug_info("WARNING: Could not load RootCertificate");
690 }
691 X509_free(rootCert);
692 free(root_cert.data);
693
694 RSA* rootPrivKey = NULL;
695 membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
696 PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL);
697 BIO_free(membp);
698 if (SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey) != 1) {
699 debug_info("WARNING: Could not load RootPrivateKey");
700 }
701 RSA_free(rootPrivKey);
702 free(root_privkey.data);
703
704 SSL *ssl = SSL_new(ssl_ctx);
705 if (!ssl) {
706 debug_info("ERROR: Could not create SSL object");
707 BIO_free(ssl_bio);
708 SSL_CTX_free(ssl_ctx);
709 return ret;
710 }
711 SSL_set_connect_state(ssl);
712 SSL_set_verify(ssl, 0, ssl_verify_callback);
713 SSL_set_bio(ssl, ssl_bio, ssl_bio);
714
715 return_me = SSL_do_handshake(ssl);
716 if (return_me != 1) {
717 debug_info("ERROR in SSL_do_handshake: %s", errorstring(SSL_get_error(ssl, return_me)));
718 BIO_free(ssl_bio);
719 SSL_CTX_free(ssl_ctx);
720 } else {
721 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
722 ssl_data_loc->session = ssl;
723 ssl_data_loc->ctx = ssl_ctx;
724 ssl_data_loc->bio = ssl_bio;
725 connection->ssl_data = ssl_data_loc;
726 ret = IDEVICE_E_SUCCESS;
727 debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl));
728 }
729#else
585 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private)); 730 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
586 731
587 /* Set up GnuTLS... */ 732 /* Set up GnuTLS... */
@@ -612,8 +757,9 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
612 debug_info("GnuTLS step 3..."); 757 debug_info("GnuTLS step 3...");
613 gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read); 758 gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read);
614 debug_info("GnuTLS step 4 -- now handshaking..."); 759 debug_info("GnuTLS step 4 -- now handshaking...");
615 if (errno) 760 if (errno) {
616 debug_info("WARN: errno says %s before handshake!", strerror(errno)); 761 debug_info("WARN: errno says %s before handshake!", strerror(errno));
762 }
617 return_me = gnutls_handshake(ssl_data_loc->session); 763 return_me = gnutls_handshake(ssl_data_loc->session);
618 debug_info("GnuTLS handshake done..."); 764 debug_info("GnuTLS handshake done...");
619 765
@@ -628,6 +774,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
628 ret = IDEVICE_E_SUCCESS; 774 ret = IDEVICE_E_SUCCESS;
629 debug_info("SSL mode enabled"); 775 debug_info("SSL mode enabled");
630 } 776 }
777#endif
631 return ret; 778 return ret;
632} 779}
633 780
@@ -649,9 +796,15 @@ idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection)
649 return IDEVICE_E_SUCCESS; 796 return IDEVICE_E_SUCCESS;
650 } 797 }
651 798
799#ifdef HAVE_OPENSSL
800 if (connection->ssl_data->session) {
801 SSL_shutdown(connection->ssl_data->session);
802 }
803#else
652 if (connection->ssl_data->session) { 804 if (connection->ssl_data->session) {
653 gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR); 805 gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR);
654 } 806 }
807#endif
655 internal_ssl_cleanup(connection->ssl_data); 808 internal_ssl_cleanup(connection->ssl_data);
656 free(connection->ssl_data); 809 free(connection->ssl_data);
657 connection->ssl_data = NULL; 810 connection->ssl_data = NULL;