

(* Generated ProVerif specification *)
set abbreviateDerivation = false.

(* Boolean return types *)
const TRUE: bitstring [data].
const FALSE: bitstring [data].

(* Functions data *)
const UNKNOWN: bitstring [data].

(* Public key cryptography *)
fun pk (bitstring): bitstring.
fun aencrypt (bitstring, bitstring): bitstring.
reduc forall x: bitstring, y: bitstring; adecrypt (aencrypt (x, pk (y)), y) = x.
fun sign (bitstring, bitstring): bitstring.
fun verifySign (bitstring, bitstring, bitstring): bitstring
	reduc forall m: bitstring, sk: bitstring; verifySign (m, sign (m, sk), pk (sk)) = TRUE
	      otherwise forall m: bitstring, m2: bitstring, ppk: bitstring; verifySign (m, m2, ppk) = FALSE.

(* Certificates *)
fun cert (bitstring, bitstring): bitstring.
fun verifyCert (bitstring, bitstring): bitstring
	reduc forall epk: bitstring, sk: bitstring; verifyCert (cert (epk, sign (epk, sk)), pk (sk)) = TRUE
	      otherwise forall m: bitstring, ppk: bitstring; verifyCert (m, ppk) = FALSE.
reduc forall epk: bitstring, sk: bitstring; getpk (cert (epk, sign (epk,sk))) = epk.

(* Symmetric key cryptography *)
fun sencrypt (bitstring, bitstring): bitstring.
reduc forall x: bitstring, k: bitstring; sdecrypt (sencrypt (x, k), k) = x.

(* Diffie-Hellman *)
fun DH (bitstring, bitstring): bitstring.
equation forall x: bitstring, y: bitstring; DH (pk (x), y) = DH (pk (y), x).

(* MAC *)
fun MAC (bitstring, bitstring): bitstring.
fun verifyMAC (bitstring, bitstring, bitstring): bitstring
	reduc forall m: bitstring, k: bitstring; verifyMAC (m, k, MAC (m, k)) = TRUE
	      otherwise forall m: bitstring, m2: bitstring, k: bitstring; verifyMAC (m, k, m2) = FALSE.

(* HASH *)
fun hash (bitstring): bitstring.

(* Channel *)
free ch: channel.

(* Control Channel *)
free chControl: channel.
fun chControlEnc (bitstring): bitstring [private].
reduc forall x: bitstring; chControlDec (chControlEnc (x)) = x [private].

(* Basic Peano Arithmetic *)
const O: bitstring [data].
fun N (bitstring): bitstring.
free call___System___0: bitstring [private].
free call___Bob___0: bitstring [private].
free call___Alice___0: bitstring [private].
free call___CA___1: bitstring [private].
free call___CA___0: bitstring [private].

(* Constants *)

(* Secrecy Assumptions *)

(* Queries Secret *)
query attacker(new Alice___secretData).

(* Queries Event *)
query event(enteringState___Bob___receivingAliceCert()).
event enteringState___Bob___receivingAliceCert().
query event(enteringState___Bob___verifyCert()).
event enteringState___Bob___verifyCert().
query event(enteringState___Bob___state0()).
event enteringState___Bob___state0().
query event(enteringState___Bob___waitingForMessage()).
event enteringState___Bob___waitingForMessage().
query event(enteringState___Bob___messageDecrypt()).
event enteringState___Bob___messageDecrypt().
query event(enteringState___Bob___messageDecrypted()).
event enteringState___Bob___messageDecrypted().
query event(enteringState___Bob___SecretDataReceived()).
event enteringState___Bob___SecretDataReceived().
query event(enteringState___Alice___receivingBobCert()).
event enteringState___Alice___receivingBobCert().
query event(enteringState___Alice___verifyCert()).
event enteringState___Alice___verifyCert().
query event(enteringState___Alice___state0()).
event enteringState___Alice___state0().
query event(enteringState___Alice___makingMessage()).
event enteringState___Alice___makingMessage().
query event(enteringState___Alice___sendingMessage()).
event enteringState___Alice___sendingMessage().
query event(enteringState___Alice___beforeFinish()).
event enteringState___Alice___beforeFinish().
query event(enteringState___CA___waiting()).
event enteringState___CA___waiting().
query event(enteringState___CA___verifyID()).
event enteringState___CA___verifyID().

(* Authenticity *)
event authenticity___Alice___m__data___sendingMessage(bitstring).
event authenticity___Bob___m__data___messageDecrypted(bitstring).
query dummyM: bitstring; inj-event(authenticity___Bob___m__data___messageDecrypted (dummyM)) ==> inj-event(authenticity___Alice___m__data___sendingMessage (dummyM)).

let System___start (Bob___aliceID: bitstring, CA___aliceID: bitstring, Alice___bobID: bitstring, CA___bobID: bitstring, Alice___privK__data: bitstring, Alice___pubK__data: bitstring, CA___alicePubK__data: bitstring, Bob___privK__data: bitstring, Bob___pubK__data: bitstring, CA___bobPubK__data: bitstring, CA___privK__data: bitstring, CA___pubK__data: bitstring, Alice___CAPubK__data: bitstring, Bob___CAPubK__data: bitstring, sessionID: bitstring) =
	in (chControl, strong___System___01: bitstring);
	out (chControl, chControlEnc ((sessionID, call___System___0, strong___System___01))).

let System___0 (sessionID: bitstring) =
	new strong___System___02[]: bitstring;
	out (chControl, strong___System___02);
	in (chControl, chControlData: bitstring);
	let (=sessionID, =call___System___0, =strong___System___02) = chControlDec (chControlData) in
	0.

let Bob___start (Bob___aliceID: bitstring, CA___aliceID: bitstring, Alice___bobID: bitstring, CA___bobID: bitstring, Alice___privK__data: bitstring, Alice___pubK__data: bitstring, CA___alicePubK__data: bitstring, Bob___privK__data: bitstring, Bob___pubK__data: bitstring, CA___bobPubK__data: bitstring, CA___privK__data: bitstring, CA___pubK__data: bitstring, Alice___CAPubK__data: bitstring, Bob___CAPubK__data: bitstring, sessionID: bitstring) =
	new Bob___m__data[]: bitstring;
	new Bob___m2__data[]: bitstring;
	new Bob___sk__data[]: bitstring;
	new Bob___receivedData[]: bitstring;
	new Bob___alicePubK__data[]: bitstring;
	new Bob___m1__data[]: bitstring;
	new Bob___sig__data[]: bitstring;
	new Bob___certOK[]: bitstring;
	in (chControl, strong___Bob___03: bitstring);
	out (chControl, chControlEnc ((sessionID, call___Bob___0, strong___Bob___03, Bob___m__data, Bob___m2__data, Bob___sk__data, Bob___receivedData, Bob___privK__data, Bob___pubK__data, Bob___alicePubK__data, Bob___CAPubK__data, Bob___aliceID, Bob___m1__data, Bob___sig__data, Bob___certOK))).

let Bob___0 (sessionID: bitstring) =
	new strong___Bob___04[]: bitstring;
	out (chControl, strong___Bob___04);
	in (chControl, chControlData: bitstring);
	let (=sessionID, =call___Bob___0, =strong___Bob___04, Bob___m__data___1: bitstring, Bob___m2__data___1: bitstring, Bob___sk__data___1: bitstring, Bob___receivedData___1: bitstring, Bob___privK__data___1: bitstring, Bob___pubK__data___1: bitstring, Bob___alicePubK__data___1: bitstring, Bob___CAPubK__data___1: bitstring, Bob___aliceID___1: bitstring, Bob___m1__data___1: bitstring, Bob___sig__data___1: bitstring, Bob___certOK___1: bitstring) = chControlDec (chControlData) in
	event enteringState___Bob___receivingAliceCert();
	in (ch, Bob___m__data___2: bitstring);
	let (Bob___m1__data___2: bitstring, Bob___sig__data___2: bitstring) = Bob___m__data___2 in
	let Bob___certOK___2: bitstring = verifySign (Bob___m1__data___2, Bob___sig__data___2, Bob___CAPubK__data___1) in
	event enteringState___Bob___verifyCert();
	if Bob___certOK___2 = TRUE then
		let (Bob___m__data___3: bitstring, Bob___m2__data___2: bitstring) = Bob___m1__data___2 in
		event enteringState___Bob___state0();
		if Bob___m2__data___2 = Bob___aliceID___1 then
			let Bob___alicePubK__data___2: bitstring = Bob___m__data___3 in
			event enteringState___Bob___waitingForMessage();
			in (ch, Bob___m2__data___3: bitstring);
			event enteringState___Bob___messageDecrypt();
			let Bob___sk__data___2: bitstring = DH (Bob___alicePubK__data___2, Bob___privK__data___1) in
			let Bob___m__data___4: bitstring = sdecrypt (Bob___m2__data___3, Bob___sk__data___2) in
			event enteringState___Bob___messageDecrypted();
			event authenticity___Bob___m__data___messageDecrypted (Bob___m__data___4);
			let Bob___receivedData___2: bitstring = Bob___m__data___4 in
			event enteringState___Bob___SecretDataReceived().

let Alice___start (Bob___aliceID: bitstring, CA___aliceID: bitstring, Alice___bobID: bitstring, CA___bobID: bitstring, Alice___privK__data: bitstring, Alice___pubK__data: bitstring, CA___alicePubK__data: bitstring, Bob___privK__data: bitstring, Bob___pubK__data: bitstring, CA___bobPubK__data: bitstring, CA___privK__data: bitstring, CA___pubK__data: bitstring, Alice___CAPubK__data: bitstring, Bob___CAPubK__data: bitstring, sessionID: bitstring) =
	new Alice___secretData[]: bitstring;
	new Alice___m__data[]: bitstring;
	new Alice___m1__data[]: bitstring;
	new Alice___sk__data[]: bitstring;
	new Alice___bobPubK__data[]: bitstring;
	new Alice___m2__data[]: bitstring;
	new Alice___sig__data[]: bitstring;
	new Alice___certOK[]: bitstring;
	in (chControl, strong___Alice___05: bitstring);
	out (chControl, chControlEnc ((sessionID, call___Alice___0, strong___Alice___05, Alice___secretData, Alice___m__data, Alice___m1__data, Alice___sk__data, Alice___pubK__data, Alice___privK__data, Alice___bobPubK__data, Alice___CAPubK__data, Alice___bobID, Alice___m2__data, Alice___sig__data, Alice___certOK))).

let Alice___0 (sessionID: bitstring) =
	new strong___Alice___06[]: bitstring;
	out (chControl, strong___Alice___06);
	in (chControl, chControlData: bitstring);
	let (=sessionID, =call___Alice___0, =strong___Alice___06, Alice___secretData___1: bitstring, Alice___m__data___1: bitstring, Alice___m1__data___1: bitstring, Alice___sk__data___1: bitstring, Alice___pubK__data___1: bitstring, Alice___privK__data___1: bitstring, Alice___bobPubK__data___1: bitstring, Alice___CAPubK__data___1: bitstring, Alice___bobID___1: bitstring, Alice___m2__data___1: bitstring, Alice___sig__data___1: bitstring, Alice___certOK___1: bitstring) = chControlDec (chControlData) in
	event enteringState___Alice___receivingBobCert();
	in (ch, Alice___m__data___2: bitstring);
	let (Alice___m1__data___2: bitstring, Alice___sig__data___2: bitstring) = Alice___m__data___2 in
	let Alice___certOK___2: bitstring = verifySign (Alice___m1__data___2, Alice___sig__data___2, Alice___CAPubK__data___1) in
	event enteringState___Alice___verifyCert();
	if Alice___certOK___2 = TRUE then
		let (Alice___m__data___3: bitstring, Alice___m2__data___2: bitstring) = Alice___m1__data___2 in
		event enteringState___Alice___state0();
		if Alice___m2__data___2 = Alice___bobID___1 then
			let Alice___bobPubK__data___2: bitstring = Alice___m__data___3 in
			event enteringState___Alice___makingMessage();
			let Alice___sk__data___2: bitstring = DH (Alice___bobPubK__data___2, Alice___privK__data___1) in
			let Alice___m__data___4: bitstring = Alice___secretData___1 in
			let Alice___m1__data___3: bitstring = sencrypt (Alice___m__data___4, Alice___sk__data___2) in
			event enteringState___Alice___sendingMessage();
			event authenticity___Alice___m__data___sendingMessage (Alice___m__data___4);
			out (ch, Alice___m1__data___3);
			event enteringState___Alice___beforeFinish().

let CA___start (Bob___aliceID: bitstring, CA___aliceID: bitstring, Alice___bobID: bitstring, CA___bobID: bitstring, Alice___privK__data: bitstring, Alice___pubK__data: bitstring, CA___alicePubK__data: bitstring, Bob___privK__data: bitstring, Bob___pubK__data: bitstring, CA___bobPubK__data: bitstring, CA___privK__data: bitstring, CA___pubK__data: bitstring, Alice___CAPubK__data: bitstring, Bob___CAPubK__data: bitstring, sessionID: bitstring) =
	new CA___m__data[]: bitstring;
	new CA___newK__data[]: bitstring;
	new CA___newCert__data[]: bitstring;
	new CA___m1__data[]: bitstring;
	new CA___m2__data[]: bitstring;
	new CA___newID[]: bitstring;
	in (chControl, strong___CA___07: bitstring);
	out (chControl, chControlEnc ((sessionID, call___CA___0, strong___CA___07, CA___privK__data, CA___pubK__data, CA___alicePubK__data, CA___bobPubK__data, CA___aliceID, CA___bobID, CA___m__data, CA___newK__data, CA___newCert__data, CA___m1__data, CA___m2__data, CA___newID))).

let CA___1 (sessionID: bitstring) =
	new strong___CA___18[]: bitstring;
	out (chControl, strong___CA___18);
	in (chControl, chControlData: bitstring);
	let (=sessionID, =call___CA___1, =strong___CA___18, CA___privK__data___1: bitstring, CA___pubK__data___1: bitstring, CA___alicePubK__data___1: bitstring, CA___bobPubK__data___1: bitstring, CA___aliceID___1: bitstring, CA___bobID___1: bitstring, CA___m__data___1: bitstring, CA___newK__data___1: bitstring, CA___newCert__data___1: bitstring, CA___m1__data___1: bitstring, CA___m2__data___1: bitstring, CA___newID___1: bitstring) = chControlDec (chControlData) in
	event enteringState___CA___waiting();
	new choice___waiting___0[]: bitstring;
	out (ch, choice___waiting___0);
	new choice___waiting___1[]: bitstring;
	out (ch, choice___waiting___1);
	in (ch, choice___waiting: bitstring);
	if choice___waiting = choice___waiting___0 then (
		let CA___m1__data___2: bitstring = CA___bobPubK__data___1 in
		let CA___m2__data___2: bitstring = CA___bobID___1 in
		let CA___m__data___2: bitstring = (CA___m1__data___2, CA___m2__data___2) in
		let CA___m1__data___3: bitstring = sign (CA___m__data___2, CA___privK__data___1) in
		let CA___newCert__data___2: bitstring = (CA___m__data___2, CA___m1__data___3) in
		out (ch, CA___newCert__data___2);
		in (chControl, strong___CA___19: bitstring);
		out (chControl, chControlEnc ((sessionID, call___CA___1, strong___CA___19, CA___privK__data___1, CA___pubK__data___1, CA___alicePubK__data___1, CA___bobPubK__data___1, CA___aliceID___1, CA___bobID___1, CA___m__data___2, CA___newK__data___1, CA___newCert__data___2, CA___m1__data___3, CA___m2__data___2, CA___newID___1))))
	else
		if choice___waiting = choice___waiting___1 then (
			in (ch, CA___m__data___2: bitstring);
			let (CA___m1__data___2: bitstring, CA___m2__data___2: bitstring) = CA___m__data___2 in
			let CA___newK__data___2: bitstring = CA___m1__data___2 in
			let CA___newID___2: bitstring = CA___m2__data___2 in
			event enteringState___CA___verifyID();
			if not ((CA___newID___2 <> CA___aliceID___1) && (CA___newID___2 <> CA___bobID___1)) then (
				in (chControl, strong___CA___110: bitstring);
				out (chControl, chControlEnc ((sessionID, call___CA___1, strong___CA___110, CA___privK__data___1, CA___pubK__data___1, CA___alicePubK__data___1, CA___bobPubK__data___1, CA___aliceID___1, CA___bobID___1, CA___m__data___2, CA___newK__data___2, CA___newCert__data___1, CA___m1__data___2, CA___m2__data___2, CA___newID___2))))
			else
				let CA___m1__data___3: bitstring = CA___newK__data___2 in
				let CA___m2__data___3: bitstring = CA___newID___2 in
				let CA___m__data___3: bitstring = (CA___m1__data___3, CA___m2__data___3) in
				let CA___m1__data___4: bitstring = sign (CA___m__data___3, CA___privK__data___1) in
				let CA___newCert__data___2: bitstring = (CA___m__data___3, CA___m1__data___4) in
				out (ch, CA___newCert__data___2);
				in (chControl, strong___CA___111: bitstring);
				out (chControl, chControlEnc ((sessionID, call___CA___1, strong___CA___111, CA___privK__data___1, CA___pubK__data___1, CA___alicePubK__data___1, CA___bobPubK__data___1, CA___aliceID___1, CA___bobID___1, CA___m__data___3, CA___newK__data___2, CA___newCert__data___2, CA___m1__data___4, CA___m2__data___3, CA___newID___2))))
		else
			let CA___m1__data___2: bitstring = CA___alicePubK__data___1 in
			let CA___m2__data___2: bitstring = CA___aliceID___1 in
			let CA___m__data___2: bitstring = (CA___m1__data___2, CA___m2__data___2) in
			let CA___m1__data___3: bitstring = sign (CA___m__data___2, CA___privK__data___1) in
			let CA___newCert__data___2: bitstring = (CA___m__data___2, CA___m1__data___3) in
			out (ch, CA___newCert__data___2);
			in (chControl, strong___CA___112: bitstring);
			out (chControl, chControlEnc ((sessionID, call___CA___1, strong___CA___112, CA___privK__data___1, CA___pubK__data___1, CA___alicePubK__data___1, CA___bobPubK__data___1, CA___aliceID___1, CA___bobID___1, CA___m__data___2, CA___newK__data___1, CA___newCert__data___2, CA___m1__data___3, CA___m2__data___2, CA___newID___1))).

let CA___0 (sessionID: bitstring) =
	new strong___CA___013[]: bitstring;
	out (chControl, strong___CA___013);
	in (chControl, chControlData: bitstring);
	let (=sessionID, =call___CA___0, =strong___CA___013, CA___privK__data___1: bitstring, CA___pubK__data___1: bitstring, CA___alicePubK__data___1: bitstring, CA___bobPubK__data___1: bitstring, CA___aliceID___1: bitstring, CA___bobID___1: bitstring, CA___m__data___1: bitstring, CA___newK__data___1: bitstring, CA___newCert__data___1: bitstring, CA___m1__data___1: bitstring, CA___m2__data___1: bitstring, CA___newID___1: bitstring) = chControlDec (chControlData) in
	in (chControl, strong___CA___114: bitstring);
	out (chControl, chControlEnc ((sessionID, call___CA___1, strong___CA___114, CA___privK__data___1, CA___pubK__data___1, CA___alicePubK__data___1, CA___bobPubK__data___1, CA___aliceID___1, CA___bobID___1, CA___m__data___1, CA___newK__data___1, CA___newCert__data___1, CA___m1__data___1, CA___m2__data___1, CA___newID___1))).

process
	new Bob___aliceID[]: bitstring;
	let CA___aliceID: bitstring = Bob___aliceID in
	new Alice___bobID[]: bitstring;
	let CA___bobID: bitstring = Alice___bobID in
	new Alice___privK__data[]: bitstring;
	let Alice___pubK__data: bitstring = pk(Alice___privK__data) in
	out (ch, Alice___pubK__data);
	let CA___alicePubK__data: bitstring = pk(Alice___privK__data) in
	new Bob___privK__data[]: bitstring;
	let Bob___pubK__data: bitstring = pk(Bob___privK__data) in
	out (ch, Bob___pubK__data);
	let CA___bobPubK__data: bitstring = pk(Bob___privK__data) in
	new CA___privK__data[]: bitstring;
	let CA___pubK__data: bitstring = pk(CA___privK__data) in
	out (ch, CA___pubK__data);
	let Alice___CAPubK__data: bitstring = pk(CA___privK__data) in
	let Bob___CAPubK__data: bitstring = pk(CA___privK__data) in
	! (
		new sessionID[]: bitstring;
		((
			System___0 (sessionID)
		) | (
			Bob___0 (sessionID)
		) | (
			Alice___0 (sessionID)
		) | (
			CA___0 (sessionID)
		) | (
			!
				CA___1 (sessionID)
		) | (
			(
				((
					System___start (Bob___aliceID, CA___aliceID, Alice___bobID, CA___bobID, Alice___privK__data, Alice___pubK__data, CA___alicePubK__data, Bob___privK__data, Bob___pubK__data, CA___bobPubK__data, CA___privK__data, CA___pubK__data, Alice___CAPubK__data, Bob___CAPubK__data, sessionID)
				) | (
					Bob___start (Bob___aliceID, CA___aliceID, Alice___bobID, CA___bobID, Alice___privK__data, Alice___pubK__data, CA___alicePubK__data, Bob___privK__data, Bob___pubK__data, CA___bobPubK__data, CA___privK__data, CA___pubK__data, Alice___CAPubK__data, Bob___CAPubK__data, sessionID)
				) | (
					Alice___start (Bob___aliceID, CA___aliceID, Alice___bobID, CA___bobID, Alice___privK__data, Alice___pubK__data, CA___alicePubK__data, Bob___privK__data, Bob___pubK__data, CA___bobPubK__data, CA___privK__data, CA___pubK__data, Alice___CAPubK__data, Bob___CAPubK__data, sessionID)
				) | (
					CA___start (Bob___aliceID, CA___aliceID, Alice___bobID, CA___bobID, Alice___privK__data, Alice___pubK__data, CA___alicePubK__data, Bob___privK__data, Bob___pubK__data, CA___bobPubK__data, CA___privK__data, CA___pubK__data, Alice___CAPubK__data, Bob___CAPubK__data, sessionID)
				)))
		)))

(* EXPECTPV
RESULT not attacker(Alice___secretData[!1 = v]) is true.
RESULT not event(enteringState___Bob___receivingAliceCert) is false.
RESULT not event(enteringState___Bob___verifyCert) is false.
RESULT not event(enteringState___Bob___state0) is false.
RESULT not event(enteringState___Bob___waitingForMessage) is false.
RESULT not event(enteringState___Bob___messageDecrypt) is false.
RESULT not event(enteringState___Bob___messageDecrypted) is false.
RESULT not event(enteringState___Bob___SecretDataReceived) is false.
RESULT not event(enteringState___Alice___receivingBobCert) is false.
RESULT not event(enteringState___Alice___verifyCert) is false.
RESULT not event(enteringState___Alice___state0) is false.
RESULT not event(enteringState___Alice___makingMessage) is false.
RESULT not event(enteringState___Alice___sendingMessage) is false.
RESULT not event(enteringState___Alice___beforeFinish) is false.
RESULT not event(enteringState___CA___waiting) is false.
RESULT not event(enteringState___CA___verifyID) is false.
RESULT inj-event(authenticity___Bob___m__data___messageDecrypted(dummyM)) ==> inj-event(authenticity___Alice___m__data___sendingMessage(dummyM)) is false.
RESULT (but event(authenticity___Bob___m__data___messageDecrypted(dummyM)) ==> event(authenticity___Alice___m__data___sendingMessage(dummyM)) is true.)
0.364s (user 0.336s + system 0.028s), max rss 14572K
END *)
