(* Verification of Condition 5 in the definition of coercion-resistance 

This script has been obtained by transforming a similar script by 
Backes, Hritcu and Maffei available at 
http://www.infsec.cs.uni-sb.de/~maffei/ev.zip
We removed the swapping and used synchronisations (sync) instead.
We removed private channel communications, to simplify the script.
That helps both the understanding and the tool ProVerif.
We made other minor changes. *)


(* Equational theory for cryptography + autogenerated ZK-theory *)

fun public1/1.
fun blindsign/2.
fun false/0.
fun sigver/3.
fun fakezk1/3. (* autogenerated ZK-theory *)
fun sk/1.
fun fakezk0/2. (* autogenerated ZK-theory *)
fun beta1/0. (* autogenerated ZK-theory *)
fun hash/1.
fun blindmessage/1.
fun or/2.
fun sign/2.
fun fakever/3. (* autogenerated ZK-theory *)
fun pk/1.
fun fakepublic/2. (* autogenerated ZK-theory *)
fun land/2.
fun alpha1/0. (* autogenerated ZK-theory *)
fun zkver0/1. 
fun zk0/2.
fun penc/3.
fun g/2. (* autogenerated ZK-theory *)
fun blindver/3.
fun true/0.
fun message/1.
fun unblind/2.
fun blind/2.
fun formula/1. (* autogenerated ZK-theory *)
fun eq/2.
reduc dec(penc(x,pk(y),z),sk(y)) = x.
fun petfalse/0.
reduc pet(penc(x,pk(y),z1),penc(x,pk(y),z2),sk(y)) = true.
reduc equals(x,x)=x.
equation eq(x,x) = true.
equation message(sign(x,y)) = x.
equation sigver(sign(x,sk(y)),x,pk(y)) = true.
equation blindver(unblind(blindsign(blind(x,z),sk(y)),z),x,pk(y)) = true.
equation blindmessage(unblind(blindsign(blind(x,z),y),z)) = x.

equation public1(zk0(xalpha1x0,xbeta1x1)) = xbeta1x1. (* autogenerated ZK-theory for ZK(1;1;true) *)
equation formula(zk0(xalpha1x0,xbeta1x1)) = true. (* autogenerated ZK-theory for ZK(1;1;true) *)
equation public1(fakezk1(x3,xbeta1x1,y4)) = xbeta1x1. (* autogenerated ZK-theory *)
equation formula(fakezk0(x3,y4)) = y4. (* autogenerated ZK-theory *)
equation formula(fakezk1(x3,xbeta1x1,y4)) = y4. (* autogenerated ZK-theory *)
equation zkver0(zk0((cred,r2,vote,r1),(penc(vote,pk(y),r1),penc(cred,pk(y),r2),pk(y),vote,z1,z2))) = true. (* replaced by AlternativeZKVer for zk type ZK(1;1;true) *)
equation zkver0(zk0((cred,r2,vote,r1),(penc(vote,pk(y),r1),penc(cred,pk(y),r2),pk(y),z1,vote,z2))) = true. (* replaced by AlternativeZKVer for zk type ZK(1;1;true) *)
equation zkver0(zk0((cred,r2,vote,r1),(penc(vote,pk(y),r1),penc(cred,pk(y),r2),pk(y),z1,z2,vote))) = true. (* replaced by AlternativeZKVer for zk type ZK(1;1;true) *)


(* private channels *)

private free chvote.

(* public channels *)

free res,comm,c.

(* votes *)

free va,vb,vc.

(* Non-deterministic choice of the vote *)

let votechooser = 
    out(chvote,va) | out(chvote,vb) | out(chvote,vc).

(* Tallying authority accepting a bulletin with encrypted credential enccred' 
    Here, the channel res is restricted, so we remove the output on that channel
    and the computation before. *)

let tallier = 
    in(comm,zkp); 0.
    (*
    if zkver0(zkp) = true then 
    let (encvote,enccred,=pk(kT),=va,=vb,=vc)=public1(zkp) in 
    let x = pet(enccred,enccred',sk(kT)) in 
    let vote = dec(encvote,sk(kT)) in 
    out(res,vote).*)

(* Other voters *)

let othervoters =
    (* Registration: create credential *)
    new cred; 
    new r; 
    let enccred = penc(cred,pk(kT),r) in 
     (* The other voters are considered dishonest,
        we leak their credentials *)
    out(comm,(cred, sign(enccred,sk(kR))));
    (* Tallier for that voter *)
    let enccred' = enccred in tallier.

(* Tested voters *)

(* Voter that votes vote, with credential cred *)
let voter =
    new r1; 
    new r2; 
    out(comm,zk0((cred,r2,vote,r1),(penc(vote,pk(kT),r1),penc(cred,pk(kT),r2),pk(kT),va,vb,vc))).


let testedvoters = 
    new cred1; 
    new r1; 
    new cred2; 
    new r2; 
    let enccred1 = penc(cred1,pk(kT),r1) in 
    let enccred2 = penc(cred2,pk(kT),r2) in 
    out(comm,sign(enccred1,sk(kR)));
    out(comm,sign(enccred2,sk(kR))); 

    new fakecred;
    (
    (in(chvote, vote); let cred = choice[cred1,fakecred] in voter)
    |
    (let enccred' = enccred1 in tallier) |
    (let enccred' = enccred2 in tallier) 
    ).

(* 
A voter votes with either a correct credential (cred1) or a fake one
(fakecred). As long as the result of the election is not output by the
tallying authority, the adversary sees no difference.
*)

process 
	new kT; 
	new kR; 
	out(comm,(pk(kT),pk(kR))); 
	testedvoters | 
	! othervoters | 
	! votechooser 

(* EXPECTPV
RESULT Observational equivalence is true.
0.128s (user 0.128s + system 0.000s), max rss 12932K
END *)
