Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS connection with embedded-tls #3916

Open
xFranv8 opened this issue Feb 24, 2025 · 0 comments
Open

TLS connection with embedded-tls #3916

xFranv8 opened this issue Feb 24, 2025 · 0 comments

Comments

@xFranv8
Copy link

xFranv8 commented Feb 24, 2025

Hello,

I’m new to Embassy, and I’m working with a Raspberry Pi Pico W with the RP2040 chip. I’m using embedded-tls to connect to an MQTT broker, but I’m encountering the following error:

error[E0277]: the trait bound `RoscRng: CryptoRng` is not satisfied
   --> src/main.rs:188:5
    |
188 | /     tls_connection
189 | |         .open(TlsContext::new(
190 | |             &tls_config,
191 | |             UnsecureProvider::new::<Aes256GcmSha384>(rng),
192 | |         ))
    | |__________^ the trait `CryptoRng` is not implemented for `RoscRng`
    |
    = help: the following other types implement trait `CryptoRng`:
              &'a mut R
              BlockRng<R>
              SecureRoscRng
    = note: required for `RoscRng` to implement `CryptoRngCore`
    = note: required for `UnsecureProvider<Aes256GcmSha384, RoscRng>` to implement `CryptoProvider`
note: required by a bound in `embedded_tls::TlsConnection::<'a, Socket, CipherSuite>::open`
   --> /Users/xfranv8/.cargo/git/checkouts/embedded-tls-6ca93bdfa1e2460b/7936bc1/src/asynch.rs:78:19
    |
73  |     pub async fn open<'v, Provider>(
    |                  ---- required by a bound in this associated function
...
78  |         Provider: CryptoProvider<CipherSuite = CipherSuite>,
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `TlsConnection::<'a, Socket, CipherSuite>::open`

I’ve implemented the trait in embassy_rp::clocks::RoscRng as follows:

impl rand_core::CryptoRng for RoscRng {}
When I do this, the compile error is gone, but I can’t connect to my Wi-Fi network, as I get stuck waiting for a DHCP IP.

This is my current implementation:

#![no_std]
#![no_main]
#![allow(async_fn_in_trait)]

mod rng;

use cyw43::JoinOptions;
use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER};
use defmt::*;
use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket;
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::peripherals::USB;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::Pio;
use embassy_rp::usb::Driver;
use embassy_time::Timer;
use embedded_tls::{
    Aes128GcmSha256, Aes256GcmSha384, TlsConfig, TlsConnection, TlsContext, UnsecureProvider,
};
use rand::RngCore;
use rng::SecureRoscRng;
use rust_mqtt::{
    client::{
        client::MqttClient,
        client_config::{ClientConfig, MqttVersion},
    },
    packet::v5::publish_packet::QualityOfService::{self},
    utils::rng_generator::CountingRng,
};

use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};

bind_interrupts!(struct Irqs {
    USBCTRL_IRQ => embassy_rp::usb::InterruptHandler<USB>;
    PIO0_IRQ_0 => embassy_rp::pio::InterruptHandler<PIO0>;
});

const WIFI_NETWORK: &str = "DULCE HOGAR"; // change to your network SSID
const WIFI_PASSWORD: &str = "1492larrybirdverde33"; // change to your network password

#[embassy_executor::task]
async fn logger_task(driver: Driver<'static, USB>) -> ! {
    embassy_usb_logger::run!(2048, log::LevelFilter::Info, driver);
}

#[embassy_executor::task]
async fn cyw43_task(
    runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
    runner.run().await
}

#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
    runner.run().await
}

async fn connect_to_wifi<'a>(
    control: &'a mut cyw43::Control<'a>,
    stack: embassy_net::Stack<'a>,
) -> embassy_net::Stack<'a> {
    log::info!("connecting to wifi...");
    loop {
        match control
            .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
            .await
        {
            Ok(_) => break,
            Err(err) => {
                log::info!("join failed with status={}", err.status);
            }
        }
    }

    // Wait for DHCP, not necessary when using static IP
    log::info!("waiting for DHCP...");
    while !stack.is_config_up() {
        Timer::after_millis(100).await;
    }
    log::info!("DHCP is now up!");

    log::info!("waiting for link up...");
    while !stack.is_link_up() {
        Timer::after_millis(500).await;
    }
    log::info!("Link is up!");

    log::info!("waiting for stack to be up...");
    stack.wait_config_up().await;
    log::info!("Stack is up!");

    // Print IP address
    let ipv4_config = stack.config_v4();

    match ipv4_config {
        Some(ip) => {
            log::info!("IP address: {}", ip.address);
        }
        None => {
            log::info!("No IP address");
        }
    }

    stack
}

#[embassy_executor::main]
async fn main(spawner: Spawner) {
    let p = embassy_rp::init(Default::default());
    let mut rng = RoscRng;

    let driver = Driver::new(p.USB, Irqs);
    spawner.spawn(logger_task(driver)).unwrap();

    let fw =
        include_bytes!("/rppico/embassy/cyw43-firmware/43439A0.bin");
    let clm = include_bytes!(
        "/rppico/embassy/cyw43-firmware/43439A0_clm.bin"
    );

    let pwr = Output::new(p.PIN_23, Level::Low);
    let cs = Output::new(p.PIN_25, Level::High);
    let mut pio = Pio::new(p.PIO0, Irqs);
    let spi = PioSpi::new(
        &mut pio.common,
        pio.sm0,
        DEFAULT_CLOCK_DIVIDER,
        pio.irq0,
        cs,
        p.PIN_24,
        p.PIN_29,
        p.DMA_CH0,
    );

    static STATE: StaticCell<cyw43::State> = StaticCell::new();
    let state = STATE.init(cyw43::State::new());
    let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
    unwrap!(spawner.spawn(cyw43_task(runner)));

    control.init(clm).await;
    control
        .set_power_management(cyw43::PowerManagementMode::Performance)
        .await;

    let config = Config::dhcpv4(Default::default());

    // Generate random seed
    let seed = rng.next_u64();

    log::info!("Seed: {}", seed);

    // Init network stack
    static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
    let (stack, runner) = embassy_net::new(
        net_device,
        config,
        RESOURCES.init(StackResources::new()),
        seed,
    );

    unwrap!(spawner.spawn(net_task(runner)));

    let stack: embassy_net::Stack<'_> = connect_to_wifi(&mut control, stack).await;

    let host: &str = "7746c984205e47abb338ef4613b18a7e.s1.eu.hivemq.cloud:8883";

    log::info!("Creating TCP socket");
    let mut rx_buffer: [u8; 512] = [0; 512];
    let mut tx_buffer: [u8; 512] = [0; 512];
    let tcp_socket: TcpSocket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);

    log::info!("Creating TLS connection");
    let tls_config: TlsConfig<'_> = TlsConfig::new()
        .with_server_name(&host)
        .enable_rsa_signatures();

    let mut record_read_buf: [u8; 1024] = [0; 1024];
    let mut record_write_buf: [u8; 1024] = [0; 1024];

    let mut tls_connection: TlsConnection<_, Aes256GcmSha384> =
        TlsConnection::new(tcp_socket, &mut record_read_buf, &mut record_write_buf);

    tls_connection
        .open(TlsContext::new(
            &tls_config,
            UnsecureProvider::new::<Aes256GcmSha384>(rng),
        ))
        .await
        .unwrap();
    log::info!("TLS connection opened");
}

However, I can connect to Wi-Fi if I comment out the tls_connection.open() part.

Any help would be greatly appreciated.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant