mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 14:36:16 +01:00
Add OpenSSL dependency
This commit is contained in:
@@ -12,16 +12,18 @@ keywords = ["lockdownd", "ios"]
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["io-util"] }
|
||||
tokio-rustls = { version = "0.26", default-features = false }
|
||||
tokio-rustls = { version = "0.26", default-features = false, optional = true }
|
||||
rustls = { version = "0.23", default-features = false, features = [
|
||||
"std",
|
||||
"tls12",
|
||||
] }
|
||||
crossfire = { version = "2.1", optional = true }
|
||||
], optional = true }
|
||||
tokio-openssl = { version = "0.6", optional = true }
|
||||
openssl = { version = "0.10", optional = true }
|
||||
|
||||
plist = { version = "1.8" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
ns-keyed-archive = { version = "0.1.4", optional = true }
|
||||
crossfire = { version = "2.1", optional = true }
|
||||
|
||||
thiserror = { version = "2" }
|
||||
tracing = { version = "0.1.41" }
|
||||
@@ -64,8 +66,10 @@ bytes = "1.10.1"
|
||||
|
||||
[features]
|
||||
default = ["aws-lc"]
|
||||
aws-lc = ["rustls/aws-lc-rs", "tokio-rustls/aws-lc-rs"]
|
||||
ring = ["rustls/ring", "tokio-rustls/ring"]
|
||||
aws-lc = ["rustls", "rustls/aws-lc-rs", "tokio-rustls/aws-lc-rs"]
|
||||
ring = ["rustls", "rustls/ring", "tokio-rustls/ring"]
|
||||
rustls = ["dep:rustls", "dep:tokio-rustls"]
|
||||
openssl = ["dep:openssl", "dep:tokio-openssl"]
|
||||
|
||||
afc = ["dep:chrono"]
|
||||
amfi = []
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
// Jackson Coxson
|
||||
|
||||
#[cfg(feature = "pair")]
|
||||
#[cfg(all(feature = "pair", feature = "rustls"))]
|
||||
mod ca;
|
||||
pub mod pairing_file;
|
||||
pub mod plist_macro;
|
||||
pub mod provider;
|
||||
#[cfg(feature = "rustls")]
|
||||
mod sni;
|
||||
#[cfg(feature = "tunnel_tcp_stack")]
|
||||
pub mod tcp;
|
||||
@@ -27,6 +28,7 @@ pub use services::*;
|
||||
pub use xpc::RemoteXpcClient;
|
||||
|
||||
use provider::{IdeviceProvider, RsdProvider};
|
||||
#[cfg(feature = "rustls")]
|
||||
use rustls::{crypto::CryptoProvider, pki_types::ServerName};
|
||||
use std::{
|
||||
io::{self, BufWriter},
|
||||
@@ -460,57 +462,84 @@ impl Idevice {
|
||||
&mut self,
|
||||
pairing_file: &pairing_file::PairingFile,
|
||||
) -> Result<(), IdeviceError> {
|
||||
if CryptoProvider::get_default().is_none() {
|
||||
// rust-analyzer will choke on this block, don't worry about it
|
||||
let crypto_provider: CryptoProvider = {
|
||||
#[cfg(all(feature = "ring", not(feature = "aws-lc")))]
|
||||
{
|
||||
debug!("Using ring crypto backend");
|
||||
rustls::crypto::ring::default_provider()
|
||||
#[cfg(feature = "rustls")]
|
||||
{
|
||||
if CryptoProvider::get_default().is_none() {
|
||||
// rust-analyzer will choke on this block, don't worry about it
|
||||
let crypto_provider: CryptoProvider = {
|
||||
#[cfg(all(feature = "ring", not(feature = "aws-lc")))]
|
||||
{
|
||||
debug!("Using ring crypto backend");
|
||||
rustls::crypto::ring::default_provider()
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "aws-lc", not(feature = "ring")))]
|
||||
{
|
||||
debug!("Using aws-lc crypto backend");
|
||||
rustls::crypto::aws_lc_rs::default_provider()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "ring", feature = "aws-lc")))]
|
||||
{
|
||||
compile_error!(
|
||||
"No crypto backend was selected! Specify an idevice feature for a crypto backend"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ring", feature = "aws-lc"))]
|
||||
{
|
||||
// We can't throw a compile error because it breaks rust-analyzer.
|
||||
// My sanity while debugging the workspace crates are more important.
|
||||
|
||||
debug!("Using ring crypto backend, because both were passed");
|
||||
tracing::warn!(
|
||||
"Both ring && aws-lc are selected as idevice crypto backends!"
|
||||
);
|
||||
rustls::crypto::ring::default_provider()
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = CryptoProvider::install_default(crypto_provider) {
|
||||
// For whatever reason, getting the default provider will return None on iOS at
|
||||
// random. Installing the default provider a second time will return an error, so
|
||||
// we will log it but not propogate it. An issue should be opened with rustls.
|
||||
tracing::error!("Failed to set crypto provider: {e:?}");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "aws-lc", not(feature = "ring")))]
|
||||
{
|
||||
debug!("Using aws-lc crypto backend");
|
||||
rustls::crypto::aws_lc_rs::default_provider()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "ring", feature = "aws-lc")))]
|
||||
{
|
||||
compile_error!(
|
||||
"No crypto backend was selected! Specify an idevice feature for a crypto backend"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ring", feature = "aws-lc"))]
|
||||
{
|
||||
// We can't throw a compile error because it breaks rust-analyzer.
|
||||
// My sanity while debugging the workspace crates are more important.
|
||||
|
||||
debug!("Using ring crypto backend, because both were passed");
|
||||
tracing::warn!("Both ring && aws-lc are selected as idevice crypto backends!");
|
||||
rustls::crypto::ring::default_provider()
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = CryptoProvider::install_default(crypto_provider) {
|
||||
// For whatever reason, getting the default provider will return None on iOS at
|
||||
// random. Installing the default provider a second time will return an error, so
|
||||
// we will log it but not propogate it. An issue should be opened with rustls.
|
||||
tracing::error!("Failed to set crypto provider: {e:?}");
|
||||
}
|
||||
let config = sni::create_client_config(pairing_file)?;
|
||||
let connector = tokio_rustls::TlsConnector::from(Arc::new(config));
|
||||
|
||||
let socket = self.socket.take().unwrap();
|
||||
let socket = connector
|
||||
.connect(ServerName::try_from("Device").unwrap(), socket)
|
||||
.await?;
|
||||
|
||||
self.socket = Some(Box::new(socket));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
let config = sni::create_client_config(pairing_file)?;
|
||||
let connector = tokio_rustls::TlsConnector::from(Arc::new(config));
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
{
|
||||
let connector =
|
||||
openssl::ssl::SslConnector::builder(openssl::ssl::SslMethod::tls()).unwrap();
|
||||
|
||||
let socket = self.socket.take().unwrap();
|
||||
let socket = connector
|
||||
.connect(ServerName::try_from("Device").unwrap(), socket)
|
||||
.await?;
|
||||
let mut connector = connector
|
||||
.build()
|
||||
.configure()
|
||||
.unwrap()
|
||||
.into_ssl("ur mom")
|
||||
.unwrap();
|
||||
|
||||
self.socket = Some(Box::new(socket));
|
||||
connector.set_certificate(&pairing_file.host_certificate)?;
|
||||
connector.set_private_key(&pairing_file.host_private_key)?;
|
||||
connector.set_verify(openssl::ssl::SslVerifyMode::empty());
|
||||
let socket = self.socket.take().unwrap();
|
||||
let mut ssl_stream = tokio_openssl::SslStream::new(connector, socket)?;
|
||||
std::pin::Pin::new(&mut ssl_stream).connect().await?;
|
||||
self.socket = Some(Box::new(ssl_stream));
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,12 +550,24 @@ impl Idevice {
|
||||
pub enum IdeviceError {
|
||||
#[error("device socket io failed")]
|
||||
Socket(#[from] io::Error) = -1,
|
||||
#[cfg(all(feature = "rustls", not(feature = "openssl")))]
|
||||
#[error("PEM parse failed")]
|
||||
PemParseFailed(#[from] rustls::pki_types::pem::Error) = -2,
|
||||
|
||||
#[cfg(all(feature = "rustls", not(feature = "openssl")))]
|
||||
#[error("TLS error")]
|
||||
Rustls(#[from] rustls::Error) = -3,
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
#[error("TLS error")]
|
||||
Rustls(#[from] openssl::ssl::Error) = -3,
|
||||
|
||||
#[cfg(all(feature = "rustls", not(feature = "openssl")))]
|
||||
#[error("TLS verifiction build failed")]
|
||||
TlsBuilderFailed(#[from] rustls::server::VerifierBuilderError) = -4,
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
#[error("TLS verifiction build failed")]
|
||||
TlsBuilderFailed(#[from] openssl::error::ErrorStack) = -4,
|
||||
|
||||
#[error("io on plist")]
|
||||
Plist(#[from] plist::Error) = -5,
|
||||
#[error("can't convert bytes to utf8")]
|
||||
|
||||
@@ -5,7 +5,13 @@
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
use openssl::{
|
||||
pkey::{PKey, Private},
|
||||
x509::X509,
|
||||
};
|
||||
use plist::Data;
|
||||
#[cfg(feature = "rustls")]
|
||||
use rustls::pki_types::{CertificateDer, pem::PemObject};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::warn;
|
||||
@@ -14,6 +20,7 @@ use tracing::warn;
|
||||
///
|
||||
/// Contains all cryptographic materials and identifiers needed for secure communication
|
||||
/// with an iOS device, including certificates, private keys, and device identifiers.
|
||||
#[cfg(feature = "rustls")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PairingFile {
|
||||
/// Device's certificate in DER format
|
||||
@@ -38,6 +45,21 @@ pub struct PairingFile {
|
||||
pub udid: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PairingFile {
|
||||
pub device_certificate: X509,
|
||||
pub host_private_key: PKey<Private>,
|
||||
pub host_certificate: X509,
|
||||
pub root_private_key: PKey<Private>,
|
||||
pub root_certificate: X509,
|
||||
pub system_buid: String,
|
||||
pub host_id: String,
|
||||
pub escrow_bag: Vec<u8>,
|
||||
pub wifi_mac_address: String,
|
||||
pub udid: Option<String>,
|
||||
}
|
||||
|
||||
/// Internal representation of a pairing file for serialization/deserialization
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
@@ -133,6 +155,7 @@ impl PairingFile {
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `IdeviceError` if serialization fails
|
||||
#[cfg(feature = "rustls")]
|
||||
pub fn serialize(self) -> Result<Vec<u8>, crate::IdeviceError> {
|
||||
let raw = RawPairingFile::from(self);
|
||||
|
||||
@@ -140,8 +163,18 @@ impl PairingFile {
|
||||
plist::to_writer_xml(&mut buf, &raw)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
pub fn serialize(self) -> Result<Vec<u8>, crate::IdeviceError> {
|
||||
let raw = RawPairingFile::try_from(self)?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
plist::to_writer_xml(&mut buf, &raw)?;
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
impl TryFrom<RawPairingFile> for PairingFile {
|
||||
type Error = rustls::pki_types::pem::Error;
|
||||
|
||||
@@ -180,6 +213,30 @@ impl TryFrom<RawPairingFile> for PairingFile {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "openssl", not(feature = "rustls")))]
|
||||
impl TryFrom<RawPairingFile> for PairingFile {
|
||||
type Error = openssl::error::ErrorStack;
|
||||
|
||||
fn try_from(value: RawPairingFile) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
device_certificate: X509::from_pem(&Into::<Vec<u8>>::into(value.device_certificate))?,
|
||||
host_private_key: PKey::private_key_from_pem(&Into::<Vec<u8>>::into(
|
||||
value.host_private_key,
|
||||
))?,
|
||||
host_certificate: X509::from_pem(&Into::<Vec<u8>>::into(value.host_certificate))?,
|
||||
root_private_key: PKey::private_key_from_pem(&Into::<Vec<u8>>::into(
|
||||
value.root_private_key,
|
||||
))?,
|
||||
root_certificate: X509::from_pem(&Into::<Vec<u8>>::into(value.root_certificate))?,
|
||||
system_buid: value.system_buid,
|
||||
host_id: value.host_id,
|
||||
escrow_bag: value.escrow_bag.into(),
|
||||
wifi_mac_address: value.wifi_mac_address,
|
||||
udid: value.udid,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PairingFile> for RawPairingFile {
|
||||
/// Converts a structured pairing file into a raw pairing file for serialization
|
||||
fn from(value: PairingFile) -> Self {
|
||||
|
||||
@@ -243,7 +243,7 @@ impl LockdownClient {
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `IdeviceError`
|
||||
#[cfg(feature = "pair")]
|
||||
#[cfg(all(feature = "pair", feature = "rustls"))]
|
||||
pub async fn pair(
|
||||
&mut self,
|
||||
host_id: impl Into<String>,
|
||||
|
||||
Reference in New Issue
Block a user