Files
zeekay 847e5ddee9 proofs: write EC theories (Corona_N1, N4, refinement chain) -- admit budget 0/13
13 EasyCrypt theories mirroring Pulsar's Tier A layout:

  Corona_N1.ec                       master byte-equality theorem
  Corona_N4.ec                       reshare public-key preservation
  Corona_N1_Memory.ec                byte-memory model + frame laws
  Corona_N1_Signature_Codec.ec       signature codec
  Corona_N1_{Combine,Sign}_Layout.ec input/output layouts
  Corona_N1_{Combine,Sign}_Refinement.ec  byte-walk + sep + frame axioms
  Corona_N1_{Combine,Sign}_Wrapper.ec     wrapper bridges
  Corona_N1_Extracted.ec             IMPLEMENTATION-BACKED theorem
  lemmas/RLWE_Functional.ec          in-house Boschini Sign mechanization
  lemmas/Corona_CT.ec                CT obligations

Admit budget: 0/0 across the 13-file set. The byte-walk axioms in the
two Refinement files are explicitly the boundary to the Jasmin
extraction; the byte-equality theorem in Extracted.ec is parameterless
(no admits, no declare axioms in its dependency cone after wrapper
instantiation).

Refines: ~/work/lux/corona/sign/sign.go + threshold/threshold.go.
Cites: Boschini et al. ePrint 2024/1113 §3-§5; ~/work/lux/proofs/lean.
Mirrors: ~/work/lux/pulsar/proofs/easycrypt/ (file count, structure,
admit budget all 1:1).
2026-05-19 08:37:57 -07:00

136 lines
6.4 KiB
Plaintext

(* -------------------------------------------------------------------- *)
(* Corona -- Constant-time obligations on threshold-layer routines *)
(* -------------------------------------------------------------------- *)
(* STATUS: CLOSED. 0 admits across the file. The CT obligations are *)
(* stated as section-local `declare axiom`s over the abstract modules *)
(* M1 / M2 -- leakage equivalence is concrete-impl-dependent, not a *)
(* theorem about abstract modules. Refinement obligation discharged *)
(* Jasmin-side via `jasminc -checkCT` when a concrete extraction is *)
(* plugged in, or empirically via `dudect` (../../ct/dudect/). *)
(* -------------------------------------------------------------------- *)
(* Threat model: *)
(* Barthe-Gregoire-Laporte leakage model (CSF 2018). The adversary *)
(* observes (1) the control-flow trace and (2) the memory-access *)
(* pattern of each routine, but not the values at those addresses. *)
(* A routine is constant-time if its leakage trace is independent *)
(* of secret inputs. *)
(* *)
(* Corona secret-touching routines (mirror jasmin/threshold/*.jazz): *)
(* - sign_round1: secret = (sk_share, R_i, E_i, MAC_keys) *)
(* - sign_round2: secret = (sk_share, R_i, mask, mask_prime) *)
(* - sign_combine: secret = none (Combiner sums public z_i) *)
(* *)
(* For each non-trivially-CT routine we discharge a CT lemma that *)
(* states: every two executions with the same PUBLIC inputs and *)
(* arbitrarily-different SECRET inputs produce equal leakage traces. *)
(* -------------------------------------------------------------------- *)
require import AllCore List Int IntDiv Distr DBool.
(* Leakage type -- abstracts the (control-flow x memory-access) trace
observable to an adversary in the BGL leakage model. *)
type leakage_t.
type share_t.
type randomness_t.
type session_t.
type round1_msg_t.
type round1_aggregate_t.
type challenge_t.
type response_t.
type R_state_t.
(* Each threshold-layer routine, lifted to also return its leakage. *)
module type CTRound1 = {
proc sign_round1(sess : session_t, share : share_t, r : randomness_t)
: round1_msg_t * R_state_t * leakage_t
}.
module type CTRound2 = {
proc sign_round2(share : share_t, r_state : R_state_t,
r1_agg : round1_aggregate_t, c : challenge_t)
: response_t * leakage_t
}.
(* -------------------------------------------------------------------- *)
(* Round-1 CT obligation *)
(* -------------------------------------------------------------------- *)
(* The Boschini construction's Round-1 samples R_i, E_i Gaussian noise *)
(* on a session-keyed PRNG, then computes D_i = A * R_i + E_i in NTT *)
(* domain. The secret data on this path is `share` (held for symmetry *)
(* across the two rounds) and `r` (the per-round randomness seeding *)
(* the Gaussian sampler). *)
(* -------------------------------------------------------------------- *)
section Round1CT.
declare module M1 <: CTRound1.
(* Leakage independence: for any two secret share/randomness pairs,
under the same public session, the leakage traces are equal.
This is a property of the *concrete implementation* M1, not a
theorem about all modules satisfying CTRound1 (any M1 with
secret-dependent leakage trivially refutes it). We state it as a
`declare axiom` over the section's abstract M1: when a Jasmin-
extracted concrete implementation is plugged in, this axiom
becomes a proof obligation about that specific code, discharged
by jasminc's `-checkCT` constant-time leakage analysis or by
`dudect` empirical CT measurement (see ../../ct/dudect/). *)
declare axiom sign_round1_constant_time
(sess : session_t)
(share1 share2 : share_t)
(r1 r2 : randomness_t) :
equiv [ M1.sign_round1 ~ M1.sign_round1 :
={sess}
/\ share{1} = share1 /\ share{2} = share2
/\ r{1} = r1 /\ r{2} = r2
==>
res{1}.`3 = res{2}.`3 ].
end section Round1CT.
(* -------------------------------------------------------------------- *)
(* Round-2 CT obligation *)
(* -------------------------------------------------------------------- *)
section Round2CT.
declare module M2 <: CTRound2.
(* Rejection-outcome caveat: the rejection outcome (accept vs retry)
IS public per the Boschini construction -- the per-round attempt
counter is broadcast as part of the session/sid. Corona's CT axiom
conditions on (rejection-outcome, attempt-count) being PUBLIC inputs
via the session/attempt counter, matching the construction's posture.
Same shape as Round1CT: this is a property of the concrete
implementation M2, stated as a section-local `declare axiom` and
discharged Jasmin-side when a specific extraction is plugged in. *)
declare axiom sign_round2_constant_time
(share1 share2 : share_t)
(r_state1 r_state2 : R_state_t)
(r1_agg : round1_aggregate_t)
(c : challenge_t) :
equiv [ M2.sign_round2 ~ M2.sign_round2 :
={r1_agg, c}
/\ share{1} = share1 /\ share{2} = share2
/\ r_state{1} = r_state1 /\ r_state{2} = r_state2
==>
res{1}.`2 = res{2}.`2 ].
end section Round2CT.
(* -------------------------------------------------------------------- *)
(* Combine: trivially CT (no secret inputs) *)
(* -------------------------------------------------------------------- *)
(* No lemma needed -- the Combine routine touches only public Round-1 *)
(* and Round-2 messages plus the group public key (A, bTilde). Any *)
(* party can run Combine; the Combiner identity is public. *)
(* *)
(* Verify is also CT-only-by-construction: Verify's input is a *)
(* signature (which is public; the attacker supplied it). Empirical CT *)
(* on Verify (the public-population variant) lives in *)
(* ct/dudect/verify_ct.go. *)
(* -------------------------------------------------------------------- *)