Updated OpenSSL-specific code to use OpenSSL 3.0+ API
diff --git a/common/userpref.c b/common/userpref.c
index 11e28ba..b64c703 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -435,6 +435,10 @@
 	debug_info("Generating keys and certificates...");
 
 #if defined(HAVE_OPENSSL)
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_PKEY* root_pkey = EVP_RSA_gen(2048);
+	EVP_PKEY* host_pkey = EVP_RSA_gen(2048);
+#else
 	BIGNUM *e = BN_new();
 	RSA* root_keypair = RSA_new();
 	RSA* host_keypair = RSA_new();
@@ -451,6 +455,7 @@
 
 	EVP_PKEY* host_pkey = EVP_PKEY_new();
 	EVP_PKEY_assign_RSA(host_pkey, host_keypair);
+#endif
 
 	/* generate root certificate */
 	X509* root_cert = X509_new();
@@ -561,12 +566,22 @@
 		}
 	}
 
-	RSA *pubkey = NULL;
+	EVP_PKEY *pubkey = NULL;
 	{
 		BIO *membp = BIO_new_mem_buf(public_key.data, public_key.size);
-		if (!PEM_read_bio_RSAPublicKey(membp, &pubkey, NULL, NULL)) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+		if (!PEM_read_bio_PUBKEY(membp, &pubkey, NULL, NULL)) {
 			debug_info("WARNING: Could not read public key");
 		}
+#else
+		RSA *rsa_pubkey = NULL;
+		if (!PEM_read_bio_RSAPublicKey(membp, &rsa_pubkey, NULL, NULL)) {
+			debug_info("WARNING: Could not read public key");
+		} else {
+			pubkey = EVP_PKEY_new();
+			EVP_PKEY_assign_RSA(pubkey, rsa_pubkey);
+		}
+#endif
 		BIO_free(membp);
 	}
 
@@ -588,10 +603,7 @@
 		X509_set1_notAfter(dev_cert, asn1time);
 		ASN1_TIME_free(asn1time);
 
-		EVP_PKEY* pkey = EVP_PKEY_new();
-		EVP_PKEY_assign_RSA(pkey, pubkey);
-		X509_set_pubkey(dev_cert, pkey);
-		EVP_PKEY_free(pkey);
+		X509_set_pubkey(dev_cert, pubkey);
 
 		X509_add_ext_helper(dev_cert, NID_subject_key_identifier, (char*)"hash");
 		X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment");
@@ -618,6 +630,7 @@
 	X509V3_EXT_cleanup();
 	X509_free(dev_cert);
 
+	EVP_PKEY_free(pubkey);
 	EVP_PKEY_free(root_pkey);
 	EVP_PKEY_free(host_pkey);
 
diff --git a/src/idevice.c b/src/idevice.c
index 8545317..719cd28 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -1057,18 +1057,33 @@
 }
 
 #ifdef HAVE_OPENSSL
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, size_t len, int argi, long argl, int retvalue, size_t *processed)
+#else
 static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int argi, long argl, long retvalue)
+#endif
 {
+	ssize_t bytes = 0;
 	idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b);
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
 	size_t len = (size_t)argi;
+	size_t *processed = (size_t*)&bytes;
+#endif
 	switch (oper) {
 	case (BIO_CB_READ|BIO_CB_RETURN):
-		return argp ? (long)internal_ssl_read(conn, (char *)argp, len) : 0;
+		if (argp) {
+			bytes = internal_ssl_read(conn, (char *)argp, len);
+			*processed = bytes;
+			return (long)bytes;
+		}
+		return 0;
 	case (BIO_CB_PUTS|BIO_CB_RETURN):
 		len = strlen(argp);
 		// fallthrough
 	case (BIO_CB_WRITE|BIO_CB_RETURN):
-		return (long)internal_ssl_write(conn, argp, len);
+		bytes = internal_ssl_write(conn, argp, len);
+		*processed = bytes;
+		return (long)bytes;
 	default:
 		return retvalue;
 	}
@@ -1079,7 +1094,11 @@
 	BIO *b = BIO_new(BIO_s_null());
 	if (!b) return NULL;
 	BIO_set_callback_arg(b, (char *)conn);
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	BIO_set_callback_ex(b, ssl_idevice_bio_callback);
+#else
 	BIO_set_callback(b, ssl_idevice_bio_callback);
+#endif
 	return b;
 }
 
@@ -1257,6 +1276,16 @@
 	X509_free(rootCert);
 	free(root_cert.data);
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_PKEY* rootPrivKey = NULL;
+	membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
+	PEM_read_bio_PrivateKey(membp, &rootPrivKey, NULL, NULL);
+	BIO_free(membp);
+	if (SSL_CTX_use_PrivateKey(ssl_ctx, rootPrivKey) != 1) {
+		debug_info("WARNING: Could not load RootPrivateKey");
+	}
+	EVP_PKEY_free(rootPrivKey);
+#else
 	RSA* rootPrivKey = NULL;
 	membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
 	PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL);
@@ -1265,6 +1294,7 @@
 		debug_info("WARNING: Could not load RootPrivateKey");
 	}
 	RSA_free(rootPrivKey);
+#endif
 	free(root_privkey.data);
 
 	SSL *ssl = SSL_new(ssl_ctx);
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index 1684666..5694c12 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -34,6 +34,9 @@
 #include <getopt.h>
 #if defined(HAVE_OPENSSL)
 #include <openssl/sha.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/evp.h>
+#endif
 #elif defined(HAVE_GNUTLS)
 #include <gcrypt.h>
 #elif defined(HAVE_MBEDTLS)
@@ -113,7 +116,11 @@
 static void _sha1_update(void* context, const char* data, size_t len)
 {
 #if defined(HAVE_OPENSSL)
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_DigestUpdate(context, data, len);
+#else
 	SHA1_Update(context, data, len);
+#endif
 #elif defined(HAVE_GNUTLS)
 	gcry_md_write(context, data, len);
 #elif defined(HAVE_MBEDTLS)
@@ -124,9 +131,15 @@
 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)
 {
 #if defined(HAVE_OPENSSL)
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_MD_CTX* sha1 = EVP_MD_CTX_new();
+	EVP_DigestInit(sha1, EVP_sha1());
+	void* psha1 = sha1;
+#else
 	SHA_CTX sha1;
 	SHA1_Init(&sha1);
 	void* psha1 = &sha1;
+#endif
 #elif defined(HAVE_GNUTLS)
 	gcry_md_hd_t hd = NULL;
 	gcry_md_open(&hd, GCRY_MD_SHA1, 0);
@@ -180,7 +193,12 @@
 			_sha1_update(psha1, "(null)", 6);
 		}
 #if defined(HAVE_OPENSSL)
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+		EVP_DigestFinal(sha1, hash_out, NULL);
+		EVP_MD_CTX_destroy(sha1);
+#else
 		SHA1_Final(hash_out, &sha1);
+#endif
 #elif defined(HAVE_GNUTLS)
 		unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1);
 		memcpy(hash_out, newhash, 20);