Preparation work to write/encrypt response
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
9e1312b149
commit
c3aff3e8df
|
@ -14,7 +14,7 @@ use crate::{
|
|||
connection::ID,
|
||||
enc::{
|
||||
asym::{ExchangePubKey, KeyExchange, KeyID},
|
||||
sym::CipherKind,
|
||||
sym::{CipherKind, Secret},
|
||||
},
|
||||
};
|
||||
use ::std::{collections::VecDeque, num::NonZeroU64, vec::Vec};
|
||||
|
@ -250,16 +250,16 @@ impl super::HandshakeParsing for Resp {
|
|||
}
|
||||
|
||||
/// Decrypted response data
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RespData {
|
||||
/// Client nonce, copied from the request
|
||||
client_nonce: Nonce,
|
||||
pub client_nonce: Nonce,
|
||||
/// Server Connection ID
|
||||
id: ID,
|
||||
pub id: ID,
|
||||
/// Service Connection ID
|
||||
service_id: ID,
|
||||
pub service_id: ID,
|
||||
/// Service encryption key
|
||||
service_key: [u8; 32],
|
||||
pub service_key: Secret,
|
||||
}
|
||||
|
||||
impl RespData {
|
||||
|
@ -282,6 +282,6 @@ impl RespData {
|
|||
self.service_id.serialize(&mut out[start..end]);
|
||||
start = end;
|
||||
end = end + Self::NONCE_LEN;
|
||||
out[start..end].copy_from_slice(&self.service_key);
|
||||
out[start..end].copy_from_slice(self.service_key.as_ref());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ pub enum Error {
|
|||
/// Not enough data
|
||||
#[error("not enough data")]
|
||||
NotEnoughData,
|
||||
/// buffer too small
|
||||
#[error("buffer too small")]
|
||||
InsufficientBuffer,
|
||||
/// Wrong Key type found.
|
||||
/// You might have passed rsa keys where x25519 was expected
|
||||
#[error("wrong key type")]
|
||||
|
|
|
@ -30,9 +30,19 @@ impl Drop for HkdfInner {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl Clone for HkdfInner {
|
||||
fn clone(&self) -> Self {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
Self {
|
||||
hkdf: self.hkdf.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sha3 based HKDF
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Clone)]
|
||||
pub struct HkdfSha3 {
|
||||
inner: HkdfInner,
|
||||
}
|
||||
|
@ -60,3 +70,13 @@ impl HkdfSha3 {
|
|||
out.into()
|
||||
}
|
||||
}
|
||||
|
||||
// Fake debug implementation to avoid leaking secrets
|
||||
impl ::core::fmt::Debug for HkdfSha3 {
|
||||
fn fmt(
|
||||
&self,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> Result<(), ::std::fmt::Error> {
|
||||
::core::fmt::Debug::fmt("[hidden hkdf]", f)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,18 @@ use ::zeroize::Zeroize;
|
|||
|
||||
/// Secret, used for keys.
|
||||
/// Grants that on drop() we will zero out memory
|
||||
#[derive(Zeroize)]
|
||||
#[derive(Zeroize, Clone)]
|
||||
#[zeroize(drop)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct Secret([u8; 32]);
|
||||
// Fake debug implementation to avoid leaking secrets
|
||||
impl ::core::fmt::Debug for Secret {
|
||||
fn fmt(
|
||||
&self,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> Result<(), ::std::fmt::Error> {
|
||||
::core::fmt::Debug::fmt("[hidden secret]", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Secret {
|
||||
/// New randomly generated secret
|
||||
|
@ -49,12 +57,12 @@ impl CipherKind {
|
|||
/// required length of the nonce
|
||||
pub fn nonce_len(&self) -> usize {
|
||||
// TODO: how the hell do I take this from ::chacha20poly1305?
|
||||
::ring::aead::CHACHA20_POLY1305.nonce_len()
|
||||
Nonce::len()
|
||||
}
|
||||
/// required length of the key
|
||||
pub fn key_len(&self) -> usize {
|
||||
use ::chacha20poly1305::KeySizeUser;
|
||||
::chacha20poly1305::XChaCha20Poly1305::key_size()
|
||||
use ::chacha20poly1305::{KeySizeUser, XChaCha20Poly1305};
|
||||
XChaCha20Poly1305::key_size()
|
||||
}
|
||||
/// Length of the authentication tag
|
||||
pub fn tag_len(&self) -> usize {
|
||||
|
@ -109,11 +117,7 @@ impl Cipher {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn decrypt<'a>(
|
||||
&self,
|
||||
aad: AAD,
|
||||
data: &mut VecDeque<u8>,
|
||||
) -> Result<(), Error> {
|
||||
fn decrypt(&self, aad: AAD, data: &mut VecDeque<u8>) -> Result<(), Error> {
|
||||
match self {
|
||||
Cipher::XChaCha20Poly1305(cipher) => {
|
||||
use ::chacha20poly1305::{
|
||||
|
@ -147,6 +151,32 @@ impl Cipher {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn encrypt(
|
||||
&self,
|
||||
aad: AAD,
|
||||
nonce: Nonce,
|
||||
data: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
match self {
|
||||
Cipher::XChaCha20Poly1305(cipher) => {
|
||||
use ::chacha20poly1305::{
|
||||
aead::generic_array::GenericArray, AeadInPlace,
|
||||
};
|
||||
let min_len: usize = CipherKind::XChaCha20Poly1305.nonce_len()
|
||||
+ CipherKind::XChaCha20Poly1305.tag_len()
|
||||
+ 1;
|
||||
if data.len() < min_len {
|
||||
return Err(Error::InsufficientBuffer);
|
||||
}
|
||||
// write Nonce, then advance it
|
||||
|
||||
// encrypt data
|
||||
|
||||
// add tag
|
||||
}
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Receive only cipher
|
||||
|
@ -254,7 +284,7 @@ impl Nonce {
|
|||
}
|
||||
}
|
||||
/// Length of this nonce in bytes
|
||||
pub fn len() -> usize {
|
||||
pub const fn len() -> usize {
|
||||
return 12;
|
||||
}
|
||||
/// Get reference to the nonce bytes
|
||||
|
|
48
src/lib.rs
48
src/lib.rs
|
@ -61,13 +61,24 @@ struct FenrirInner {
|
|||
keys: ArcSwapAny<Arc<Vec<HandshakeKey>>>,
|
||||
}
|
||||
|
||||
/// Information needed to reply after the key exchange
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AuthNeededInfo {
|
||||
/// Parsed handshake
|
||||
pub handshake: Handshake,
|
||||
/// hkdf generated from the handshake
|
||||
pub hkdf: HkdfSha3,
|
||||
/// cipher to be used in both directions
|
||||
pub cipher: CipherKind,
|
||||
}
|
||||
|
||||
/// Intermediate actions to be taken while parsing the handshake
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum HandshakeAction {
|
||||
/// Parsing finished, all ok, nothing to do
|
||||
None,
|
||||
/// Packet parsed, now go perform authentication
|
||||
AuthNeeded(Handshake),
|
||||
AuthNeeded(AuthNeededInfo),
|
||||
}
|
||||
|
||||
// No async here
|
||||
|
@ -144,7 +155,13 @@ impl FenrirInner {
|
|||
}
|
||||
req.set_data(dirsync::ReqData::deserialize(&req.data)?);
|
||||
|
||||
return Ok(HandshakeAction::AuthNeeded(handshake));
|
||||
let cipher = req.cipher;
|
||||
|
||||
return Ok(HandshakeAction::AuthNeeded(AuthNeededInfo {
|
||||
handshake,
|
||||
hkdf,
|
||||
cipher,
|
||||
}));
|
||||
}
|
||||
DirSync::Resp(resp) => {
|
||||
todo!();
|
||||
|
@ -396,7 +413,7 @@ impl Fenrir {
|
|||
}
|
||||
};
|
||||
match action {
|
||||
HandshakeAction::AuthNeeded(hshake) => {
|
||||
HandshakeAction::AuthNeeded(authinfo) => {
|
||||
let tk_check = match token_check.load_full() {
|
||||
Some(tk_check) => tk_check,
|
||||
None => {
|
||||
|
@ -410,7 +427,7 @@ impl Fenrir {
|
|||
dirsync::{self, DirSync},
|
||||
HandshakeData,
|
||||
};
|
||||
match hshake.data {
|
||||
match authinfo.handshake.data {
|
||||
HandshakeData::DirSync(ds) => match ds {
|
||||
DirSync::Req(req) => {
|
||||
use dirsync::ReqInner;
|
||||
|
@ -458,6 +475,29 @@ impl Fenrir {
|
|||
let srv_secret =
|
||||
enc::sym::Secret::new_rand(&fenrir.rand);
|
||||
|
||||
let resp_data = dirsync::RespData {
|
||||
client_nonce: req_data.nonce,
|
||||
id: auth_conn_id,
|
||||
service_id: srv_conn_id,
|
||||
service_key: srv_secret,
|
||||
};
|
||||
// build response
|
||||
let secret_send =
|
||||
authinfo.hkdf.get_secret(b"to_client");
|
||||
let cipher_send = CipherRecv::new(
|
||||
authinfo.cipher,
|
||||
secret_send,
|
||||
);
|
||||
use crate::enc::sym::AAD;
|
||||
let aad = AAD(&mut []); // no aad for now
|
||||
/*
|
||||
match cipher_send.encrypt(aad, &mut req.data.ciphertext()) {
|
||||
Ok(()) => req.data.mark_as_cleartext(),
|
||||
Err(e) => {
|
||||
return Err(handshake::Error::Key(e).into());
|
||||
}
|
||||
}
|
||||
*/
|
||||
todo!()
|
||||
}
|
||||
_ => {
|
||||
|
|
Loading…
Reference in New Issue