Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,46 @@ exclude = [
"rustfmt.toml",
]

#[features]
#not-embedded = ["ed25519-dalek", "get_if_addrs", "hyper"]

[dependencies]
aead = "0.4"
aead = "0.5"
async-trait = "0.1"
byteorder = "1.3"
bytes = "1.0"
chacha20poly1305 = "0.8"
ed25519-dalek = { version = "1.0", features = ["std", "serde"] }
chacha20poly1305 = "0.10.1"
erased-serde = "0.3"
macaddr = { version = "1.0.1", features = ["serde"] }
futures = "0.3"
get_if_addrs = "0.5"
hkdf = "0.11"
hyper = { version = "0.14", features = ["server", "http1"] }
libmdns = "0.6"
log = "0.4"
num = "0.2"
rand = "0.7"
serde = { version = "1.0", features = ["rc", "derive"] }
serde_json = "1.0"
sha2 = "0.9"
signature = "1.1"
signature = "2.1.0"
srp = "0.5"
thiserror = "1.0"
tokio = "1.8"
tokio = { version = "1.28.1", features = ["rt"] }
url = "2.1"
uuid = { version = "0.8", features = ["v4", "serde"] }
x25519-dalek = "0.6"
uuid = { version = "1.3", features = ["serde", "v4"] }
rand = "0.8.5"

ed25519-dalek = { version = "2.0.0-rc.2", features = ["serde", "std"] }
x25519-dalek = "2.0.0-rc.2"

hyper = { version = "0.14", features = ["server", "http1"] }
get_if_addrs = { version = "0.5", optional = true }
libmdns = { version = "0.6", optional = true }

cfg-if = "0.1"

[build-dependencies]
handlebars = "2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "0.8", features = ["v4", "serde"] }
uuid = { version = "1.3", features = ["v4", "serde"] }

[dev-dependencies]
env_logger = "0.8"
Expand Down
9 changes: 6 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ed25519_dalek::Keypair as Ed25519Keypair;
//use eui48::MacAddress;
use crate::Ed25519Keypair;
use macaddr::MacAddr6 as MacAddress;

use rand::{rngs::OsRng, Rng};
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
Expand Down Expand Up @@ -120,15 +120,18 @@ fn generate_random_mac_address() -> MacAddress {
/// Generates an Ed25519 keypair.
fn generate_ed25519_keypair() -> Ed25519Keypair {
let mut csprng = OsRng {};
Ed25519Keypair::generate(&mut csprng)
todo!()
//Ed25519Keypair::generate(&mut csprng)
}

/// Returns the IP of the system's first non-loopback network interface or defaults to `127.0.0.1`.
fn get_local_ip() -> IpAddr {
#[cfg(get_if_addrs)]
for iface in get_if_addrs::get_if_addrs().unwrap() {
if !iface.is_loopback() {
return iface.ip();
}
}
#[cfg(not(get_if_addrs))]
"127.0.0.1".parse().unwrap()
}
10 changes: 6 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ pub enum Error {
Hyper(#[from] hyper::Error),
#[error("Task Join Error: {0}")]
TaskJoin(#[from] tokio::task::JoinError),
#[error("AEAD Error")]
Aead,

#[error("Chacha Error")]
Chacha,

#[error("HKDF Invalid Length Error")]
HkdfInvalidLength,
#[error("UTF-8 Error: {0}")]
Expand All @@ -63,6 +65,6 @@ pub enum Error {
MpscSend(#[from] mpsc::SendError<()>),
}

impl From<aead::Error> for Error {
fn from(_: aead::Error) -> Self { Error::Aead }
impl From<chacha20poly1305::Error> for Error {
fn from(_: chacha20poly1305::Error) -> Self { Error::Chacha }
}
2 changes: 1 addition & 1 deletion src/hap_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ impl ToString for HapType {
fn to_string(&self) -> String {
match self {
HapType::Unknown => "unknown".into(),
HapType::Custom(uuid) => uuid.to_hyphenated().to_string(),
HapType::Custom(uuid) => uuid.hyphenated().to_string(),
HapType::AccessCodeControlPoint => "262".into(),
HapType::AccessCodeSupportedConfiguration => "261".into(),
HapType::AccessControlLevel => "E5".into(),
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use ed25519_dalek::Keypair as Ed25519Keypair;
pub use ed25519_dalek::SigningKey as Ed25519Keypair;
pub use futures;
pub use macaddr::MacAddr6 as MacAddress;
pub use serde_json;
Expand Down
4 changes: 2 additions & 2 deletions src/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ impl From<SrpAuthError> for Error {
}
}

impl From<aead::Error> for Error {
fn from(err: aead::Error) -> Self {
impl From<chacha20poly1305::Error> for Error {
fn from(err: chacha20poly1305::Error) -> Self {
error!("{:?}", err);
Error::Authentication
}
Expand Down
39 changes: 29 additions & 10 deletions src/transport/http/handler/pair_setup.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
use aead::{generic_array::GenericArray, AeadInPlace, NewAead};
use chacha20poly1305::ChaCha20Poly1305;
use aead::{generic_array::GenericArray};
use chacha20poly1305::{
ChaCha20Poly1305,
KeyInit,
AeadInPlace,
};
use futures::future::{BoxFuture, FutureExt};
use hyper::{body::Buf, Body};
use log::{debug, info};
use num::BigUint;

use hyper::{body::Buf, Body};
use rand::{rngs::OsRng, RngCore};

use sha2::{digest::Digest, Sha512};
use signature::{Signer, Verifier};
use ed25519_dalek::{Signer, Verifier};
use srp::{
client::{srp_private_key, SrpClient},
groups::G_3072,
Expand Down Expand Up @@ -276,12 +282,25 @@ async fn handle_exchange(

let sub_tlv = tlv::decode(&decrypted_data);
let device_pairing_id = sub_tlv.get(&(Type::Identifier as u8)).ok_or(tlv::Error::Unknown)?;
let device_ltpk = ed25519_dalek::PublicKey::from_bytes(
sub_tlv.get(&(Type::PublicKey as u8)).ok_or(tlv::Error::Unknown)?,

let device_ltpk = ed25519_dalek::VerifyingKey::from_bytes(
&TryInto::<[u8; 32]>::try_into(
sub_tlv.get(&(Type::PublicKey as u8)).ok_or(tlv::Error::Unknown)?.clone(),
).map_err(|_| tlv::Error::Unknown)?
)?;
/*
let device_ltpk = x25519_dalek::PublicKey::from(
TryInto::<[u8; 32]>::try_into(
sub_tlv.get(&(Type::PublicKey as u8)).ok_or(tlv::Error::Unknown)?.clone(),
).map_err(|_| tlv::Error::Unknown)?
);
*/

let device_signature = ed25519_dalek::Signature::from_bytes(
sub_tlv.get(&(Type::Signature as u8)).ok_or(tlv::Error::Unknown)?,
)?;
&TryInto::<[u8; 64]>::try_into(
sub_tlv.get(&(Type::Signature as u8)).ok_or(tlv::Error::Unknown)?.clone()
).map_err(|_| tlv::Error::Unknown)?
);

let device_x = hkdf_extract_and_expand(
b"Pair-Setup-Controller-Sign-Salt",
Expand Down Expand Up @@ -326,12 +345,12 @@ async fn handle_exchange(
let mut accessory_info: Vec<u8> = Vec::new();
accessory_info.extend(&accessory_x);
accessory_info.extend(device_id.as_bytes());
accessory_info.extend(config.device_ed25519_keypair.public.as_bytes());
accessory_info.extend(config.device_ed25519_keypair.verifying_key().as_bytes());
let accessory_signature = config.device_ed25519_keypair.sign(&accessory_info);

let encoded_sub_tlv = vec![
Value::Identifier(device_id),
Value::PublicKey(config.device_ed25519_keypair.public.as_bytes().to_vec()),
Value::PublicKey(config.device_ed25519_keypair.verifying_key().as_bytes().to_vec()),
Value::Signature(accessory_signature.to_bytes().to_vec()),
]
.encode();
Expand Down
13 changes: 8 additions & 5 deletions src/transport/http/handler/pair_verify.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use aead::{generic_array::GenericArray, AeadInPlace, NewAead};
use chacha20poly1305::ChaCha20Poly1305;
use aead::generic_array::GenericArray;
use chacha20poly1305::{ChaCha20Poly1305, KeyInit, AeadInPlace};
use futures::{
channel::oneshot,
future::{BoxFuture, FutureExt},
Expand All @@ -11,6 +11,7 @@ use signature::{Signer, Verifier};
use std::str;
use uuid::Uuid;
use x25519_dalek::{EphemeralSecret, PublicKey};
use ed25519_dalek::VerifyingKey;

use crate::{
pointer,
Expand Down Expand Up @@ -217,8 +218,10 @@ async fn handle_finish(
let device_pairing_id = sub_tlv.get(&(Type::Identifier as u8)).ok_or(tlv::Error::Unknown)?;
debug!("raw device pairing ID: {:?}", &device_pairing_id);
let device_signature = ed25519_dalek::Signature::from_bytes(
sub_tlv.get(&(Type::Signature as u8)).ok_or(tlv::Error::Unknown)?,
)?;
&TryInto::<[u8; 64]>::try_into(
sub_tlv.get(&(Type::Signature as u8)).ok_or(tlv::Error::Unknown)?.clone()
).map_err(|_| tlv::Error::Unknown)?
);
debug!("device signature: {:?}", &device_signature);

let uuid_str = str::from_utf8(device_pairing_id)?;
Expand All @@ -232,7 +235,7 @@ async fn handle_finish(
device_info.extend(device_pairing_id);
device_info.extend(session.b_pub.as_bytes());

if ed25519_dalek::PublicKey::from_bytes(&pairing.public_key)?
if VerifyingKey::from_bytes(&pairing.public_key)?
.verify(&device_info, &device_signature)
.is_err()
{
Expand Down
6 changes: 3 additions & 3 deletions src/transport/http/handler/pairings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ async fn handle_add(
let mut s = storage.lock().await;
match s.load_pairing(&pairing_uuid).await {
Ok(mut pairing) => {
if ed25519_dalek::PublicKey::from_bytes(&pairing.public_key)?
!= ed25519_dalek::PublicKey::from_bytes(&ltpk)?
if x25519_dalek::PublicKey::from(pairing.public_key)
!= x25519_dalek::PublicKey::from(TryInto::<[u8; 32]>::try_into(ltpk).map_err(|_| tlv::Error::Unknown)?)
{
return Err(tlv::Error::Unknown);
}
Expand Down Expand Up @@ -240,7 +240,7 @@ async fn handle_list(
let pairings = storage.lock().await.list_pairings().await?;
let mut list = vec![Value::State(StepNumber::Res as u8)];
for (i, pairing) in pairings.iter().enumerate() {
list.push(Value::Identifier(pairing.id.to_hyphenated().to_string()));
list.push(Value::Identifier(pairing.id.hyphenated().to_string()));
list.push(Value::PublicKey(pairing.public_key.to_vec()));
list.push(Value::Permissions(pairing.permissions.clone()));
if i < pairings.len() {
Expand Down
8 changes: 4 additions & 4 deletions src/transport/http/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{
sync::Arc,
task::{Context, Poll},
};
use tokio::net::TcpListener;
use std::net::TcpListener;

use crate::{
event::Event,
Expand Down Expand Up @@ -186,12 +186,12 @@ impl Server {
drop(config_lock);

info!("binding TCP listener on {}", &socket_addr);
let listener = TcpListener::bind(socket_addr).await?;
let listener = TcpListener::bind(socket_addr)?;

mdns_responder.lock().await.update_records().await;

loop {
let (stream, _socket_addr) = listener.accept().await?;
let (stream, _socket_addr) = listener.accept()?;

debug!("incoming TCP stream from {}", stream.peer_addr()?);

Expand Down Expand Up @@ -255,7 +255,7 @@ impl Server {
http.http1_keep_alive(true);
http.http1_preserve_header_case(true);

tokio::spawn(encrypted_stream.map_err(|e| error!("{:?}", e)).map(|_| ()));
//tokio::spawn(encrypted_stream.map_err(|e| error!("{:?}", e)).map(|_| ()));
tokio::spawn(
http.serve_connection(stream_wrapper, api)
.map_err(|e| error!("{:?}", e))
Expand Down
32 changes: 29 additions & 3 deletions src/transport/mdns.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
use libmdns::{Responder, Service};

cfg_if::cfg_if! {
if #[cfg(libmdns)] {
use libmdns::{Responder, Service};
} else {
type Responder = ();
type Service= ();
}
}

use log::debug;

use crate::pointer;
Expand All @@ -14,7 +23,14 @@ pub struct MdnsResponder {
impl MdnsResponder {
/// Creates a new mDNS Responder.
pub async fn new(config: pointer::Config) -> Self {
let (responder, task) = libmdns::Responder::with_default_handle().expect("creating mDNS responder");
cfg_if::cfg_if! {
if #[cfg(libmdns)] {
let (responder, task) = libmdns::Responder::with_default_handle().expect("creating mDNS responder");
} else {
let (responder, task) = todo!();
}
}


MdnsResponder {
config,
Expand All @@ -38,9 +54,12 @@ impl MdnsResponder {

drop(c);

todo!();
/*
self.service = Some(self.responder.register("_hap._tcp".into(), name, port, &[
&tr[0], &tr[1], &tr[2], &tr[3], &tr[4], &tr[5], &tr[6], &tr[7],
]));
*/

debug!("setting mDNS records: {:?}", &tr);
}
Expand All @@ -51,7 +70,14 @@ impl MdnsResponder {
Some(task) => task,
// if the task handle is gone, recreate the whole responder
None => {
let (responder, task) = libmdns::Responder::with_default_handle().expect("creating mDNS responder");
cfg_if::cfg_if! {
if #[cfg(libmdns)] {
let (responder, task) = libmdns::Responder::with_default_handle().expect("creating mDNS responder");

} else {
let (responder, task) = todo!();
}
}
self.responder = responder;

task
Expand Down
Loading