Merge branch 'windows-fix' into 'main'
0.1.10 Release : Correct Windows DNS resolution and Crypto issues Closes #259, #260, and #273 See merge request veilid/veilid!138
This commit is contained in:
commit
e8845df385
@ -1,3 +1,12 @@
|
||||
**Changes in Veilid 0.1.10**
|
||||
- BREAKING CHANGE: ALL MUST UPDATE
|
||||
* VLD0 now adds a BLAKE3 hash round on the DH output to further separate it from the raw key exchange
|
||||
* Bootstraps are fixed now due to DH issue
|
||||
- Windows crate update caused build and nul termination issues for DNS resolver
|
||||
- Fix for network key on the veilid-server command line
|
||||
- Strict verification for Ed25519 enabled
|
||||
- Domain separation for VLD0 signing and crypt
|
||||
|
||||
**Changes in Veilid 0.1.9**
|
||||
- SECURITY FIX
|
||||
* DESCRIPTION: Decompression was occurring in an unbounded way upon envelope receipt.
|
||||
|
@ -288,7 +288,7 @@ impl Envelope {
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt and authenticate message
|
||||
// Encrypt message
|
||||
let encrypted_body = vcrypto.crypt_no_auth_unaligned(&body, &self.nonce.bytes, &dh_secret);
|
||||
|
||||
// Write body
|
||||
|
@ -139,7 +139,9 @@ pub async fn test_no_auth(vcrypto: CryptoSystemVersion) {
|
||||
pub async fn test_dh(vcrypto: CryptoSystemVersion) {
|
||||
trace!("test_dh");
|
||||
let (dht_key, dht_key_secret) = vcrypto.generate_keypair().into_split();
|
||||
assert!(vcrypto.validate_keypair(&dht_key, &dht_key_secret));
|
||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||
assert!(vcrypto.validate_keypair(&dht_key2, &dht_key_secret2));
|
||||
|
||||
let r1 = vcrypto.compute_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||
let r2 = vcrypto.compute_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||
|
@ -9,35 +9,39 @@ use chacha20::XChaCha20;
|
||||
use chacha20poly1305 as ch;
|
||||
use chacha20poly1305::aead::AeadInPlace;
|
||||
use chacha20poly1305::KeyInit;
|
||||
use core::convert::TryInto;
|
||||
use curve25519_dalek::digest::Digest;
|
||||
use ed25519_dalek as ed;
|
||||
use x25519_dalek as xd;
|
||||
|
||||
const VEILID_DOMAIN_SIGN: &[u8] = b"VLD0_SIGN";
|
||||
const VEILID_DOMAIN_CRYPT: &[u8] = b"VLD0_CRYPT";
|
||||
|
||||
const AEAD_OVERHEAD: usize = 16;
|
||||
pub const CRYPTO_KIND_VLD0: CryptoKind = FourCC(*b"VLD0");
|
||||
|
||||
fn ed25519_to_x25519_pk(key: &ed::VerifyingKey) -> VeilidAPIResult<xd::PublicKey> {
|
||||
let mp = key.to_montgomery();
|
||||
Ok(xd::PublicKey::from(mp.to_bytes()))
|
||||
fn public_to_x25519_pk(public: &PublicKey) -> VeilidAPIResult<xd::PublicKey> {
|
||||
let pk_ed = ed::VerifyingKey::from_bytes(&public.bytes).map_err(VeilidAPIError::internal)?;
|
||||
Ok(xd::PublicKey::from(*pk_ed.to_montgomery().as_bytes()))
|
||||
}
|
||||
fn ed25519_to_x25519_sk(key: &ed::SigningKey) -> VeilidAPIResult<xd::StaticSecret> {
|
||||
Ok(xd::StaticSecret::from(*key.to_scalar().as_bytes()))
|
||||
fn secret_to_x25519_sk(secret: &SecretKey) -> VeilidAPIResult<xd::StaticSecret> {
|
||||
// NOTE: ed::SigningKey.to_scalar() does not produce an unreduced scalar, we want the raw bytes here
|
||||
// See https://github.com/dalek-cryptography/curve25519-dalek/issues/565
|
||||
let hash: [u8; SIGNATURE_LENGTH] = ed::Sha512::default()
|
||||
.chain_update(secret.bytes)
|
||||
.finalize()
|
||||
.into();
|
||||
let mut output = [0u8; SECRET_KEY_LENGTH];
|
||||
output.copy_from_slice(&hash[..SECRET_KEY_LENGTH]);
|
||||
|
||||
Ok(xd::StaticSecret::from(output))
|
||||
}
|
||||
|
||||
pub fn vld0_generate_keypair() -> KeyPair {
|
||||
let mut csprng = VeilidRng {};
|
||||
let keypair = ed::SigningKey::generate(&mut csprng);
|
||||
let dht_key = PublicKey::new(
|
||||
keypair.to_keypair_bytes()[ed::SECRET_KEY_LENGTH..]
|
||||
.try_into()
|
||||
.expect("should fit"),
|
||||
);
|
||||
let dht_key_secret = SecretKey::new(
|
||||
keypair.to_keypair_bytes()[0..ed::SECRET_KEY_LENGTH]
|
||||
.try_into()
|
||||
.expect("should fit"),
|
||||
);
|
||||
let signing_key = ed::SigningKey::generate(&mut csprng);
|
||||
let verifying_key = signing_key.verifying_key();
|
||||
let dht_key = PublicKey::new(verifying_key.to_bytes());
|
||||
let dht_key_secret = SecretKey::new(signing_key.to_bytes());
|
||||
|
||||
KeyPair::new(dht_key, dht_key_secret)
|
||||
}
|
||||
@ -130,11 +134,17 @@ impl CryptoSystem for CryptoSystemVLD0 {
|
||||
SharedSecret::new(s)
|
||||
}
|
||||
fn compute_dh(&self, key: &PublicKey, secret: &SecretKey) -> VeilidAPIResult<SharedSecret> {
|
||||
let pk_ed = ed::VerifyingKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?;
|
||||
let pk_xd = ed25519_to_x25519_pk(&pk_ed)?;
|
||||
let sk_ed = ed::SigningKey::from_bytes(&secret.bytes);
|
||||
let sk_xd = ed25519_to_x25519_sk(&sk_ed)?;
|
||||
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
|
||||
let pk_xd = public_to_x25519_pk(&key)?;
|
||||
let sk_xd = secret_to_x25519_sk(&secret)?;
|
||||
|
||||
let dh_bytes = sk_xd.diffie_hellman(&pk_xd).to_bytes();
|
||||
|
||||
let mut hasher = blake3::Hasher::new();
|
||||
hasher.update(VEILID_DOMAIN_CRYPT);
|
||||
hasher.update(&dh_bytes);
|
||||
let output = hasher.finalize();
|
||||
|
||||
Ok(SharedSecret::new(*output.as_bytes()))
|
||||
}
|
||||
fn generate_keypair(&self) -> KeyPair {
|
||||
vld0_generate_keypair()
|
||||
@ -200,11 +210,11 @@ impl CryptoSystem for CryptoSystemVLD0 {
|
||||
let keypair = ed::SigningKey::from_keypair_bytes(&kpb)
|
||||
.map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?;
|
||||
|
||||
let mut dig = Blake3Digest512::new();
|
||||
let mut dig: ed::Sha512 = ed::Sha512::default();
|
||||
dig.update(data);
|
||||
|
||||
let sig_bytes = keypair
|
||||
.sign_prehashed(dig, None)
|
||||
.sign_prehashed(dig, Some(VEILID_DOMAIN_SIGN))
|
||||
.map_err(VeilidAPIError::internal)?;
|
||||
|
||||
let sig = Signature::new(sig_bytes.to_bytes());
|
||||
@ -222,10 +232,11 @@ impl CryptoSystem for CryptoSystemVLD0 {
|
||||
let pk = ed::VerifyingKey::from_bytes(&dht_key.bytes)
|
||||
.map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?;
|
||||
let sig = ed::Signature::from_bytes(&signature.bytes);
|
||||
let mut dig = Blake3Digest512::new();
|
||||
|
||||
let mut dig: ed::Sha512 = ed::Sha512::default();
|
||||
dig.update(data);
|
||||
|
||||
pk.verify_prehashed_strict(dig, None, &sig)
|
||||
pk.verify_prehashed_strict(dig, Some(VEILID_DOMAIN_SIGN), &sig)
|
||||
.map_err(|e| VeilidAPIError::parse_error("Verification failed", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -79,21 +79,19 @@ pub async fn txt_lookup<S: AsRef<str>>(host: S) -> EyreResult<Vec<String>> {
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "windows")] {
|
||||
use core::ffi::c_void;
|
||||
use windows::core::PSTR;
|
||||
use std::ffi::CStr;
|
||||
use windows::core::{PSTR,PCSTR};
|
||||
use std::ffi::{CStr, CString};
|
||||
use windows::Win32::NetworkManagement::Dns::{DnsQuery_UTF8, DnsFree, DNS_TYPE_TEXT, DNS_QUERY_STANDARD, DNS_RECORDA, DnsFreeRecordList};
|
||||
|
||||
let mut out = Vec::new();
|
||||
unsafe {
|
||||
let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut();
|
||||
let status = DnsQuery_UTF8(host.as_ref(), DNS_TYPE_TEXT as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut());
|
||||
if status != 0 {
|
||||
bail!("Failed to resolve TXT record");
|
||||
}
|
||||
let host = CString::new(host.as_ref()).wrap_err("invalid host string")?;
|
||||
DnsQuery_UTF8(PCSTR::from_raw(host.as_bytes_with_nul().as_ptr()), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, None, &mut p_query_results as *mut *mut DNS_RECORDA, None).wrap_err("Failed to resolve TXT record")?;
|
||||
|
||||
let mut p_record: *mut DNS_RECORDA = p_query_results;
|
||||
while !p_record.is_null() {
|
||||
if (*p_record).wType == DNS_TYPE_TEXT as u16 {
|
||||
if (*p_record).wType == DNS_TYPE_TEXT.0 {
|
||||
let count:usize = (*p_record).Data.TXT.dwStringCount.try_into().unwrap();
|
||||
let string_array: *const PSTR = &(*p_record).Data.TXT.pStringArray[0];
|
||||
for n in 0..count {
|
||||
@ -107,7 +105,7 @@ pub async fn txt_lookup<S: AsRef<str>>(host: S) -> EyreResult<Vec<String>> {
|
||||
}
|
||||
p_record = (*p_record).pNext;
|
||||
}
|
||||
DnsFree(p_query_results as *const c_void, DnsFreeRecordList);
|
||||
DnsFree(Some(p_query_results as *const c_void), DnsFreeRecordList);
|
||||
}
|
||||
Ok(out)
|
||||
|
||||
@ -139,8 +137,8 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult<String> {
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "windows")] {
|
||||
use core::ffi::c_void;
|
||||
use windows::core::PSTR;
|
||||
use std::ffi::CStr;
|
||||
use windows::core::{PSTR,PCSTR};
|
||||
use std::ffi::{CStr, CString};
|
||||
use windows::Win32::NetworkManagement::Dns::{DnsQuery_UTF8, DnsFree, DNS_TYPE_PTR, DNS_QUERY_STANDARD, DNS_RECORDA, DnsFreeRecordList};
|
||||
|
||||
let host = match ip_addr {
|
||||
@ -159,14 +157,12 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult<String> {
|
||||
|
||||
unsafe {
|
||||
let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut();
|
||||
let status = DnsQuery_UTF8(host, DNS_TYPE_PTR as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut());
|
||||
if status != 0 {
|
||||
bail!("Failed to resolve PTR record");
|
||||
}
|
||||
let host = CString::new(host).wrap_err("invalid host string")?;
|
||||
DnsQuery_UTF8(PCSTR::from_raw(host.as_bytes_with_nul().as_ptr()), DNS_TYPE_PTR, DNS_QUERY_STANDARD, None, &mut p_query_results as *mut *mut DNS_RECORDA, None).wrap_err("Failed to resolve PTR record")?;
|
||||
|
||||
let mut p_record: *mut DNS_RECORDA = p_query_results;
|
||||
while !p_record.is_null() {
|
||||
if (*p_record).wType == DNS_TYPE_PTR as u16 {
|
||||
if (*p_record).wType == DNS_TYPE_PTR.0 {
|
||||
let p_name_host: PSTR = (*p_record).Data.PTR.pNameHost;
|
||||
let c_str: &CStr = CStr::from_ptr(p_name_host.0 as *const i8);
|
||||
if let Ok(str_slice) = c_str.to_str() {
|
||||
@ -176,7 +172,7 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult<String> {
|
||||
}
|
||||
p_record = (*p_record).pNext;
|
||||
}
|
||||
DnsFree(p_query_results as *const c_void, DnsFreeRecordList);
|
||||
DnsFree(Some(p_query_results as *const c_void), DnsFreeRecordList);
|
||||
}
|
||||
bail!("No records returned");
|
||||
} else {
|
||||
|
@ -97,20 +97,16 @@ cfg_if! {
|
||||
|
||||
pub fn setup() {
|
||||
SETUP_ONCE.call_once(|| {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "tracing")] {
|
||||
use tracing_subscriber::{filter, fmt, prelude::*};
|
||||
let mut filters = filter::Targets::new().with_default(filter::LevelFilter::TRACE);
|
||||
for ig in DEFAULT_LOG_IGNORE_LIST {
|
||||
filters = filters.with_target(ig, filter::LevelFilter::OFF);
|
||||
}
|
||||
let fmt_layer = fmt::layer();
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt_layer)
|
||||
.with(filters)
|
||||
.init();
|
||||
}
|
||||
use tracing_subscriber::{filter, fmt, prelude::*};
|
||||
let mut filters = filter::Targets::new().with_default(filter::LevelFilter::INFO);
|
||||
for ig in DEFAULT_LOG_IGNORE_LIST {
|
||||
filters = filters.with_target(ig, filter::LevelFilter::OFF);
|
||||
}
|
||||
let fmt_layer = fmt::layer();
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt_layer)
|
||||
.with(filters)
|
||||
.init();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
use super::*;
|
||||
use lz4_flex::block;
|
||||
|
||||
use crate::apibail_generic;
|
||||
|
||||
pub fn compress_prepend_size(input: &[u8]) -> Vec<u8> {
|
||||
block::compress_prepend_size(input)
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.1"
|
||||
version: "1.17.2"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -168,14 +168,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -212,18 +204,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.15"
|
||||
version: "0.12.16"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.5.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -329,10 +321,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -385,10 +377,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "0.6.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -411,7 +403,15 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.1.7"
|
||||
version: "0.1.9"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -437,5 +437,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.5.0"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
flutter: ">=3.10.6"
|
||||
|
Loading…
Reference in New Issue
Block a user