use std::{
net::{Ipv4Addr, SocketAddr},
time::{Duration, SystemTime},
};
use embedded_io_adapters::tokio_1::FromTokio;
use embedded_tls::{webpki::CertVerifier, *};
use log::{error, info};
use p256::{
SecretKey,
ecdsa::{DerSignature, SigningKey},
};
use pem_parser::pem_to_der;
use rand::rngs::OsRng;
use rust_mqtt::{
buffer::*,
client::{
Client,
options::{ConnectOptions, DisconnectOptions},
},
};
use signature::SignerMut;
use tokio::{net::TcpStream, time::sleep};
#[derive(Default)]
struct Provider {
rng: OsRng,
verifier: CertVerifier<Aes128GcmSha256, SystemTime, 4096>,
}
impl CryptoProvider for Provider {
type CipherSuite = Aes128GcmSha256;
type Signature = DerSignature;
fn rng(&mut self) -> impl embedded_tls::CryptoRngCore {
&mut self.rng
}
fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Aes128GcmSha256>, TlsError> {
Ok(&mut self.verifier)
}
fn signer(
&mut self,
key_der: &[u8],
) -> Result<(impl SignerMut<Self::Signature>, SignatureScheme), TlsError> {
let secret_key =
SecretKey::from_sec1_der(key_der).map_err(|_| TlsError::InvalidPrivateKey)?;
Ok((
SigningKey::from(&secret_key),
SignatureScheme::EcdsaSecp256r1Sha256,
))
}
}
#[tokio::main]
async fn main() {
env_logger::init();
#[cfg(feature = "alloc")]
let mut buffer = AllocBuffer;
#[cfg(feature = "bump")]
let mut buffer = [0; 1024];
#[cfg(feature = "bump")]
let mut buffer = BumpBuffer::new(&mut buffer);
let mut client = Client::<'_, _, _, 1, 1, 1, 0>::new(&mut buffer);
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8883);
let connection = TcpStream::connect(addr).await.unwrap();
let connection = FromTokio::new(connection);
let ca_cert = pem_to_der(include_str!("./pki/ca-cert.pem"));
let client_cert = pem_to_der(include_str!("./pki/client-cert.pem"));
let client_key = pem_to_der(include_str!("./pki/client-key.pem"));
let config = TlsConfig::new()
.with_ca(Certificate::X509(&ca_cert))
.with_cert(Certificate::X509(&client_cert))
.with_priv_key(&client_key)
.with_server_name("localhost");
let mut record_read_buf = [0; 16384];
let mut record_write_buf = [0; 16384];
let mut tls_connection =
TlsConnection::new(connection, &mut record_read_buf, &mut record_write_buf);
tls_connection
.open(TlsContext::new(&config, Provider::default()))
.await
.expect("error establishing TLS connection");
match client
.connect(tls_connection, &ConnectOptions::new().clean_start(), None)
.await
{
Ok(c) => info!("Connected to server: {c:?}"),
Err(e) => {
error!("Failed to connect to server: {e:?}");
return;
}
}
sleep(Duration::from_secs(5)).await;
client
.disconnect(&DisconnectOptions {
publish_will: false,
session_expiry_interval: None,
})
.await
.unwrap();
}