(*

The Protocol

xP - public key of A
yP - public key of B
zP - public key of C

x - secret key of A
y - secret key of B
z - secret key of C

A -> B,C: aP, CertA
A -> B,C: bP, CertB
A -> B,C: cP, CertC

key_A = H((e(bP,cP)^a,e(yP,zP)^x))
key_B = H((e(aP,cP)^b,e(xP,zP)^y))
key_C = H((e(aP,bP)^c,e(xP,yP)^z))

*)

param verboseClauses = short.

(* The public channel *)

free c.

(* Symmetric cryptography *)

fun enc/2.
reduc dec(k, enc(k, m)) = m.

(* Certificates *)

private fun cert/2.
reduc readcert(cert(x,y)) = (x,y).

(* Pairing *)
fun e/2.
fun exp/2.
fun mult/2.

(* hash *)
fun hash/1.

(* The point on elliptic curve *)

fun point/0.

(* Query *)
query attacker:secret.

(* Processes *)
let processA =

        (* Nonce generation *)
        new na;
        new nx;

        (* Public key generation *)
	let pkA = mult(point,nx) in
        let CertA = cert(A, pkA) in

        (* Send the information out into network *)
        let aP = mult(point,na) in
	out(c, (aP, CertA));

        (* A waits for the message from B *)
	in(c, (bP, CertB));
        let (=B, yP) = readcert(CertB) in

        (* A waits for the message from C *)
	in(c, (cP, CertC));
        let (=C, zP) = readcert(CertC) in

        let kABC = hash((exp(e(bP,cP),na),exp(e(yP,zP),nx))) in

        (* A,B, and C start to communicate *)
        out(c, enc(kABC, secret));
        0.

let processB =

        (* Nonce generation *)
        new nb;
        new ny;

        (* Public key generation *)
	let pkB = mult(point,ny) in
        let CertB = cert(B, pkB) in

        (* Send the information out into network *)
        let bP = mult(point,nb) in
	out(c, (bP, CertB));

        (* B waits for the message from A *)
	in(c, (aP, CertA));
        let (=A, xP) = readcert(CertA) in

        (* B waits for the message from C *)
	in(c, (cP, CertC));
        let (=C, zP) = readcert(CertC) in

        let kABC = hash((exp(e(aP,cP),nb),exp(e(xP,zP),ny))) in

        (* A,B, and C start to communicate *)
        out(c, enc(kABC, secret));
        0.

let processC =

        (* Nonce generation *)
        new nc;
        new nz;

        (* Public key generation *)
	let pkC = mult(point,nz) in
        let CertC = cert(C, pkC) in

        (* Send the information out into network *)
        let cP = mult(point,nc) in
	out(c, (cP, CertC));

        (* C waits for the message from B *)
	in(c, (bP, CertB));
        let (=B, yP) = readcert(CertB) in

        (* C waits for the message from A *)
	in(c, (aP, CertA));
        let (=A, xP) = readcert(CertA) in
        
        let kABC = hash((exp(e(aP,bP),nc),exp(e(xP,yP),nz))) in

        (* A,B, and C start to communicate *)
        out(c, enc(kABC, secret));
        0.

let simpleCA =
	in(c, pubkey);
	new n;
	out(c, cert(n,pubkey)).

process 

    new A; new B; new C;
    new secret;
    ((!processA) | (!processB) | (!processC) | (!simpleCA))
