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
impl Session
Sourcepub fn import<'a>(
self,
psk: &[u8],
session_binding: impl Into<Option<SessionBinding<'a>>>,
) -> Result<Self, SessionError>
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 ..]Sourcepub fn serialize<'a>(
self,
out: &mut [u8],
session_binding: impl Into<Option<SessionBinding<'a>>>,
) -> Result<usize, SessionError>
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.
Sourcepub fn export_secret(
&self,
context: &[u8],
out: &mut [u8],
) -> Result<(), SessionError>
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").
Sourcepub fn deserialize<'a>(
bytes: &[u8],
session_binding: impl Into<Option<SessionBinding<'a>>>,
) -> Result<Self, SessionError>
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.
Sourcepub fn transport_channel(&mut self) -> Result<Transport, SessionError>
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.
Sourcepub fn identifier(&self) -> &[u8; 32]
pub fn identifier(&self) -> &[u8; 32]
Output the channel identifier.
Trait Implementations§
Source§impl Deserialize for Session
impl Deserialize for Session
Source§fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, Error>
fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, Error>
bytes from the provided a std::io::Read
and returns the populated struct. Read more