Skip to content
Open
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
49 changes: 24 additions & 25 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,51 @@ repository = "https://github.com/drogue-iot/embedded-tls"
license = "Apache-2.0"
keywords = ["embedded", "async", "tls", "no_std", "network"]
exclude = [".github"]
rust-version = "1.86"

[dependencies]
portable-atomic = { version = "1.6.0", default-features = false }
p256 = { version = "0.13.2", default-features = false, features = [
p256 = { version = "0.14.0-pre.11", default-features = false, features = [
"ecdh",
"ecdsa",
"pkcs8",
"sha256",
] }
rand_core = { version = "0.6.3", default-features = false }
hkdf = "0.12.3"
hmac = "0.12.1"
sha2 = { version = "0.10.2", default-features = false }
aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] }
digest = { version = "0.10.3", default-features = false, features = [
"core-api",
] }
typenum = { version = "1.15.0", default-features = false }
heapless = { version = "0.8", default-features = false }
heapless_typenum = { package = "heapless", version = "0.6", default-features = false }
embedded-io = "0.6"
embedded-io-async = "0.6"
embedded-io-adapters = { version = "0.6", optional = true }
generic-array = { version = "0.14", default-features = false }
webpki = { package = "rustls-webpki", version = "0.101.7", default-features = false, optional = true }
signature = { version = "2.2", default-features = false }
ecdsa = { version = "0.16.9", default-features = false }
rand_core = { version = "0.9.3", default-features = false }
hkdf = "0.13.0-rc.1"
hmac = "0.13.0-rc.2"
sha2 = { version = "0.11.0-rc.2", default-features = false }
aes-gcm = { version = "0.11.0-rc.1", default-features = false, features = ["aes"] }
digest = "0.11.0-rc.2"
heapless = { version = "0.9.1", default-features = false }
embedded-io = { git = "https://github.com/rust-embedded/embedded-hal", rev = "ba020960dbe4dca076de999fa087edde021ef5df" }
embedded-io-async = { git = "https://github.com/rust-embedded/embedded-hal", rev = "ba020960dbe4dca076de999fa087edde021ef5df" }
embedded-io-adapters = { git = "https://github.com/rust-embedded/embedded-hal", rev = "ba020960dbe4dca076de999fa087edde021ef5df", optional = true }
webpki = { package = "rustls-webpki", version = "0.103.6", default-features = false, optional = true }
signature = { version = "3.0.0-rc.4", default-features = false }
ecdsa = { version = "0.17.0-rc.7", default-features = false }
thiserror = "2"
pkcs8 = { version = "0.11.0-rc.7", default-features = false }

# Logging alternatives
log = { version = "0.4", optional = true }
defmt = { version = "0.3", optional = true }
defmt = { version = "1.0.1", optional = true }

[dev-dependencies]
env_logger = "0.11"
tokio = { version = "1", features = ["full"] }
mio = { version = "0.8.3", features = ["os-poll", "net"] }
rustls = "0.21.6"
rustls-pemfile = "1.0"
mio = { version = "1.0.4", features = ["os-poll", "net"] }
rustls = { git = "https://github.com/rustls/rustls", rev = "96e7fdcb5ab65c8da13d0ea73ccfa85fc08ac712", default-features = false, features = ["ring", "std"] }
rustls-pemfile = "2.2.0"
serde = { version = "1.0", features = ["derive"] }
rand = "0.8"
rand = "0.9"
log = "0.4"
pem-parser = "0.1.1"
openssl = "0.10.44"

[features]
default = ["std", "log", "tokio"]
defmt = ["dep:defmt", "embedded-io/defmt-03", "heapless/defmt-03"]
defmt = ["dep:defmt", "embedded-io/defmt", "heapless/defmt"]
std = ["embedded-io/std", "embedded-io-async/std"]
tokio = ["embedded-io-adapters/tokio-1"]
alloc = []
12 changes: 5 additions & 7 deletions examples/blocking/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::net::TcpStream;
use std::time::SystemTime;

use embedded_io::Write as _;
use embedded_io_adapters::std::FromStd;
use embedded_tls::blocking::*;
use embedded_tls::webpki::CertVerifier;
use rand::rngs::OsRng;
use std::net::TcpStream;
use std::time::SystemTime;

struct Provider {
rng: OsRng,
verifier: CertVerifier<Aes128GcmSha256, SystemTime, 4096>,
}

Expand All @@ -16,8 +15,8 @@ impl CryptoProvider for Provider {

type Signature = &'static [u8];

fn rng(&mut self) -> impl embedded_tls::CryptoRngCore {
&mut self.rng
fn rng(&mut self) -> impl embedded_tls::CryptoRng {
rand::rng()
}

fn verifier(
Expand All @@ -44,7 +43,6 @@ fn main() {
tls.open(TlsContext::new(
&config,
Provider {
rng: OsRng,
verifier: CertVerifier::new(),
},
))
Expand Down
6 changes: 3 additions & 3 deletions examples/embassy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use embedded_io_async::Write;
use embedded_tls::{Aes128GcmSha256, TlsConfig, TlsConnection, TlsContext, UnsecureProvider};
use heapless::Vec;
use log::*;
use rand::{rngs::OsRng, RngCore};
use rand::RngCore;
use static_cell::StaticCell;

#[derive(Parser)]
Expand Down Expand Up @@ -47,7 +47,7 @@ async fn main_task(spawner: Spawner) {

// Generate random seed
let mut seed = [0; 8];
OsRng.fill_bytes(&mut seed);
rand::rng().fill_bytes(&mut seed);
let seed = u64::from_le_bytes(seed);

// Init network stack
Expand Down Expand Up @@ -86,7 +86,7 @@ async fn main_task(spawner: Spawner) {

tls.open(TlsContext::new(
&config,
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
UnsecureProvider::new::<Aes128GcmSha256>(rand::rng()),
))
.await
.expect("error establishing TLS connection");
Expand Down
6 changes: 3 additions & 3 deletions examples/tokio-psk/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![macro_use]

use std::error::Error;

use embedded_io_adapters::tokio_1::FromTokio;
use embedded_io_async::Write as _;
use embedded_tls::*;
use rand::rngs::OsRng;
use std::error::Error;
use tokio::net::TcpStream;

#[tokio::main]
Expand All @@ -27,7 +27,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

tls.open(TlsContext::new(
&config,
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
UnsecureProvider::new::<Aes128GcmSha256>(rand::rng()),
))
.await
.expect("error establishing TLS connection");
Expand Down
6 changes: 3 additions & 3 deletions examples/tokio/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![macro_use]

use std::error::Error;

use embedded_io_adapters::tokio_1::FromTokio;
use embedded_io_async::Write as _;
use embedded_tls::*;
use rand::rngs::OsRng;
use std::error::Error;
use tokio::net::TcpStream;

#[tokio::main]
Expand All @@ -25,7 +25,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

tls.open(TlsContext::new(
&config,
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
UnsecureProvider::new::<Aes128GcmSha256>(rand::rng()),
))
.await
.expect("error establishing TLS connection");
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Before upgrading check that everything is available on all tier1 targets here:
# https://rust-lang.github.io/rustup-components-history
[toolchain]
channel = "1.85"
channel = "1.86"
components = [ "rustfmt", "clippy" ]
targets = [ "thumbv7em-none-eabi" ]
48 changes: 22 additions & 26 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
use core::marker::PhantomData;

use crate::TlsError;
use crate::cipher_suites::CipherSuite;
use crate::extensions::extension_data::signature_algorithms::SignatureScheme;
use crate::extensions::extension_data::supported_groups::NamedGroup;
use crate::handshake::certificate::CertificateRef;
pub use crate::handshake::certificate_verify::CertificateVerifyRef;
use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, KeyInit};
use aes_gcm::{AeadInOut, Aes128Gcm, Aes256Gcm, KeyInit};
use digest::array::ArraySize;
use digest::core_api::BlockSizeUser;
use digest::typenum::{Sum, U10, U12, U16, U32};
use digest::{Digest, FixedOutput, OutputSizeUser, Reset};
use ecdsa::elliptic_curve::SecretKey;
use generic_array::ArrayLength;
use heapless::Vec;
use p256::ecdsa::SigningKey;
use rand_core::CryptoRngCore;
use rand_core::CryptoRng;
pub use sha2::Sha256;

pub use sha2::Sha384;
use typenum::{Sum, U10, U12, U16, U32};

use crate::TlsError;
use crate::cipher_suites::CipherSuite;
pub use crate::extensions::extension_data::max_fragment_length::MaxFragmentLength;
use crate::extensions::extension_data::signature_algorithms::SignatureScheme;
use crate::extensions::extension_data::supported_groups::NamedGroup;
use crate::handshake::certificate::CertificateRef;
pub use crate::handshake::certificate_verify::CertificateVerifyRef;

pub const TLS_RECORD_OVERHEAD: usize = 128;

Expand All @@ -34,12 +33,12 @@ type LabelBuffer<CipherSuite> = Sum<
/// Represents a TLS 1.3 cipher suite
pub trait TlsCipherSuite {
const CODE_POINT: u16;
type Cipher: KeyInit<KeySize = Self::KeyLen> + AeadInPlace<NonceSize = Self::IvLen>;
type KeyLen: ArrayLength<u8>;
type IvLen: ArrayLength<u8>;
type Cipher: KeyInit<KeySize = Self::KeyLen> + AeadInOut<NonceSize = Self::IvLen>;
type KeyLen: ArraySize;
type IvLen: ArraySize;

type Hash: Digest + Reset + Clone + OutputSizeUser + BlockSizeUser + FixedOutput;
type LabelBufferSize: ArrayLength<u8>;
type LabelBufferSize: ArraySize;
}

pub struct Aes128GcmSha256;
Expand Down Expand Up @@ -148,7 +147,7 @@ pub trait CryptoProvider {
type CipherSuite: TlsCipherSuite;
type Signature: AsRef<[u8]>;

fn rng(&mut self) -> impl CryptoRngCore;
fn rng(&mut self) -> impl CryptoRng;

fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, crate::TlsError> {
Err::<&mut NoVerify, _>(crate::TlsError::Unimplemented)
Expand All @@ -158,8 +157,7 @@ pub trait CryptoProvider {
fn signer(
&mut self,
_key_der: &[u8],
) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
{
) -> Result<(impl signature::Signer<Self::Signature>, SignatureScheme), crate::TlsError> {
Err::<(NoSign, _), crate::TlsError>(crate::TlsError::Unimplemented)
}
}
Expand All @@ -169,7 +167,7 @@ impl<T: CryptoProvider> CryptoProvider for &mut T {

type Signature = T::Signature;

fn rng(&mut self) -> impl CryptoRngCore {
fn rng(&mut self) -> impl CryptoRng {
T::rng(self)
}

Expand All @@ -180,8 +178,7 @@ impl<T: CryptoProvider> CryptoProvider for &mut T {
fn signer(
&mut self,
key_der: &[u8],
) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
{
) -> Result<(impl signature::Signer<Self::Signature>, SignatureScheme), crate::TlsError> {
T::signer(self, key_der)
}
}
Expand All @@ -199,7 +196,7 @@ pub struct UnsecureProvider<CipherSuite, RNG> {
_marker: PhantomData<CipherSuite>,
}

impl<RNG: CryptoRngCore> UnsecureProvider<(), RNG> {
impl<RNG: CryptoRng> UnsecureProvider<(), RNG> {
pub fn new<CipherSuite: TlsCipherSuite>(rng: RNG) -> UnsecureProvider<CipherSuite, RNG> {
UnsecureProvider {
rng,
Expand All @@ -208,21 +205,20 @@ impl<RNG: CryptoRngCore> UnsecureProvider<(), RNG> {
}
}

impl<CipherSuite: TlsCipherSuite, RNG: CryptoRngCore> CryptoProvider
impl<CipherSuite: TlsCipherSuite, RNG: CryptoRng> CryptoProvider
for UnsecureProvider<CipherSuite, RNG>
{
type CipherSuite = CipherSuite;
type Signature = p256::ecdsa::DerSignature;

fn rng(&mut self) -> impl CryptoRngCore {
fn rng(&mut self) -> impl CryptoRng {
&mut self.rng
}

fn signer(
&mut self,
key_der: &[u8],
) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
{
) -> Result<(impl signature::Signer<Self::Signature>, SignatureScheme), crate::TlsError> {
let secret_key =
SecretKey::from_sec1_der(key_der).map_err(|_| TlsError::InvalidPrivateKey)?;

Expand Down
38 changes: 19 additions & 19 deletions src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
use core::fmt::Debug;

use aes_gcm::aead::{AeadCore, AeadInOut, KeyInit};
use digest::Digest;
use digest::typenum::Unsigned;
use embedded_io::Error as _;
use embedded_io::{Read as BlockingRead, Write as BlockingWrite};
use embedded_io_async::{Read as AsyncRead, Write as AsyncWrite};
use p256::ecdh::EphemeralSecret;
use signature::Signer;

use crate::application_data::ApplicationData;
use crate::buffer::CryptoBuffer;
use crate::config::{TlsCipherSuite, TlsConfig};
use crate::content_types::ContentType;
use crate::handshake::{ClientHandshake, ServerHandshake};
use crate::key_schedule::{KeySchedule, ReadKeySchedule, WriteKeySchedule};
use crate::parse_buffer::ParseBuffer;
use crate::record::{ClientRecord, ServerRecord};
use crate::record_reader::RecordReader;
use crate::write_buffer::WriteBuffer;
Expand All @@ -9,21 +24,6 @@ use crate::{
alert::{Alert, AlertDescription, AlertLevel},
handshake::{certificate::CertificateRef, certificate_request::CertificateRequest},
};
use core::fmt::Debug;
use digest::Digest;
use embedded_io::Error as _;
use embedded_io::{Read as BlockingRead, Write as BlockingWrite};
use embedded_io_async::{Read as AsyncRead, Write as AsyncWrite};

use crate::application_data::ApplicationData;
use crate::buffer::CryptoBuffer;
use digest::generic_array::typenum::Unsigned;
use p256::ecdh::EphemeralSecret;
use signature::SignerMut;

use crate::content_types::ContentType;
use crate::parse_buffer::ParseBuffer;
use aes_gcm::aead::{AeadCore, AeadInPlace, KeyInit};

pub(crate) fn decrypt_record<CipherSuite>(
key_schedule: &mut ReadKeySchedule<CipherSuite>,
Expand Down Expand Up @@ -548,14 +548,14 @@ where
Provider: CryptoProvider,
{
let (result, record) = match crypto_provider.signer(config.priv_key) {
Ok((mut signing_key, signature_scheme)) => {
Ok((signing_key, signature_scheme)) => {
let ctx_str = b"TLS 1.3, client CertificateVerify\x00";
let mut msg: heapless::Vec<u8, 130> = heapless::Vec::new();
msg.resize(64, 0x20).map_err(|()| TlsError::EncodeError)?;
msg.resize(64, 0x20).map_err(|_| TlsError::EncodeError)?;
msg.extend_from_slice(ctx_str)
.map_err(|()| TlsError::EncodeError)?;
.map_err(|_| TlsError::EncodeError)?;
msg.extend_from_slice(&key_schedule.transcript_hash().clone().finalize())
.map_err(|()| TlsError::EncodeError)?;
.map_err(|_| TlsError::EncodeError)?;

let signature = signing_key.sign(&msg);

Expand Down
Loading
Loading