summaryrefslogtreecommitdiffstats
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
parent294cf69b256419e407b1eac04634752412ee7756 (diff)
downloadlibimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.gz
libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.bz2
Add OpenSSL support
-rw-r--r--configure.ac37
-rw-r--r--src/Makefile.am4
-rw-r--r--src/idevice.c155
-rw-r--r--src/idevice.h16
-rw-r--r--src/lockdown.c164
-rw-r--r--src/lockdown.h7
-rw-r--r--src/userpref.c233
-rw-r--r--src/userpref.h22
-rw-r--r--tools/Makefile.am4
-rw-r--r--tools/idevicebackup.c77
-rw-r--r--tools/idevicebackup2.c1
11 files changed, 659 insertions, 61 deletions
diff --git a/configure.ac b/configure.ac
index feb5d11..299b6ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,11 +27,8 @@ AC_PROG_LIBTOOL
27 27
28# Checks for libraries. 28# Checks for libraries.
29PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= 0.1.4) 29PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= 0.1.4)
30PKG_CHECK_MODULES(libgnutls, gnutls >= 2.2.0)
31PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1)
32PKG_CHECK_MODULES(libplist, libplist >= 0.15) 30PKG_CHECK_MODULES(libplist, libplist >= 0.15)
33PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15) 31PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15)
34AC_CHECK_LIB(gcrypt, gcry_control, [AC_SUBST(libgcrypt_LIBS,[-lgcrypt])], [AC_MSG_ERROR([libgcrypt is required to build libimobiledevice])])
35AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) 32AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])])
36 33
37PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no) 34PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no)
@@ -98,6 +95,39 @@ fi
98 95
99AM_CONDITIONAL([HAVE_SWIG],[test "x$SWIG" != "xfalse"]) 96AM_CONDITIONAL([HAVE_SWIG],[test "x$SWIG" != "xfalse"])
100 97
98AC_ARG_ENABLE([openssl],
99 [AS_HELP_STRING([--disable-openssl],
100 [Do not look for OpenSSL])],
101 [use_openssl=no],
102 [use_openssl=yes])
103
104PKG_CHECK_MODULES(openssl, openssl >= 0.9.8, have_openssl=yes, have_openssl=no)
105if test "x$have_openssl" = "xyes"; then
106 if test "x$use_openssl" != "xyes"; then
107 enable_openssl=no
108 echo "*** Note: OpenSSL support explicitly disabled ***"
109 else
110 enable_openssl=yes
111 fi
112else
113 if test "x$use_openssl" == "xyes" -a "x$have_openssl" != "xyes"; then
114 AC_MSG_ERROR([OpenSSL support explicitly requested but OpenSSL could not be found])
115 fi
116fi
117
118if test "x$enable_openssl" = "xyes"; then
119 AC_DEFINE(HAVE_OPENSSL, 1, [Define if you have OpenSSL support])
120 AC_SUBST(openssl_CFLAGS)
121 AC_SUBST(openssl_LIBS)
122 ssl_provider="OpenSSL";
123else
124 PKG_CHECK_MODULES(libgnutls, gnutls >= 2.2.0)
125 AC_CHECK_LIB(gcrypt, gcry_control, [AC_SUBST(libgcrypt_LIBS,[-lgcrypt])], [AC_MSG_ERROR([libgcrypt is required to build libimobiledevice with GnuTLS])])
126 PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1)
127 ssl_provider="GnuTLS"
128fi
129
130
101AC_SUBST([DEV_SUB]) 131AC_SUBST([DEV_SUB])
102 132
103 133
@@ -186,6 +216,7 @@ Configuration for $PACKAGE $VERSION:
186 Debug code ..............: $building_debug_code 216 Debug code ..............: $building_debug_code
187 Dev tools ...............: $building_dev_tools 217 Dev tools ...............: $building_dev_tools
188 Python bindings .........: $python_bindings 218 Python bindings .........: $python_bindings
219 SSL support .............: $ssl_provider
189 220
190 Now type 'make' to build $PACKAGE $VERSION, 221 Now type 'make' to build $PACKAGE $VERSION,
191 and then 'make install' for installation. 222 and then 'make install' for installation.
diff --git a/src/Makefile.am b/src/Makefile.am
index 5531f8d..c7ab0cf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
1AM_CPPFLAGS = -I$(top_srcdir)/include 1AM_CPPFLAGS = -I$(top_srcdir)/include
2 2
3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) 3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS)
4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) ${libpthread_LIBS} 4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) ${libpthread_LIBS} $(openssl_LIBS)
5 5
6lib_LTLIBRARIES = libimobiledevice.la 6lib_LTLIBRARIES = libimobiledevice.la
7libimobiledevice_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIMOBILEDEVICE_SO_VERSION) -no-undefined 7libimobiledevice_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIMOBILEDEVICE_SO_VERSION) -no-undefined
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;
diff --git a/src/idevice.h b/src/idevice.h
index 231b3ab..65fdae0 100644
--- a/src/idevice.h
+++ b/src/idevice.h
@@ -21,8 +21,18 @@
21#ifndef IDEVICE_H 21#ifndef IDEVICE_H
22#define IDEVICE_H 22#define IDEVICE_H
23 23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#ifdef HAVE_OPENSSL
29#include <openssl/ssl.h>
30#else
24#include <gnutls/gnutls.h> 31#include <gnutls/gnutls.h>
25#include <gnutls/x509.h> 32#include <gnutls/x509.h>
33#endif
34
35#include "userpref.h"
26 36
27#include "libimobiledevice/libimobiledevice.h" 37#include "libimobiledevice/libimobiledevice.h"
28 38
@@ -31,12 +41,18 @@ enum connection_type {
31}; 41};
32 42
33struct ssl_data_private { 43struct ssl_data_private {
44#ifdef HAVE_OPENSSL
45 SSL *session;
46 SSL_CTX *ctx;
47 BIO *bio;
48#else
34 gnutls_certificate_credentials_t certificate; 49 gnutls_certificate_credentials_t certificate;
35 gnutls_session_t session; 50 gnutls_session_t session;
36 gnutls_x509_privkey_t root_privkey; 51 gnutls_x509_privkey_t root_privkey;
37 gnutls_x509_crt_t root_cert; 52 gnutls_x509_crt_t root_cert;
38 gnutls_x509_privkey_t host_privkey; 53 gnutls_x509_privkey_t host_privkey;
39 gnutls_x509_crt_t host_cert; 54 gnutls_x509_crt_t host_cert;
55#endif
40}; 56};
41typedef struct ssl_data_private *ssl_data_t; 57typedef struct ssl_data_private *ssl_data_t;
42 58
diff --git a/src/lockdown.c b/src/lockdown.c
index 0f1e1b2..f22fb08 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -20,14 +20,24 @@
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 <string.h> 27#include <string.h>
24#include <stdlib.h> 28#include <stdlib.h>
25#define _GNU_SOURCE 1 29#define _GNU_SOURCE 1
26#define __USE_GNU 1 30#define __USE_GNU 1
27#include <stdio.h> 31#include <stdio.h>
28#include <ctype.h> 32#include <ctype.h>
33#ifdef HAVE_OPENSSL
34#include <openssl/pem.h>
35#include <openssl/x509.h>
36#include <openssl/x509v3.h>
37#else
29#include <libtasn1.h> 38#include <libtasn1.h>
30#include <gnutls/x509.h> 39#include <gnutls/x509.h>
40#endif
31#include <plist/plist.h> 41#include <plist/plist.h>
32 42
33#include "property_list_service.h" 43#include "property_list_service.h"
@@ -40,6 +50,7 @@
40#define RESULT_SUCCESS 0 50#define RESULT_SUCCESS 0
41#define RESULT_FAILURE 1 51#define RESULT_FAILURE 1
42 52
53#ifndef HAVE_OPENSSL
43const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 54const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
44 {"PKCS1", 536872976, 0}, 55 {"PKCS1", 536872976, 0},
45 {0, 1073741836, 0}, 56 {0, 1073741836, 0},
@@ -48,6 +59,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
48 {"publicExponent", 3, 0}, 59 {"publicExponent", 3, 0},
49 {0, 0, 0} 60 {0, 0, 0}
50}; 61};
62#endif
51 63
52/** 64/**
53 * Internally used function for checking the result from lockdown's answer 65 * Internally used function for checking the result from lockdown's answer
@@ -567,7 +579,7 @@ lockdownd_error_t lockdownd_get_device_uuid(lockdownd_client_t client, char **uu
567 * 579 *
568 * @return LOCKDOWN_E_SUCCESS on success 580 * @return LOCKDOWN_E_SUCCESS on success
569 */ 581 */
570lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key) 582lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key)
571{ 583{
572 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 584 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
573 plist_t value = NULL; 585 plist_t value = NULL;
@@ -783,13 +795,13 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor
783 * 795 *
784 * @return LOCKDOWN_E_SUCCESS on success 796 * @return LOCKDOWN_E_SUCCESS on success
785 */ 797 */
786static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist) 798static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char *host_id, plist_t *pair_record_plist)
787{ 799{
788 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 800 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
789 801
790 gnutls_datum_t device_cert = { NULL, 0 }; 802 key_data_t device_cert = { NULL, 0 };
791 gnutls_datum_t host_cert = { NULL, 0 }; 803 key_data_t host_cert = { NULL, 0 };
792 gnutls_datum_t root_cert = { NULL, 0 }; 804 key_data_t root_cert = { NULL, 0 };
793 805
794 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); 806 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
795 if (ret != LOCKDOWN_E_SUCCESS) { 807 if (ret != LOCKDOWN_E_SUCCESS) {
@@ -844,7 +856,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_
844 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 856 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
845 plist_t dict = NULL; 857 plist_t dict = NULL;
846 plist_t dict_record = NULL; 858 plist_t dict_record = NULL;
847 gnutls_datum_t public_key = { NULL, 0 }; 859 key_data_t public_key = { NULL, 0 };
848 int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ 860 int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */
849 861
850 if (pair_record && pair_record->host_id) { 862 if (pair_record && pair_record->host_id) {
@@ -1096,14 +1108,145 @@ lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client)
1096 * LOCKDOWN_E_INVALID_CONF if the internal configuration system failed, 1108 * LOCKDOWN_E_INVALID_CONF if the internal configuration system failed,
1097 * LOCKDOWN_E_SSL_ERROR if the certificates could not be generated 1109 * LOCKDOWN_E_SSL_ERROR if the certificates could not be generated
1098 */ 1110 */
1099lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert, 1111lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * odevice_cert,
1100 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert) 1112 key_data_t * ohost_cert, key_data_t * oroot_cert)
1101{ 1113{
1102 if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) 1114 if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert)
1103 return LOCKDOWN_E_INVALID_ARG; 1115 return LOCKDOWN_E_INVALID_ARG;
1104 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 1116 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
1105 userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; 1117 userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR;
1106 1118
1119#ifdef HAVE_OPENSSL
1120 BIO *membio = BIO_new_mem_buf(public_key.data, public_key.size);
1121 RSA *pubkey = NULL;
1122 if (!PEM_read_bio_RSAPublicKey(membio, &pubkey, NULL, NULL)) {
1123 debug_info("%s: Could not read public key", __func__);
1124 }
1125 BIO_free(membio);
1126
1127 /* now generate certificates */
1128 key_data_t root_privkey, host_privkey;
1129 key_data_t root_cert, host_cert;
1130 X509* dev_cert;
1131
1132 root_cert.data = NULL;
1133 root_cert.size = 0;
1134 host_cert.data = NULL;
1135 host_cert.size = 0;
1136
1137 dev_cert = X509_new();
1138
1139 root_privkey.data = NULL;
1140 root_privkey.size = 0;
1141 host_privkey.data = NULL;
1142 host_privkey.size = 0;
1143
1144 uret = userpref_get_keys_and_certs(&root_privkey, &root_cert, &host_privkey, &host_cert);
1145 if (USERPREF_E_SUCCESS == uret) {
1146 /* generate device certificate */
1147 ASN1_INTEGER* sn = ASN1_INTEGER_new();
1148 ASN1_INTEGER_set(sn, 0);
1149 X509_set_serialNumber(dev_cert, sn);
1150 ASN1_INTEGER_free(sn);
1151 X509_set_version(dev_cert, 2);
1152
1153 X509_EXTENSION* ext;
1154 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) {
1155 debug_info("ERROR: X509V3_EXT_conf_nid failed");
1156 }
1157 X509_add_ext(dev_cert, ext, -1);
1158
1159 ASN1_TIME* asn1time = ASN1_TIME_new();
1160 ASN1_TIME_set(asn1time, time(NULL));
1161 X509_set_notBefore(dev_cert, asn1time);
1162 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
1163 X509_set_notAfter(dev_cert, asn1time);
1164 ASN1_TIME_free(asn1time);
1165
1166 BIO* membp;
1167
1168 X509* rootCert = NULL;
1169 membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
1170 PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
1171 BIO_free(membp);
1172 if (!rootCert) {
1173 debug_info("Could not read RootCertificate%*s");
1174 } else {
1175 debug_info("RootCertificate loaded");
1176 EVP_PKEY* pkey = EVP_PKEY_new();
1177 EVP_PKEY_assign_RSA(pkey, pubkey);
1178 X509_set_pubkey(dev_cert, pkey);
1179 EVP_PKEY_free(pkey);
1180 X509_free(rootCert);
1181 }
1182
1183 EVP_PKEY* rootPriv = NULL;
1184 membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
1185 PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL);
1186 BIO_free(membp);
1187 if (!rootPriv) {
1188 debug_info("Could not read RootPrivateKey");
1189 } else {
1190 debug_info("RootPrivateKey loaded");
1191 if (X509_sign(dev_cert, rootPriv, EVP_sha1())) {
1192 ret = LOCKDOWN_E_SUCCESS;
1193 } else {
1194 debug_info("signing failed");
1195 }
1196 EVP_PKEY_free(rootPriv);
1197 }
1198
1199 if (LOCKDOWN_E_SUCCESS == ret) {
1200 /* if everything went well, export in PEM format */
1201 key_data_t pem_root_cert = { NULL, 0 };
1202 key_data_t pem_host_cert = { NULL, 0 };
1203
1204 uret = userpref_get_certs_as_pem(&pem_root_cert, &pem_host_cert);
1205 if (USERPREF_E_SUCCESS == uret) {
1206 /* copy buffer for output */
1207 membp = BIO_new(BIO_s_mem());
1208 if (PEM_write_bio_X509(membp, dev_cert) > 0) {
1209 odevice_cert->size = BIO_get_mem_data(membp, &odevice_cert->data);
1210 }
1211
1212 ohost_cert->data = malloc(pem_host_cert.size);
1213 memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size);
1214 ohost_cert->size = pem_host_cert.size;
1215
1216 oroot_cert->data = malloc(pem_root_cert.size);
1217 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);
1218 oroot_cert->size = pem_root_cert.size;
1219
1220 free(pem_root_cert.data);
1221 free(pem_host_cert.data);
1222 }
1223 }
1224 }
1225 X509V3_EXT_cleanup();
1226 X509_free(dev_cert);
1227
1228 switch(uret) {
1229 case USERPREF_E_INVALID_ARG:
1230 ret = LOCKDOWN_E_INVALID_ARG;
1231 break;
1232 case USERPREF_E_INVALID_CONF:
1233 ret = LOCKDOWN_E_INVALID_CONF;
1234 break;
1235 case USERPREF_E_SSL_ERROR:
1236 ret = LOCKDOWN_E_SSL_ERROR;
1237 default:
1238 break;
1239 }
1240
1241 if (root_cert.data)
1242 free(root_cert.data);
1243 if (host_cert.data)
1244 free(host_cert.data);
1245 if (root_privkey.data)
1246 free(root_privkey.data);
1247 if (host_privkey.data)
1248 free(host_privkey.data);
1249#else
1107 gnutls_datum_t modulus = { NULL, 0 }; 1250 gnutls_datum_t modulus = { NULL, 0 };
1108 gnutls_datum_t exponent = { NULL, 0 }; 1251 gnutls_datum_t exponent = { NULL, 0 };
1109 1252
@@ -1200,8 +1343,8 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu
1200 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); 1343 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);
1201 oroot_cert->size = pem_root_cert.size; 1344 oroot_cert->size = pem_root_cert.size;
1202 1345
1203 free(pem_root_cert.data); 1346 gnutls_free(pem_root_cert.data);
1204 free(pem_host_cert.data); 1347 gnutls_free(pem_host_cert.data);
1205 1348
1206 if (dev_pem.data) 1349 if (dev_pem.data)
1207 gnutls_free(dev_pem.data); 1350 gnutls_free(dev_pem.data);
@@ -1238,6 +1381,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu
1238 gnutls_free(exponent.data); 1381 gnutls_free(exponent.data);
1239 1382
1240 gnutls_free(der_pub_key.data); 1383 gnutls_free(der_pub_key.data);
1384#endif
1241 1385
1242 return ret; 1386 return ret;
1243} 1387}
diff --git a/src/lockdown.h b/src/lockdown.h
index a25e59d..a08b040 100644
--- a/src/lockdown.h
+++ b/src/lockdown.h
@@ -22,7 +22,7 @@
22#ifndef LOCKDOWND_H 22#ifndef LOCKDOWND_H
23#define LOCKDOWND_H 23#define LOCKDOWND_H
24 24
25#include <gnutls/gnutls.h> 25#include "userpref.h"
26 26
27#include "libimobiledevice/lockdown.h" 27#include "libimobiledevice/lockdown.h"
28#include "property_list_service.h" 28#include "property_list_service.h"
@@ -35,8 +35,7 @@ struct lockdownd_client_private {
35 char *label; 35 char *label;
36}; 36};
37 37
38lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key); 38lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key);
39lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * device_cert, 39lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * device_cert, key_data_t * host_cert, key_data_t * root_cert);
40 gnutls_datum_t * host_cert, gnutls_datum_t * root_cert);
41 40
42#endif 41#endif
diff --git a/src/userpref.c b/src/userpref.c
index f4e9fe6..409eb27 100644
--- a/src/userpref.c
+++ b/src/userpref.c
@@ -19,13 +19,23 @@
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
22#include <stdio.h> 25#include <stdio.h>
23#include <stdint.h> 26#include <stdint.h>
24#include <stdlib.h> 27#include <stdlib.h>
25#include <string.h> 28#include <string.h>
29#ifdef HAVE_OPENSSL
30#include <openssl/pem.h>
31#include <openssl/rsa.h>
32#include <openssl/x509.h>
33#include <openssl/x509v3.h>
34#else
26#include <gnutls/gnutls.h> 35#include <gnutls/gnutls.h>
27#include <gnutls/x509.h> 36#include <gnutls/x509.h>
28#include <gcrypt.h> 37#include <gcrypt.h>
38#endif
29 39
30#include <dirent.h> 40#include <dirent.h>
31#include <libgen.h> 41#include <libgen.h>
@@ -526,7 +536,7 @@ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count)
526 * @return 1 on success and 0 if no public key is given or if it has already 536 * @return 1 on success and 0 if no public key is given or if it has already
527 * been marked as connected previously. 537 * been marked as connected previously.
528 */ 538 */
529userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key) 539userpref_error_t userpref_set_device_public_key(const char *uuid, key_data_t public_key)
530{ 540{
531 if (NULL == public_key.data) 541 if (NULL == public_key.data)
532 return USERPREF_E_INVALID_ARG; 542 return USERPREF_E_INVALID_ARG;
@@ -583,14 +593,14 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid)
583} 593}
584 594
585/** 595/**
586 * Private function which reads the given file into a gnutls structure. 596 * Private function which reads the given file into a key_data_t structure.
587 * 597 *
588 * @param file The filename of the file to read 598 * @param file The filename of the file to read
589 * @param data The pointer at which to store the data. 599 * @param data The pointer at which to store the data.
590 * 600 *
591 * @return 1 if the file contents where read successfully and 0 otherwise. 601 * @return 1 if the file contents where read successfully and 0 otherwise.
592 */ 602 */
593static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) 603static int userpref_get_file_contents(const char *file, key_data_t * data)
594{ 604{
595 int success; 605 int success;
596 unsigned long int size = 0; 606 unsigned long int size = 0;
@@ -637,7 +647,7 @@ static int userpref_get_file_contents(const char *file, gnutls_datum_t * data)
637 647
638 free(filepath); 648 free(filepath);
639 649
640 /* Add it to the gnutls_datnum_t structure */ 650 /* Add it to the key_data_t structure */
641 if (success) { 651 if (success) {
642 data->data = (uint8_t*) content; 652 data->data = (uint8_t*) content;
643 data->size = size; 653 data->size = size;
@@ -655,6 +665,121 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
655{ 665{
656 userpref_error_t ret = USERPREF_E_SSL_ERROR; 666 userpref_error_t ret = USERPREF_E_SSL_ERROR;
657 667
668 key_data_t root_key_pem = { NULL, 0 };
669 key_data_t root_cert_pem = { NULL, 0 };
670 key_data_t host_key_pem = { NULL, 0 };
671 key_data_t host_cert_pem = { NULL, 0 };
672
673#ifdef HAVE_OPENSSL
674 RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
675 RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
676
677 EVP_PKEY* root_pkey = EVP_PKEY_new();
678 EVP_PKEY_assign_RSA(root_pkey, root_keypair);
679
680 EVP_PKEY* host_pkey = EVP_PKEY_new();
681 EVP_PKEY_assign_RSA(host_pkey, host_keypair);
682
683 /* generate root certificate */
684 X509* root_cert = X509_new();
685 {
686 /* set serial number */
687 ASN1_INTEGER* sn = ASN1_INTEGER_new();
688 ASN1_INTEGER_set(sn, 0);
689 X509_set_serialNumber(root_cert, sn);
690 ASN1_INTEGER_free(sn);
691
692 /* set version */
693 X509_set_version(root_cert, 2);
694
695 /* set x509v3 basic constraints */
696 X509_EXTENSION* ext;
697 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:TRUE"))) {
698 debug_info("ERROR: X509V3_EXT_conf_nid failed");
699 }
700 X509_add_ext(root_cert, ext, -1);
701
702 /* set key validity */
703 ASN1_TIME* asn1time = ASN1_TIME_new();
704 ASN1_TIME_set(asn1time, time(NULL));
705 X509_set_notBefore(root_cert, asn1time);
706 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
707 X509_set_notAfter(root_cert, asn1time);
708 ASN1_TIME_free(asn1time);
709
710 /* use root public key for root cert */
711 X509_set_pubkey(root_cert, root_pkey);
712 /* sign root cert with root private key */
713 X509_sign(root_cert, root_pkey, EVP_sha1());
714 }
715
716 /* create host certificate */
717 X509* host_cert = X509_new();
718 {
719 /* set serial number */
720 ASN1_INTEGER* sn = ASN1_INTEGER_new();
721 ASN1_INTEGER_set(sn, 0);
722 X509_set_serialNumber(host_cert, sn);
723 ASN1_INTEGER_free(sn);
724
725 /* set version */
726 X509_set_version(host_cert, 2);
727
728 /* set x509v3 basic constraints */
729 X509_EXTENSION* ext;
730 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) {
731 debug_info("ERROR: X509V3_EXT_conf_nid failed");
732 }
733 X509_add_ext(host_cert, ext, -1);
734
735 /* set x509v3 key usage */
736 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, (char*)"digitalSignature,keyEncipherment"))) {
737 debug_info("ERROR: X509V3_EXT_conf_nid failed");
738 }
739 X509_add_ext(host_cert, ext, -1);
740
741 /* set key validity */
742 ASN1_TIME* asn1time = ASN1_TIME_new();
743 ASN1_TIME_set(asn1time, time(NULL));
744 X509_set_notBefore(host_cert, asn1time);
745 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
746 X509_set_notAfter(host_cert, asn1time);
747 ASN1_TIME_free(asn1time);
748
749 /* use host public key for host cert */
750 X509_set_pubkey(host_cert, host_pkey);
751
752 /* sign host cert with root private key */
753 X509_sign(host_cert, root_pkey, EVP_sha1());
754 }
755
756 if (root_cert && root_pkey && host_cert && host_pkey) {
757 BIO* membp;
758
759 membp = BIO_new(BIO_s_mem());
760 if (PEM_write_bio_X509(membp, root_cert) > 0) {
761 root_cert_pem.size = BIO_get_mem_data(membp, &root_cert_pem.data);
762 }
763 membp = BIO_new(BIO_s_mem());
764 if (PEM_write_bio_PrivateKey(membp, root_pkey, NULL, NULL, 0, 0, NULL) > 0) {
765 root_key_pem.size = BIO_get_mem_data(membp, &root_key_pem.data);
766 }
767 membp = BIO_new(BIO_s_mem());
768 if (PEM_write_bio_X509(membp, host_cert) > 0) {
769 host_cert_pem.size = BIO_get_mem_data(membp, &host_cert_pem.data);
770 }
771 membp = BIO_new(BIO_s_mem());
772 if (PEM_write_bio_PrivateKey(membp, host_pkey, NULL, NULL, 0, 0, NULL) > 0) {
773 host_key_pem.size = BIO_get_mem_data(membp, &host_key_pem.data);
774 }
775 }
776
777 EVP_PKEY_free(root_pkey);
778 EVP_PKEY_free(host_pkey);
779
780 X509_free(host_cert);
781 X509_free(root_cert);
782#else
658 gnutls_x509_privkey_t root_privkey; 783 gnutls_x509_privkey_t root_privkey;
659 gnutls_x509_crt_t root_cert; 784 gnutls_x509_crt_t root_cert;
660 gnutls_x509_privkey_t host_privkey; 785 gnutls_x509_privkey_t host_privkey;
@@ -697,8 +822,6 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
697 /* export to PEM format */ 822 /* export to PEM format */
698 size_t root_key_export_size = 0; 823 size_t root_key_export_size = 0;
699 size_t host_key_export_size = 0; 824 size_t host_key_export_size = 0;
700 gnutls_datum_t root_key_pem = { NULL, 0 };
701 gnutls_datum_t host_key_pem = { NULL, 0 };
702 825
703 gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size); 826 gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);
704 gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size); 827 gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size);
@@ -713,8 +836,6 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
713 836
714 size_t root_cert_export_size = 0; 837 size_t root_cert_export_size = 0;
715 size_t host_cert_export_size = 0; 838 size_t host_cert_export_size = 0;
716 gnutls_datum_t root_cert_pem = { NULL, 0 };
717 gnutls_datum_t host_cert_pem = { NULL, 0 };
718 839
719 gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size); 840 gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);
720 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size); 841 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size);
@@ -727,6 +848,10 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
727 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); 848 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
728 host_cert_pem.size = host_cert_export_size; 849 host_cert_pem.size = host_cert_export_size;
729 850
851 //restore gnutls env
852 gnutls_global_deinit();
853 gnutls_global_init();
854#endif
730 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && 855 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
731 NULL != host_cert_pem.data && 0 != host_cert_pem.size) 856 NULL != host_cert_pem.data && 0 != host_cert_pem.size)
732 ret = USERPREF_E_SUCCESS; 857 ret = USERPREF_E_SUCCESS;
@@ -734,14 +859,14 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
734 /* store values in config file */ 859 /* store values in config file */
735 userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem); 860 userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem);
736 861
737 gnutls_free(root_key_pem.data); 862 if (root_key_pem.data)
738 gnutls_free(root_cert_pem.data); 863 free(root_key_pem.data);
739 gnutls_free(host_key_pem.data); 864 if (root_cert_pem.data)
740 gnutls_free(host_cert_pem.data); 865 free(root_cert_pem.data);
741 866 if (host_key_pem.data)
742 //restore gnutls env 867 free(host_key_pem.data);
743 gnutls_global_deinit(); 868 if (host_cert_pem.data)
744 gnutls_global_init(); 869 free(host_cert_pem.data);
745 870
746 return ret; 871 return ret;
747} 872}
@@ -754,18 +879,33 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
754 * 879 *
755 * @return 1 if the key was successfully imported. 880 * @return 1 if the key was successfully imported.
756 */ 881 */
882#ifdef HAVE_OPENSSL
883static userpref_error_t userpref_import_key(const char* key_name, key_data_t* key)
884#else
757static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key) 885static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key)
886#endif
758{ 887{
888#ifdef HAVE_OPENSSL
889 if (!key)
890 return USERPREF_E_SUCCESS;
891#endif
759 userpref_error_t ret = USERPREF_E_INVALID_CONF; 892 userpref_error_t ret = USERPREF_E_INVALID_CONF;
760 gnutls_datum_t pem_key = { NULL, 0 }; 893 key_data_t pem_key = { NULL, 0 };
761
762 if (userpref_get_file_contents(key_name, &pem_key)) { 894 if (userpref_get_file_contents(key_name, &pem_key)) {
763 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM)) 895#ifdef HAVE_OPENSSL
764 ret = USERPREF_E_SUCCESS; 896 key->data = (unsigned char*)malloc(pem_key.size);
765 else 897 memcpy(key->data, pem_key.data, pem_key.size);
766 ret = USERPREF_E_SSL_ERROR; 898 key->size = pem_key.size;
899 ret = USERPREF_E_SUCCESS;
900#else
901 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM))
902 ret = USERPREF_E_SUCCESS;
903 else
904 ret = USERPREF_E_SSL_ERROR;
905#endif
767 } 906 }
768 gnutls_free(pem_key.data); 907 if (pem_key.data)
908 free(pem_key.data);
769 return ret; 909 return ret;
770} 910}
771 911
@@ -777,18 +917,34 @@ static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_pr
777 * 917 *
778 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported. 918 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.
779 */ 919 */
920#ifdef HAVE_OPENSSL
921static userpref_error_t userpref_import_crt(const char* crt_name, key_data_t* cert)
922#else
780static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert) 923static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert)
924#endif
781{ 925{
926#ifdef HAVE_OPENSSL
927 if (!cert)
928 return USERPREF_E_SUCCESS;
929#endif
782 userpref_error_t ret = USERPREF_E_INVALID_CONF; 930 userpref_error_t ret = USERPREF_E_INVALID_CONF;
783 gnutls_datum_t pem_cert = { NULL, 0 }; 931 key_data_t pem_cert = { NULL, 0 };
784 932
785 if (userpref_get_file_contents(crt_name, &pem_cert)) { 933 if (userpref_get_file_contents(crt_name, &pem_cert)) {
786 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM)) 934#ifdef HAVE_OPENSSL
787 ret = USERPREF_E_SUCCESS; 935 cert->data = (unsigned char*)malloc(pem_cert.size);
788 else 936 memcpy(cert->data, pem_cert.data, pem_cert.size);
789 ret = USERPREF_E_SSL_ERROR; 937 cert->size = pem_cert.size;
938 ret = USERPREF_E_SUCCESS;
939#else
940 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM))
941 ret = USERPREF_E_SUCCESS;
942 else
943 ret = USERPREF_E_SSL_ERROR;
944#endif
790 } 945 }
791 gnutls_free(pem_cert.data); 946 if (pem_cert.data)
947 free(pem_cert.data);
792 return ret; 948 return ret;
793} 949}
794 950
@@ -805,7 +961,11 @@ static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_cr
805 * 961 *
806 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise 962 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise
807 */ 963 */
964#ifdef HAVE_OPENSSL
965userpref_error_t userpref_get_keys_and_certs(key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt)
966#else
808userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt) 967userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt)
968#endif
809{ 969{
810 userpref_error_t ret = USERPREF_E_SUCCESS; 970 userpref_error_t ret = USERPREF_E_SUCCESS;
811 971
@@ -821,7 +981,6 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,
821 if (ret == USERPREF_E_SUCCESS) 981 if (ret == USERPREF_E_SUCCESS)
822 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt); 982 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt);
823 983
824
825 if (USERPREF_E_SUCCESS != ret) { 984 if (USERPREF_E_SUCCESS != ret) {
826 //we had problem reading or importing root cert 985 //we had problem reading or importing root cert
827 //try with a new ones. 986 //try with a new ones.
@@ -851,7 +1010,7 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,
851 * 1010 *
852 * @return 1 if the certificates were successfully retrieved, 0 otherwise 1011 * @return 1 if the certificates were successfully retrieved, 0 otherwise
853 */ 1012 */
854userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert) 1013userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert)
855{ 1014{
856 if (!pem_root_cert || !pem_host_cert) 1015 if (!pem_root_cert || !pem_host_cert)
857 return USERPREF_E_INVALID_ARG; 1016 return USERPREF_E_INVALID_ARG;
@@ -859,8 +1018,14 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls
859 if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) 1018 if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert))
860 return USERPREF_E_SUCCESS; 1019 return USERPREF_E_SUCCESS;
861 else { 1020 else {
862 gnutls_free(pem_root_cert->data); 1021 if (pem_root_cert->data) {
863 gnutls_free(pem_host_cert->data); 1022 free(pem_root_cert->data);
1023 pem_root_cert->size = 0;
1024 }
1025 if (pem_host_cert->data) {
1026 free(pem_host_cert->data);
1027 pem_host_cert->size = 0;
1028 }
864 } 1029 }
865 return USERPREF_E_INVALID_CONF; 1030 return USERPREF_E_INVALID_CONF;
866} 1031}
@@ -877,7 +1042,7 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls
877 * 1042 *
878 * @return 1 on success and 0 otherwise. 1043 * @return 1 on success and 0 otherwise.
879 */ 1044 */
880userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert) 1045userpref_error_t userpref_set_keys_and_certs(key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert)
881{ 1046{
882 FILE *pFile; 1047 FILE *pFile;
883 char *pem; 1048 char *pem;
diff --git a/src/userpref.h b/src/userpref.h
index e16fd65..0e959ba 100644
--- a/src/userpref.h
+++ b/src/userpref.h
@@ -22,7 +22,19 @@
22#ifndef USERPREF_H 22#ifndef USERPREF_H
23#define USERPREF_H 23#define USERPREF_H
24 24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#ifdef HAVE_OPENSSL
30typedef struct {
31 unsigned char *data;
32 unsigned int size;
33} key_data_t;
34#else
25#include <gnutls/gnutls.h> 35#include <gnutls/gnutls.h>
36typedef gnutls_datum_t key_data_t;
37#endif
26 38
27#ifndef LIBIMOBILEDEVICE_INTERNAL 39#ifndef LIBIMOBILEDEVICE_INTERNAL
28#ifdef WIN32 40#ifdef WIN32
@@ -41,10 +53,14 @@
41 53
42typedef int16_t userpref_error_t; 54typedef int16_t userpref_error_t;
43 55
56#ifdef HAVE_OPENSSL
57LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt);
58#else
44LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); 59LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt);
45LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert); 60#endif
46LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); 61LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_keys_and_certs(key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert);
47LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key); 62LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert);
63LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, key_data_t public_key);
48userpref_error_t userpref_remove_device_public_key(const char *uuid); 64userpref_error_t userpref_remove_device_public_key(const char *uuid);
49LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_public_key(const char *uuid); 65LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_public_key(const char *uuid);
50userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count); 66userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count);
diff --git a/tools/Makefile.am b/tools/Makefile.am
index f23b0b1..19b2f92 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,7 +1,7 @@
1AM_CPPFLAGS = -I$(top_srcdir)/include 1AM_CPPFLAGS = -I$(top_srcdir)/include
2 2
3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(LFS_CFLAGS) 3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS)
4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) 4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS)
5 5
6bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate 6bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate
7 7
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index 867eaad..f744e70 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -20,13 +20,21 @@
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 <stdio.h> 27#include <stdio.h>
24#include <string.h> 28#include <string.h>
25#include <errno.h> 29#include <errno.h>
26#include <stdlib.h> 30#include <stdlib.h>
27#include <signal.h> 31#include <signal.h>
28#include <glib.h> 32#include <glib.h>
33#ifdef HAVE_OPENSSL
34#include <openssl/sha.h>
35#else
29#include <gcrypt.h> 36#include <gcrypt.h>
37#endif
30#include <unistd.h> 38#include <unistd.h>
31 39
32#include <libimobiledevice/libimobiledevice.h> 40#include <libimobiledevice/libimobiledevice.h>
@@ -66,7 +74,11 @@ enum device_link_file_status_t {
66 74
67static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out) 75static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out)
68{ 76{
77#ifdef HAVE_OPENSSL
78 SHA1((const unsigned char*)input, size, hash_out);
79#else
69 gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size); 80 gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size);
81#endif
70} 82}
71 83
72static int compare_hash(const unsigned char *hash1, const unsigned char *hash2, int hash_len) 84static int compare_hash(const unsigned char *hash1, const unsigned char *hash2, int hash_len)
@@ -82,6 +94,10 @@ static int compare_hash(const unsigned char *hash1, const unsigned char *hash2,
82 94
83static void compute_datahash(const char *path, const char *destpath, uint8_t greylist, const char *domain, const char *appid, const char *version, unsigned char *hash_out) 95static void compute_datahash(const char *path, const char *destpath, uint8_t greylist, const char *domain, const char *appid, const char *version, unsigned char *hash_out)
84{ 96{
97#ifdef HAVE_OPENSSL
98 SHA_CTX sha1;
99 SHA1_Init(&sha1);
100#else
85 gcry_md_hd_t hd = NULL; 101 gcry_md_hd_t hd = NULL;
86 gcry_md_open(&hd, GCRY_MD_SHA1, 0); 102 gcry_md_open(&hd, GCRY_MD_SHA1, 0);
87 if (!hd) { 103 if (!hd) {
@@ -89,44 +105,103 @@ static void compute_datahash(const char *path, const char *destpath, uint8_t gre
89 return; 105 return;
90 } 106 }
91 gcry_md_reset(hd); 107 gcry_md_reset(hd);
92 108#endif
93 FILE *f = fopen(path, "rb"); 109 FILE *f = fopen(path, "rb");
94 if (f) { 110 if (f) {
95 unsigned char buf[16384]; 111 unsigned char buf[16384];
96 size_t len; 112 size_t len;
97 while ((len = fread(buf, 1, 16384, f)) > 0) { 113 while ((len = fread(buf, 1, 16384, f)) > 0) {
114#ifdef HAVE_OPENSSL
115 SHA1_Update(&sha1, buf, len);
116#else
98 gcry_md_write(hd, buf, len); 117 gcry_md_write(hd, buf, len);
118#endif
99 } 119 }
100 fclose(f); 120 fclose(f);
121#ifdef HAVE_OPENSSL
122 SHA1_Update(&sha1, destpath, strlen(destpath));
123 SHA1_Update(&sha1, ";", 1);
124#else
101 gcry_md_write(hd, destpath, strlen(destpath)); 125 gcry_md_write(hd, destpath, strlen(destpath));
102 gcry_md_write(hd, ";", 1); 126 gcry_md_write(hd, ";", 1);
127#endif
103 if (greylist == 1) { 128 if (greylist == 1) {
129#ifdef HAVE_OPENSSL
130 SHA1_Update(&sha1, "true", 4);
131#else
104 gcry_md_write(hd, "true", 4); 132 gcry_md_write(hd, "true", 4);
133#endif
105 } else { 134 } else {
135#ifdef HAVE_OPENSSL
136 SHA1_Update(&sha1, "false", 5);
137#else
106 gcry_md_write(hd, "false", 5); 138 gcry_md_write(hd, "false", 5);
139#endif
107 } 140 }
141#ifdef HAVE_OPENSSL
142 SHA1_Update(&sha1, ";", 1);
143#else
108 gcry_md_write(hd, ";", 1); 144 gcry_md_write(hd, ";", 1);
145#endif
109 if (domain) { 146 if (domain) {
147#ifdef HAVE_OPENSSL
148 SHA1_Update(&sha1, domain, strlen(domain));
149#else
110 gcry_md_write(hd, domain, strlen(domain)); 150 gcry_md_write(hd, domain, strlen(domain));
151#endif
111 } else { 152 } else {
153#ifdef HAVE_OPENSSL
154 SHA1_Update(&sha1, "(null)", 6);
155#else
112 gcry_md_write(hd, "(null)", 6); 156 gcry_md_write(hd, "(null)", 6);
157#endif
113 } 158 }
159#ifdef HAVE_OPENSSL
160 SHA1_Update(&sha1, ";", 1);
161#else
114 gcry_md_write(hd, ";", 1); 162 gcry_md_write(hd, ";", 1);
163#endif
115 if (appid) { 164 if (appid) {
165#ifdef HAVE_OPENSSL
166 SHA1_Update(&sha1, appid, strlen(appid));
167#else
116 gcry_md_write(hd, appid, strlen(appid)); 168 gcry_md_write(hd, appid, strlen(appid));
169#endif
117 } else { 170 } else {
171#ifdef HAVE_OPENSSL
172 SHA1_Update(&sha1, "(null)", 6);
173#else
118 gcry_md_write(hd, "(null)", 6); 174 gcry_md_write(hd, "(null)", 6);
175#endif
119 } 176 }
177#ifdef HAVE_OPENSSL
178 SHA1_Update(&sha1, ";", 1);
179#else
120 gcry_md_write(hd, ";", 1); 180 gcry_md_write(hd, ";", 1);
181#endif
121 if (version) { 182 if (version) {
183#ifdef HAVE_OPENSSL
184 SHA1_Update(&sha1, version, strlen(version));
185#else
122 gcry_md_write(hd, version, strlen(version)); 186 gcry_md_write(hd, version, strlen(version));
187#endif
123 } else { 188 } else {
189#ifdef HAVE_OPENSSL
190 SHA1_Update(&sha1, "(null)", 6);
191#else
124 gcry_md_write(hd, "(null)", 6); 192 gcry_md_write(hd, "(null)", 6);
193#endif
125 } 194 }
195#ifdef HAVE_OPENSSL
196 SHA1_Final(hash_out, &sha1);
197#else
126 unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1); 198 unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1);
127 memcpy(hash_out, newhash, 20); 199 memcpy(hash_out, newhash, 20);
200#endif
128 } 201 }
202#ifndef HAVE_OPENSSL
129 gcry_md_close(hd); 203 gcry_md_close(hd);
204#endif
130} 205}
131 206
132static void print_hash(const unsigned char *hash, int len) 207static void print_hash(const unsigned char *hash, int len)
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 30ec272..5d067bf 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -27,7 +27,6 @@
27#include <signal.h> 27#include <signal.h>
28#include <glib.h> 28#include <glib.h>
29#include <glib/gstdio.h> 29#include <glib/gstdio.h>
30#include <gcrypt.h>
31#include <unistd.h> 30#include <unistd.h>
32 31
33#if !GLIB_CHECK_VERSION(2,25,0) 32#if !GLIB_CHECK_VERSION(2,25,0)