*most* cryptography functions finished

This commit is contained in:
c0repwn3r 2022-12-12 20:24:48 -05:00
parent cd25dd1d0e
commit 611ae05913
Signed by: core
GPG key ID: FDBF740DADDCEECF
12 changed files with 169 additions and 15 deletions

View file

@ -1,4 +1,4 @@
use std::net::{IpAddr, Ipv4Addr};
use std::net::{Ipv4Addr};
use quicktap::cidr::{IpInet, Ipv4Inet};
use quicktap::drivers::tun::TunDevice;
use quicktap::drivers::tungeneric::{GenericDriver, GenericInterface};

View file

@ -9,6 +9,15 @@ edition = "2021"
cidr = "0.2.1"
etherparse = "0.13.0"
blake2 = "0.10.5"
tai64 = "4.0.0"
x25519-dalek = "2.0.0-pre.1"
rand = "0.8.5"
hmac = "0.12.1"
chacha20poly1305 = "0.10.1"
[target.'cfg(unix)'.dependencies]
tun = "0.5.4"
tun = "0.5.4"
[dev-dependencies]
hex_lit = "0.1.1"
hex = "0.4.3"

View file

@ -1,10 +0,0 @@
use std::error::Error;
use blake2::Blake2sVar;
pub fn crypto_hash(input: &[u8]) -> Result<[u8; 32], Box<dyn Error>> {
let mut hasher = Blake2sVar::new(32)?;
hasher.update(input);
let mut result_buf = [0u8; 32];
hasher.finalize_variable(&mut result_buf)?;
Ok(result_buf)
}

View file

@ -36,7 +36,7 @@ impl GenericDriver for TunDevice {
/// Upon finding a successful packet inside the internal buffer, or the .clear() method being called, the internal buffer will be cleared.
fn read(&mut self) -> Result<TunPacket, Box<dyn Error>> {
self.packet_buf = [0u8; 4096];
let read_amt = self.device.read(&mut self.packet_buf)?;
let _ = self.device.read(&mut self.packet_buf)?;
let ip_header = IpHeader::from_slice(&self.packet_buf);
if let Ok((packet_header, _, _)) = ip_header {
// Found a packet. Clear read buffers

View file

@ -1,6 +1,6 @@
use std::error::Error;
use cidr::IpInet;
use etherparse::{IpHeader, SlicedPacket};
use etherparse::{IpHeader};
#[derive(Debug)]
pub struct TunPacket {

View file

@ -1,3 +1,3 @@
pub mod drivers; // Baremetal network drivers for various platforms
pub use cidr;
pub mod crypto;
pub mod qcrypto;

View file

@ -0,0 +1,38 @@
use chacha20poly1305::{ChaCha20Poly1305, Error, Key, KeyInit, XChaCha20Poly1305};
use chacha20poly1305::aead::{Aead, Payload, Nonce};
pub fn qcrypto_aead(key: &[u8; 32], counter: u64, plaintext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();
let mut nonce_bytes = [0u8; 12];
nonce_bytes[4..].copy_from_slice(&counter.to_le_bytes());
let mut payload = Payload::from(plaintext);
payload.aad = authtext;
cipher.encrypt(&Nonce::<ChaCha20Poly1305>::from(nonce_bytes), payload)
}
pub fn qcrypto_aead_decrypt(key: &[u8; 32], counter: u64, ciphertext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();
let mut nonce_bytes = [0u8; 12];
nonce_bytes[4..].copy_from_slice(&counter.to_le_bytes());
let mut payload = Payload::from(ciphertext);
payload.aad = authtext;
cipher.decrypt(&Nonce::<ChaCha20Poly1305>::from(nonce_bytes), payload)
}
pub fn qcrypto_xaead(key: &[u8; 32], nonce: &[u8; 24], plaintext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
let mut payload = Payload::from(plaintext);
payload.aad = authtext;
cipher.encrypt(Nonce::<XChaCha20Poly1305>::from_slice(nonce), payload)
}
pub fn qcrypto_xaead_decrypt(key: &[u8; 32], nonce: &[u8; 24], ciphertext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
let mut payload = Payload::from(ciphertext);
payload.aad = authtext;
cipher.decrypt(Nonce::<XChaCha20Poly1305>::from_slice(nonce), payload)
}

View file

@ -0,0 +1,30 @@
use blake2::{Blake2s256, Blake2sMac, Digest};
use blake2::digest::{KeyInit, FixedOutput, Update};
use hmac::SimpleHmac;
type HmacBlake2s = SimpleHmac<Blake2s256>;
pub fn qcrypto_hash(input: &[u8]) -> [u8; 32] {
let mut hasher = Blake2s256::new();
Update::update(&mut hasher, input);
hasher.finalize().into()
}
pub fn qcrypto_mac(key: &[u8], input: &[u8]) -> [u8; 16] {
let mut hasher = Blake2sMac::new_from_slice(key).unwrap();
hasher.update(input);
hasher.finalize_fixed().into()
}
pub fn qcrypto_hmac(key: &[u8], input: &[u8]) -> [u8; 32] {
let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();
Update::update(&mut hasher, input);
hasher.finalize_fixed().into()
}
pub fn qcrypto_hmac_twice(key: &[u8], input: &[u8], input2: &[u8]) -> [u8; 32] {
let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();
Update::update(&mut hasher, input);
Update::update(&mut hasher, input2);
hasher.finalize_fixed().into()
}

View file

@ -0,0 +1,17 @@
use std::error::Error;
use crate::qcrypto::hashes::{qcrypto_hmac, qcrypto_hmac_twice};
pub fn qcrypto_hkdf<const N: usize>(key: &[u8], input: &[u8]) -> Result<[[u8; 32]; N], Box<dyn Error>> {
let mut result_array = [[0u8; 32]; N];
let t0 = qcrypto_hmac(key, input);
let t1 = qcrypto_hmac(&t0, &[1u8]);
result_array[0] = t1;
for n in 0..N {
result_array[n-1] = qcrypto_hmac_twice(&t0, &result_array[n-2], &[n as u8]);
}
Ok(result_array)
}

View file

@ -1,4 +1,16 @@
use tai64::Tai64N;
pub mod hashes;
pub mod pki;
pub mod aead;
#[cfg(test)]
pub mod tests;
pub mod hkdf;
pub fn timestamp() -> Tai64N {
Tai64N::now()
}
pub const CONSTURCTION: &str = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s";
pub const IDENTIFIER: &str = "WireGuard v1 zx2c4 Jason@zx2c4.com";

View file

@ -0,0 +1,14 @@
use rand::rngs::OsRng;
use x25519_dalek::{PublicKey, SharedSecret, StaticSecret};
type Keypair = (StaticSecret, PublicKey);
pub fn qcrypto_dh_generate() -> Keypair {
let secret = StaticSecret::new(OsRng);
let public = PublicKey::from(&secret);
(secret, public)
}
pub fn qcrypto_dh(secret: &StaticSecret, public: &PublicKey) -> SharedSecret {
secret.diffie_hellman(public)
}

View file

@ -0,0 +1,44 @@
use hex_lit::hex;
use x25519_dalek::PublicKey;
use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt};
use crate::qcrypto::hashes::{qcrypto_hash, qcrypto_hmac, qcrypto_mac};
use crate::qcrypto::pki::{qcrypto_dh, qcrypto_dh_generate};
#[test]
fn qcrypto_hash_test() {
assert_eq!(qcrypto_hash(&[0u8; 32]), hex!("320b5ea99e653bc2b593db4130d10a4efd3a0b4cc2e1a6672b678d71dfbd33ad"))
}
#[test]
fn qcrypto_mac_test() {
assert_eq!(qcrypto_mac(&[0u8; 32], &[0u8; 32]), hex!("086de86cfb256a2bc40740062bcf4dcc"))
}
#[test]
fn qcrypto_hmac_test() {
assert_eq!(qcrypto_hmac(&[0u8; 32], &[0u8; 32]), hex!("025108dc4694cac66d549e152b967e41e516cc7568111822bf1ca44cb89bcbca"));
}
#[test]
fn qcrypto_pki_generate_test() {
let keypair = qcrypto_dh_generate();
assert_eq!(keypair.1, PublicKey::from(&keypair.0))
}
#[test]
fn qcrypto_dh_test() {
let alice = qcrypto_dh_generate();
let bob = qcrypto_dh_generate();
let secret = qcrypto_dh(&alice.0, &bob.1);
let secret2 = qcrypto_dh(&bob.0, &alice.1);
assert_eq!(secret.as_bytes(), secret2.as_bytes())
}
#[test]
fn qcrypto_aead_test() {
let ciphertext = qcrypto_aead(&[0u8; 32], 0, &[0u8; 32], &[0u8; 32]).unwrap();
assert_eq!(qcrypto_aead_decrypt(&[0u8; 32], 0, &ciphertext, &[0u8; 32]).unwrap(), [0u8; 32].to_vec())
}
#[test]
fn qcrypto_xaead_test() {
let ciphertext = qcrypto_xaead(&[0u8; 32], &[0u8; 24], &[0u8; 32], &[0u8; 32]).unwrap();
assert_eq!(qcrypto_xaead_decrypt(&[0u8; 32], &[0u8; 24], &ciphertext, &[0u8; 32]).unwrap(), [0u8; 32].to_vec())
}