diff options
| -rw-r--r-- | configure.ac | 37 | ||||
| -rw-r--r-- | src/Makefile.am | 4 | ||||
| -rw-r--r-- | src/idevice.c | 155 | ||||
| -rw-r--r-- | src/idevice.h | 16 | ||||
| -rw-r--r-- | src/lockdown.c | 164 | ||||
| -rw-r--r-- | src/lockdown.h | 7 | ||||
| -rw-r--r-- | src/userpref.c | 233 | ||||
| -rw-r--r-- | src/userpref.h | 22 | ||||
| -rw-r--r-- | tools/Makefile.am | 4 | ||||
| -rw-r--r-- | tools/idevicebackup.c | 77 | ||||
| -rw-r--r-- | tools/idevicebackup2.c | 1 | 
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  # Checks for libraries.  PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= 0.1.4) -PKG_CHECK_MODULES(libgnutls, gnutls >= 2.2.0) -PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1)  PKG_CHECK_MODULES(libplist, libplist >= 0.15)  PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15) -AC_CHECK_LIB(gcrypt, gcry_control, [AC_SUBST(libgcrypt_LIBS,[-lgcrypt])], [AC_MSG_ERROR([libgcrypt is required to build libimobiledevice])])  AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])])  PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no) @@ -98,6 +95,39 @@ fi  AM_CONDITIONAL([HAVE_SWIG],[test "x$SWIG" != "xfalse"]) +AC_ARG_ENABLE([openssl], +            [AS_HELP_STRING([--disable-openssl], +            [Do not look for OpenSSL])], +            [use_openssl=no], +            [use_openssl=yes]) + +PKG_CHECK_MODULES(openssl, openssl >= 0.9.8, have_openssl=yes, have_openssl=no) +if test "x$have_openssl" = "xyes"; then +  if test "x$use_openssl" != "xyes"; then +    enable_openssl=no +    echo "*** Note: OpenSSL support explicitly disabled ***" +  else +    enable_openssl=yes +  fi +else +  if test "x$use_openssl" == "xyes" -a "x$have_openssl" != "xyes"; then +    AC_MSG_ERROR([OpenSSL support explicitly requested but OpenSSL could not be found]) +  fi +fi + +if test "x$enable_openssl" = "xyes"; then +  AC_DEFINE(HAVE_OPENSSL, 1, [Define if you have OpenSSL support]) +  AC_SUBST(openssl_CFLAGS) +  AC_SUBST(openssl_LIBS) +  ssl_provider="OpenSSL"; +else +  PKG_CHECK_MODULES(libgnutls, gnutls >= 2.2.0) +  AC_CHECK_LIB(gcrypt, gcry_control, [AC_SUBST(libgcrypt_LIBS,[-lgcrypt])], [AC_MSG_ERROR([libgcrypt is required to build libimobiledevice with GnuTLS])]) +  PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1) +  ssl_provider="GnuTLS" +fi + +  AC_SUBST([DEV_SUB]) @@ -186,6 +216,7 @@ Configuration for $PACKAGE $VERSION:    Debug code ..............: $building_debug_code    Dev tools ...............: $building_dev_tools    Python bindings .........: $python_bindings +  SSL support .............: $ssl_provider    Now type 'make' to build $PACKAGE $VERSION,    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 @@  AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) ${libpthread_LIBS} +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS) +AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) ${libpthread_LIBS} $(openssl_LIBS)  lib_LTLIBRARIES = libimobiledevice.la  libimobiledevice_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 @@   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA    */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +  #include <stdlib.h>  #include <string.h>  #include <errno.h>  #include <usbmuxd.h> +#ifdef HAVE_OPENSSL +#include <openssl/ssl.h> +#else  #include <gnutls/gnutls.h> +#endif  #include "idevice.h"  #include "userpref.h"  #include "debug.h" +#ifdef HAVE_OPENSSL +static int openssl_init_done = 0; +#endif +  static idevice_event_cb_t event_cb = NULL;  static 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  	}  	if (connection->ssl_data) { +#ifdef HAVE_OPENSSL +		int sent = SSL_write(connection->ssl_data->session, (const void*)data, (int)len); +		debug_info("SSL_write %d, sent %d", len, sent); +#else  		ssize_t sent = gnutls_record_send(connection->ssl_data->session, (void*)data, (size_t)len); +#endif  		if ((uint32_t)sent == (uint32_t)len) {  			*sent_bytes = sent;  			return IDEVICE_E_SUCCESS; @@ -359,7 +376,12 @@ idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connecti  	}  	if (connection->ssl_data) { +#ifdef HAVE_OPENSSL +		int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len); +		debug_info("SSL_read %d, received %d", len, received); +#else  		ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); +#endif  		if (received > 0) {  			*recv_bytes = received;  			return IDEVICE_E_SUCCESS; @@ -413,7 +435,12 @@ idevice_error_t idevice_connection_receive(idevice_connection_t connection, char  	}  	if (connection->ssl_data) { +#ifdef HAVE_OPENSSL +		int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len); +		debug_info("SSL_read %d, received %d", len, received); +#else  		ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); +#endif  		if (received > 0) {  			*recv_bytes = received;  			return IDEVICE_E_SUCCESS; @@ -453,6 +480,7 @@ idevice_error_t idevice_get_uuid(idevice_t device, char **uuid)  	return IDEVICE_E_SUCCESS;  } +#ifndef HAVE_OPENSSL  /**   * Internally used gnutls callback function for receiving encrypted data.   */ @@ -514,6 +542,7 @@ static ssize_t internal_ssl_write(gnutls_transport_ptr_t transport, char *buffer  	debug_info("post-send sent %i bytes", bytes);  	return bytes;  } +#endif  /**   * Internally used function for cleaning up SSL stuff. @@ -523,6 +552,14 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)  	if (!ssl_data)  		return; +#ifdef HAVE_OPENSSL +	if (ssl_data->session) { +		SSL_free(ssl_data->session); +	} +	if (ssl_data->ctx) { +		SSL_CTX_free(ssl_data->ctx); +	} +#else  	if (ssl_data->session) {  		gnutls_deinit(ssl_data->session);  	} @@ -541,8 +578,45 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)  	if (ssl_data->host_privkey) {  		gnutls_x509_privkey_deinit(ssl_data->host_privkey);  	} +#endif +} + +#ifdef HAVE_OPENSSL +static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) +{ +	return 1; +} + +#ifndef STRIP_DEBUG_CODE +static const char *errorstring(int e) +{ +    switch(e) { +	case SSL_ERROR_NONE: +	    return "SSL_ERROR_NONE"; +	case SSL_ERROR_SSL: +	    return "SSL_ERROR_SSL"; +	case SSL_ERROR_WANT_READ: +	    return "SSL_ERROR_WANT_READ"; +	case SSL_ERROR_WANT_WRITE: +	    return "SSL_ERROR_WANT_WRITE"; +	case SSL_ERROR_WANT_X509_LOOKUP: +	    return "SSL_ERROR_WANT_X509_LOOKUP"; +	case SSL_ERROR_SYSCALL: +	    return "SSL_ERROR_SYSCALL"; +	case SSL_ERROR_ZERO_RETURN: +	    return "SSL_ERROR_ZERO_RETURN"; +        case SSL_ERROR_WANT_CONNECT: +	    return "SSL_ERROR_WANT_CONNECT"; +	case SSL_ERROR_WANT_ACCEPT: +	    return "SSL_ERROR_WANT_ACCEPT"; +	default: +	    return "UNKOWN_ERROR_VALUE"; +    }  } +#endif +#endif +#ifndef HAVE_OPENSSL  /**   * Internally used gnutls callback function that gets called during handshake.   */ @@ -564,6 +638,7 @@ static int internal_cert_callback (gnutls_session_t session, const gnutls_datum_  	}  	return res;  } +#endif  /**   * Enables SSL for the given connection. @@ -582,6 +657,76 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)  	idevice_error_t ret = IDEVICE_E_SSL_ERROR;  	uint32_t return_me = 0; +#ifdef HAVE_OPENSSL +	key_data_t root_cert = { NULL, 0 }; +	key_data_t root_privkey = { NULL, 0 }; + +	userpref_error_t uerr = userpref_get_keys_and_certs(&root_privkey, &root_cert, NULL, NULL); +	if (uerr != USERPREF_E_SUCCESS) { +		debug_info("Error %d when loading keys and certificates! %d", uerr); +	} + +	/* Set up OpenSSL */ +	BIO *ssl_bio = BIO_new(BIO_s_socket()); +	if (!ssl_bio) { +		debug_info("ERROR: Could not create SSL bio."); +		return ret; +	} +	BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); + +	if (openssl_init_done == 0) { +		SSL_library_init(); +		openssl_init_done = 1; +	} +	SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); + +	BIO* membp; +	X509* rootCert = NULL; +	membp = BIO_new_mem_buf(root_cert.data, root_cert.size); +	PEM_read_bio_X509(membp, &rootCert, NULL, NULL); +	BIO_free(membp); +	if (SSL_CTX_use_certificate(ssl_ctx, rootCert) != 1) { +		debug_info("WARNING: Could not load RootCertificate"); +	} +	X509_free(rootCert); +	free(root_cert.data); + +	RSA* rootPrivKey = NULL; +	membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); +	PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL); +	BIO_free(membp); +	if (SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey) != 1) { +		debug_info("WARNING: Could not load RootPrivateKey"); +	} +	RSA_free(rootPrivKey); +	free(root_privkey.data); + +	SSL *ssl = SSL_new(ssl_ctx); +	if (!ssl) { +		debug_info("ERROR: Could not create SSL object"); +		BIO_free(ssl_bio); +		SSL_CTX_free(ssl_ctx); +		return ret; +	} +	SSL_set_connect_state(ssl); +	SSL_set_verify(ssl, 0, ssl_verify_callback); +	SSL_set_bio(ssl, ssl_bio, ssl_bio); + +	return_me = SSL_do_handshake(ssl); +        if (return_me != 1) { +		debug_info("ERROR in SSL_do_handshake: %s", errorstring(SSL_get_error(ssl, return_me))); +		BIO_free(ssl_bio); +		SSL_CTX_free(ssl_ctx); +	} else { +		ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private)); +		ssl_data_loc->session = ssl; +		ssl_data_loc->ctx = ssl_ctx; +		ssl_data_loc->bio = ssl_bio; +		connection->ssl_data = ssl_data_loc; +		ret = IDEVICE_E_SUCCESS; +		debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl)); +	} +#else  	ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));  	/* Set up GnuTLS... */ @@ -612,8 +757,9 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)  	debug_info("GnuTLS step 3...");  	gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read);  	debug_info("GnuTLS step 4 -- now handshaking..."); -	if (errno) +	if (errno) {  		debug_info("WARN: errno says %s before handshake!", strerror(errno)); +	}  	return_me = gnutls_handshake(ssl_data_loc->session);  	debug_info("GnuTLS handshake done..."); @@ -628,6 +774,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)  		ret = IDEVICE_E_SUCCESS;  		debug_info("SSL mode enabled");  	} +#endif  	return ret;  } @@ -649,9 +796,15 @@ idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection)  		return IDEVICE_E_SUCCESS;  	} +#ifdef HAVE_OPENSSL +	if (connection->ssl_data->session) { +		SSL_shutdown(connection->ssl_data->session); +	} +#else  	if (connection->ssl_data->session) {  		gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR);  	} +#endif  	internal_ssl_cleanup(connection->ssl_data);  	free(connection->ssl_data);  	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 @@  #ifndef IDEVICE_H  #define IDEVICE_H +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_OPENSSL +#include <openssl/ssl.h> +#else  #include <gnutls/gnutls.h>  #include <gnutls/x509.h> +#endif + +#include "userpref.h"  #include "libimobiledevice/libimobiledevice.h" @@ -31,12 +41,18 @@ enum connection_type {  };  struct ssl_data_private { +#ifdef HAVE_OPENSSL +	SSL *session; +	SSL_CTX *ctx; +	BIO *bio; +#else  	gnutls_certificate_credentials_t certificate;  	gnutls_session_t session;  	gnutls_x509_privkey_t root_privkey;  	gnutls_x509_crt_t root_cert;  	gnutls_x509_privkey_t host_privkey;  	gnutls_x509_crt_t host_cert; +#endif  };  typedef struct ssl_data_private *ssl_data_t; 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 @@   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA   */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +  #include <string.h>  #include <stdlib.h>  #define _GNU_SOURCE 1  #define __USE_GNU 1  #include <stdio.h>  #include <ctype.h> +#ifdef HAVE_OPENSSL +#include <openssl/pem.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#else  #include <libtasn1.h>  #include <gnutls/x509.h> +#endif  #include <plist/plist.h>  #include "property_list_service.h" @@ -40,6 +50,7 @@  #define RESULT_SUCCESS 0  #define RESULT_FAILURE 1 +#ifndef HAVE_OPENSSL  const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {  	{"PKCS1", 536872976, 0},  	{0, 1073741836, 0}, @@ -48,6 +59,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {  	{"publicExponent", 3, 0},  	{0, 0, 0}  }; +#endif  /**   * 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   *   * @return LOCKDOWN_E_SUCCESS on success   */ -lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key) +lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key)  {  	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;  	plist_t value = NULL; @@ -783,13 +795,13 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor   *   * @return LOCKDOWN_E_SUCCESS on success   */ -static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist) +static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char *host_id, plist_t *pair_record_plist)  {  	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; -	gnutls_datum_t device_cert = { NULL, 0 }; -	gnutls_datum_t host_cert = { NULL, 0 }; -	gnutls_datum_t root_cert = { NULL, 0 }; +	key_data_t device_cert = { NULL, 0 }; +	key_data_t host_cert = { NULL, 0 }; +	key_data_t root_cert = { NULL, 0 };  	ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);  	if (ret != LOCKDOWN_E_SUCCESS) { @@ -844,7 +856,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_  	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;  	plist_t dict = NULL;  	plist_t dict_record = NULL; -	gnutls_datum_t public_key = { NULL, 0 }; +	key_data_t public_key = { NULL, 0 };  	int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */  	if (pair_record && pair_record->host_id) { @@ -1096,14 +1108,145 @@ lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client)   *  LOCKDOWN_E_INVALID_CONF if the internal configuration system failed,   *  LOCKDOWN_E_SSL_ERROR if the certificates could not be generated   */ -lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert, -									   gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert) +lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * odevice_cert, +									   key_data_t * ohost_cert, key_data_t * oroot_cert)  {  	if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert)  		return LOCKDOWN_E_INVALID_ARG;  	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;  	userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; +#ifdef HAVE_OPENSSL +	BIO *membio = BIO_new_mem_buf(public_key.data, public_key.size); +	RSA *pubkey = NULL; +	if (!PEM_read_bio_RSAPublicKey(membio, &pubkey, NULL, NULL)) { +		debug_info("%s: Could not read public key", __func__);	 +	} +	BIO_free(membio); + +	/* now generate certificates */ +	key_data_t root_privkey, host_privkey; +	key_data_t root_cert, host_cert; +	X509* dev_cert; + +	root_cert.data = NULL; +	root_cert.size = 0; +	host_cert.data = NULL; +	host_cert.size = 0; + +	dev_cert = X509_new(); + +	root_privkey.data = NULL; +	root_privkey.size = 0; +	host_privkey.data = NULL; +	host_privkey.size = 0; + +	uret = userpref_get_keys_and_certs(&root_privkey, &root_cert, &host_privkey, &host_cert); +	if (USERPREF_E_SUCCESS == uret) { +		/* generate device certificate */ +		ASN1_INTEGER* sn = ASN1_INTEGER_new(); +		ASN1_INTEGER_set(sn, 0); +		X509_set_serialNumber(dev_cert, sn); +		ASN1_INTEGER_free(sn); +		X509_set_version(dev_cert, 2); + +		X509_EXTENSION* ext; +		if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) { +			debug_info("ERROR: X509V3_EXT_conf_nid failed"); +		} +		X509_add_ext(dev_cert, ext, -1); + +		ASN1_TIME* asn1time = ASN1_TIME_new(); +		ASN1_TIME_set(asn1time, time(NULL)); +		X509_set_notBefore(dev_cert, asn1time); +		ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +		X509_set_notAfter(dev_cert, asn1time); +		ASN1_TIME_free(asn1time); +	 +		BIO* membp; + +		X509* rootCert = NULL; +		membp = BIO_new_mem_buf(root_cert.data, root_cert.size); +		PEM_read_bio_X509(membp, &rootCert, NULL, NULL); +		BIO_free(membp); +		if (!rootCert) { +			debug_info("Could not read RootCertificate%*s"); +		} else { +			debug_info("RootCertificate loaded"); +			EVP_PKEY* pkey = EVP_PKEY_new(); +			EVP_PKEY_assign_RSA(pkey, pubkey); +			X509_set_pubkey(dev_cert, pkey); +			EVP_PKEY_free(pkey); +			X509_free(rootCert); +		} + +		EVP_PKEY* rootPriv = NULL; +		membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); +		PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL); +		BIO_free(membp); +		if (!rootPriv) { +			debug_info("Could not read RootPrivateKey"); +		} else { +			debug_info("RootPrivateKey loaded"); +			if (X509_sign(dev_cert, rootPriv, EVP_sha1())) { +				ret = LOCKDOWN_E_SUCCESS; +			} else { +				debug_info("signing failed"); +			} +			EVP_PKEY_free(rootPriv); +		} + +		if (LOCKDOWN_E_SUCCESS == ret) { +			/* if everything went well, export in PEM format */ +			key_data_t pem_root_cert = { NULL, 0 }; +			key_data_t pem_host_cert = { NULL, 0 }; + +			uret = userpref_get_certs_as_pem(&pem_root_cert, &pem_host_cert); +			if (USERPREF_E_SUCCESS == uret) { +				/* copy buffer for output */ +				membp = BIO_new(BIO_s_mem()); +				if (PEM_write_bio_X509(membp, dev_cert) > 0) { +					odevice_cert->size = BIO_get_mem_data(membp, &odevice_cert->data); +				} + +				ohost_cert->data = malloc(pem_host_cert.size); +				memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size); +				ohost_cert->size = pem_host_cert.size; + +				oroot_cert->data = malloc(pem_root_cert.size); +				memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); +				oroot_cert->size = pem_root_cert.size; + +				free(pem_root_cert.data); +				free(pem_host_cert.data); +			} +		} +	} +	X509V3_EXT_cleanup(); +	X509_free(dev_cert); + +	switch(uret) { +	case USERPREF_E_INVALID_ARG: +		ret = LOCKDOWN_E_INVALID_ARG; +		break; +	case USERPREF_E_INVALID_CONF: +		ret = LOCKDOWN_E_INVALID_CONF; +		break; +	case USERPREF_E_SSL_ERROR: +		ret = LOCKDOWN_E_SSL_ERROR; +	default: +		break; +	} + +	if (root_cert.data) +		free(root_cert.data); +	if (host_cert.data) +		free(host_cert.data); +	if (root_privkey.data) +		free(root_privkey.data); +	if (host_privkey.data) +		free(host_privkey.data); +#else  	gnutls_datum_t modulus = { NULL, 0 };  	gnutls_datum_t exponent = { NULL, 0 }; @@ -1200,8 +1343,8 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu  						memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);  						oroot_cert->size = pem_root_cert.size; -						free(pem_root_cert.data); -						free(pem_host_cert.data); +						gnutls_free(pem_root_cert.data); +						gnutls_free(pem_host_cert.data);  						if (dev_pem.data)  							gnutls_free(dev_pem.data); @@ -1238,6 +1381,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu  	gnutls_free(exponent.data);  	gnutls_free(der_pub_key.data); +#endif  	return ret;  } 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 @@  #ifndef LOCKDOWND_H  #define LOCKDOWND_H -#include <gnutls/gnutls.h> +#include "userpref.h"  #include "libimobiledevice/lockdown.h"  #include "property_list_service.h" @@ -35,8 +35,7 @@ struct lockdownd_client_private {  	char *label;  }; -lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key); -lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * device_cert, -									   gnutls_datum_t * host_cert, gnutls_datum_t * root_cert); +lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key); +lockdownd_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);  #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 @@   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA   */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif  #include <stdio.h>  #include <stdint.h>  #include <stdlib.h>  #include <string.h> +#ifdef HAVE_OPENSSL +#include <openssl/pem.h> +#include <openssl/rsa.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#else  #include <gnutls/gnutls.h>  #include <gnutls/x509.h>  #include <gcrypt.h> +#endif  #include <dirent.h>  #include <libgen.h> @@ -526,7 +536,7 @@ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count)   * @return 1 on success and 0 if no public key is given or if it has already   *         been marked as connected previously.   */ -userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key) +userpref_error_t userpref_set_device_public_key(const char *uuid, key_data_t public_key)  {  	if (NULL == public_key.data)  		return USERPREF_E_INVALID_ARG; @@ -583,14 +593,14 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid)  }  /** - * Private function which reads the given file into a gnutls structure. + * Private function which reads the given file into a key_data_t structure.   *   * @param file The filename of the file to read   * @param data The pointer at which to store the data.   *   * @return 1 if the file contents where read successfully and 0 otherwise.   */ -static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) +static int userpref_get_file_contents(const char *file, key_data_t * data)  {  	int success;  	unsigned long int size = 0; @@ -637,7 +647,7 @@ static int userpref_get_file_contents(const char *file, gnutls_datum_t * data)  	free(filepath); -	/* Add it to the gnutls_datnum_t structure */ +	/* Add it to the key_data_t structure */  	if (success) {  		data->data = (uint8_t*) content;  		data->size = size; @@ -655,6 +665,121 @@ static userpref_error_t userpref_gen_keys_and_cert(void)  {  	userpref_error_t ret = USERPREF_E_SSL_ERROR; +	key_data_t root_key_pem = { NULL, 0 }; +	key_data_t root_cert_pem = { NULL, 0 }; +	key_data_t host_key_pem = { NULL, 0 }; +	key_data_t host_cert_pem = { NULL, 0 }; + +#ifdef HAVE_OPENSSL +	RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL); +	RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL); + +	EVP_PKEY* root_pkey = EVP_PKEY_new(); +	EVP_PKEY_assign_RSA(root_pkey, root_keypair); + +	EVP_PKEY* host_pkey = EVP_PKEY_new(); +	EVP_PKEY_assign_RSA(host_pkey, host_keypair); + +	/* generate root certificate */ +	X509* root_cert = X509_new(); +	{ +		/* set serial number */ +		ASN1_INTEGER* sn = ASN1_INTEGER_new(); +		ASN1_INTEGER_set(sn, 0); +		X509_set_serialNumber(root_cert, sn); +		ASN1_INTEGER_free(sn); + +		/* set version */ +		X509_set_version(root_cert, 2); + +		/* set x509v3 basic constraints */ +		X509_EXTENSION* ext; +		if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:TRUE"))) { +			debug_info("ERROR: X509V3_EXT_conf_nid failed"); +		} +		X509_add_ext(root_cert, ext, -1); + +		/* set key validity */ +		ASN1_TIME* asn1time = ASN1_TIME_new(); +		ASN1_TIME_set(asn1time, time(NULL)); +		X509_set_notBefore(root_cert, asn1time); +		ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +		X509_set_notAfter(root_cert, asn1time); +		ASN1_TIME_free(asn1time); + +		/* use root public key for root cert */ +		X509_set_pubkey(root_cert, root_pkey); +		/* sign root cert with root private key */ +		X509_sign(root_cert, root_pkey, EVP_sha1()); +	} + +	/* create host certificate */ +	X509* host_cert = X509_new(); +	{ +		/* set serial number */ +		ASN1_INTEGER* sn = ASN1_INTEGER_new(); +		ASN1_INTEGER_set(sn, 0); +		X509_set_serialNumber(host_cert, sn); +		ASN1_INTEGER_free(sn); + +		/* set version */ +		X509_set_version(host_cert, 2); + +		/* set x509v3 basic constraints */ +		X509_EXTENSION* ext; +		if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) { +			debug_info("ERROR: X509V3_EXT_conf_nid failed"); +		} +		X509_add_ext(host_cert, ext, -1); + +		/* set x509v3 key usage */ +		if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, (char*)"digitalSignature,keyEncipherment"))) { +			debug_info("ERROR: X509V3_EXT_conf_nid failed"); +		} +		X509_add_ext(host_cert, ext, -1); + +		/* set key validity */ +		ASN1_TIME* asn1time = ASN1_TIME_new(); +		ASN1_TIME_set(asn1time, time(NULL)); +		X509_set_notBefore(host_cert, asn1time); +		ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +		X509_set_notAfter(host_cert, asn1time); +		ASN1_TIME_free(asn1time); + +		/* use host public key for host cert */	 +		X509_set_pubkey(host_cert, host_pkey); + +		/* sign host cert with root private key */ +		X509_sign(host_cert, root_pkey, EVP_sha1()); +	} + +	if (root_cert && root_pkey && host_cert && host_pkey) { +		BIO* membp; + +		membp = BIO_new(BIO_s_mem()); +		if (PEM_write_bio_X509(membp, root_cert) > 0) { +			root_cert_pem.size = BIO_get_mem_data(membp, &root_cert_pem.data); +		} +		membp = BIO_new(BIO_s_mem()); +		if (PEM_write_bio_PrivateKey(membp, root_pkey, NULL, NULL, 0, 0, NULL) > 0) { +			root_key_pem.size = BIO_get_mem_data(membp, &root_key_pem.data); +		} +		membp = BIO_new(BIO_s_mem()); +		if (PEM_write_bio_X509(membp, host_cert) > 0) { +			host_cert_pem.size = BIO_get_mem_data(membp, &host_cert_pem.data); +		} +		membp = BIO_new(BIO_s_mem()); +		if (PEM_write_bio_PrivateKey(membp, host_pkey, NULL, NULL, 0, 0, NULL) > 0) { +			host_key_pem.size = BIO_get_mem_data(membp, &host_key_pem.data); +		} +	} + +	EVP_PKEY_free(root_pkey); +	EVP_PKEY_free(host_pkey); + +	X509_free(host_cert); +	X509_free(root_cert); +#else  	gnutls_x509_privkey_t root_privkey;  	gnutls_x509_crt_t root_cert;  	gnutls_x509_privkey_t host_privkey; @@ -697,8 +822,6 @@ static userpref_error_t userpref_gen_keys_and_cert(void)  	/* export to PEM format */  	size_t root_key_export_size = 0;  	size_t host_key_export_size = 0; -	gnutls_datum_t root_key_pem = { NULL, 0 }; -	gnutls_datum_t host_key_pem = { NULL, 0 };  	gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);  	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)  	size_t root_cert_export_size = 0;  	size_t host_cert_export_size = 0; -	gnutls_datum_t root_cert_pem = { NULL, 0 }; -	gnutls_datum_t host_cert_pem = { NULL, 0 };  	gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);  	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)  	gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);  	host_cert_pem.size = host_cert_export_size; +	//restore gnutls env +	gnutls_global_deinit(); +	gnutls_global_init(); +#endif  	if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&  		NULL != host_cert_pem.data && 0 != host_cert_pem.size)  		ret = USERPREF_E_SUCCESS; @@ -734,14 +859,14 @@ static userpref_error_t userpref_gen_keys_and_cert(void)  	/* store values in config file */  	userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem); -	gnutls_free(root_key_pem.data); -	gnutls_free(root_cert_pem.data); -	gnutls_free(host_key_pem.data); -	gnutls_free(host_cert_pem.data); - -	//restore gnutls env -	gnutls_global_deinit(); -	gnutls_global_init(); +	if (root_key_pem.data) +		free(root_key_pem.data); +	if (root_cert_pem.data) +		free(root_cert_pem.data); +	if (host_key_pem.data) +		free(host_key_pem.data); +	if (host_cert_pem.data) +		free(host_cert_pem.data);  	return ret;  } @@ -754,18 +879,33 @@ static userpref_error_t userpref_gen_keys_and_cert(void)   *   * @return 1 if the key was successfully imported.   */ +#ifdef HAVE_OPENSSL +static userpref_error_t userpref_import_key(const char* key_name, key_data_t* key) +#else  static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key) +#endif  { +#ifdef HAVE_OPENSSL +	if (!key) +		return USERPREF_E_SUCCESS; +#endif  	userpref_error_t ret = USERPREF_E_INVALID_CONF; -	gnutls_datum_t pem_key = { NULL, 0 }; - +	key_data_t pem_key = { NULL, 0 };  	if (userpref_get_file_contents(key_name, &pem_key)) { -			if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM)) -				ret = USERPREF_E_SUCCESS; -			else -				ret = USERPREF_E_SSL_ERROR; +#ifdef HAVE_OPENSSL +		key->data = (unsigned char*)malloc(pem_key.size); +		memcpy(key->data, pem_key.data, pem_key.size); +		key->size = pem_key.size; +		ret = USERPREF_E_SUCCESS; +#else +		if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM)) +			ret = USERPREF_E_SUCCESS; +		else +			ret = USERPREF_E_SSL_ERROR; +#endif  	} -	gnutls_free(pem_key.data); +	if (pem_key.data) +		free(pem_key.data);  	return ret;  } @@ -777,18 +917,34 @@ static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_pr   *   * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.   */ +#ifdef HAVE_OPENSSL +static userpref_error_t userpref_import_crt(const char* crt_name, key_data_t* cert) +#else  static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert) +#endif  { +#ifdef HAVE_OPENSSL +	if (!cert) +		return USERPREF_E_SUCCESS; +#endif  	userpref_error_t ret = USERPREF_E_INVALID_CONF; -	gnutls_datum_t pem_cert = { NULL, 0 }; +	key_data_t pem_cert = { NULL, 0 };  	if (userpref_get_file_contents(crt_name, &pem_cert)) { -			if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM)) -				ret = USERPREF_E_SUCCESS; -			else -				ret = USERPREF_E_SSL_ERROR; +#ifdef HAVE_OPENSSL +		cert->data = (unsigned char*)malloc(pem_cert.size); +		memcpy(cert->data, pem_cert.data, pem_cert.size); +		cert->size = pem_cert.size; +		ret = USERPREF_E_SUCCESS; +#else +		if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM)) +			ret = USERPREF_E_SUCCESS; +		else +			ret = USERPREF_E_SSL_ERROR; +#endif  	} -	gnutls_free(pem_cert.data); +	if (pem_cert.data) +		free(pem_cert.data);  	return ret;  } @@ -805,7 +961,11 @@ static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_cr   *   * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise   */ +#ifdef HAVE_OPENSSL +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) +#else  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) +#endif  {  	userpref_error_t ret = USERPREF_E_SUCCESS; @@ -821,7 +981,6 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,  	if (ret == USERPREF_E_SUCCESS)  		ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt); -  	if (USERPREF_E_SUCCESS != ret) {  		//we had problem reading or importing root cert  		//try with a new ones. @@ -851,7 +1010,7 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,   *   * @return 1 if the certificates were successfully retrieved, 0 otherwise   */ -userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert) +userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert)  {  	if (!pem_root_cert || !pem_host_cert)  		return USERPREF_E_INVALID_ARG; @@ -859,8 +1018,14 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls  	if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert))  		return USERPREF_E_SUCCESS;  	else { -		gnutls_free(pem_root_cert->data); -		gnutls_free(pem_host_cert->data); +		if (pem_root_cert->data) { +			free(pem_root_cert->data); +			pem_root_cert->size = 0; +		} +		if (pem_host_cert->data) { +			free(pem_host_cert->data); +			pem_host_cert->size = 0; +		}  	}  	return USERPREF_E_INVALID_CONF;  } @@ -877,7 +1042,7 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls   *   * @return 1 on success and 0 otherwise.   */ -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) +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)  {  	FILE *pFile;  	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 @@  #ifndef USERPREF_H  #define USERPREF_H +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_OPENSSL +typedef struct { +	unsigned char *data; +	unsigned int size; +} key_data_t; +#else  #include <gnutls/gnutls.h> +typedef gnutls_datum_t key_data_t; +#endif  #ifndef LIBIMOBILEDEVICE_INTERNAL  #ifdef WIN32 @@ -41,10 +53,14 @@  typedef int16_t userpref_error_t; +#ifdef HAVE_OPENSSL +LIBIMOBILEDEVICE_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); +#else  LIBIMOBILEDEVICE_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); -LIBIMOBILEDEVICE_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); -LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); -LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key); +#endif +LIBIMOBILEDEVICE_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); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, key_data_t public_key);  userpref_error_t userpref_remove_device_public_key(const char *uuid);  LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_public_key(const char *uuid);  userpref_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 @@  AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) +AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS)  bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate 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 @@   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA    */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +  #include <stdio.h>  #include <string.h>  #include <errno.h>  #include <stdlib.h>  #include <signal.h>  #include <glib.h> +#ifdef HAVE_OPENSSL +#include <openssl/sha.h> +#else  #include <gcrypt.h> +#endif  #include <unistd.h>  #include <libimobiledevice/libimobiledevice.h> @@ -66,7 +74,11 @@ enum device_link_file_status_t {  static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out)  { +#ifdef HAVE_OPENSSL +	SHA1((const unsigned char*)input, size, hash_out); +#else  	gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size); +#endif  }  static 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,  static 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)  { +#ifdef HAVE_OPENSSL +	SHA_CTX sha1; +	SHA1_Init(&sha1); +#else  	gcry_md_hd_t hd = NULL;  	gcry_md_open(&hd, GCRY_MD_SHA1, 0);  	if (!hd) { @@ -89,44 +105,103 @@ static void compute_datahash(const char *path, const char *destpath, uint8_t gre  		return;  	}  	gcry_md_reset(hd); - +#endif  	FILE *f = fopen(path, "rb");  	if (f) {  		unsigned char buf[16384];  		size_t len;  		while ((len = fread(buf, 1, 16384, f)) > 0) { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, buf, len); +#else  			gcry_md_write(hd, buf, len); +#endif  		}  		fclose(f); +#ifdef HAVE_OPENSSL +		SHA1_Update(&sha1, destpath, strlen(destpath)); +		SHA1_Update(&sha1, ";", 1); +#else  		gcry_md_write(hd, destpath, strlen(destpath));  		gcry_md_write(hd, ";", 1); +#endif  		if (greylist == 1) { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, "true", 4); +#else  			gcry_md_write(hd, "true", 4); +#endif  		} else { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, "false", 5); +#else  			gcry_md_write(hd, "false", 5); +#endif  		} +#ifdef HAVE_OPENSSL +		SHA1_Update(&sha1, ";", 1); +#else  		gcry_md_write(hd, ";", 1); +#endif  		if (domain) { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, domain, strlen(domain)); +#else  			gcry_md_write(hd, domain, strlen(domain)); +#endif  		} else { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, "(null)", 6); +#else  			gcry_md_write(hd, "(null)", 6); +#endif  		} +#ifdef HAVE_OPENSSL +		SHA1_Update(&sha1, ";", 1); +#else  		gcry_md_write(hd, ";", 1); +#endif  		if (appid) { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, appid, strlen(appid)); +#else  			gcry_md_write(hd, appid, strlen(appid)); +#endif  		} else { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, "(null)", 6); +#else  			gcry_md_write(hd, "(null)", 6); +#endif  		} +#ifdef HAVE_OPENSSL +		SHA1_Update(&sha1, ";", 1); +#else  		gcry_md_write(hd, ";", 1); +#endif  		if (version) { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, version, strlen(version)); +#else  			gcry_md_write(hd, version, strlen(version)); +#endif  		} else { +#ifdef HAVE_OPENSSL +			SHA1_Update(&sha1, "(null)", 6); +#else  			gcry_md_write(hd, "(null)", 6); +#endif  		} +#ifdef HAVE_OPENSSL +		SHA1_Final(hash_out, &sha1); +#else  		unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1);  		memcpy(hash_out, newhash, 20); +#endif  	} +#ifndef HAVE_OPENSSL  	gcry_md_close(hd); +#endif  }  static 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 @@  #include <signal.h>  #include <glib.h>  #include <glib/gstdio.h> -#include <gcrypt.h>  #include <unistd.h>  #if !GLIB_CHECK_VERSION(2,25,0)  | 
