[]Struct ossuary::OssuaryConnection

pub struct OssuaryConnection { /* fields omitted */ }

Context for interacting with an encrypted communication channel

All interaction with ossuary's encrypted channels is performed via a OssuaryConnection instance. It holds all of the state required to maintain one side of an encrypted connection.

A context is created with OssuaryConnection::new, passing it a ConnectionType identifying whether it is to act as a client or server. Server contexts can optionally require authentication, verified by providing a list of public keys of permitted clients with OssuaryConnection::add_authorized_keys. Clients, on the other hand, authenticate by setting their secret key with OssuaryConnection::set_secret_key.

A server must create one OssuaryConnection per connected client. Multiple connections cannot be multiplexed in one context.

A OssuaryConnection keeps temporary buffers for both received and soon-to-be transmitted data. This means they are not particularly small objects, but in exchange they can read and write from/to streams set in non-blocking mode without blocking single-threaded applications.

Establishing a connection involves calling OssuaryConnection::send_handshake and OssuaryConnection::recv_handshake in a loop until OssuaryConnection::handshake_done returns true.

Once established, data to encrypt and send is passed to OssuaryConnection::send_data and received data to decrypt is passed to OssuaryConnection::recv_data.

Your program should be structured so that any failures during transmission cause it to fall back to the handshake loop to attempt a reconnection.

Methods

impl OssuaryConnection

pub fn new(
    conn_type: ConnectionType,
    auth_secret_key: Option<&[u8]>
) -> Result<OssuaryConnection, OssuaryError>

Allocate a new OssuaryConnection.

conn_type is a ConnectionType indicating whether this instance is for a client or server.

auth_secret_key is the secret portion of the long-term Ed25519 key used for host authentication. If None is provided, a keypair will be generated for the lifetime of this connection object. This key can be changed with OssuaryConnection::set_secret_key.

pub fn disconnect(&mut self, error: bool)

Terminate a connection, or an on-going connection attempt.

Calling this immediately closes the local end of Ossuary's connection, and queues a disconnect packet to be sent to the remote host to inform it to close its end.

After calling disconnect(), the application should continue calling Ossuary's functions (or at least its handshake functions) in a loop until OssuaryConnection::handshake_done returns the matching error. This allows Ossuary to generate the final disconnect packet.

The handshake will return OssuaryError::ConnectionFailed if 'error' is true, or OssuaryError::ConnectionClosed otherwise.

'error' - Indicates the reason for termination. True means the channel is being closed because of some error, False means it is being closed due to completion or a clean shutdown.

pub fn is_server(&self) -> bool

Whether this context represents a server (as opposed to a client).

pub fn add_authorized_key(&mut self, key: &[u8]) -> Result<(), OssuaryError>

Add public key of permitted remote hosts

During the handshake, both hosts will be required to sign a challenge with their secret authentication key. The host sends both the signature and the public key it signed with. The other side validates the signature, and verifies that the public key is in the list of authorized keys.

Unauthenticated servers do not verify the public key. Authenticated servers do verify the public key, and reject the connection if the key is unknown. Clients verify the public key, and raise OssuaryError::UntrustedServer if the key is unknown, permitting a Trust-On-First-Use scheme if desired.

If a key is rejected, permanent connection failures are raised on both sides.

pub fn add_authorized_keys<'a, T>(
    &mut self,
    keys: T
) -> Result<usize, OssuaryError> where
    T: IntoIterator<Item = &'a [u8]>, 

Add public keys of permitted remote hosts

keys must be an iterable of &[u8] slices containing valid 32-byte ed25519 public keys.

See OssuaryConnection::add_authorized_key for documentation.

pub fn set_secret_key(&mut self, key: &[u8]) -> Result<(), OssuaryError>

Set authentication secret signing key

Changes the secret authentication key of this side of the connection, which was previously set by OssuaryConnection::new

key must be a &[u8] slice containing a valid 32-byte ed25519 signing key. Signing keys should be kept secret and should be stored securely.

This key is used to authenticate during the handshake if the remote server requires authentication. During the handshake, the server will send a challenge (a buffer of random bytes) which the client signs with this secret key. The client returns its public key and the signature of the challenge data to identify which key it is using for authentication, and to prove possession of the secret key.

pub fn local_public_key(&self) -> Result<&[u8], OssuaryError>

Get the local host's authentication public key

When a secret key is set with OssuaryConnection::set_secret_key, the matching public key is calculated. This function returns that public key, which can be shared with a remote server for future authentication.

pub fn remote_public_key(&self) -> Result<&[u8], OssuaryError>

Get the remote host's authentication public key

When a connection is established, or during the initial handshake after reeiving an OssuaryError::UntrustedServer response, this returns the remote side's authentication public key. This is typically needed by a client to get the remote server's key for a Trust-On-First-Use scheme.

impl OssuaryConnection

pub fn send_handshake<T, U>(&mut self, buf: T) -> Result<usize, OssuaryError> where
    T: DerefMut<Target = U>,
    U: Write

Write the next handshake packet into the given buffer

If a handshake packet is ready to be sent, this function writes the encrypted packet into the provided buffer.

This is a critical part of the handshaking stage, when a connection to a remote host is securely established. Each side of the connection must call send_handshake() continuously, and any data that is written to the data buffer must be sent to the remote host. This should be done until OssuaryConnection::handshake_done() returns true.

Note that Ossuary does not perform network operations itself. It is the caller's responsibility to put the written data on the wire. However, you may pass a 'buf' that does this automatically, such as a TcpStream.

Returns the number of bytes written into buf, or an error. You must handle OssuaryError::WouldBlock, which is a recoverable error, but indicates that some bytes were written to the buffer.

pub fn recv_handshake<T, U>(&mut self, buf: T) -> Result<usize, OssuaryError> where
    T: DerefMut<Target = U>,
    U: Read

Read the next handshake packet from the given buffer

If a handshake packet has been received, this function reads and parses the encrypted packet from the provided buffer and updates its internal connection state.

This is a critical part of the handshaking stage, when a connection to a remote host is securely established. Each side of the connection must call recv_handshake() whenever data is received from the network until OssuaryConnection::handshake_done() returns true.

Returns the number of bytes read from buf, or an error. It is the caller's responsibility to ensure that the consumed bytes are removed from the data buffer before it is used again. You must handle OssuaryError::WouldBlock, which is a recoverable error, but indicates that some bytes were also read from the buffer.

pub fn handshake_done(&mut self) -> Result<bool, OssuaryError>

Returns whether the handshake process is complete.

Returns an error if the connection has failed, and specifically raises OssuaryError::UntrustedServer if the handshake has stalled because the remote host sent an authentication key that is not trusted.

In the event of an untrusted server, calling OssuaryConnection::add_authorized_key will mark the key as trusted and allow the handshake to continue. This should only be done if the application is implementing a Trust-On-First-Use policy, and has verified that the remote host's key has never been seen before. It is always best practice to prompt the user in this case before continuing.

impl OssuaryConnection

pub fn send_data<T, U>(
    &mut self,
    in_buf: &[u8],
    out_buf: T
) -> Result<usize, OssuaryError> where
    T: DerefMut<Target = U>,
    U: Write

Encrypts data into a packet suitable for sending over the network

The caller provides unencrypted plaintext data, in any format, in the in_buf buffer. send_data() encrypts it and writes it in the proper packet format into out_buf.

This is the core function for data transmission via ossuary. All data to be sent over an Ossuary connection should pass through this function.

Note that Ossuary does not perform network operations itself. It is the caller's responsibility to put the written data on the wire. However, you may pass a 'buf' that does this automatically, such as a TcpStream.

Returns the number of bytes written to out_buf, or an error.

You must handle OssuaryError::WouldBlock, which is a recoverable error, but indicates that some bytes were written to the buffer. If any bytes are written to out_buf, it can be assumed that all of in_buf was consumed. In the event of a WouldBlock error, you can either continue calling send_data() with the next data to be sent, or you can use OssuaryConnection::flush() to explicitly finish writing the packet.

pub fn recv_data<T, U, R, V>(
    &mut self,
    in_buf: T,
    out_buf: R
) -> Result<(usize, usize), OssuaryError> where
    T: DerefMut<Target = U>,
    U: Read,
    R: DerefMut<Target = V>,
    V: Write

Decrypts data from a packet received from a remote host

The caller provides encrypted data from a remote host in the in_buf buffer. recv_data() decrypts it and writes the plaintext result into out_buf.

This is the core function for data transmission via ossuary. All data received over an Ossuary connection should pass through this function.

Returns the number of bytes written to out_buf, or an error.

You must handle OssuaryError::WouldBlock, which is a recoverable error, but indicates that some bytes were read from in_buf. This indicates that an incomplete packet was received.

pub fn flush<R, V>(&mut self, out_buf: R) -> Result<usize, OssuaryError> where
    R: DerefMut<Target = V>,
    V: Write

Write any cached encrypted data waiting to be sent

If a previous call to OssuaryConnection::send_data was unable to write out all of its data, the remaining data is cached internally. It can be explicitly flushed by calling this function until it returns 0.

After each call, it is the caller's responsibility to put the written data onto the network, unless out_buf is an object that handles that implicitly, such as a TcpStream.

Trait Implementations

impl Default for OssuaryConnection

Auto Trait Implementations

Blanket Implementations

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Clear for T where
    T: InitializableFromZeroed + ?Sized

impl<T> InitializableFromZeroed for T where
    T: Default

impl<T> Same<T> for T

type Output = T

Should always be Self