(*************************************************************
 *                                                           *
 *  Cryptographic protocol verifier                          *
 *                                                           *
 *  Bruno Blanchet, Vincent Cheval, and Marc Sylvestre       *
 *                                                           *
 *  Copyright (C) INRIA, CNRS 2000-2020                      *
 *                                                           *
 *************************************************************)

(*

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details (in file LICENSE).

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*)
(* 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.

c:encrypt(decr(Nb[k[Kas[],Kbs[],Na[host(Kbs[])]],host(Kas[])]),k[Kas[],Kbs[],Na[host(Kbs[])]])
c:encrypt\(decr\(Nb\[k\[Kas\[\],Kbs\[\],Na\[host\(Kbs\[\]\)\]\],host\(Kas\[\]\)\]\),k\[Kas\[\],Kbs\[\],Na\[host\(Kbs\[\]\)\]\]\)
 *)

param verboseRules = yes.

param selFun = Nounifset.

pred c/1 elimVar, decompData.

fun encrypt/2.

fun host/1.

fun decr/1.

not c:Kas[].
not c:Kbs[].

query c:secretB[].

reduc

(* Attacker *)

c:k & c:encrypt(m,k) -> c:m;
c:host(Kas[]);
c:host(Kbs[]);
c:host(Kcs[]);
c:Kcs[];
c:x & c:y -> c:encrypt(x,y);
c:x -> c:decr(x);
(* c:decr(x) -> c:x; *)

(* A *)

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

(* B *)

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

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

(* S *)

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