Preparation work to write/encrypt response

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2023-02-22 21:10:00 +01:00
parent 9e1312b149
commit c3aff3e8df
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
5 changed files with 116 additions and 23 deletions

View File

@ -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());
}
}

View File

@ -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")]

View File

@ -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)
}
}

View File

@ -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

View File

@ -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!()
}
_ => {