(*

The Protocol

A -> B: aP, CertA
B -> C: aP, CertA, bP, CertB
C -> A: bP, CertB, cP, CertC, enc(K_abc, sign(Kc, (A,B,aP,bP,cP))
A -> B: cP, CertC, enc(K_abc, sign(Kc, (A,B,aP,bP,cP))), enc(K_abc, sign(Ka, (B,C,aP,bP,cP)))
B -> C: enc(K_abc, sign(Ka, (B,C,aP,bP,cP))), enc(K_abc, sign(Kb, (A,C,aP,bP,cP)))
B -> A: enc(K_abc, sign(Kb, (A,C,aP,bP,cP)))

*)

param verboseClauses = short.

(* The public channel *)

free c.

(* Symmetric cryptography *)

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

(* Signatures *)

private fun cert/2.
fun pk/1.
fun sign/2.
reduc readcert(cert(x,y)) = (x,y).
reduc retrieve(pk(k), sign(k,m)) = m.

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

(* The point on elliptic curve *)

fun point/0.

(* Secrecy assumptions *)

not attacker:skA.
not attacker:skB.
not attacker:skC.

query attacker:secret.

(* Processes *)
let processA =

	(* A is the initializator of the protocol *)
        new skA;
	let pkA = pk(skA) in
        let CertA = cert(A, pkA) in

        new Na;
        let aP = mult(point,Na) in
	out(c, (aP, CertA));

        (* A waits for the message from C *)
	in(c, (bP, CertB, cP, CertC, message_c));
        let kABC = exp(e(bP,cP),Na) in
        let Sc = dec(kABC, message_c) in
        let (=B, pkB) = readcert(CertB) in
        let (=C, pkC) = readcert(CertC) in

        (* A checks the signature of C and sends the next message to B *)
        let (=A, =B, =aP, =bP, =cP) = retrieve(pkC, Sc) in
        let Sa = sign(skA, (B, C, aP, bP, cP)) in
        out(c, (cP, CertC, enc(kABC, Sc), enc(kABC, Sa)));

        (* A receives the last message from B *)
        in(c, message_b);
        let Sb = dec(kABC, message_b) in
        let (=A, =C, =aP, =bP, =cP) = retrieve(pkB, Sb) in

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

let processB =


        new skB;
        let pkB = pk(skB) in
        let CertB = cert(B, pkB) in

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

        (* B sends a message to C *)
        new Nb;
        let bP = mult(point,Nb) in
	out(c, (aP, CertA, bP, CertB));

        (* B waits for the next message from A *)
        in(c, (cP, CertC, message_c, message_a));
        let kABC = exp(e(aP,cP),Nb) in
        let Sc = dec(kABC, message_c) in
        let Sa = dec(kABC, message_a) in
        let (=C, pkC) = readcert(CertC) in

        (* B checks the signatures of A and C and sends the next messages to both A and C *)
        let (=A, =B, =aP, =bP, =cP) = retrieve(pkC, Sc) in
        let (=B, =C, =aP, =bP, =cP) = retrieve(pkA, Sa) in
        let Sb = sign(skB, (A, C, aP, bP, cP)) in

        out(c, (enc(kABC, Sa), enc(kABC, Sb)));
        out(c, (enc(kABC, Sb)));

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

let processC =

        new skC;
        let pkC = pk(skC) in
        let CertC = cert(C, pkC) in

	(* C waits for a message from B *)
        in(c, (aP, CertA, bP, CertB));
        let (=A, pkA) = readcert(CertA) in
        let (=B, pkB) = readcert(CertB) in

        new Nc;
        let cP = mult(point,Nc) in
        let Sc = sign(skC, (A, B, aP, bP, cP)) in
        let kABC = exp(e(aP,bP),Nc) in
	out(c, (bP, CertB, cP, CertC, enc(kABC, Sc)));

        (* C receives the last message from B *)
        in(c, (message_a, message_b));
        let Sa = dec(kABC, message_a) in
        let Sb = dec(kABC, message_b) in

        let (=A, =C, =aP, =bP, =cP) = retrieve(pkB, Sb) in
        let (=B, =C, =aP, =bP, =cP) = retrieve(pkA, Sa) 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))
