(* Needham Shroeder shared key protocol

The weakness of this protocol is that if an attacker has
a session key k[Kas[], Kbs[], Na[Kbs[],c0]]
for one c0, he can have all secrets of B, since B cannot
distinguish different sessions.

With the "Weight" selection function, the analyzer determines himself
all the nounif clauses that have to be added, and achieves termination.
(Even in this rather complicated case.)

Three predicates:
comp:M iff M is a term containing only names of session0
cs0:M iff the attacker can get M in session0
cs1:M iff the attacker can get M in session1 using compromised terms 
of session0.

Rules:
1) rules for comp:
2) comp:x1 & ... & comp:xn -> cs0:a[session0,x1, ..., xn] for every 
session name a
3) the usual rules of the protocol with cs0 and session0
4) cs0:M -> cs1:M
5) the usual rules of the protocol with cs1 and session1

The difference wrt needham-shr-orig6 is that the rules 
	cs0:host(Kas[]);
	cs0:host(Kbs[]);
	cs0:host(Kcs[]);
	cs0:Kcs[];
are replaced by 
	cs0:host(x);
and similarly for cs1.

 *)

pred cs0/1 elimVar, decompData.
pred cs1/1 elimVar, decompData.
pred comp/1 elimVar, decompData.

fun encrypt/2.

fun host/1.

(* constants 0 and 1 *)

data c0/0.
data c1/0.

data decr/1.

data session0/0.
data session1/0.

not cs0:Kas[].
not cs0:Kbs[].
not cs1:Kas[].
not cs1:Kbs[].

query cs1:secretA[session1].
query cs1:secretB[session1].

reduc

(* Attacker *)

cs0:k & cs0:encrypt(m,k) -> cs0:m;
cs0:host(x);
cs0:x & cs0:y -> cs0:encrypt(x,y);

(* key compromise *)

comp:Kas[];
comp:Kbs[];
comp:x -> comp:Na[x,session0];
comp:x & comp:y -> comp:Nb[x,y,session0];
comp:x & comp:y & comp:z -> comp:k[x,y,z,session0]; 
comp:x -> comp:host(x);
comp:x & comp:y -> comp:encrypt(x,y);
comp:secretA[session0];
comp:secretB[session0];

comp:x -> cs0:Na[x, session0];
comp:x & comp:y -> cs0:Nb[x,y,session0];
comp:x & comp:y & comp:z -> cs0:k[x,y,z,session0]; 
cs0:secretA[session0];
cs0:secretB[session0];


(* A *)

cs0:h -> cs0:(host(Kas[]), h, Na[h,session0]);
cs0:encrypt((Na[h,session0], h, key, m), Kas[]) -> cs0:m;
cs0:encrypt((Na[h,session0], h, key, m), Kas[]) & cs0:encrypt(n, key) -> cs0:encrypt(decr(n), key);

cs0:encrypt((Na[host(Kbs[]),session0], host(Kbs[]), key, m), Kas[]) -> cs0:encrypt(secretA[session0], key);


(* B *)

cs0:encrypt((key, h), Kbs[]) -> cs0:encrypt(Nb[key,h,session0], key);

cs0:encrypt((key, host(Kas[])), Kbs[]) & cs0:encrypt(decr(Nb[key,host(Kas[]),session0]), key) -> cs0:encrypt(secretB[session0], key);

(* S *)

cs0:(host(Ks1), host(Ks2), n) -> cs0:encrypt((n, host(Ks2), k[Ks1, Ks2, n, session0], encrypt((k[Ks1, Ks2, n, session0], host(Ks1)), Ks2)), Ks1);

(* Implication *)

cs0:x -> cs1:x;

(* Attacker *)

cs1:k & cs1:encrypt(m,k) -> cs1:m;
cs1:host(x);
cs1:x & cs1:y -> cs1:encrypt(x,y);

(* A *)

cs1:h -> cs1:(host(Kas[]), h, Na[h,session1]);
cs1:encrypt((Na[h,session1], h, key, m), Kas[]) -> cs1:m;
cs1:encrypt((Na[h,session1], h, key, m), Kas[]) & cs1:encrypt(n, key) -> cs1:encrypt(decr(n), key);

cs1:encrypt((Na[host(Kbs[]),session1], host(Kbs[]), key, m), Kas[]) -> cs1:encrypt(secretA[session1], key);


(* B *)

cs1:encrypt((key, h), Kbs[]) -> cs1:encrypt(Nb[key,h,session1], key);

cs1:encrypt((key, host(Kas[])), Kbs[]) & cs1:encrypt(decr(Nb[key,host(Kas[]),session1]), key) -> cs1:encrypt(secretB[session1], key);

(* S *)

cs1:(host(Ks1), host(Ks2), n) -> cs1:encrypt((n, host(Ks2), k[Ks1, Ks2, n, session1], encrypt((k[Ks1, Ks2, n, session1], host(Ks1)), Ks2)), Ks1).

(* EXPECTPV
RESULT goal reachable: cs1:secretB[session1()]
RESULT goal unreachable: cs1:secretA[session1()]
0.024s (user 0.020s + system 0.004s), max rss 9152K
END *)
