143 lines
3.6 KiB
Rust
143 lines
3.6 KiB
Rust
use core::cmp::min;
|
|
use core::mem::MaybeUninit;
|
|
use core::slice;
|
|
|
|
use bearssl_sys::*;
|
|
|
|
pub enum Error {
|
|
/// A session resumption has been attempted with a distinct version or cipher suite.
|
|
SessionResumptionMismatch,
|
|
|
|
/// Other side has sent an invalid signature.
|
|
BadSignature,
|
|
|
|
/// The error code is unknown or not wrapped around yet.
|
|
Unknown,
|
|
}
|
|
|
|
/// TLS engine used by both server and client connections.
|
|
#[repr(transparent)]
|
|
pub struct TlsEngine {
|
|
pub(crate) context: br_ssl_engine_context,
|
|
}
|
|
|
|
impl TlsEngine {
|
|
/// Push some plaintext bytes into engine.
|
|
///
|
|
/// Returns how many bytes were copied on success.
|
|
pub fn push_write(&mut self, src: &[u8]) -> Result<usize, Error> {
|
|
let buf = unsafe {
|
|
let mut l = MaybeUninit::<usize>::uninit();
|
|
|
|
let b = br_ssl_engine_sendapp_buf(&self.context, l.as_mut_ptr());
|
|
|
|
if b.is_null() {
|
|
return Err(Error::Unknown);
|
|
}
|
|
|
|
slice::from_raw_parts_mut(b, l.assume_init_read())
|
|
};
|
|
|
|
let len = match min(buf.len(), src.len()) {
|
|
0 => return Err(Error::Unknown),
|
|
l => l,
|
|
};
|
|
|
|
buf[..len].copy_from_slice(&src[..len]);
|
|
|
|
unsafe {
|
|
br_ssl_engine_sendapp_ack(&mut self.context, len);
|
|
}
|
|
|
|
Ok(len)
|
|
}
|
|
|
|
/// Get the TLS record that has wrapped the pushed data. Returns an error or how many bytes of TLS record were written to `dst`.
|
|
pub fn pull_write(&mut self, dst: &mut [u8]) -> Result<usize, Error> {
|
|
let buf = unsafe {
|
|
let mut l = MaybeUninit::<usize>::uninit();
|
|
|
|
let b = br_ssl_engine_sendrec_buf(&self.context, l.as_mut_ptr());
|
|
|
|
if b.is_null() {
|
|
return Err(Error::Unknown);
|
|
}
|
|
|
|
slice::from_raw_parts(b, l.assume_init_read())
|
|
};
|
|
|
|
let len = match min(buf.len(), dst.len()) {
|
|
0 => return Err(Error::Unknown),
|
|
l => l,
|
|
};
|
|
|
|
dst[..len].copy_from_slice(&buf[..len]);
|
|
|
|
unsafe {
|
|
br_ssl_engine_sendrec_ack(&mut self.context, len);
|
|
}
|
|
|
|
Ok(len)
|
|
}
|
|
|
|
/// Push incoming TLS record to be decrypted.
|
|
pub fn push_read(&mut self, src: &[u8]) -> Result<usize, Error> {
|
|
let buf = unsafe {
|
|
let mut l = MaybeUninit::<usize>::uninit();
|
|
|
|
let b = br_ssl_engine_recvrec_buf(&self.context, l.as_mut_ptr());
|
|
|
|
if b.is_null() {
|
|
return Err(Error::Unknown);
|
|
}
|
|
|
|
slice::from_raw_parts_mut(b, l.assume_init_read())
|
|
};
|
|
|
|
let len = match min(buf.len(), src.len()) {
|
|
0 => return Err(Error::Unknown),
|
|
l => l,
|
|
};
|
|
|
|
buf[..len].copy_from_slice(&src[..len]);
|
|
|
|
unsafe {
|
|
br_ssl_engine_recvrec_ack(&mut self.context, len);
|
|
}
|
|
|
|
Ok(len)
|
|
}
|
|
|
|
/// Get the application data pushed before.
|
|
pub fn pull_read(&mut self, dst: &mut [u8]) -> Result<usize, Error> {
|
|
let buf = unsafe {
|
|
let mut l = MaybeUninit::<usize>::uninit();
|
|
|
|
let b = br_ssl_engine_recvapp_buf(&self.context, l.as_mut_ptr());
|
|
|
|
if b.is_null() {
|
|
return Err(Error::Unknown);
|
|
}
|
|
|
|
slice::from_raw_parts(b, l.assume_init_read())
|
|
};
|
|
|
|
let len = match min(buf.len(), dst.len()) {
|
|
0 => return Err(Error::Unknown),
|
|
l => l,
|
|
};
|
|
|
|
dst[..len].copy_from_slice(&buf[..len]);
|
|
|
|
unsafe {
|
|
br_ssl_engine_recvapp_ack(&mut self.context, len);
|
|
}
|
|
|
|
Ok(len)
|
|
}
|
|
|
|
pub fn shutdown_recieved(&self) -> bool {
|
|
self.context.shutdown_recv != 0
|
|
}
|
|
}
|