pub struct Session<S> { /* private fields */ }Expand description
Secure-channel session state.
The phantom parameter S tracks which step of the Annex D.4 handshake
the session is in. Each transition consumes the old Session and yields
a new one in the next state — calling methods out of order is therefore a
compile error rather than a runtime fault.
stateDiagram-v2
[*] --> Disconnected: new(scbk)
Disconnected --> Challenged: challenge(RND.A)
Challenged --> Cryptogrammed: receive_ccrypt(ccrypt) ✔
Challenged --> Disconnected: receive_ccrypt(ccrypt) ✘<br/>BadCryptogram
Cryptogrammed --> Secure: confirm_rmac_i(mac) ✔
Cryptogrammed --> Disconnected: confirm_rmac_i(mac) ✘<br/>BadCryptogram
Secure --> Secure: mac() / verify()<br/>seal_data() / open_data()All fields are zeroized when the session is dropped (regardless of which
state it is in), so cancelled or panicking flows do not leave the SCBK or
derived material in memory. Note that Clone is preserved for ergonomic
fork-and-mirror flows: cloning duplicates the key material, and only the
dropped clone is zeroized — the surviving clone still holds keys until it
is dropped in turn.
Implementations§
Source§impl Session<Disconnected>
impl Session<Disconnected>
Sourcepub fn new(scbk: [u8; 16]) -> Self
pub fn new(scbk: [u8; 16]) -> Self
Begin a new session, holding the SCBK we will use.
§Example
use osdp::secure::{SCBK_D, Session};
use osdp::secure::session::Disconnected;
let session = Session::<Disconnected>::new(SCBK_D);
// The next step is `session.challenge(rnd_a)` once we've sent osdp_CHLNG.Sourcepub fn challenge(self, rnd_a: [u8; 8]) -> Session<Challenged>
pub fn challenge(self, rnd_a: [u8; 8]) -> Session<Challenged>
Move to Challenged by capturing the RND.A we are about to send.
Source§impl Session<Challenged>
impl Session<Challenged>
Sourcepub fn receive_ccrypt(
self,
ccrypt: &CCrypt,
) -> Result<Session<Cryptogrammed>, (Session<Disconnected>, SecureSessionError)>
pub fn receive_ccrypt( self, ccrypt: &CCrypt, ) -> Result<Session<Cryptogrammed>, (Session<Disconnected>, SecureSessionError)>
Verify the PD’s CCrypt and move to Cryptogrammed.
Source§impl Session<Cryptogrammed>
impl Session<Cryptogrammed>
Sourcepub fn server_cryptogram(&self) -> [u8; 16]
pub fn server_cryptogram(&self) -> [u8; 16]
Compute the server cryptogram to ship in osdp_SCRYPT.
Sourcepub fn initial_rmac(&self) -> [u8; 16]
pub fn initial_rmac(&self) -> [u8; 16]
Initial R-MAC, computed from S-MAC1/S-MAC2 over the server cryptogram.
Sourcepub fn confirm_rmac_i(
self,
their_rmac_i: &[u8; 16],
) -> Result<Session<Secure>, (Session<Disconnected>, SecureSessionError)>
pub fn confirm_rmac_i( self, their_rmac_i: &[u8; 16], ) -> Result<Session<Secure>, (Session<Disconnected>, SecureSessionError)>
PD echoed back our initial R-MAC; advance to fully Secure.
Source§impl Session<Secure>
impl Session<Secure>
Sourcepub fn mac(&mut self, bytes: &[u8]) -> [u8; 16]
pub fn mac(&mut self, bytes: &[u8]) -> [u8; 16]
Compute the MAC trailer for an outgoing packet body.
bytes is the SOM..end-of-DATA region (as per super::mac::cbc_mac).
Sourcepub fn verify(
&mut self,
bytes: &[u8],
wire_mac: &[u8; 4],
) -> Result<(), SecureSessionError>
pub fn verify( &mut self, bytes: &[u8], wire_mac: &[u8; 4], ) -> Result<(), SecureSessionError>
Verify a received MAC against our locally-computed value.
Sourcepub fn keys(&self) -> &SessionKeys
pub fn keys(&self) -> &SessionKeys
Borrow the derived session keys (for AES-CBC DATA encryption).
Sourcepub fn last_other_mac(&self) -> &[u8; 16]
pub fn last_other_mac(&self) -> &[u8; 16]
Last MAC the other end produced (used as encryption ICV per Annex D).