(* There was an internal error in attack reconstruction
   (image of a name not found).
   The expected result is "Could not reconstruct an attack" *)

(* This is an attempt to model Authenticated GDH.2 (AGDH.2) protocol
of Giuseppe Ateniese, Michael Steiner and Gene Tsudik for 3
participants. The model is only a special case: I am trying to prove
correctness for a single run of the protocol. Group membership is
assumed to be static. *)

(*      
	p0 shares long term key h0 with p3.
	p1 shares long term key h1 with p3.
	p2 shares long term key h2 with p3.
	p0 send {g^n0} to p1. 
	p1 sends {g^n0, g^n1, g^(n0*n1)} to p2.
	p2 send {g^n0n1, g^n1n2, g^n0n2, g^n0n1n2} to p3.
	p3 sets group key to g^n0n1n2n3.
	p3 bcast {g^(n0n1n3h0), g^(n0n2n3h1), g^(n1n2n3h2} to everyone.
	Everyone then recovers their key.  
*)


free c01. 
free c30.
free c12.
free c31.
free c23.
free c32.
free c. 



private free m, h0, h1, h2.


(* Check if attacker can recover m*)
 
query  attacker:m.  



(* Shared key cryptography *)

fun enc/2.
fun dec/2.
equation dec(enc(x,y),y) = x.


(* Diffie-Hellman functions *)
(* Exponential and Diffie-Hellman *)

data g/0.

fun exp/2.

(*

Model properties of exp.

*)

equation exp(exp(g,x),y) = exp(exp(g,y),x).
equation exp(exp(exp(g,y),z),x)=exp(exp(exp(g,y),x),z).
equation exp(exp(exp(g,y),z),x)=exp(exp(exp(g,x),z),y).
equation exp(exp(exp(exp(g,x),y),z),t)=exp(exp(exp(exp(g,x),y),t),z).
equation exp(exp(exp(exp(g,x),y),z),t)=exp(exp(exp(exp(g,x),z),t),y).
equation exp(exp(exp(exp(g,x),y),z),t)=exp(exp(exp(exp(g,y),z),t),x).



(*

Model the invserse as a destructor.  

*)

reduc inv(exp(exp(exp(exp(g,x),y),z),t),t) = exp(exp(exp(g,x),y),z);
      inv(exp(exp(exp(exp(g,x),y),z),t),z) = exp(exp(exp(g,x),y),t);
      inv(exp(exp(exp(exp(g,x),y),z),t),y) = exp(exp(exp(g,x),z),t);
      inv(exp(exp(exp(exp(g,x),y),z),t),x) = exp(exp(exp(g,y),z),t);
      inv(exp(exp(exp(g,y),z),t),y) = exp(exp(g,t),z);
      inv(exp(exp(exp(g,y),z),t),z) = exp(exp(g,y),t);
      inv(exp(exp(exp(g,y),z),t),t) = exp(exp(g,y),z);
      inv(exp(exp(g,y),z),z) = exp(g,y);
      inv(exp(exp(g,y),z),y) = exp(g,z).
     
      

(* processes *)



let p0 = new n0; 
	let gn0 = exp(g,n0) in
         	out(c01,gn0); 
		in(c30,x1); 
		let k1 = inv(x1,h0) in
		let k = exp(k1,n0) in
		out(c, enc(m,k)).

let p1 = new n1; 
	 let gn1 = exp(g,n1) in
         	in(c01, x0); 
         	let k = exp(x0,n1) in 
                         out(c12,(x0,gn1,k)); (* (g^n0, g^n1, g^n0n1) *)
			 in(c31,v).
			 

			
let p2 = new n2;
	 let gn2 = exp(g,n2) in
	 in(c12,(t,u,v));
	 out(c23,(v,exp(t,n2),exp(u,n2),exp(v,n2))); 
	 (* (g^n0n1, g^n0n2, g^n1n2, g^n0n1n2) *)
	 in(c32,w).
		

		
let p3 = new n3;
	 let gn3 = exp(g,n3) in
	  	in(c23,(u,v,w,x));
		out(c32,exp(exp(u,n3),h2)); (* g^n0n1n3h2 *)
		out(c31,exp(exp(v,n3),h1)); (* g^n0n2n3h1 *)
		out(c30,exp(exp(w,n3),h0)). (* g^n1n2n3h0 *)

		 

process  ( p0 | p1 | p2 | p3 )
