Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0eb47d9e authored by Charlie Boutier's avatar Charlie Boutier Committed by Automerger Merge Worker
Browse files

Merge changes I70d6272c,I7761a31b am: 23783b7b am: 7834b689 am: 28c26872 am: 1dada0ed

parents 681e8715 1dada0ed
Loading
Loading
Loading
Loading
+71 −2
Original line number Diff line number Diff line
// Bluetooth Core, Vol 2, Part C, 4.2.5

use super::features;
use crate::num_hci_command_packets;
use crate::packets::{hci, lmp};
use crate::procedure::Context;

use hci::LMPFeaturesPage1Bits::SecureConnectionsHostSupport;
use hci::LMPFeaturesPage2Bits::SecureConnectionsControllerSupport;

pub async fn initiate(ctx: &impl Context) {
    // TODO: handle turn off
    let _ = ctx.receive_hci_command::<hci::SetConnectionEncryptionPacket>().await;
@@ -36,11 +40,18 @@ pub async fn initiate(ctx: &impl Context) {
        )
        .await;

    let aes_ccm = features::supported_on_both_page1(ctx, SecureConnectionsHostSupport).await
        && features::supported_on_both_page2(ctx, SecureConnectionsControllerSupport).await;

    ctx.send_hci_event(
        hci::EncryptionChangeBuilder {
            status: hci::ErrorCode::Success,
            connection_handle: ctx.peer_handle(),
            encryption_enabled: hci::EncryptionEnabled::On,
            encryption_enabled: if aes_ccm {
                hci::EncryptionEnabled::BrEdrAesCcm
            } else {
                hci::EncryptionEnabled::On
            },
        }
        .build(),
    );
@@ -72,12 +83,70 @@ pub async fn respond(ctx: &impl Context) {
        .build(),
    );

    let aes_ccm = features::supported_on_both_page1(ctx, SecureConnectionsHostSupport).await
        && features::supported_on_both_page2(ctx, SecureConnectionsControllerSupport).await;

    ctx.send_hci_event(
        hci::EncryptionChangeBuilder {
            status: hci::ErrorCode::Success,
            connection_handle: ctx.peer_handle(),
            encryption_enabled: hci::EncryptionEnabled::On,
            encryption_enabled: if aes_ccm {
                hci::EncryptionEnabled::BrEdrAesCcm
            } else {
                hci::EncryptionEnabled::On
            },
        }
        .build(),
    );
}

#[cfg(test)]
mod tests {
    use super::initiate;
    use super::respond;
    use crate::procedure::Context;
    use crate::test::{sequence, TestContext};

    use crate::packets::hci::LMPFeaturesPage1Bits::SecureConnectionsHostSupport;
    use crate::packets::hci::LMPFeaturesPage2Bits::SecureConnectionsControllerSupport;

    #[test]
    fn accept_encryption() {
        let context = TestContext::new();
        let procedure = respond;

        include!("../../test/ENC/BV-01-C.in");
    }

    #[test]
    fn initiate_encryption() {
        let context = TestContext::new();
        let procedure = initiate;

        include!("../../test/ENC/BV-05-C.in");
    }

    #[test]
    fn accept_aes_ccm_encryption_request() {
        let context = TestContext::new()
            .with_page_1_feature(SecureConnectionsHostSupport)
            .with_page_2_feature(SecureConnectionsControllerSupport)
            .with_peer_page_1_feature(SecureConnectionsHostSupport)
            .with_peer_page_2_feature(SecureConnectionsControllerSupport);
        let procedure = respond;

        include!("../../test/ENC/BV-26-C.in");
    }

    #[test]
    fn initiate_aes_ccm_encryption() {
        let context = TestContext::new()
            .with_page_1_feature(SecureConnectionsHostSupport)
            .with_page_2_feature(SecureConnectionsControllerSupport)
            .with_peer_page_1_feature(SecureConnectionsHostSupport)
            .with_peer_page_2_feature(SecureConnectionsControllerSupport);
        let procedure = initiate;

        include!("../../test/ENC/BV-34-C.in");
    }
}
+20 −9
Original line number Diff line number Diff line
// Bluetooth Core, Vol 2, Part C, 4.3.4

use num_traits::ToPrimitive;

use crate::packets::lmp;
use crate::procedure::Context;

@@ -34,21 +36,30 @@ pub async fn respond(ctx: &impl Context) {
    );
}

pub async fn supported_on_both_page1(
    ctx: &impl Context,
    feature: crate::packets::hci::LMPFeaturesPage1Bits,
) -> bool {
    use num_traits::ToPrimitive;
    let feature_mask = feature.to_u64().unwrap();
    let local_supported = ctx.extended_features(1) & feature_mask != 0;
async fn supported_on_both_page(ctx: &impl Context, page_number: u8, feature_mask: u64) -> bool {
    let local_supported = ctx.extended_features(page_number) & feature_mask != 0;
    // Lazy peer features
    let peer_supported = async move {
        let page = if let Some(page) = ctx.peer_extended_features(1) {
        let page = if let Some(page) = ctx.peer_extended_features(page_number) {
            page
        } else {
            crate::procedure::features::initiate(ctx, 1).await
            crate::procedure::features::initiate(ctx, page_number).await
        };
        page & feature_mask != 0
    };
    local_supported && peer_supported.await
}

pub async fn supported_on_both_page1(
    ctx: &impl Context,
    feature: crate::packets::hci::LMPFeaturesPage1Bits,
) -> bool {
    supported_on_both_page(ctx, 1, feature.to_u64().unwrap()).await
}

pub async fn supported_on_both_page2(
    ctx: &impl Context,
    feature: crate::packets::hci::LMPFeaturesPage2Bits,
) -> bool {
    supported_on_both_page(ctx, 2, feature.to_u64().unwrap()).await
}
+29 −11
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

use num_traits::ToPrimitive;

use crate::ec::PrivateKey;
use crate::packets::{hci, lmp};

@@ -17,11 +19,35 @@ pub struct TestContext {
    pub hci_events: RefCell<VecDeque<hci::EventPacket>>,
    pub hci_commands: RefCell<VecDeque<hci::CommandPacket>>,
    private_key: RefCell<Option<PrivateKey>>,
    features_pages: [u64; 3],
    peer_features_pages: [u64; 3],
}

impl TestContext {
    pub fn new() -> Self {
        Default::default()
        Self::default()
            .with_page_1_feature(hci::LMPFeaturesPage1Bits::SecureSimplePairingHostSupport)
            .with_peer_page_1_feature(hci::LMPFeaturesPage1Bits::SecureSimplePairingHostSupport)
    }

    pub fn with_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self {
        self.features_pages[1] |= feature.to_u64().unwrap();
        self
    }

    pub fn with_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self {
        self.features_pages[2] |= feature.to_u64().unwrap();
        self
    }

    pub fn with_peer_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self {
        self.peer_features_pages[1] |= feature.to_u64().unwrap();
        self
    }

    pub fn with_peer_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self {
        self.peer_features_pages[2] |= feature.to_u64().unwrap();
        self
    }
}

@@ -67,19 +93,11 @@ impl Context for TestContext {
    }

    fn peer_extended_features(&self, features_page: u8) -> Option<u64> {
        if features_page == 1 {
            Some(1)
        } else {
            Some(0)
        }
        Some(self.peer_features_pages[features_page as usize])
    }

    fn extended_features(&self, features_page: u8) -> u64 {
        if features_page == 1 {
            1
        } else {
            0
        }
        self.features_pages[features_page as usize]
    }

    fn get_private_key(&self) -> Option<PrivateKey> {
+32 −0
Original line number Diff line number Diff line
sequence! { procedure, context,
    // ACL Connection Established
    Lower Tester -> IUT: EncryptionModeReq {
        transaction_id: 0,
        encryption_mode: 0x01,
    }
    IUT ->Lower Tester: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::EncryptionModeReq,
    }
    Lower Tester -> IUT: EncryptionKeySizeReq {
        transaction_id: 0,
        key_size: 0x10,
    }
    IUT -> Lower Tester: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::EncryptionKeySizeReq,
    }
    Lower Tester -> IUT: StartEncryptionReq {
        transaction_id: 0,
        random_number: [0; 16],
    }
    IUT -> Lower Tester: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::StartEncryptionReq,
    }
    IUT -> Upper Tester: EncryptionChange {
        status: ErrorCode::Success,
        connection_handle: context.peer_handle(),
        encryption_enabled: EncryptionEnabled::On,
    }
}
+40 −0
Original line number Diff line number Diff line
sequence! { procedure, context,
    // ACL Connection Established
    Upper Tester -> IUT: SetConnectionEncryption {
        connection_handle: context.peer_handle(),
        encryption_enable: Enable::Enabled
    }
    IUT -> Upper Tester: SetConnectionEncryptionStatus {
       num_hci_command_packets: 1,
       status: ErrorCode::Success,
    }
    IUT -> Lower Tester: EncryptionModeReq {
        transaction_id: 0,
        encryption_mode: 0x01,
    }
    Lower Tester -> IUT: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::EncryptionModeReq,
    }
    IUT -> Lower Tester: EncryptionKeySizeReq {
        transaction_id: 0,
        key_size: 0x10,
    }
    Lower Tester -> IUT: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::EncryptionKeySizeReq,
    }
    IUT -> Lower Tester: StartEncryptionReq {
        transaction_id: 0,
        random_number: [0; 16],
    }
    Lower Tester -> IUT: Accepted {
        transaction_id: 0,
        accepted_opcode: Opcode::StartEncryptionReq,
    }
    IUT -> Upper Tester: EncryptionChange {
        status: ErrorCode::Success,
        connection_handle: context.peer_handle(),
        encryption_enabled: EncryptionEnabled::On,
    }
}
Loading