Skip to content

Commit d7c9b93

Browse files
authored
Merge pull request #135 from MathiasKoch/feature/client-cert-verification
feature(*): Add missing implementation to support Client Certificate Authorization
2 parents 328a974 + 0564440 commit d7c9b93

28 files changed

+730
-260
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Add missing implementation to support Client Certificate Authorization (#135)
11+
1012
## 0.17.0 - 2024-01-06
1113

1214
- Update to stable rust

Cargo.toml

+11-3
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ exclude = [".github"]
1313

1414
[dependencies]
1515
atomic-polyfill = "1"
16-
p256 = { version = "0.13.2", default-features = false, features = [ "ecdh", "arithmetic" ] }
16+
p256 = { version = "0.13.2", default-features = false, features = [
17+
"ecdh",
18+
"ecdsa",
19+
"sha256",
20+
] }
1721
rand_core = { version = "0.6.3", default-features = false }
1822
hkdf = "0.12.3"
1923
hmac = "0.12.1"
2024
sha2 = { version = "0.10.2", default-features = false }
2125
aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] }
22-
digest = { version = "0.10.3", default-features = false, features = ["core-api"] }
26+
digest = { version = "0.10.3", default-features = false, features = [
27+
"core-api",
28+
] }
2329
typenum = { version = "1.15.0", default-features = false }
2430
heapless = { version = "0.8", default-features = false }
2531
heapless_typenum = { package = "heapless", version = "0.6", default-features = false }
@@ -28,13 +34,15 @@ embedded-io-async = "0.6"
2834
embedded-io-adapters = { version = "0.6", optional = true }
2935
generic-array = { version = "0.14", default-features = false }
3036
webpki = { package = "rustls-webpki", version = "0.101.7", default-features = false, optional = true }
37+
signature = { version = "2.2", default-features = false }
38+
ecdsa = { version = "0.16.9", default-features = false }
3139

3240
# Logging alternatives
3341
log = { version = "0.4", optional = true }
3442
defmt = { version = "0.3", optional = true }
3543

3644
[dev-dependencies]
37-
env_logger = "0.10"
45+
env_logger = "0.11"
3846
tokio = { version = "1", features = ["full"] }
3947
mio = { version = "0.8.3", features = ["os-poll", "net"] }
4048
rustls = "0.21.6"

examples/blocking/src/main.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@ use rand::rngs::OsRng;
66
use std::net::TcpStream;
77
use std::time::SystemTime;
88

9+
struct Provider {
10+
rng: OsRng,
11+
verifier: CertVerifier<Aes128GcmSha256, SystemTime, 4096>,
12+
}
13+
14+
impl CryptoProvider for Provider {
15+
type CipherSuite = Aes128GcmSha256;
16+
17+
type Signature = &'static [u8];
18+
19+
fn rng(&mut self) -> impl embedded_tls::CryptoRngCore {
20+
&mut self.rng
21+
}
22+
23+
fn verifier(
24+
&mut self,
25+
) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, embedded_tls::TlsError> {
26+
Ok(&mut self.verifier)
27+
}
28+
}
29+
930
fn main() {
1031
env_logger::init();
1132
let stream = TcpStream::connect("127.0.0.1:12345").expect("error connecting to server");
@@ -14,15 +35,18 @@ fn main() {
1435
let mut read_record_buffer = [0; 16384];
1536
let mut write_record_buffer = [0; 16384];
1637
let config = TlsConfig::new().with_server_name("localhost");
17-
let mut tls: TlsConnection<FromStd<TcpStream>, Aes128GcmSha256> = TlsConnection::new(
38+
let mut tls = TlsConnection::new(
1839
FromStd::new(stream),
1940
&mut read_record_buffer,
2041
&mut write_record_buffer,
2142
);
22-
let mut rng = OsRng;
2343

24-
tls.open::<OsRng, CertVerifier<Aes128GcmSha256, SystemTime, 4096>>(TlsContext::new(
25-
&config, &mut rng,
44+
tls.open(TlsContext::new(
45+
&config,
46+
Provider {
47+
rng: OsRng,
48+
verifier: CertVerifier::new(),
49+
},
2650
))
2751
.expect("error establishing TLS connection");
2852

examples/embassy/src/main.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
55
use embassy_net_tuntap::TunTapDevice;
66
use embassy_time::Duration;
77
use embedded_io_async::Write;
8-
use embedded_tls::{Aes128GcmSha256, NoVerify, TlsConfig, TlsConnection, TlsContext};
8+
use embedded_tls::{Aes128GcmSha256, TlsConfig, TlsConnection, TlsContext, UnsecureProvider};
99
use heapless::Vec;
1010
use log::*;
1111
use rand::{rngs::OsRng, RngCore};
@@ -57,7 +57,7 @@ async fn main_task(spawner: Spawner) {
5757
device,
5858
config,
5959
RESOURCES.init(StackResources::<3>::new()),
60-
seed
60+
seed,
6161
));
6262

6363
// Launch network task
@@ -81,14 +81,15 @@ async fn main_task(spawner: Spawner) {
8181

8282
let mut read_record_buffer = [0; 16384];
8383
let mut write_record_buffer = [0; 16384];
84-
let mut rng = OsRng;
8584
let config = TlsConfig::new().with_server_name("example.com");
86-
let mut tls: TlsConnection<TcpSocket, Aes128GcmSha256> =
87-
TlsConnection::new(socket, &mut read_record_buffer, &mut write_record_buffer);
88-
89-
tls.open::<OsRng, NoVerify>(TlsContext::new(&config, &mut rng))
90-
.await
91-
.expect("error establishing TLS connection");
85+
let mut tls = TlsConnection::new(socket, &mut read_record_buffer, &mut write_record_buffer);
86+
87+
tls.open(TlsContext::new(
88+
&config,
89+
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
90+
))
91+
.await
92+
.expect("error establishing TLS connection");
9293

9394
tls.write_all(b"ping").await.expect("error writing data");
9495
tls.flush().await.expect("error flushing data");

examples/nrf52/src/main.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ use hal::rng::Rng;
1717
#[entry]
1818
fn main() -> ! {
1919
let p = hal::pac::Peripherals::take().unwrap();
20-
let mut rng = Rng::new(p.RNG);
20+
let rng = Rng::new(p.RNG);
2121
defmt::info!("Connected");
2222
let mut read_record_buffer = [0; 16384];
2323
let mut write_record_buffer = [0; 16384];
2424
let config = TlsConfig::new().with_server_name("example.com");
25-
let mut tls: TlsConnection<Dummy, Aes128GcmSha256> =
26-
TlsConnection::new(Dummy {}, &mut read_record_buffer, &mut write_record_buffer);
25+
let mut tls = TlsConnection::new(Dummy {}, &mut read_record_buffer, &mut write_record_buffer);
2726

28-
tls.open::<Rng, NoVerify>(TlsContext::new(&config, &mut rng))
29-
.expect("error establishing TLS connection");
27+
tls.open(TlsContext::new(
28+
&config,
29+
UnsecureProvider::new::<Aes128GcmSha256>(rng),
30+
))
31+
.expect("error establishing TLS connection");
3032

3133
tls.write_all(b"ping").expect("error writing data");
3234
tls.flush().expect("error flushing data");

examples/tokio-psk/src/main.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
1919
let config = TlsConfig::new()
2020
.with_server_name("localhost")
2121
.with_psk(&[0xaa, 0xbb, 0xcc, 0xdd], &[b"vader"]);
22-
let mut rng = OsRng;
23-
let mut tls: TlsConnection<FromTokio<TcpStream>, Aes128GcmSha256> = TlsConnection::new(
22+
let mut tls = TlsConnection::new(
2423
FromTokio::new(stream),
2524
&mut read_record_buffer,
2625
&mut write_record_buffer,
2726
);
2827

29-
tls.open::<OsRng, NoVerify>(TlsContext::new(&config, &mut rng))
30-
.await
31-
.expect("error establishing TLS connection");
28+
tls.open(TlsContext::new(
29+
&config,
30+
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
31+
))
32+
.await
33+
.expect("error establishing TLS connection");
3234

3335
tls.write_all(b"ping").await.expect("error writing data");
3436
tls.flush().await.expect("error flushing data");

examples/tokio/src/main.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
1717
let mut read_record_buffer = [0; 16384];
1818
let mut write_record_buffer = [0; 16384];
1919
let config = TlsConfig::new().with_server_name("localhost");
20-
let mut rng = OsRng;
21-
let mut tls: TlsConnection<FromTokio<TcpStream>, Aes128GcmSha256> = TlsConnection::new(
20+
let mut tls = TlsConnection::new(
2221
FromTokio::new(stream),
2322
&mut read_record_buffer,
2423
&mut write_record_buffer,
2524
);
2625

27-
tls.open::<OsRng, NoVerify>(TlsContext::new(&config, &mut rng))
28-
.await
29-
.expect("error establishing TLS connection");
26+
tls.open(TlsContext::new(
27+
&config,
28+
UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
29+
))
30+
.await
31+
.expect("error establishing TLS connection");
3032

3133
tls.write_all(b"ping").await.expect("error writing data");
3234
tls.flush().await.expect("error flushing data");

src/asynch.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use crate::TlsError;
1212
use embedded_io::Error as _;
1313
use embedded_io::ErrorType;
1414
use embedded_io_async::{BufRead, Read as AsyncRead, Write as AsyncWrite};
15-
use rand_core::{CryptoRng, RngCore};
1615

1716
pub use crate::config::*;
1817
#[cfg(feature = "std")]
@@ -71,16 +70,20 @@ where
7170
///
7271
/// Returns an error if the handshake does not proceed. If an error occurs, the connection
7372
/// instance must be recreated.
74-
pub async fn open<'v, RNG, Verifier>(
73+
pub async fn open<'v, Provider>(
7574
&mut self,
76-
context: TlsContext<'v, CipherSuite, RNG>,
75+
mut context: TlsContext<'v, Provider>,
7776
) -> Result<(), TlsError>
7877
where
79-
RNG: CryptoRng + RngCore,
80-
Verifier: TlsVerifier<'v, CipherSuite>,
78+
Provider: CryptoProvider<CipherSuite = CipherSuite>,
8179
{
82-
let mut handshake: Handshake<CipherSuite, Verifier> =
83-
Handshake::new(Verifier::new(context.config.server_name));
80+
let mut handshake: Handshake<CipherSuite> = Handshake::new();
81+
if let (Ok(verifier), Some(server_name)) = (
82+
context.crypto_provider.verifier(),
83+
context.config.server_name,
84+
) {
85+
verifier.set_hostname_verification(server_name)?;
86+
}
8487
let mut state = State::ClientHello;
8588

8689
while state != State::ApplicationData {
@@ -92,7 +95,7 @@ where
9295
&mut self.record_write_buf,
9396
&mut self.key_schedule,
9497
context.config,
95-
context.rng,
98+
&mut context.crypto_provider,
9699
)
97100
.await?;
98101
trace!("State {:?} -> {:?}", state, next_state);

src/blocking.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::split::{SplitState, SplitStateContainer};
1010
use crate::write_buffer::WriteBuffer;
1111
use embedded_io::Error as _;
1212
use embedded_io::{BufRead, ErrorType, Read, Write};
13-
use rand_core::{CryptoRng, RngCore};
1413

1514
pub use crate::config::*;
1615
#[cfg(feature = "std")]
@@ -70,16 +69,20 @@ where
7069
///
7170
/// Returns an error if the handshake does not proceed. If an error occurs, the connection
7271
/// instance must be recreated.
73-
pub fn open<'v, RNG, Verifier>(
72+
pub fn open<'v, Provider>(
7473
&mut self,
75-
context: TlsContext<'v, CipherSuite, RNG>,
74+
mut context: TlsContext<'v, Provider>,
7675
) -> Result<(), TlsError>
7776
where
78-
RNG: CryptoRng + RngCore,
79-
Verifier: TlsVerifier<'v, CipherSuite>,
77+
Provider: CryptoProvider<CipherSuite = CipherSuite>,
8078
{
81-
let mut handshake: Handshake<CipherSuite, Verifier> =
82-
Handshake::new(Verifier::new(context.config.server_name));
79+
let mut handshake: Handshake<CipherSuite> = Handshake::new();
80+
if let (Ok(verifier), Some(server_name)) = (
81+
context.crypto_provider.verifier(),
82+
context.config.server_name,
83+
) {
84+
verifier.set_hostname_verification(server_name)?;
85+
}
8386
let mut state = State::ClientHello;
8487

8588
while state != State::ApplicationData {
@@ -90,7 +93,7 @@ where
9093
&mut self.record_write_buf,
9194
&mut self.key_schedule,
9295
context.config,
93-
context.rng,
96+
&mut context.crypto_provider,
9497
)?;
9598
trace!("State {:?} -> {:?}", state, next_state);
9699
state = next_state;

0 commit comments

Comments
 (0)