free c : channel.

fun isSum(bitstring,bitstring,bitstring) : bitstring [private].
reduc forall r,x,a,b : bitstring; open(isSum(x,a,b)) = (x,a,b) [private].

const ok : bitstring.
fun equal(bitstring,bitstring) : bitstring
reduc forall x,a,b,b':bitstring; equal(x,x) = ok.

let P(x:bitstring,a:bitstring,b:bitstring) =
  out(c, isSum(x,a,b));
  out(c, a);
  0.

let Q() =
  in(c, in1:bitstring);
  let (x:bitstring,a:bitstring,b:bitstring) = open(in1) in
  in(c, in2:bitstring);
  let (x':bitstring,a':bitstring,b':bitstring) = open(in2) in
  out(c, equal(x,x'));
  0.


process
  (* l'attaquant choisit les constantes utilisees pour creer les bulletins *)
  in(c, (x1:bitstring, x2:bitstring));
  in(c, (a1:bitstring));
  in(c, b:bool);
  (
    (if b then out(c, choice[x1,x2]) else out(c, choice[x2,x1])) |
    Q() |
    0
  )

(*** ProVerif output ****
MacBook-Pro-de-Debant:proverif debant$ ./proverif /Users/debant/post-doc/belenios-verif/bug-proverif.pv
Biprocess 0 (that is, the initial process):
{1}in(c, (x1: bitstring,x2: bitstring));
{2}in(c, a1: bitstring);
{3}in(c, (b1: bitstring,b3: bitstring));
(
    {4}let x: bitstring = choice[x1,x2] in
    {5}let b: bitstring = choice[b1,b3] in
    {6}out(c, isSum(x,a1,b));
    {7}out(c, a1)
) | (
    {8}in(c, in1: bitstring);
    {9}let (x_1: bitstring,a: bitstring,b_1: bitstring) = open(in1) in
    {10}in(c, in2: bitstring);
    {11}let (x': bitstring,a': bitstring,b': bitstring) = open(in2) in
    {12}out(c, equal(x_1,x'))
) | (
    0
)

-- Observational equivalence in biprocess 1 (that is, biprocess 0, with let moved downwards):
{1}in(c, (x1: bitstring,x2: bitstring));
{2}in(c, a1: bitstring);
{3}in(c, (b1: bitstring,b3: bitstring));
(
    {5}let b: bitstring = choice[b1,b3] in
    {4}let x: bitstring = choice[x1,x2] in
    {6}out(c, isSum(x,a1,b));
    {7}out(c, a1)
) | (
    {8}in(c, in1: bitstring);
    {9}let (x_1: bitstring,a: bitstring,b_1: bitstring) = open(in1) in
    {10}in(c, in2: bitstring);
    {11}let (x': bitstring,a': bitstring,b': bitstring) = open(in2) in
    {12}out(c, equal(x_1,x'))
) | (
    0
)

Translating the process into Horn clauses...
Termination warning: v ≠ v_1 && attacker2(v_2,v) && attacker2(v_2,v_1) -> bad
Selecting 0
Termination warning: v ≠ v_1 && attacker2(v,v_2) && attacker2(v_1,v_2) -> bad
Selecting 0
Completing...
Termination warning: v ≠ v_1 && attacker2(v_2,v) && attacker2(v_2,v_1) -> bad
Selecting 0
Termination warning: v ≠ v_1 && attacker2(v,v_2) && attacker2(v_1,v_2) -> bad
Selecting 0
goal reachable: bad

Derivation:

1. The attacker has some term x2_1 (resp. x_2).
attacker2(x2_1,x_2).

2. The attacker has some term x_3 (resp. x1_1).
attacker2(x_3,x1_1).

3. By 2, the attacker may know x_3 (resp. x1_1).
By 1, the attacker may know x2_1 (resp. x_2).
Using the function 2-tuple the attacker may obtain (x_3,x2_1) (resp. (x1_1,x_2)).
attacker2((x_3,x2_1),(x1_1,x_2)).

4. The attacker has some term a1_1 (resp. a1_2).
attacker2(a1_1,a1_2).

5. The attacker has some term b3_1 (resp. b_2).
attacker2(b3_1,b_2).

6. The attacker has some term b_3 (resp. b1_1).
attacker2(b_3,b1_1).

7. By 6, the attacker may know b_3 (resp. b1_1).
By 5, the attacker may know b3_1 (resp. b_2).
Using the function 2-tuple the attacker may obtain (b_3,b3_1) (resp. (b1_1,b_2)).
attacker2((b_3,b3_1),(b1_1,b_2)).

8. The message (x_3,x2_1) (resp. (x1_1,x_2)) that the attacker may have by 3 may be received at input {1}.
The message a1_1 (resp. a1_2) that the attacker may have by 4 may be received at input {2}.
The message (b_3,b3_1) (resp. (b1_1,b_2)) that the attacker may have by 7 may be received at input {3}.
So the message isSum(x_3,a1_1,b_3) (resp. isSum(x_2,a1_2,b_2)) may be sent to the attacker at output {6}.
attacker2(isSum(x_3,a1_1,b_3),isSum(x_2,a1_2,b_2)).

9. The attacker has some term x_4 (resp. x1_2).
attacker2(x_4,x1_2).

10. By 9, the attacker may know x_4 (resp. x1_2).
By 1, the attacker may know x2_1 (resp. x_2).
Using the function 2-tuple the attacker may obtain (x_4,x2_1) (resp. (x1_2,x_2)).
attacker2((x_4,x2_1),(x1_2,x_2)).

11. The attacker has some term b_4 (resp. b1_2).
attacker2(b_4,b1_2).

12. By 11, the attacker may know b_4 (resp. b1_2).
By 5, the attacker may know b3_1 (resp. b_2).
Using the function 2-tuple the attacker may obtain (b_4,b3_1) (resp. (b1_2,b_2)).
attacker2((b_4,b3_1),(b1_2,b_2)).

13. The message (x_4,x2_1) (resp. (x1_2,x_2)) that the attacker may have by 10 may be received at input {1}.
The message a1_1 (resp. a1_2) that the attacker may have by 4 may be received at input {2}.
The message (b_4,b3_1) (resp. (b1_2,b_2)) that the attacker may have by 12 may be received at input {3}.
So the message isSum(x_4,a1_1,b_4) (resp. isSum(x_2,a1_2,b_2)) may be sent to the attacker at output {6}.
attacker2(isSum(x_4,a1_1,b_4),isSum(x_2,a1_2,b_2)).

14. By 13, the attacker may know isSum(x_4,a1_1,b_4) (resp. isSum(x_2,a1_2,b_2)).
By 8, the attacker may know isSum(x_3,a1_1,b_3) (resp. isSum(x_2,a1_2,b_2)).
We have isSum(x_4,a1_1,b_4) ≠ isSum(x_3,a1_1,b_3).
The attacker tests equality between the two terms he knows, which may allow it to distinguish cases.
bad.


Unified b_4 with b1_2
Unified x_4 with x1_2
Unified x_3 with x1_2
Unified x1_1 with x1_2
Unified b_3 with b1_2
Unified b1_1 with b1_2
Unified b3_1 with b_2
Unified a1_1 with a1_2
Unified x2_1 with x_2
Iterating unifyDerivation.
Fixpoint reached: nothing more to unify.
Unification made an inequality become false.
Trying with the initial derivation tree instead.
Could not find a trace corresponding to this derivation.
RESULT Observational equivalence cannot be proved.
Looking for simplified processes ...
Internal error: unexpected link in copy_binder v
Please report bug to proverif-dev@inria.fr, including input file and output

*)

(* EXPECTPV
RESULT Observational equivalence cannot be proved.
RESULT Observational equivalence cannot be proved.
0.044s (user 0.044s + system 0.000s), max rss 9248K
END *)
