Skip to main content

Session

Struct Session 

Source
pub struct Session { /* private fields */ }
Expand description

A long-term session derived from the final handshake state.

Allows the creation of up to u64::MAX distinct, bi-directional secure Channels between initiator and responder, via Session::channel.

The Session can be stored using Session::serialize and loaded using Session::deserialize, which expects references to the same public keys that were used in session creation to succeed.

Warning: Session state must only be stored and loaded using Session::serialize and Session::deserialize. While Session implements tls_codec::{Serialize, Deserialize}, the associated methods should not be called directly, since they do not consume the Session. This opens up the possibility of continual use of a session that has also been serialized. If the serialized session is then deserialized, the deserialized version is stale and using it to re-derive Channels will result in nonce re-use with the potential for loss of confidentiality.

Implementations§

Source§

impl Session

Source

pub fn import<'a>( self, psk: &[u8], session_binding: impl Into<Option<SessionBinding<'a>>>, ) -> Result<Self, SessionError>

Import a secret, replacing the main session secret

A secret psk that is at least 32 bytes long can be imported into the session, replacing the original main session secret K_S with a fresh secret derived from the psk and K_S. If a public key binding is provided it must be the same as for the original session, but the new session will derive a fresh session ID and update the running transcript tx for future imports.

In detail:

K_import = KDF(K_S || psk, "secret import")
tx' = Hash(tx || session_ID)

// From here: treat K_import as though it was the outcome of a handshake
K_S' = KDF(K_import, "session secret" | tx')
session_ID' = KDF(K_S', "shared key id")
§Example
// Initiator and responder finish the handshake resulting in
// `initiator_session` and `responder_session` both bound to public
// keys in `session_binding`.

// WARN: In real usage, `psk` should be at least 32 bytes of high
// entropy randomness.
let psk = [0xab; 32];

// Re-key the initiator session, providing the old session
// binding. This sustains the binding to these public keys.
// `session_binding`, if provided must match the binding of the
// original session.
let initiator_session = initiator_session.import(psk.as_slice(), session_binding).unwrap();

// Re-key the responder session, providing the old session
// binding. This sustains the binding to these public keys.
// `session_binding`, if provided must match the binding of the
// original session.
let responder_session = initiator_session.import(psk.as_slice(), session_binding).unwrap();

// [.. If `psk` was the same on both sides, you can now derive
// transport channels from the re-keyed session as before ..]

// WARN: In real usage, `another_psk` should be at least 32 bytes of high
// entropy randomness.
let another_psk = [0xcd; 32];

// Re-key the initiator session, stripping the binding to the original
// handshake public keys. Once the binding has been stripped it cannot
// be re-established without performing a fresh handshake. Exercise
// with caution to avoid session misbinding attacks.
let unbound_initiator_session = initiator_session.import(another_psk.as_slice(), None).unwrap();

// Re-key the responder session, stripping the binding to the original
// handshake public keys. Once the binding has been stripped it cannot
// be re-established without performing a fresh handshake. Exercise
// with caution to avoid session misbinding attacks.
let unbound_responder_session = responder_session.import(another_psk.as_slice(), None).unwrap();

// [.. If `psk` was the same on both sides, you can now derive
// transport channels from the re-keyed session as before ..]
Source

pub fn serialize<'a>( self, out: &mut [u8], session_binding: impl Into<Option<SessionBinding<'a>>>, ) -> Result<usize, SessionError>

Serializes the session state for storage.

We require the caller to input the public keys (if any) that were used to create the session, in order to enforce they have access to all keys necessary to deserialize the session later on.

WARN: tls_serialize should not be called directly, since it does not consume Session. This opens the possibility for nonce re-use by deserializing a stale Session since the original could be used after serialization.

Source

pub fn export_secret( &self, context: &[u8], out: &mut [u8], ) -> Result<(), SessionError>

Export a secret derived from the main session key.

Derives a secret K from the main session key as K = KDF(K_session, context || "PSQ secret export").

Source

pub fn deserialize<'a>( bytes: &[u8], session_binding: impl Into<Option<SessionBinding<'a>>>, ) -> Result<Self, SessionError>

Deserialize a session state.

If the session was bound to a set of public keys, those same public keys must be provided to validate the binding on deserialization.

Source

pub fn transport_channel(&mut self) -> Result<Transport, SessionError>

Derive a new secure transport channel from the session state.

The new transport channel allows both peers to send and receive messages AEAD encrypted under a fresh channel key derived from the long-term session key.

Source

pub fn identifier(&self) -> &[u8; 32]

Output the channel identifier.

Trait Implementations§

Source§

impl Deserialize for Session

Source§

fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, Error>

This function deserializes the bytes from the provided a std::io::Read and returns the populated struct. Read more
Source§

fn tls_deserialize_exact(bytes: impl AsRef<[u8]>) -> Result<Self, Error>
where Self: Sized,

This function deserializes the provided bytes and returns the populated struct. All bytes must be consumed. Read more
Source§

impl Serialize for &Session

Source§

fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, Error>

Serialize self and write it to the writer. The function returns the number of bytes written to writer.
Source§

fn tls_serialize_detached(&self) -> Result<Vec<u8>, Error>

Serialize self and return it as a byte vector.
Source§

impl Serialize for Session

Source§

fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, Error>

Serialize self and write it to the writer. The function returns the number of bytes written to writer.
Source§

fn tls_serialize_detached(&self) -> Result<Vec<u8>, Error>

Serialize self and return it as a byte vector.
Source§

impl Size for &Session

Source§

impl Size for Session

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Classify for T

Source§

type Classified = T

Source§

fn classify(self) -> T

Source§

impl<T> Declassify for T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

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

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V