From 8b1af4cf80eff619d3465925dce7fe572fc09224 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Wed, 14 Sep 2011 18:55:59 +0200 Subject: Add OpenSSL support --- configure.ac | 37 +++++++- src/Makefile.am | 4 +- src/idevice.c | 155 +++++++++++++++++++++++++++++++- src/idevice.h | 16 ++++ src/lockdown.c | 164 +++++++++++++++++++++++++++++++--- src/lockdown.h | 7 +- src/userpref.c | 233 +++++++++++++++++++++++++++++++++++++++++-------- src/userpref.h | 22 ++++- tools/Makefile.am | 4 +- tools/idevicebackup.c | 77 +++++++++++++++- 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 +#endif + #include #include #include #include +#ifdef HAVE_OPENSSL +#include +#else #include +#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 +#endif + +#ifdef HAVE_OPENSSL +#include +#else #include #include +#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 +#endif + #include #include #define _GNU_SOURCE 1 #define __USE_GNU 1 #include #include +#ifdef HAVE_OPENSSL +#include +#include +#include +#else #include #include +#endif #include #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 +#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 +#endif #include #include #include #include +#ifdef HAVE_OPENSSL +#include +#include +#include +#include +#else #include #include #include +#endif #include #include @@ -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 +#endif + +#ifdef HAVE_OPENSSL +typedef struct { + unsigned char *data; + unsigned int size; +} key_data_t; +#else #include +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 +#endif + #include #include #include #include #include #include +#ifdef HAVE_OPENSSL +#include +#else #include +#endif #include #include @@ -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 #include #include -#include #include #if !GLIB_CHECK_VERSION(2,25,0) -- cgit v1.1-32-gdbae