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

(*

    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

*)
(* Bellovin, Merritt, Oakland 92, section 2.1 *)

free c.

(* Symmetric cryptography
   One does not know whether decryption succeeds or not *)

fun enc/2.
fun dec/2.
equation dec(enc(x,y),y) = x.
equation enc(dec(x,y),y) = x.

(* Public key cryptography *)

fun penc/2.
fun pk/1.
reduc pdec(penc(x,pk(y)),y) = x.

free hostA.
private free P.
weaksecret P.

let processA =
	new sEA;
	let EA = pk(sEA) in
	out(c, (hostA, enc(EA, P)));
	in(c,m2);
	let R = pdec(dec(m2,P),sEA) in
	new challengeA;
	out(c, enc((challengeA), R));
	in(c, m4);
	let (=challengeA, challengeB) = dec(m4, R) in
	out(c, enc((challengeB), R)).


let processB =
	in(c, (=hostA, m));
	let EA = dec(m, P) in
	new R;
	out(c, enc(penc(R, EA), P));
	in(c,m3);
	let (challengeA) = dec(m3, R) in
	new challengeB;
	out(c, enc((challengeA, challengeB), R));
	in(c, m5);
	if dec(m5, R) = (challengeB) then
	0.

process 

	(!processA) | (!processB)
