embedded_tls/
lib.rs

1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2#![doc = include_str!("../README.md")]
3#![warn(clippy::pedantic)]
4#![allow(
5    clippy::module_name_repetitions,
6    clippy::cast_possible_truncation,
7    clippy::cast_sign_loss,
8    clippy::missing_errors_doc // TODO
9)]
10
11/*!
12# Example
13
14```
15use embedded_tls::*;
16use embedded_io_adapters::tokio_1::FromTokio;
17use rand::rngs::OsRng;
18use tokio::net::TcpStream;
19
20#[tokio::main]
21async fn main() {
22    let stream = TcpStream::connect("google.com:443")
23        .await
24        .expect("error creating TCP connection");
25
26    println!("TCP connection opened");
27    let mut read_record_buffer = [0; 16384];
28    let mut write_record_buffer = [0; 16384];
29    let config = TlsConfig::new().with_server_name("google.com").enable_rsa_signatures();
30    let mut tls = TlsConnection::new(
31        FromTokio::new(stream),
32        &mut read_record_buffer,
33        &mut write_record_buffer,
34    );
35
36    // Allows disabling cert verification, in case you are using PSK and don't need it, or are just testing.
37    // otherwise, use embedded_tls::webpki::CertVerifier, which only works on std for now.
38    tls.open(TlsContext::new(
39        &config,
40        UnsecureProvider::new::<Aes128GcmSha256>(OsRng),
41    ))
42    .await
43    .expect("error establishing TLS connection");
44
45    println!("TLS session opened");
46}
47```
48*/
49
50// This mod MUST go first, so that the others see its macros.
51pub(crate) mod fmt;
52
53use parse_buffer::ParseError;
54pub mod alert;
55mod application_data;
56pub mod blocking;
57mod buffer;
58mod change_cipher_spec;
59mod cipher_suites;
60mod common;
61mod config;
62mod connection;
63mod content_types;
64mod crypto_engine;
65mod extensions;
66pub mod flush_policy;
67mod handshake;
68mod key_schedule;
69mod parse_buffer;
70pub mod read_buffer;
71mod record;
72mod record_reader;
73mod write_buffer;
74
75pub use config::UnsecureProvider;
76pub use extensions::extension_data::signature_algorithms::SignatureScheme;
77pub use handshake::certificate_verify::CertificateVerify;
78pub use rand_core::{CryptoRng, CryptoRngCore};
79
80#[cfg(feature = "webpki")]
81pub mod webpki;
82
83#[cfg(feature = "rustpki")]
84mod der_certificate;
85#[cfg(feature = "rustpki")]
86pub mod pki;
87
88mod asynch;
89pub use asynch::*;
90
91pub use flush_policy::*;
92
93#[derive(Debug, Copy, Clone)]
94#[cfg_attr(feature = "defmt", derive(defmt::Format))]
95pub enum TlsError {
96    ConnectionClosed,
97    Unimplemented,
98    MissingHandshake,
99    HandshakeAborted(alert::AlertLevel, alert::AlertDescription),
100    AbortHandshake(alert::AlertLevel, alert::AlertDescription),
101    IoError,
102    InternalError,
103    InvalidRecord,
104    UnknownContentType,
105    InvalidNonceLength,
106    InvalidTicketLength,
107    UnknownExtensionType,
108    InsufficientSpace,
109    InvalidHandshake,
110    InvalidCipherSuite,
111    InvalidSignatureScheme,
112    InvalidSignature,
113    InvalidExtensionsLength,
114    InvalidSessionIdLength,
115    InvalidSupportedVersions,
116    InvalidApplicationData,
117    InvalidKeyShare,
118    InvalidCertificate,
119    InvalidCertificateEntry,
120    InvalidCertificateRequest,
121    InvalidPrivateKey,
122    UnableToInitializeCryptoEngine,
123    ParseError(ParseError),
124    OutOfMemory,
125    CryptoError,
126    EncodeError,
127    DecodeError,
128    Io(embedded_io::ErrorKind),
129}
130
131impl embedded_io::Error for TlsError {
132    fn kind(&self) -> embedded_io::ErrorKind {
133        if let Self::Io(k) = self {
134            *k
135        } else {
136            error!("TLS error: {:?}", self);
137            embedded_io::ErrorKind::Other
138        }
139    }
140}
141
142impl core::fmt::Display for TlsError {
143    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
144        write!(f, "{self:?}")
145    }
146}
147
148impl core::error::Error for TlsError {}
149
150#[cfg(feature = "std")]
151mod stdlib {
152    use crate::config::TlsClock;
153
154    use std::time::SystemTime;
155    impl TlsClock for SystemTime {
156        fn now() -> Option<u64> {
157            Some(
158                SystemTime::now()
159                    .duration_since(SystemTime::UNIX_EPOCH)
160                    .unwrap()
161                    .as_secs(),
162            )
163        }
164    }
165}
166
167/// An internal function to mark an unused value.
168///
169/// All calls to this should be removed before 1.x.
170fn unused<T>(_: T) {}