(* Needham Shroeder shared key protocol

Notice that we have slightly changed the protocol such that
the analyzer terminates. The
	{ Nb }Kab -> { Nb-1 }Kab 
is replaced by
	{ Nb, 0 }Kab -> { Nb, 1 }Kab

 *)



fun msg/2.		(* msg(t, text), network traffic at time t. *)

fun store/2.		(* store(t, data), host stored data at time t. *)

fun session/4.		(* session(t, host1, host2, key), host1 and
			   host2 established a connection at time t
			   using shared key.  *)

fun encrypt/2.          (* encrypt(text, key) *)
fun host/1.		(* host(key), hostname for key K_{host,server} *)

(* constants 0 and 1 *)
fun c0/0.
fun c1/0.

(* times, now, latter, last *)
fun t0/0.
fun t1/0.
fun tn/0.

(***** desired reachable goals *****)

query net:msg(t1, secretA[t1, i]).
query net:msg(t1, secretB[t1, i]).

param selFun = NounifsetMaxsize.
nounif net:msg(tn,k25).
nounif net:msg(t1,k25).
nounif net:msg( *t25, k25).

reduc

(* Attacker *)

(* given a key, the attacker can en/decrypt a message *)
net:msg(t, k) & net:msg(t, encrypt(m,k)) -> net:msg(t, m);
net:msg(t, x) & net:msg(t, y) -> net:msg(t, encrypt(x,y));

(* the attacker may invent a host and its key pair *)
net:msg(t, x) -> net:msg(t, host(x));

(* the attacker knows the public keys of its victims *)
net:msg(t, host(Kas[]));
net:msg(t, host(Kbs[]));

net:msg(t0, c0);
net:msg(t0, c1);

(* Any message the attacker sees now, it can replay latter *)
net:msg(t0, m) -> net:msg(t1, m);
net:msg(t1, m) -> net:msg(tn, m);
(* Adding this clause yields termination! 
net:msg(t0, m) -> net:msg(tn, m); *)

(* Any value which A or B stores for sometime (e.g. on disk), the
   attacker may eventually recover. *)
disk:store(t0, x) -> net:msg(t1, x);
disk:store(t1, x) -> net:msg(tn, x);

(* Msg 1, A -> S : A, B, N_A
   Na[hb,t,i] -> A notes that it used Na to initiate a handshake for
   host hb at time t. *)

net:msg(t, hb) ->
    net:msg(t, (host(Kas[]), hb, Na[hb,t,i]));

(* Msg 2, S -> A : {N_A, B, K, {K, A}_K_B }_K_A *)

net:msg(t, (host(ka), host(kb), n)) -> 
    net:msg(t, encrypt( ( n, host(kb), key[ka,kb,n],
                          encrypt((key[ka,kb,n], host(ka)), kb)
                        ), ka));

(* Msg 3, A -> B : {K, A}_K_B 
   A may store K from Msg2; the attacker may discover it after some
   time.
 *)

net:msg(t, encrypt((Na[hb,t,i], hb, k, m), Kas[])) ->
    net:msg(t, m);

net:msg(t, encrypt((Na[hb,t,i], hb, k, m), Kas[])) ->
    disk:store(t, k);

(* Msg 4, B -> A : {N_B,0}_K 
   Nb[ha,t,k,i] -> B notes that it used Nb to finish handshake for
   host ha at time t using key k. *)

net:msg(t, encrypt((k, ha), Kbs[])) ->
    net:msg(t, encrypt((Nb[ha,t,k,i], c0), k));

(* Msg 5, A -> B : {N_B,1}_K 
   A has completed the handshake to use K for securely talking to B.
 *)

net:msg(t, encrypt((nb, c0), k)) ->
    net:msg(t, encrypt((nb, c1), k));

net:msg(t, encrypt((Na[h2,t,i], h2, k, m), Kas[])) &
net:msg(t, encrypt((nb, c0), k)) ->
    a:session(t, host(Kas[]), h2, k);

(* B's response to Msg 5: B notes that it can use K for securely
   talking to A. *)

net:msg(t, encrypt((k, h1), Kbs[])) &
net:msg(t, encrypt((Nb[h1,t,k,i], c1), k)) ->
    b:session(t, host(Kbs[]), h1, k);

(* Msg 6a, A -> B : {SecretA}_K *)

a:session(t, host(Kas[]), host(Kbs[]), k) ->
    net:msg(t, encrypt(secretA[t, i], k));

(* Msg 6b, B -> A : {SecretB}_K *)

b:session(t, host(Kbs[]), host(Kas[]), key) ->
    net:msg(t, encrypt(secretB[t, i], key)).
