[Documentation], [Changelog]
The [LibreSSL] project provides a free TLS and crypto stack that was forked from [OpenSSL] in 2014. The goals are to provide a modernized codebase, improved security, and to apply best practice development processes.
[LibreSSL] provides C APIs that are compatible to [OpenSSL]'s [libssl] and [libcrypto] libraries. It also provides [libtls], a new TLS library that is designed to make it easier to write foolproof applications.
This workspace of Rust crates provides language bindings for [libtls] only, as the other [LibreSSL] APIs can be used with the existing [rust-openssl] crate. [LibreSSL] versions 2.9.0 through 3.0.2 (or later) are supported.
The following crates are included: - [libtls-sys]: FFI bindings. - [libtls]: Rust bindings. - [tokio-libtls]: [Tokio] bindings.
Async I/O with [tokio-libtls] requires Rust 1.39 or later for
[async-await]. This crate does not provide any backwards
compatibility but you can use version 1.0.0
on older Rust versions.
```rust use libtls::{config::{self, TlsConfig}, error};
fn tlsserverconfig() -> error::Result
fn main() { let tlsconfig = tlsserver_config().unwrap(); } ```
The same configuration can be created using the TlsConfigBuilder
builder pattern:
rust
fn tls_server_config() -> error::Result<TlsConfig> {
let tls_config = TlsConfigBuilder::new()
.keypair_file("tests/eccert.crt", "tests/eccert.key", None)
.protocols(libtls_sys::TLS_PROTOCOL_TLSv1_2)
.build()?;
Ok(tls_config)
}
A TLS connection:
```rust use libtls::{config::TlsConfigBuilder, error}; use std::io::{Read, Write};
fn synchttpsconnect(servername: &str) -> error::Result<()> { let addr = &(servername.to_owned() + ":443");
let request = format!(
"GET / HTTP/1.1\r\n\
Host: {}\r\n\
Connection: close\r\n\r\n",
servername
);
let mut tls = TlsConfigBuilder::new().client()?;
tls.connect(addr, None)?;
tls.write(request.as_bytes())?;
let mut buf = vec![0u8; 1024];
tls.read(&mut buf)?;
let ok = b"HTTP/1.1 200 OK\r\n";
assert_eq!(&buf[..ok.len()], ok);
Ok(())
}
fn main() { synchttpsconnect("www.example.com").unwrap(); } ```
A non-blocking and asynchronous TLS connection using [Tokio] and the [tokio-libtls] crate:
```rust use std::io; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio_libtls::prelude::*;
async fn asynchttpsconnect(servername: String) -> io::Result<()> { let request = format!( "GET / HTTP/1.1\r\n\ Host: {}\r\n\ Connection: close\r\n\r\n", servername );
let config = TlsConfigBuilder::new().build()?;
let mut tls = AsyncTls::connect(&(servername + ":443"), &config, None).await?;
tls.write_all(request.as_bytes()).await?;
let mut buf = vec![0u8; 1024];
tls.read_exact(&mut buf).await?;
let ok = b"HTTP/1.1 200 OK\r\n";
assert_eq!(&buf[..ok.len()], ok);
Ok(())
}
async fn main() { asynchttpsconnect("www.example.com".to_owned()).await.unwrap(); } ```
An asynchronous TLS server:
```rust async fn echoserver(cert: &str, key: &str) -> io::Result<()> { let config = TlsConfigBuilder::new() .keypairfile(cert, key, None) .build()?;
let addr: SocketAddr = "[::1]:7".parse().unwrap();
let mut listener = TcpListener::bind(&addr).await?;
loop {
let (tcp, _) = listener.accept().await?;
let mut tls = AsyncTls::accept_stream(tcp, &config, None).await?;
tokio::spawn(async move {
loop {
let mut buf = vec![0u8; 1024];
if !tls.read(&mut buf).await.is_ok() || !tls.write_all(&buf).await.is_ok() {
break;
}
}
});
}
} ```
Licensed under an OpenBSD-ISC-style license, see [LICENSE] for details.