CryptoVerif and Tamarin models, minor doc updates
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
This commit is contained in:
parent
9ba7ea2def
commit
3acaa0fa3f
18 changed files with 2925 additions and 8 deletions
116
cryptoverif/LO_Stream_Secrecy.cv
Normal file
116
cryptoverif/LO_Stream_Secrecy.cv
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
(* LO-Stream: Chunk Confidentiality + Integrity (Theorem 13, P1+P2)
|
||||
*
|
||||
* Adapted from CryptoVerif's TLS 1.3 Record Protocol example.
|
||||
*
|
||||
* IND-CPA: Bit-guessing game — adversary submits two equal-length plaintexts,
|
||||
* receives encryption of one based on secret bit b0. Advantage = Pr[guess b0].
|
||||
*
|
||||
* INT-CTXT: Injective correspondence — if decryption succeeds at (count, msg),
|
||||
* encryption must have produced (count, msg).
|
||||
*
|
||||
* Nonce uniqueness enforced via table lookup (nonce-respecting adversary, §9.11(f)).
|
||||
* Nonce derivation: chunk_nonce = xor(base_nonce, count) with injectivity equation.
|
||||
*
|
||||
* Reduces to: XChaCha20-Poly1305 IND-CPA + INT-CTXT.
|
||||
*)
|
||||
|
||||
type key [fixed, large].
|
||||
type seqn [fixed].
|
||||
type nonce_t [fixed, large].
|
||||
type add_data [bounded].
|
||||
|
||||
param N_enc, N_dec.
|
||||
|
||||
(* ---------- Nonce derivation with injectivity ---------- *)
|
||||
(* §15.2: chunk_nonce = base_nonce XOR mask(index, tag_byte)
|
||||
* Modeled as xor(iv, count) per TLS 1.3 record protocol pattern.
|
||||
* CryptoVerif needs the explicit injectivity equation. *)
|
||||
|
||||
fun xor(key, seqn): nonce_t.
|
||||
|
||||
equation forall k: key, n: seqn, n': seqn;
|
||||
(xor(k, n) = xor(k, n')) = (n = n').
|
||||
|
||||
(* ---------- AEAD (IND-CPA + INT-CTXT under unique nonces) ---------- *)
|
||||
|
||||
proba P_cpa.
|
||||
proba P_ctxt.
|
||||
|
||||
expand AEAD_nonce(key, bitstring, bitstring, add_data, nonce_t,
|
||||
enc, dec, injbot, Z, P_cpa, P_ctxt).
|
||||
|
||||
(* Per-chunk AAD includes base_nonce + count (§15.4) *)
|
||||
fun derive_aad(key, seqn): add_data [data].
|
||||
|
||||
letfun stream_encrypt(k: key, n: nonce_t, m: bitstring, aad: add_data) =
|
||||
enc(m, aad, k, n).
|
||||
letfun stream_decrypt(k: key, n: nonce_t, c: bitstring, aad: add_data) =
|
||||
dec(c, aad, k, n).
|
||||
|
||||
(* ---------- Tables for nonce uniqueness (§9.11(f) game hypothesis) ---------- *)
|
||||
|
||||
table table_enc_nonce(seqn).
|
||||
table table_dec_nonce(seqn).
|
||||
|
||||
(* ---------- Security queries ---------- *)
|
||||
|
||||
(* P1 (IND-CPA): secret bit indistinguishable *)
|
||||
query secret b0 [cv_bit].
|
||||
|
||||
(* P2 (INT-CTXT): injective correspondence *)
|
||||
event Sent(seqn, bitstring).
|
||||
event Received(seqn, bitstring).
|
||||
|
||||
query count: seqn, msg: bitstring;
|
||||
inj-event(Received(count, msg)) ==> inj-event(Sent(count, msg))
|
||||
public_vars b0.
|
||||
|
||||
(* ---------- Channels ---------- *)
|
||||
|
||||
channel c_start, c_ready, c_enc_in, c_enc_out, c_dec_in, c_dec_out.
|
||||
|
||||
(* ---------- Encrypt oracle ---------- *)
|
||||
(* Adversary submits (m0, m1, count). Oracle encrypts m_b where b = b0.
|
||||
* Count must not have been used before (nonce-respecting). *)
|
||||
|
||||
let Encrypt(k: key, iv: key, b: bool) =
|
||||
!N_enc
|
||||
in(c_enc_in, (clear1: bitstring, clear2: bitstring, count: seqn));
|
||||
(* Nonce-respecting: reject reused counter *)
|
||||
get table_enc_nonce(=count) in yield else
|
||||
insert table_enc_nonce(count);
|
||||
(* Equal-length requirement for IND-CPA *)
|
||||
if Z(clear1) = Z(clear2) then
|
||||
let clear = if_fun(b, clear1, clear2) in
|
||||
let aad: add_data = derive_aad(iv, count) in
|
||||
let nonce = xor(iv, count) in
|
||||
event Sent(count, clear);
|
||||
let cipher = stream_encrypt(k, nonce, clear, aad) in
|
||||
out(c_enc_out, cipher).
|
||||
|
||||
(* ---------- Decrypt oracle ---------- *)
|
||||
(* Adversary submits (ciphertext, count). Must not reuse count. *)
|
||||
|
||||
let Decrypt(k: key, iv: key) =
|
||||
!N_dec
|
||||
in(c_dec_in, (cipher: bitstring, count: seqn));
|
||||
get table_dec_nonce(=count) in yield else
|
||||
insert table_dec_nonce(count);
|
||||
let aad: add_data = derive_aad(iv, count) in
|
||||
let nonce = xor(iv, count) in
|
||||
let injbot(clear) = stream_decrypt(k, nonce, cipher, aad) in
|
||||
event Received(count, clear).
|
||||
|
||||
(* ---------- Main process ---------- *)
|
||||
|
||||
process
|
||||
in(c_start, ());
|
||||
new b0: bool;
|
||||
new k: key;
|
||||
new iv: key; (* base_nonce — public *)
|
||||
out(c_ready, iv);
|
||||
(Encrypt(k, iv, b0) | Decrypt(k, iv))
|
||||
|
||||
(* EXPECTED
|
||||
All queries proved.
|
||||
END *)
|
||||
Loading…
Add table
Add a link
Reference in a new issue