mirror of https://github.com/ospab/ostp.git
86 lines
2.9 KiB
Rust
86 lines
2.9 KiB
Rust
use snow::{Builder, HandshakeState, TransportState};
|
|
|
|
use crate::protocol::ProtocolError;
|
|
|
|
const NN_NOISE_PARAMS: &str = "Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s";
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum NoiseRole {
|
|
Initiator,
|
|
Responder,
|
|
}
|
|
|
|
pub enum NoiseSession {
|
|
Handshake(Box<HandshakeState>),
|
|
Transport(TransportState),
|
|
}
|
|
|
|
impl NoiseSession {
|
|
pub fn new(
|
|
role: NoiseRole,
|
|
psk: &[u8; 32],
|
|
) -> Result<Self, ProtocolError> {
|
|
let params = NN_NOISE_PARAMS
|
|
.parse()
|
|
.map_err(|_| ProtocolError::Crypto("noise-params".to_string()))?;
|
|
|
|
let mut builder = Builder::new(params);
|
|
builder = builder.psk(0, psk);
|
|
|
|
let handshake = match role {
|
|
NoiseRole::Initiator => builder
|
|
.build_initiator()
|
|
.map_err(|_| ProtocolError::Crypto("noise-init".to_string()))?,
|
|
NoiseRole::Responder => builder
|
|
.build_responder()
|
|
.map_err(|_| ProtocolError::Crypto("noise-responder".to_string()))?,
|
|
};
|
|
|
|
Ok(Self::Handshake(Box::new(handshake)))
|
|
}
|
|
|
|
pub fn write_handshake(&mut self, payload: &[u8], out: &mut [u8]) -> Result<usize, ProtocolError> {
|
|
match self {
|
|
NoiseSession::Handshake(hs) => hs
|
|
.write_message(payload, out)
|
|
.map_err(|_| ProtocolError::Crypto("noise-write".to_string())),
|
|
NoiseSession::Transport(_) => Err(ProtocolError::State("noise already in transport".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn read_handshake(&mut self, input: &[u8], out: &mut [u8]) -> Result<usize, ProtocolError> {
|
|
match self {
|
|
NoiseSession::Handshake(hs) => hs
|
|
.read_message(input, out)
|
|
.map_err(|e| ProtocolError::Crypto(format!("noise-read: {:?}", e))),
|
|
NoiseSession::Transport(_) => Err(ProtocolError::State("noise already in transport".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn handshake_hash(&self, out: &mut [u8]) -> Result<(), ProtocolError> {
|
|
match self {
|
|
NoiseSession::Handshake(hs) => {
|
|
let hash = hs.get_handshake_hash();
|
|
if out.len() != hash.len() {
|
|
return Err(ProtocolError::Crypto("handshake hash length mismatch".to_string()));
|
|
}
|
|
out.copy_from_slice(hash);
|
|
Ok(())
|
|
}
|
|
NoiseSession::Transport(_) => Err(ProtocolError::State("noise already in transport".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn into_transport(self) -> Result<Self, ProtocolError> {
|
|
match self {
|
|
NoiseSession::Handshake(hs) => {
|
|
let transport = hs
|
|
.into_transport_mode()
|
|
.map_err(|_| ProtocolError::Crypto("noise-transport".to_string()))?;
|
|
Ok(NoiseSession::Transport(transport))
|
|
}
|
|
NoiseSession::Transport(_) => Ok(self),
|
|
}
|
|
}
|
|
}
|