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,
|
connection::ID,
|
||||||
enc::{
|
enc::{
|
||||||
asym::{ExchangePubKey, KeyExchange, KeyID},
|
asym::{ExchangePubKey, KeyExchange, KeyID},
|
||||||
sym::CipherKind,
|
sym::{CipherKind, Secret},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use ::std::{collections::VecDeque, num::NonZeroU64, vec::Vec};
|
use ::std::{collections::VecDeque, num::NonZeroU64, vec::Vec};
|
||||||
|
@ -250,16 +250,16 @@ impl super::HandshakeParsing for Resp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypted response data
|
/// Decrypted response data
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RespData {
|
pub struct RespData {
|
||||||
/// Client nonce, copied from the request
|
/// Client nonce, copied from the request
|
||||||
client_nonce: Nonce,
|
pub client_nonce: Nonce,
|
||||||
/// Server Connection ID
|
/// Server Connection ID
|
||||||
id: ID,
|
pub id: ID,
|
||||||
/// Service Connection ID
|
/// Service Connection ID
|
||||||
service_id: ID,
|
pub service_id: ID,
|
||||||
/// Service encryption key
|
/// Service encryption key
|
||||||
service_key: [u8; 32],
|
pub service_key: Secret,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RespData {
|
impl RespData {
|
||||||
|
@ -282,6 +282,6 @@ impl RespData {
|
||||||
self.service_id.serialize(&mut out[start..end]);
|
self.service_id.serialize(&mut out[start..end]);
|
||||||
start = end;
|
start = end;
|
||||||
end = end + Self::NONCE_LEN;
|
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
|
/// Not enough data
|
||||||
#[error("not enough data")]
|
#[error("not enough data")]
|
||||||
NotEnoughData,
|
NotEnoughData,
|
||||||
|
/// buffer too small
|
||||||
|
#[error("buffer too small")]
|
||||||
|
InsufficientBuffer,
|
||||||
/// Wrong Key type found.
|
/// Wrong Key type found.
|
||||||
/// You might have passed rsa keys where x25519 was expected
|
/// You might have passed rsa keys where x25519 was expected
|
||||||
#[error("wrong key type")]
|
#[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
|
/// Sha3 based HKDF
|
||||||
#[allow(missing_debug_implementations)]
|
#[derive(Clone)]
|
||||||
pub struct HkdfSha3 {
|
pub struct HkdfSha3 {
|
||||||
inner: HkdfInner,
|
inner: HkdfInner,
|
||||||
}
|
}
|
||||||
|
@ -60,3 +70,13 @@ impl HkdfSha3 {
|
||||||
out.into()
|
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.
|
/// Secret, used for keys.
|
||||||
/// Grants that on drop() we will zero out memory
|
/// Grants that on drop() we will zero out memory
|
||||||
#[derive(Zeroize)]
|
#[derive(Zeroize, Clone)]
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
#[allow(missing_debug_implementations)]
|
|
||||||
pub struct Secret([u8; 32]);
|
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 {
|
impl Secret {
|
||||||
/// New randomly generated secret
|
/// New randomly generated secret
|
||||||
|
@ -49,12 +57,12 @@ impl CipherKind {
|
||||||
/// required length of the nonce
|
/// required length of the nonce
|
||||||
pub fn nonce_len(&self) -> usize {
|
pub fn nonce_len(&self) -> usize {
|
||||||
// TODO: how the hell do I take this from ::chacha20poly1305?
|
// TODO: how the hell do I take this from ::chacha20poly1305?
|
||||||
::ring::aead::CHACHA20_POLY1305.nonce_len()
|
Nonce::len()
|
||||||
}
|
}
|
||||||
/// required length of the key
|
/// required length of the key
|
||||||
pub fn key_len(&self) -> usize {
|
pub fn key_len(&self) -> usize {
|
||||||
use ::chacha20poly1305::KeySizeUser;
|
use ::chacha20poly1305::{KeySizeUser, XChaCha20Poly1305};
|
||||||
::chacha20poly1305::XChaCha20Poly1305::key_size()
|
XChaCha20Poly1305::key_size()
|
||||||
}
|
}
|
||||||
/// Length of the authentication tag
|
/// Length of the authentication tag
|
||||||
pub fn tag_len(&self) -> usize {
|
pub fn tag_len(&self) -> usize {
|
||||||
|
@ -109,11 +117,7 @@ impl Cipher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn decrypt<'a>(
|
fn decrypt(&self, aad: AAD, data: &mut VecDeque<u8>) -> Result<(), Error> {
|
||||||
&self,
|
|
||||||
aad: AAD,
|
|
||||||
data: &mut VecDeque<u8>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
match self {
|
match self {
|
||||||
Cipher::XChaCha20Poly1305(cipher) => {
|
Cipher::XChaCha20Poly1305(cipher) => {
|
||||||
use ::chacha20poly1305::{
|
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
|
/// Receive only cipher
|
||||||
|
@ -254,7 +284,7 @@ impl Nonce {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Length of this nonce in bytes
|
/// Length of this nonce in bytes
|
||||||
pub fn len() -> usize {
|
pub const fn len() -> usize {
|
||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
/// Get reference to the nonce bytes
|
/// 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>>>,
|
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
|
/// Intermediate actions to be taken while parsing the handshake
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum HandshakeAction {
|
pub enum HandshakeAction {
|
||||||
/// Parsing finished, all ok, nothing to do
|
/// Parsing finished, all ok, nothing to do
|
||||||
None,
|
None,
|
||||||
/// Packet parsed, now go perform authentication
|
/// Packet parsed, now go perform authentication
|
||||||
AuthNeeded(Handshake),
|
AuthNeeded(AuthNeededInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
// No async here
|
// No async here
|
||||||
|
@ -144,7 +155,13 @@ impl FenrirInner {
|
||||||
}
|
}
|
||||||
req.set_data(dirsync::ReqData::deserialize(&req.data)?);
|
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) => {
|
DirSync::Resp(resp) => {
|
||||||
todo!();
|
todo!();
|
||||||
|
@ -396,7 +413,7 @@ impl Fenrir {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match action {
|
match action {
|
||||||
HandshakeAction::AuthNeeded(hshake) => {
|
HandshakeAction::AuthNeeded(authinfo) => {
|
||||||
let tk_check = match token_check.load_full() {
|
let tk_check = match token_check.load_full() {
|
||||||
Some(tk_check) => tk_check,
|
Some(tk_check) => tk_check,
|
||||||
None => {
|
None => {
|
||||||
|
@ -410,7 +427,7 @@ impl Fenrir {
|
||||||
dirsync::{self, DirSync},
|
dirsync::{self, DirSync},
|
||||||
HandshakeData,
|
HandshakeData,
|
||||||
};
|
};
|
||||||
match hshake.data {
|
match authinfo.handshake.data {
|
||||||
HandshakeData::DirSync(ds) => match ds {
|
HandshakeData::DirSync(ds) => match ds {
|
||||||
DirSync::Req(req) => {
|
DirSync::Req(req) => {
|
||||||
use dirsync::ReqInner;
|
use dirsync::ReqInner;
|
||||||
|
@ -458,6 +475,29 @@ impl Fenrir {
|
||||||
let srv_secret =
|
let srv_secret =
|
||||||
enc::sym::Secret::new_rand(&fenrir.rand);
|
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!()
|
todo!()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
Loading…
Reference in New Issue