use super::Protocol;
use super::buffers::{RecvBuffer, SendBuffer};
use super::cipher::Cipher;
use super::error::HandshakeError;
use super::hash::Hash;
use super::process;
use super::role::Role;
use super::transport::Transport;
use crate::curve::{Curve, DhCurve};
use crate::provider::{CryptoKeyProvider, DhProvider};
#[doc(hidden)]
pub use super::handshake::HandshakeInner;
#[doc(hidden)]
pub fn new_handshake<Proto, CP>(
provider: CP,
prologue: &[u8],
) -> HandshakeInner<Proto::Curve, Proto::Cipher, Proto::Hash, CP>
where
Proto: Protocol,
CP: CryptoKeyProvider<Proto::Curve>,
{
HandshakeInner::new::<Proto>(provider, prologue)
}
#[doc(hidden)]
pub fn set_rs<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
remote_static: Cu::PublicKey,
) where
Cu: Curve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
inner.symmetric.mix_hash(remote_static.as_ref());
inner.rs = Some(remote_static);
}
#[doc(hidden)]
pub fn set_s<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
static_key: CP::PrivateKey,
) -> Result<(), HandshakeError>
where
Cu: Curve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let s_pub = inner
.provider
.public_key(&static_key)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_hash(s_pub.as_ref());
inner.s_pub = Some(s_pub);
inner.s = Some(static_key);
Ok(())
}
#[doc(hidden)]
pub fn local_ephemeral<Cu, Ci, H, CP>(
inner: &HandshakeInner<Cu, Ci, H, CP>,
) -> Option<&Cu::PublicKey>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
inner.e_pub.as_ref()
}
#[doc(hidden)]
pub fn remote_ephemeral<Cu, Ci, H, CP>(
inner: &HandshakeInner<Cu, Ci, H, CP>,
) -> Option<&Cu::PublicKey>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
inner.re.as_ref()
}
#[doc(hidden)]
pub fn remote_static<Cu, Ci, H, CP>(inner: &HandshakeInner<Cu, Ci, H, CP>) -> Option<&Cu::PublicKey>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
inner.rs.as_ref()
}
#[doc(hidden)]
pub fn send_e<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
out: &mut [u8],
) -> Result<usize, HandshakeError>
where
Cu: DhCurve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let e = inner
.provider
.generate_ephemeral_key()
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
let e_pub = inner
.provider
.public_key(&e)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
let mut buffer = SendBuffer::new(out);
buffer.write(e_pub.as_ref());
inner.symmetric.mix_hash(e_pub.as_ref());
if inner.has_psk {
inner.symmetric.mix_key(e_pub.as_ref());
}
inner.e = Some(e);
inner.e_pub = Some(e_pub);
Ok(buffer.finish().len())
}
#[doc(hidden)]
pub fn send_s<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
out: &mut [u8],
static_key: CP::PrivateKey,
) -> Result<usize, HandshakeError>
where
Cu: Curve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let mut buffer = SendBuffer::new(out);
process::send_s(inner, &mut buffer, static_key)?;
Ok(buffer.finish().len())
}
#[doc(hidden)]
pub fn recv_e<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
input: &[u8],
) -> Result<(Cu::PublicKey, usize), HandshakeError>
where
Cu: Curve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let mut buffer = RecvBuffer::new(input);
let re = process::recv_e(inner, &mut buffer)?;
let consumed = input.len() - buffer.remaining().len();
Ok((re, consumed))
}
#[doc(hidden)]
pub fn recv_s<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
input: &[u8],
) -> Result<(Cu::PublicKey, usize), HandshakeError>
where
Cu: Curve,
Cu::PublicKey: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let mut buffer = RecvBuffer::new(input);
let rs = process::recv_s(inner, &mut buffer)?;
let consumed = input.len() - buffer.remaining().len();
Ok((rs, consumed))
}
#[doc(hidden)]
pub fn es_initiator<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let e = inner
.e
.as_ref()
.ok_or(HandshakeError::MissingEphemeralKey)?;
let rs = inner
.rs
.as_ref()
.ok_or(HandshakeError::MissingRemoteStatic)?;
let ss = inner
.provider
.dh(e, rs)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn es_responder<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let s = inner.s.as_ref().ok_or(HandshakeError::MissingStaticKey)?;
let re = inner
.re
.as_ref()
.ok_or(HandshakeError::MissingRemoteEphemeral)?;
let ss = inner
.provider
.dh(s, re)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn ee<Cu, Ci, H, CP>(inner: &mut HandshakeInner<Cu, Ci, H, CP>) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let e = inner
.e
.as_ref()
.ok_or(HandshakeError::MissingEphemeralKey)?;
let re = inner
.re
.as_ref()
.ok_or(HandshakeError::MissingRemoteEphemeral)?;
let ss = inner
.provider
.dh(e, re)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn se_initiator<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let s = inner.s.as_ref().ok_or(HandshakeError::MissingStaticKey)?;
let re = inner
.re
.as_ref()
.ok_or(HandshakeError::MissingRemoteEphemeral)?;
let ss = inner
.provider
.dh(s, re)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn se_responder<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let e = inner
.e
.as_ref()
.ok_or(HandshakeError::MissingEphemeralKey)?;
let rs = inner
.rs
.as_ref()
.ok_or(HandshakeError::MissingRemoteStatic)?;
let ss = inner
.provider
.dh(e, rs)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn ss<Cu, Ci, H, CP>(inner: &mut HandshakeInner<Cu, Ci, H, CP>) -> Result<(), HandshakeError>
where
Cu: DhCurve,
Cu::SharedSecret: AsRef<[u8]>,
Ci: Cipher,
H: Hash,
CP: DhProvider<Cu>,
{
let s = inner.s.as_ref().ok_or(HandshakeError::MissingStaticKey)?;
let rs = inner
.rs
.as_ref()
.ok_or(HandshakeError::MissingRemoteStatic)?;
let ss = inner
.provider
.dh(s, rs)
.map_err(|e| HandshakeError::Crypto(Box::new(e)))?;
inner.symmetric.mix_key(ss.as_ref());
Ok(())
}
#[doc(hidden)]
pub fn psk<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
psk: &crate::psk::Psk,
) -> Result<(), HandshakeError>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
process::do_psk(inner, psk)
}
#[doc(hidden)]
pub fn send_tail<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
out: &mut [u8],
payload: &[u8],
) -> Result<usize, HandshakeError>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let mut buffer = SendBuffer::new(out);
process::send_payload(inner, &mut buffer, payload)?;
Ok(buffer.finish().len())
}
#[doc(hidden)]
pub fn recv_tail<Cu, Ci, H, CP>(
inner: &mut HandshakeInner<Cu, Ci, H, CP>,
input: &[u8],
payload_out: &mut [u8],
) -> Result<(), HandshakeError>
where
Cu: Curve,
Ci: Cipher,
H: Hash,
CP: CryptoKeyProvider<Cu>,
{
let mut buffer = RecvBuffer::new(input);
process::recv_payload(inner, &mut buffer, payload_out)
}
#[doc(hidden)]
pub fn into_transport<Proto, R, CP>(
inner: HandshakeInner<Proto::Curve, Proto::Cipher, Proto::Hash, CP>,
) -> Transport<Proto>
where
Proto: Protocol,
R: Role,
CP: CryptoKeyProvider<Proto::Curve>,
{
process::recv_to_transport::<Proto, R, CP>(inner)
}