initial commit
Some checks failed
CI / lint (push) Successful in 1m37s
CI / test-python (push) Successful in 1m49s
CI / test-zig (push) Successful in 1m39s
CI / test-wasm (push) Successful in 1m54s
CI / test (push) Successful in 14m44s
CI / miri (push) Successful in 14m18s
CI / build (push) Successful in 1m9s
CI / fuzz-regression (push) Successful in 9m9s
CI / publish (push) Failing after 1m10s
CI / publish-python (push) Failing after 1m46s
CI / publish-wasm (push) Has been cancelled
Some checks failed
CI / lint (push) Successful in 1m37s
CI / test-python (push) Successful in 1m49s
CI / test-zig (push) Successful in 1m39s
CI / test-wasm (push) Successful in 1m54s
CI / test (push) Successful in 14m44s
CI / miri (push) Successful in 14m18s
CI / build (push) Successful in 1m9s
CI / fuzz-regression (push) Successful in 9m9s
CI / publish (push) Failing after 1m10s
CI / publish-python (push) Failing after 1m46s
CI / publish-wasm (push) Has been cancelled
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
This commit is contained in:
commit
1d99048c95
165830 changed files with 79062 additions and 0 deletions
101
soliton/fuzz/fuzz_targets/fuzz_kex_receive_session.rs
Normal file
101
soliton/fuzz/fuzz_targets/fuzz_kex_receive_session.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#![no_main]
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use soliton::{
|
||||
identity::{generate_identity, GeneratedIdentity, HybridSignature, IdentityPublicKey, IdentitySecretKey},
|
||||
kex::{receive_session, SessionInit},
|
||||
primitives::xwing,
|
||||
};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
struct BobKeys {
|
||||
ik_pk: IdentityPublicKey,
|
||||
ik_sk: IdentitySecretKey,
|
||||
spk_sk: xwing::SecretKey,
|
||||
}
|
||||
|
||||
// Fixed Bob identity + SPK keypair — keygen is expensive, amortise across runs.
|
||||
static BOB: LazyLock<BobKeys> = LazyLock::new(|| {
|
||||
let GeneratedIdentity { public_key: ik_pk, secret_key: ik_sk, .. } = generate_identity().unwrap();
|
||||
let (_spk_pk, spk_sk) = xwing::keygen().unwrap();
|
||||
BobKeys { ik_pk, ik_sk, spk_sk }
|
||||
});
|
||||
|
||||
// Fixed Alice identity (the "known sender" Bob trusts).
|
||||
static ALICE_PK: LazyLock<IdentityPublicKey> = LazyLock::new(|| generate_identity().unwrap().public_key);
|
||||
|
||||
const SIG: usize = 3373;
|
||||
const FP: usize = 32;
|
||||
const XPK: usize = 1216;
|
||||
const XCT: usize = 1120;
|
||||
|
||||
// Wire layout:
|
||||
// sig (3373) | sender_fp (32) | recipient_fp (32) | sender_ek (1216)
|
||||
// | ct_ik (1120) | ct_spk (1120) | spk_id (4 BE) | has_opk (1)
|
||||
// | [ct_opk (1120) | opk_id (4 BE)] ← only if has_opk & 0x01
|
||||
// | crypto_version (rest, strict UTF-8; bail if invalid)
|
||||
const MIN: usize = SIG + FP + FP + XPK + XCT + XCT + 4 + 1;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
if data.len() < MIN {
|
||||
return;
|
||||
}
|
||||
let mut off = 0;
|
||||
|
||||
let Ok(sig) = HybridSignature::from_bytes(data[off..off + SIG].to_vec()) else { return; };
|
||||
off += SIG;
|
||||
|
||||
let sender_ik_fingerprint: [u8; FP] = data[off..off + FP].try_into().unwrap();
|
||||
off += FP;
|
||||
let recipient_ik_fingerprint: [u8; FP] = data[off..off + FP].try_into().unwrap();
|
||||
off += FP;
|
||||
|
||||
let Ok(sender_ek) = xwing::PublicKey::from_bytes(data[off..off + XPK].to_vec()) else { return; };
|
||||
off += XPK;
|
||||
|
||||
let Ok(ct_ik) = xwing::Ciphertext::from_bytes(data[off..off + XCT].to_vec()) else { return; };
|
||||
off += XCT;
|
||||
let Ok(ct_spk) = xwing::Ciphertext::from_bytes(data[off..off + XCT].to_vec()) else { return; };
|
||||
off += XCT;
|
||||
|
||||
let spk_id = u32::from_be_bytes(data[off..off + 4].try_into().unwrap());
|
||||
off += 4;
|
||||
|
||||
let has_opk = data[off] & 0x01 != 0;
|
||||
off += 1;
|
||||
|
||||
let (ct_opk, opk_id) = if has_opk {
|
||||
if data.len() < off + XCT + 4 {
|
||||
return;
|
||||
}
|
||||
let Ok(ct) = xwing::Ciphertext::from_bytes(data[off..off + XCT].to_vec()) else { return; };
|
||||
off += XCT;
|
||||
let id = u32::from_be_bytes(data[off..off + 4].try_into().unwrap());
|
||||
off += 4;
|
||||
(Some(ct), Some(id))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
// Use strict from_utf8 to match decode_session_init, which rejects
|
||||
// non-UTF-8 bytes with Error::InvalidData. Lossy decoding would allow
|
||||
// replacement-character strings that can never reach receive_session in
|
||||
// real protocol flow (the wire parser rejects them first).
|
||||
let Ok(crypto_version) = String::from_utf8(data[off..].to_vec()) else { return; };
|
||||
|
||||
let si = SessionInit {
|
||||
crypto_version,
|
||||
sender_ik_fingerprint,
|
||||
recipient_ik_fingerprint,
|
||||
sender_ek,
|
||||
ct_ik,
|
||||
ct_spk,
|
||||
spk_id,
|
||||
ct_opk,
|
||||
opk_id,
|
||||
};
|
||||
|
||||
// receive_session must never panic regardless of input.
|
||||
// Exercises: crypto_version check, fingerprint checks, hybrid signature
|
||||
// verification, KEM decapsulation, HKDF, and rollback on failure.
|
||||
let _ = receive_session(&BOB.ik_pk, &BOB.ik_sk, &ALICE_PK, &si, &sig, &BOB.spk_sk, None);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue