Skip to main content

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