Skip to content

Commit

Permalink
Merge pull request #30 from bjoernQ/experiment/security-manager
Browse files Browse the repository at this point in the history
Secure Simple Pairing (Numeric Comparison)
  • Loading branch information
bjoernQ authored Dec 14, 2023
2 parents 0406a5f + 2868181 commit 9ea965a
Show file tree
Hide file tree
Showing 15 changed files with 1,769 additions and 43 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ This is a BLE peripheral stack in Rust. (no-std / no-alloc)

To use it you need an implementation of embedded-io offering communication with HCI.

This is early POC / WIP! You are warned!

The goal is just to have _something_ that works for testing and demos.
I have no plan to add advanced features like pairing and bonding (while it should be possible to add that).
The goal is just to have _something_ that works for testing,demos and personal projects - no intentions to make this pass certification tests.

## License

Expand Down
16 changes: 14 additions & 2 deletions bleps-dedup/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use proc_macro::TokenStream;
use proc_macro::{Delimiter, TokenStream};
use proc_macro_error::proc_macro_error;

#[derive(Debug)]
Expand Down Expand Up @@ -40,7 +40,7 @@ pub fn dedup(input: TokenStream) -> TokenStream {
current.extend([tok]);
}
},
proc_macro::TokenTree::Group(_group) => {
proc_macro::TokenTree::Group(group) if group.delimiter() == Delimiter::Brace => {
if !current.is_empty() {
impls.push(Implementation {
is_async: impl_is_async,
Expand Down Expand Up @@ -109,8 +109,16 @@ fn de_async(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
}
proc_macro2::TokenTree::Punct(p) => {
if p.as_char() == '.' {
if let Some(prev) = prev.clone() {
output.extend([prev]);
}
prev = Some(tok);
} else {
if let Some(prev) = prev.clone() {
output.extend([prev]);
}
prev = None;

output.extend([tok]);
}
}
Expand All @@ -135,5 +143,9 @@ fn de_async(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
}
}

if let Some(prev) = prev.clone() {
output.extend([prev]);
}

output
}
8 changes: 8 additions & 0 deletions bleps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,25 @@ bleps-dedup = { path = "../bleps-dedup" }
log = "0.4.16"
embedded-io-blocking = { package = "embedded-io", version = "0.6.1" }
embedded-io-async = { version = "0.6.0", optional = true }
bitfield = "0.14.0"
futures = { version = "0.3", default-features = false, optional = true }
critical-section = { version = "1.0.1", optional = true }
defmt = {version = "0.3", optional = true }
bleps-macros = { path = "../bleps-macros", optional = true }
rand_core = "0.6.4"

p256 = { version = "0.13.2", default-features = false, features = ["ecdh","arithmetic"], optional = true }
aes = { version = "0.8.2", optional = true }
cmac = { version = "0.7.2", optional = true }

[dev-dependencies]
env_logger = "0.10.0"
p256 = { version = "0.13.2", default-features = true }

[features]
async = [ "dep:embedded-io-async", "dep:futures", "dep:critical-section", "bleps-dedup/generate-async" ]
macros = [ "bleps-macros" ]
crypto = [ "dep:p256", "dep:aes", "dep:cmac" ]
defmt = [ "dep:defmt" ]
mtu128 = []
mtu256 = []
7 changes: 7 additions & 0 deletions bleps/src/acl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ impl AclPacket {
pub fn read(connector: &dyn HciConnection) -> Self {
let raw_handle_buffer = [connector.read().unwrap(), connector.read().unwrap()];
let (pb, bc, handle) = Self::decode_raw_handle(raw_handle_buffer);
log::debug!(
"raw handle {:08b} {:08b} - boundary {:?}",
raw_handle_buffer[0],
raw_handle_buffer[1],
pb
);

let len = u16::from_le_bytes([connector.read().unwrap(), connector.read().unwrap()]);
log::info!("read len {}", len);
let data = Data::read(connector, len as usize);

Self {
Expand Down
79 changes: 73 additions & 6 deletions bleps/src/async_attribute_server.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,72 @@
#[cfg(not(feature = "crypto"))]
use core::marker::PhantomData;

use core::cell::RefCell;

use critical_section::Mutex;
use futures::future::Either;
use futures::pin_mut;
use rand_core::{CryptoRng, RngCore};

#[cfg(feature = "crypto")]
use crate::sm::AsyncSecurityManager;

use crate::{
asynch::Ble,
att::Uuid,
attribute::Attribute,
attribute_server::{AttributeServerError, NotificationData, WorkResult},
Addr,
};

pub struct AttributeServer<'a, T>
pub struct AttributeServer<'a, T, R: CryptoRng + RngCore>
where
T: embedded_io_async::Read + embedded_io_async::Write,
{
pub(crate) ble: &'a mut Ble<T>,
pub(crate) src_handle: u16,
pub(crate) mtu: u16,
pub(crate) attributes: &'a mut [Attribute<'a>],

#[cfg(feature = "crypto")]
pub(crate) security_manager: AsyncSecurityManager<'a, Ble<T>, R>,

#[cfg(feature = "crypto")]
pub(crate) pin_callback: Option<&'a mut dyn FnMut(u32)>,

#[cfg(not(feature = "crypto"))]
phantom: PhantomData<R>,
}

impl<'a, T> AttributeServer<'a, T>
impl<'a, T, R: CryptoRng + RngCore> AttributeServer<'a, T, R>
where
T: embedded_io_async::Read + embedded_io_async::Write,
{
pub fn new(ble: &'a mut Ble<T>, attributes: &'a mut [Attribute<'a>]) -> AttributeServer<'a, T> {
/// Create a new instance of the AttributeServer
///
/// When _NOT_ using the `crypto` feature you can pass a mutual reference to `bleps::no_rng::NoRng`
pub fn new(
ble: &'a mut Ble<T>,
attributes: &'a mut [Attribute<'a>],
rng: &'a mut R,
) -> AttributeServer<'a, T, R> {
AttributeServer::new_with_ltk(
ble,
attributes,
Addr::from_le_bytes(false, [0u8; 6]),
None,
rng,
)
}

/// Create a new instance, optionally provide an LTK
pub fn new_with_ltk(
ble: &'a mut Ble<T>,
attributes: &'a mut [Attribute<'a>],
_local_addr: Addr,
_ltk: Option<u128>,
_rng: &'a mut R,
) -> AttributeServer<'a, T, R> {
for (i, attr) in attributes.iter_mut().enumerate() {
attr.handle = i as u16 + 1;
}
Expand All @@ -41,19 +82,45 @@ where

log::trace!("{:#x?}", &attributes);

#[cfg(feature = "crypto")]
let mut security_manager = AsyncSecurityManager::new(_rng);
#[cfg(feature = "crypto")]
{
security_manager.local_address = Some(_local_addr);
security_manager.ltk = _ltk;
}

AttributeServer {
ble,
src_handle: 0,
mtu: crate::attribute_server::BASE_MTU,
attributes,

#[cfg(feature = "crypto")]
security_manager,

#[cfg(feature = "crypto")]
pin_callback: None,

#[cfg(not(feature = "crypto"))]
phantom: PhantomData::default(),
}
}

/// Get the current LTK
pub fn get_ltk(&self) -> Option<u128> {
#[cfg(feature = "crypto")]
return self.security_manager.ltk;

#[cfg(not(feature = "crypto"))]
None
}

/// Run the GATT server until disconnect
pub async fn run<F, R>(&mut self, notifier: &'a mut F) -> Result<(), AttributeServerError>
pub async fn run<F, N>(&mut self, notifier: &'a mut F) -> Result<(), AttributeServerError>
where
F: FnMut() -> R,
R: core::future::Future<Output = NotificationData>,
F: FnMut() -> N,
N: core::future::Future<Output = NotificationData>,
{
let notification_to_send = Mutex::new(RefCell::new(None));
loop {
Expand Down
Loading

0 comments on commit 9ea965a

Please sign in to comment.