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

*)
(* Comparing an abstract MAC primitive to its implementation using
   hashes of blocks, as explained in "mobile values", section 6. 
   This example amounts to a change of signature, with
   the implementation signature having additional equations for the
   benefit of the attacker. *)

fun mac/2. (* MAC specification, with no equation. *)
private fun impl/2. (* choice of a MAC implementation *)

fun f/2. (* variable-length keyed hash *)
fun h/2. (* keyed-hash for a single block *)

(* 
The first, broken implementation uses 
equation impl(k,x) = f(k,x).

The second, correct implementation uses 
equation impl(k,x) = f(k,f(k,x)).
*)

equation impl(k,x) = f(k,f(k,x)).

equation h(f(x,y),z) = f(x,(y,z)).  

free c, c1, c2.

process
	new k;
	(
	  ( !in(c1, x); out(c,(x,choice[mac(k,x),impl(k,x)])))
	|       
	  ( in(c,(x,m)); if choice[mac(k,x),impl(k,x)] = m then out(c2,x))
	)
