- [[[ Broken commit. ]]]

Stuff seems to be working again, slightly less efficient though (count
  states).
This commit is contained in:
ccremers 2006-02-27 16:08:17 +00:00
parent bb16bd755e
commit b49d13b6ee
12 changed files with 714 additions and 454 deletions

View File

@ -378,6 +378,12 @@ fixAgentKeylevels (void)
int int
add_read_goals (const int run, const int old, const int new) add_read_goals (const int run, const int old, const int new)
{ {
if (new <= sys->runs[run].height)
{
return 0;
}
else
{
int count; int count;
int i; int i;
Roledef rd; Roledef rd;
@ -413,6 +419,7 @@ add_read_goals (const int run, const int old, const int new)
eprintf ("\n"); eprintf ("\n");
} }
return count; return count;
}
} }
//! Determine the run that follows from a substitution. //! Determine the run that follows from a substitution.
@ -756,114 +763,75 @@ getPriorityOfNeededKey (const System sys, const Term keyneeded)
return prioritylevel; return prioritylevel;
} }
//! Try to bind a specific existing run to a goal.
//! Make a decryption chain from a binding to some run,index using the key list, and callback if this works.
/** /**
* The idea is that we try to bind it this specific run and index. If this * Callback return value is int, but is effectively ignored.
* requires keys, then we should add such goals as well with the required
* decryptor things.
*
* The key goals are bound to the goal. Iterates on success.
*/ */
void void
bind_existing_to_goal (const Binding b, const int run, const int index) createDecryptionChain (const Binding b, const int run, const int index,
Termlist keylist, int (*callback) (void))
{ {
int old_length; if (keylist == NULL)
int newgoals;
Term goalterm;
int subterm_unification_needs (Term tbig, const int r, const int e)
{ {
Term t; // Immediate binding, no key needed.
if (goal_bind (b, run, index))
void bind_iterate (Termlist tl)
{ {
if (goal_bind (b, r, e)) callback ();
{
if (switches.output == PROOF)
{
indentPrint ();
eprintf ("Iterating for ");
termPrint (b->term);
eprintf (" to occur first in ");
termPrint (roledef_shift (sys->runs[run].start, index)->
message);
eprintf ("\n");
}
iterate ();
goal_unbind (b); goal_unbind (b);
return;
} }
} }
else
t = deVar (b->term);
tbig = deVar (tbig);
// First check whether it unifies in a simple way
unify (t, tbig, NULL, bind_iterate);
// The other options are unification on subparts
if (realTermTuple (tbig))
{ {
// Either one will do Term tdecr, tkey;
subterm_unification_needs (TermOp1 (tbig), r, e);
subterm_unification_needs (TermOp1 (tbig), r, e);
}
if (realTermEncrypt (tbig))
{
Term keyneeded;
Roledef rddecrypt;
int smallrun; int smallrun;
int prioritylevel;
int newgoals; // Some decryptor is needed for the term in the list
Binding bnew;
indentDepth++; indentDepth++;
// Maybe we can bind to the inner thing. Try.
// Add decryptor run tdecr = keylist->term;
keyneeded = inverseKey (sys->know->inverses, TermKey (tbig)); tkey = inverseKey (sys->know->inverses, TermKey (tdecr));
prioritylevel = getPriorityOfNeededKey (sys, keyneeded); smallrun = create_decryptor (tdecr, tkey);
smallrun = create_decryptor (tbig, keyneeded); {
Roledef rddecrypt;
Binding bnew;
int newgoals;
int prioritylevel;
/*
* 2. Add goal bindings
*/
rddecrypt = sys->runs[smallrun].start; rddecrypt = sys->runs[smallrun].start;
// Add goal for tdecr copy
newgoals = goal_add (rddecrypt->message, smallrun, 0, 0);
if (newgoals != 1)
{
error
("Added %i goals (instead of one) for decryptor goal 1, weird.",
newgoals);
}
// This is the unique new goal
bnew = (Binding) sys->bindings->data;
// Add goal for needed key copy
prioritylevel = getPriorityOfNeededKey (sys, tkey);
newgoals += goal_add (rddecrypt->next->message, smallrun, 1,
prioritylevel);
if (switches.output == PROOF) if (switches.output == PROOF)
{ {
indentPrint (); indentPrint ();
eprintf eprintf
("This introduces the obligation to decrypt the following subterm: "); ("This introduces the obligation to decrypt the following subterm: ");
termPrint (tbig); termPrint (tdecr);
eprintf (" to be decrypted using "); eprintf (" to be decrypted using ");
termPrint (keyneeded); termPrint (tkey);
eprintf ("\n"); eprintf ("\n");
}
/*
* 2. Add goal bindings
*/
newgoals = goal_add (rddecrypt->message, smallrun, 0, 0);
if (newgoals >= 0)
{
if (newgoals > 1)
{
error
("Added more than one goal for decryptor goal 1, weird.");
}
else
{
// This is the unique new goal then
bnew = (Binding) sys->bindings->data;
}
}
else
{
error ("No new binding added for inner message.");
// No new binding? Weird, but fair enough
bnew = NULL;
}
newgoals += goal_add (rddecrypt->next->message, smallrun, 1,
prioritylevel);
if (switches.output == PROOF)
{
indentPrint (); indentPrint ();
eprintf eprintf
("To this end, we added two new goals and one new send: "); ("To this end, we added two new goals and one new send: ");
@ -878,257 +846,122 @@ bind_existing_to_goal (const Binding b, const int run, const int index)
/* /*
* 3. Bind open goal to decryptor? * 3. Bind open goal to decryptor?
*/ */
if (goal_bind (bnew, r, e)) if (goal_bind (b, smallrun, 2))
{ {
if (switches.output == PROOF) if (switches.output == PROOF)
{ {
indentPrint (); indentPrint ();
eprintf ("Bound: trying new subterm_unfication_needs.\n"); eprintf ("Bound: trying new createDecryptionChain.\n");
} }
subterm_unification_needs (TermOp (tbig), smallrun, 2);
goal_unbind (bnew); // Iterate with the new goal
createDecryptionChain (bnew, run, index, keylist->next, callback);
goal_unbind (b);
} }
/* /*
* clean up * clean up
*/ */
termDelete (keyneeded);
goal_remove_last (newgoals); goal_remove_last (newgoals);
}
semiRunDestroy (); semiRunDestroy ();
termDelete (tkey);
indentDepth--; indentDepth--;
} }
}
old_length = sys->runs[run].height;
if (index >= old_length)
{
newgoals = add_read_goals (run, old_length, index + 1);
}
else
{
newgoals = 0;
}
goalterm = roledef_shift (sys->runs[run].start, index)->message;
subterm_unification_needs (goalterm, run, index);
if (newgoals > 0)
{
goal_remove_last (newgoals);
}
sys->runs[run].height = old_length;
} }
//! Try to bind a specific existing run to a goal. //! Try to bind a specific existing run to a goal.
/** /**
* The key goals are bound to the goal. * The idea is that we try to bind it this specific run and index. If this
* requires keys, then we should add such goals as well with the required
* decryptor things.
* *
*@todo This is currently NOT correct. The point is that the key chain * The key goals are bound to the goal. Iterates on success.
* cannot uniquely define a path through a term in general, and
* a rewrite of termMguSubterm is needed. It should not yield the
* needed keys, but simply the path throught the term. This would enable
* reconstruction of the keys anyway. TODO
*
*@param b binding to fix (bind), destination filled in
*@param run run of binding start
*@param index index in run of binding start
*/ */
int void
bind_existing_to_goal_old (const Binding b, const int run, const int index) bind_existing_to_goal (const Binding b, const int run, const int index)
{ {
Roledef rd; Term bigterm;
int flag;
int unifiesWithKeys (Termlist substlist, Termlist keylist)
{
int old_length; int old_length;
int newgoals; int newgoals;
int found;
int subterm_iterate (Termlist substlist, Termlist cryptlist) // We need some adapting because the height would increase; we therefore
{ // have to add read goals before we know whether it unifies.
int flag;
found++;
flag = 1;
/**
* Now create the new bindings
*/
int newgoals;
int newruns;
int stillvalid;
Binding smalltermbinding;
stillvalid = true; // New stuff is valid (no cycles)
newgoals = 0; // No new goals introduced (yet)
newruns = 0; // New runs introduced
smalltermbinding = b; // Start off with destination binding
indentDepth++;
#ifdef DEBUG
if (DEBUGL (4))
{
eprintf ("Trying to bind the small term ");
termPrint (b->term);
eprintf (" as coming from the big send ");
termPrint (rd->message);
eprintf (" , binding ");
termPrint (b->term);
eprintf ("\nCrypted list needed: ");
termlistPrint (cryptlist);
eprintf ("\n");
}
#endif
if (cryptlist != NULL && switches.output == PROOF)
{
indentPrint ();
eprintf
("This introduces the obligation to decrypt the following encrypted subterms: ");
termlistPrint (cryptlist);
eprintf ("\n");
}
/* The order of the cryptlist is inner -> outer */
while (stillvalid && cryptlist != NULL && smalltermbinding != NULL)
{
/*
* Invariants:
*
* smalltermbinding binding to be satisfied next (and for which a decryptor is needed)
*/
Term keyneeded;
int prioritylevel;
int smallrun;
int count;
Roledef rddecrypt;
Binding bnew;
int res;
/*
* 1. Add decryptor
*/
keyneeded =
inverseKey (sys->know->inverses, TermKey (cryptlist->term));
prioritylevel = getPriorityOfNeededKey (sys, keyneeded);
smallrun = create_decryptor (cryptlist->term, keyneeded);
rddecrypt = sys->runs[smallrun].start;
termDelete (keyneeded);
newruns++;
/*
* 2. Add goal bindings
*/
count = goal_add (rddecrypt->message, smallrun, 0, 0);
newgoals = newgoals + count;
if (count >= 0)
{
if (count > 1)
{
error
("Added more than one goal for decryptor goal 1, weird.");
}
else
{
// This is the unique new goal then
bnew = (Binding) sys->bindings->data;
}
}
else
{
// No new binding? Weird, but fair enough
bnew = NULL;
}
newgoals =
newgoals + goal_add (rddecrypt->next->message, smallrun, 1,
prioritylevel);
/*
* 3. Bind open goal to decryptor
*/
res = goal_bind (smalltermbinding, smallrun, 2); // returns 0 iff invalid
if (res != 0)
{
// Allright, good binding, proceed with next
smalltermbinding = bnew;
}
else
{
stillvalid = false;
}
/* progression */
cryptlist = cryptlist->next;
}
/*
* Decryptors for any nested keys have been added. Now we can fill the
* final binding.
*/
if (stillvalid)
{
if (goal_bind (smalltermbinding, run, index))
{
proof_suppose_binding (b);
#ifdef DEBUG
if (DEBUGL (4))
{
indentPrint ();
eprintf ("Added %i new goals, iterating.\n", newgoals);
}
#endif
/* Iterate process */
indentDepth++;
flag = flag && iterate ();
indentDepth--;
goal_unbind (b);
}
else
{
proof_cannot_bind (b, run, index);
}
}
goal_remove_last (newgoals);
while (newruns > 0)
{
semiRunDestroy ();
newruns--;
}
indentDepth--;
return flag;
}
//----------------------------
// Roledef entry
rd = roledef_shift (sys->runs[run].start, index);
// Fix length
old_length = sys->runs[run].height; old_length = sys->runs[run].height;
if ((index + 1) > old_length)
newgoals = add_read_goals (run, old_length, index + 1); newgoals = add_read_goals (run, old_length, index + 1);
else
newgoals = 0;
// Bind to existing run
found = 0;
flag = termMguSubTerm (b->term, rd->message,
subterm_iterate, sys->know->inverses, NULL);
// Did it work?
if (found == 0 && switches.output == PROOF)
{ {
indentPrint (); // wrap substitution lists
eprintf ("Cannot bind ");
termPrint (b->term); void wrapSubst (Termlist sl)
eprintf (" to run %i, index %i because it does not subterm-unify.\n", {
run, index); if (sl == NULL)
{
// new create key goals, bind etc.
createDecryptionChain (b, run, index, keylist, iterate);
} }
// Reset length else
{
int neworders;
int allgood;
// the idea is, that a substitution in run x with
// something containing should be wrapped; this
// occurs for all subterms of other runs.
int makeDepend (Term t)
{
int r1, e1;
r1 = TermRunid (t);
e1 = firstOccurrence (sys, r1, t, SEND);
if (dependPushEvent (r1, e1, run, index))
{
neworders++;
return true;
}
else
{
allgood = false;
return false;
}
}
neworders = 0;
allgood = true;
iterateTermOther (run, sl->term, makeDepend);
if (allgood)
{
wrapSubst (sl->next);
}
while (neworders > 0)
{
neworders--;
dependPopEvent ();
}
}
}
wrapSubst (substlist);
}
// undo
goal_remove_last (newgoals); goal_remove_last (newgoals);
sys->runs[run].height = old_length; sys->runs[run].height = old_length;
return flag; return true;
}
bigterm = roledef_shift (sys->runs[run].start, index)->message;
subtermUnify (bigterm, b->term, NULL, NULL, unifiesWithKeys);
} }
//! Bind a goal to an existing regular run, if possible //! Bind a goal to an existing regular run, if possible
int int
bind_existing_run (const Binding b, const Protocol p, const Role r, bind_existing_run (const Binding b, const Protocol p, const Role r,
@ -1181,11 +1014,12 @@ bind_new_run (const Binding b, const Protocol p, const Role r,
const int index) const int index)
{ {
int run; int run;
int newgoals;
run = semiRunCreate (p, r); run = semiRunCreate (p, r);
proof_suppose_run (run, 0, index + 1); proof_suppose_run (run, 0, index + 1);
{ {
int newgoals;
newgoals = add_read_goals (run, 0, index + 1); newgoals = add_read_goals (run, 0, index + 1);
indentDepth++; indentDepth++;
bind_existing_to_goal (b, run, index); bind_existing_to_goal (b, run, index);
@ -1269,6 +1103,9 @@ printSemiState ()
} }
//! Check if a binding duplicates an old one: if so, simply connect //! Check if a binding duplicates an old one: if so, simply connect
/**
* If it returns true, it has bound the b_new binding, which we must unbind later.
*/
int int
bind_old_goal (const Binding b_new) bind_old_goal (const Binding b_new)
{ {
@ -1339,7 +1176,36 @@ bind_goal_new_m0 (const Binding b)
termPrint (b->term); termPrint (b->term);
eprintf (" from the initial knowledge.\n"); eprintf (" from the initial knowledge.\n");
} }
{
// Now we also want to add bindings to have this run before all other runs
void wrapRunOrders (const int otherrun)
{
if (otherrun < 0)
{
// No more runs to do
flag = flag && iterate (); flag = flag && iterate ();
}
else
{
if (otherrun != run)
{
if (dependPushEvent (run, 0, otherrun, 0))
{
wrapRunOrders (otherrun - 1);
dependPopEvent ();
}
}
else
{
wrapRunOrders (otherrun - 1);
}
}
}
wrapRunOrders (sys->maxruns - 1);
}
goal_unbind (b); goal_unbind (b);
} }
else else
@ -1389,10 +1255,6 @@ bind_goal_new_encrypt (const Binding b)
if (!realTermLeaf (term)) if (!realTermLeaf (term))
{ {
int run;
int index;
int newgoals;
Roledef rd;
Term t1, t2; Term t1, t2;
if (!realTermEncrypt (term)) if (!realTermEncrypt (term))
@ -1407,8 +1269,14 @@ bind_goal_new_encrypt (const Binding b)
if (t2 != TERM_Hidden) if (t2 != TERM_Hidden)
{ {
int run;
can_be_encrypted = 1; can_be_encrypted = 1;
run = semiRunCreate (INTRUDER, I_RRS); run = semiRunCreate (INTRUDER, I_RRS);
{
int index;
Roledef rd;
rd = sys->runs[run].start; rd = sys->runs[run].start;
rd->message = termDuplicateUV (t1); rd->message = termDuplicateUV (t1);
rd->next->message = termDuplicateUV (t2); rd->next->message = termDuplicateUV (t2);
@ -1426,7 +1294,11 @@ bind_goal_new_encrypt (const Binding b)
termPrint (t2); termPrint (t2);
eprintf ("\n"); eprintf ("\n");
} }
{
int newgoals;
newgoals = add_read_goals (run, 0, index + 1); newgoals = add_read_goals (run, 0, index + 1);
{
indentDepth++; indentDepth++;
if (goal_bind (b, run, index)) if (goal_bind (b, run, index))
@ -1440,7 +1312,10 @@ bind_goal_new_encrypt (const Binding b)
proof_cannot_bind (b, run, index); proof_cannot_bind (b, run, index);
} }
indentDepth--; indentDepth--;
}
goal_remove_last (newgoals); goal_remove_last (newgoals);
}
}
semiRunDestroy (); semiRunDestroy ();
} }
} }
@ -1456,7 +1331,6 @@ bind_goal_new_encrypt (const Binding b)
} }
} }
return flag; return flag;
} }
@ -1637,7 +1511,7 @@ bind_goal_old_intruder_run (Binding b)
//! Bind a goal in all possible ways //! Bind a goal in all possible ways
int int
bind_goal (const Binding b) bind_goal_all_options (const Binding b)
{ {
if (b->blocked) if (b->blocked)
{ {
@ -2091,26 +1965,28 @@ iterate ()
{ {
if (!prune_bounds (sys)) if (!prune_bounds (sys))
{ {
Binding b; Binding btup;
// Are there any tuple goals? // Are there any tuple goals?
b = select_tuple_goal (); btup = select_tuple_goal ();
if (b != NULL) if (btup != NULL)
{ {
// Expand tuple goal // Expand tuple goal
int count; int count;
// mark as blocked for iteration // mark as blocked for iteration
binding_block (b); binding_block (btup);
// simply adding will detect the tuple and add the new subgoals // simply adding will detect the tuple and add the new subgoals
count = goal_add (b->term, b->run_to, b->ev_to, b->level); count =
goal_add (btup->term, btup->run_to, btup->ev_to,
btup->level);
// Show this in output // Show this in output
if (switches.output == PROOF) if (switches.output == PROOF)
{ {
indentPrint (); indentPrint ();
eprintf ("Expanding tuple goal "); eprintf ("Expanding tuple goal ");
termPrint (b->term); termPrint (btup->term);
eprintf (" into %i subgoals.\n", count); eprintf (" into %i subgoals.\n", count);
} }
@ -2119,7 +1995,7 @@ iterate ()
// undo // undo
goal_remove_last (count); goal_remove_last (count);
binding_unblock (b); binding_unblock (btup);
} }
else else
{ {
@ -2159,7 +2035,7 @@ iterate ()
/* /*
* bind this goal in all possible ways and iterate * bind this goal in all possible ways and iterate
*/ */
flag = bind_goal (b); flag = bind_goal_all_options (b);
} }
} }
} }
@ -2316,9 +2192,11 @@ arachne ()
{ {
// others we simply test... // others we simply test...
int run; int run;
int newruns;
Protocol p; Protocol p;
Role r; Role r;
newruns = 0;
sys->current_claim = cl; sys->current_claim = cl;
attack_length = INT_MAX; attack_length = INT_MAX;
attack_leastcost = INT_MAX; attack_leastcost = INT_MAX;
@ -2338,34 +2216,57 @@ arachne ()
eprintf (" at index %i.\n", cl->ev); eprintf (" at index %i.\n", cl->ev);
} }
indentDepth++; indentDepth++;
run = semiRunCreate (p, r); run = semiRunCreate (p, r);
proof_suppose_run (run, 0, cl->ev + 1); newruns++;
add_read_goals (run, 0, cl->ev + 1); {
int newgoals;
/**
* Add specific goal info
*/
add_claim_specifics (sys, cl,
roledef_shift (sys->runs[run].start,
cl->ev));
int realStart (void)
{
#ifdef DEBUG #ifdef DEBUG
if (DEBUGL (5)) if (DEBUGL (5))
{ {
printSemiState (); printSemiState ();
} }
#endif #endif
iterate_buffer_attacks (); return iterate_buffer_attacks ();
//! Destroy
while (sys->bindings != NULL)
{
goal_remove_last (1);
} }
while (sys->maxruns > 0)
proof_suppose_run (run, 0, cl->ev + 1);
newgoals = add_read_goals (run, 0, cl->ev + 1);
/**
* Add specific goal info and iterate
*/
add_claim_specifics (sys, cl,
roledef_shift (sys->runs[run].start,
cl->ev), realStart);
goal_remove_last (newgoals);
}
//! Destroy
while (sys->maxruns > 0 && newruns > 0)
{ {
semiRunDestroy (); semiRunDestroy ();
newruns--;
} }
#ifdef DEBUG
if (sys->bindings != NULL)
{
error ("sys->bindings NOT empty after claim test.");
}
if (sys->maxruns != 0)
{
error ("%i undestroyed runs left after claim test.",
sys->maxruns);
}
if (newruns != 0)
{
error ("Lost %i runs after claim test.", newruns);
}
#endif
//! Indent back //! Indent back
indentDepth--; indentDepth--;

View File

@ -739,12 +739,19 @@ prune_claim_specifics (const System sys)
return 0; return 0;
} }
//! Setup system for specific claim test //! Setup system for specific claim test and iterate
void int
add_claim_specifics (const System sys, const Claimlist cl, const Roledef rd) add_claim_specifics (const System sys, const Claimlist cl, const Roledef rd,
int (*callback) (void))
{ {
/*
* different cases
*/
if (cl->type == CLAIM_Secret) if (cl->type == CLAIM_Secret)
{ {
int newgoals;
int flag;
/** /**
* Secrecy claim * Secrecy claim
*/ */
@ -764,7 +771,12 @@ add_claim_specifics (const System sys, const Claimlist cl, const Roledef rd)
* be reached (without reaching the attack). * be reached (without reaching the attack).
*/ */
cl->count = statesIncrease (cl->count); cl->count = statesIncrease (cl->count);
goal_add (rd->message, 0, cl->ev, 0); // Assumption that all claims are in run 0 newgoals = goal_add (rd->message, 0, cl->ev, 0); // Assumption that all claims are in run 0
flag = callback ();
goal_remove_last (newgoals);
return flag;
} }
if (cl->type == CLAIM_Reachable) if (cl->type == CLAIM_Reachable)
@ -779,7 +791,10 @@ add_claim_specifics (const System sys, const Claimlist cl, const Roledef rd)
rolecount = termlistLength (protocol->rolenames); rolecount = termlistLength (protocol->rolenames);
switches.runs = rolecount; switches.runs = rolecount;
} }
return callback ();
} }
return callback ();
} }
//! Count a false claim //! Count a false claim

View File

@ -9,8 +9,8 @@ int arachne_claim_nisynch (const System sys, const int claim_run,
const int claim_index); const int claim_index);
int prune_claim_specifics (const System sys); int prune_claim_specifics (const System sys);
void add_claim_specifics (const System sys, const Claimlist cl, const int add_claim_specifics (const System sys, const Claimlist cl, const
Roledef rd); Roledef rd, int (*callback) (void));
void count_false_claim (const System sys); void count_false_claim (const System sys);
int property_check (const System sys); int property_check (const System sys);

View File

@ -1427,10 +1427,10 @@ compute_prec_sets (const System sys)
r1 = 0; r1 = 0;
while (r1 < sys->rolecount) while (r1 < sys->rolecount)
{ {
ev1 = 0; ev1 = 1;
while (ev1 < (sys->roleeventmax - 1)) while (ev1 < (sys->roleeventmax))
{ {
SETBIT (prec + rowsize * index (r1, ev1), index (r1, ev1 + 1)); SETBIT (prec + rowsize * index (r1, ev1 - 1), index (r1, ev1));
ev1++; ev1++;
} }
r1++; r1++;
@ -1472,6 +1472,13 @@ compute_prec_sets (const System sys)
r1++; r1++;
} }
#ifdef DEBUG
if (DEBUGL (5))
{
show_matrix ();
}
#endif
/* /*
* Compute transitive closure (Warshall). * Compute transitive closure (Warshall).
*/ */

View File

@ -40,6 +40,14 @@ struct depeventgraph
//! Pointer shorthard //! Pointer shorthard
typedef struct depeventgraph *Depeventgraph; typedef struct depeventgraph *Depeventgraph;
/*
* External
* ---------------------------------------------------------------
*/
extern Protocol INTRUDER; //!< The intruder protocol
extern Role I_M; //!< special role; precedes all other events always
/* /*
* Globals * Globals
* --------------------------------------------------------------- * ---------------------------------------------------------------
@ -266,18 +274,12 @@ dependPopGeneric (void)
currentdepgraph = dgprev; currentdepgraph = dgprev;
} }
//! Construct graph dependencies from sys // Dependencies from role order
/**
* uses currentdepgraph->sys
*/
void void
dependFromSys (void) dependDefaultRoleOrder (void)
{ {
int r; int r;
List bl;
// There are two types of orderings.
// 1. Role orderings (within runs)
for (r = 0; r < currentdepgraph->sys->maxruns; r++) for (r = 0; r < currentdepgraph->sys->maxruns; r++)
{ {
int e; int e;
@ -287,10 +289,14 @@ dependFromSys (void)
setDependEvent (r, e - 1, r, e); setDependEvent (r, e - 1, r, e);
} }
} }
}
// Dependencies fro bindings order
void
dependDefaultBindingOrder (void)
{
List bl;
// 2. Binding orderings
// We implicitly assume these cause no cycles (by construction this is
// correct)
for (bl = currentdepgraph->sys->bindings; bl != NULL; bl = bl->next) for (bl = currentdepgraph->sys->bindings; bl != NULL; bl = bl->next)
{ {
Binding b; Binding b;
@ -313,6 +319,17 @@ dependFromSys (void)
} }
} }
//! Construct graph dependencies from sys
/**
* uses currentdepgraph->sys
*/
void
dependFromSys (void)
{
dependDefaultRoleOrder ();
dependDefaultBindingOrder ();
}
//! Detect whether the graph has a cycle. If so, a node can get to itself (through the cycle) //! Detect whether the graph has a cycle. If so, a node can get to itself (through the cycle)
int int
hasCycle () hasCycle ()
@ -386,6 +403,9 @@ isDependEvent (const int r1, const int e1, const int r2, const int e2)
void void
dependPushRun (const System sys) dependPushRun (const System sys)
{ {
#ifdef DEBUG
debug (5, "Push dependGraph for new run\n");
#endif
dependPushGeneric (dependCreate (sys)); dependPushGeneric (dependCreate (sys));
dependFromSys (); dependFromSys ();
} }
@ -401,6 +421,9 @@ dependPopRun (void)
globalError--; globalError--;
error ("Trying to pop graph created for new binding."); error ("Trying to pop graph created for new binding.");
} }
#ifdef DEBUG
debug (5, "Pop dependGraph for new run\n");
#endif
dependPopGeneric (); dependPopGeneric ();
} }
@ -432,12 +455,21 @@ dependPushEvent (const int r1, const int e1, const int r2, const int e2)
else else
{ {
// No immediate cycle: new graph, return true TODO disabled // No immediate cycle: new graph, return true TODO disabled
if ((1 == 0) && ((r1 == r2) && (e1 == e2)) if ((1 == 1) && (((r1 == r2) && (e1 == e2))
|| isDependEvent (r1, e1, r2, e2)) || isDependEvent (r1, e1, r2, e2)))
{ {
// if n->n or the binding already existed, no changes // if n->n or the binding already existed, no changes
// no change: add zombie // no change: add zombie
currentdepgraph->zombie += 1; currentdepgraph->zombie += 1;
#ifdef DEBUG
debug (5, "Push dependGraph for new event (zombie push)\n");
if (DEBUGL (5))
{
globalError++;
eprintf ("r%ii%i --> r%ii%i\n", r1, e1, r2, e2);
globalError--;
}
#endif
} }
else else
{ {
@ -455,6 +487,15 @@ dependPushEvent (const int r1, const int e1, const int r2, const int e2)
dependPopEvent (); dependPopEvent ();
return false; return false;
} }
#ifdef DEBUG
debug (5, "Push dependGraph for new event (real push)\n");
if (DEBUGL (5))
{
globalError++;
eprintf ("r%ii%i --> r%ii%i\n", r1, e1, r2, e2);
globalError--;
}
#endif
} }
return true; return true;
} }
@ -464,6 +505,16 @@ dependPushEvent (const int r1, const int e1, const int r2, const int e2)
void void
dependPopEvent (void) dependPopEvent (void)
{ {
if (currentdepgraph->zombie > 0)
{
// zombie pushed
#ifdef DEBUG
debug (5, "Pop dependGraph for new event (zombie pop)\n");
#endif
currentdepgraph->zombie -= 1;
}
else
{
if (currentdepgraph->fornewrun) if (currentdepgraph->fornewrun)
{ {
globalError++; globalError++;
@ -471,16 +522,15 @@ dependPopEvent (void)
globalError--; globalError--;
error ("Trying to pop graph created for new run."); error ("Trying to pop graph created for new run.");
} }
if (currentdepgraph->zombie > 0)
{
// zombie pushed
currentdepgraph->zombie -= 1;
}
else else
{ {
// real graph // real graph
#ifdef DEBUG
debug (5, "Pop dependGraph for new event (real pop)\n");
#endif
dependPopGeneric (); dependPopGeneric ();
} }
}
} }
//! Current event to node //! Current event to node

116
src/mgu.c
View File

@ -117,30 +117,36 @@ termlistSubstReset (Termlist tl)
* The callback receives a list of variables, that were previously open, but are now closed * The callback receives a list of variables, that were previously open, but are now closed
* in such a way that the two terms unify. * in such a way that the two terms unify.
* *
* The callback must return true for the iteration to proceed: if it returns false, a single call would abort the scan.
* The return value shows this: it is false if the scan was aborted, and true if not.
*/ */
void int
unify (Term t1, Term t2, Termlist tl, void (*callback) (Termlist)) unify (Term t1, Term t2, Termlist tl, int (*callback) (Termlist))
{ {
int proceed;
proceed = true;
/* added for speed */ /* added for speed */
t1 = deVar (t1); t1 = deVar (t1);
t2 = deVar (t2); t2 = deVar (t2);
if (t1 == t2) if (t1 == t2)
{ {
callback (tl); return proceed && callback (tl);
return;
} }
int callsubst (Termlist tl, Term t, Term tsubst) int callsubst (Termlist tl, Term t, Term tsubst)
{ {
int proceed;
t->subst = tsubst; t->subst = tsubst;
#ifdef DEBUG #ifdef DEBUG
showSubst (t); showSubst (t);
#endif #endif
tl = termlistAdd (tl, t); tl = termlistAdd (tl, t);
callback (tl); proceed = callback (tl);
tl = termlistDelTerm (tl); tl = termlistDelTerm (tl);
t->subst = NULL; t->subst = NULL;
return; return proceed;
} }
if (!(hasTermVariable (t1) || hasTermVariable (t2))) if (!(hasTermVariable (t1) || hasTermVariable (t2)))
@ -149,13 +155,12 @@ unify (Term t1, Term t2, Termlist tl, void (*callback) (Termlist))
if (isTermEqual (t1, t2)) if (isTermEqual (t1, t2))
{ {
// Equal! // Equal!
callback (tl); return proceed && callback (tl);
return;
} }
else else
{ {
// Can never be fixed, no variables // Can never be fixed, no variables
return; return proceed;
} }
} }
@ -183,8 +188,7 @@ unify (Term t1, Term t2, Termlist tl, void (*callback) (Termlist))
t1 = t2; t1 = t2;
t2 = t3; t2 = t3;
} }
callsubst (tl, t1, t2); return proceed && callsubst (tl, t1, t2);
return;
} }
/* symmetrical tests for single variable. /* symmetrical tests for single variable.
@ -193,61 +197,115 @@ unify (Term t1, Term t2, Termlist tl, void (*callback) (Termlist))
if (realTermVariable (t2)) if (realTermVariable (t2))
{ {
if (termSubTerm (t1, t2) || !goodsubst (t2, t1)) if (termSubTerm (t1, t2) || !goodsubst (t2, t1))
return; return proceed;
else else
{ {
callsubst (tl, t2, t1); return proceed && callsubst (tl, t2, t1);
return;
} }
} }
if (realTermVariable (t1)) if (realTermVariable (t1))
{ {
if (termSubTerm (t2, t1) || !goodsubst (t1, t2)) if (termSubTerm (t2, t1) || !goodsubst (t1, t2))
return; return proceed;
else else
{ {
callsubst (tl, t1, t2); return proceed && callsubst (tl, t1, t2);
return;
} }
} }
/* left & right are compounds with variables */ /* left & right are compounds with variables */
if (t1->type != t2->type) if (t1->type != t2->type)
return; return proceed;
/* identical compound types */ /* identical compound types */
/* encryption first */ /* encryption first */
if (realTermEncrypt (t1)) if (realTermEncrypt (t1))
{ {
void unify_combined_enc (Termlist tl) int unify_combined_enc (Termlist tl)
{ {
// now the keys are unified (subst in this tl) // now the keys are unified (subst in this tl)
// and we try the inner terms // and we try the inner terms
unify (TermOp (t1), TermOp (t2), tl, callback); return unify (TermOp (t1), TermOp (t2), tl, callback);
return;
} }
unify (TermKey (t1), TermKey (t2), tl, unify_combined_enc); return proceed
return; && unify (TermKey (t1), TermKey (t2), tl, unify_combined_enc);
} }
/* tupling second /* tupling second
non-associative version ! TODO other version */ non-associative version ! TODO other version */
if (isTermTuple (t1)) if (isTermTuple (t1))
{ {
void unify_combined_tup (Termlist tl) int unify_combined_tup (Termlist tl)
{ {
// now the keys are unified (subst in this tl) // now the keys are unified (subst in this tl)
// and we try the inner terms // and we try the inner terms
unify (TermOp2 (t1), TermOp2 (t2), tl, callback); return unify (TermOp2 (t1), TermOp2 (t2), tl, callback);
return;
} }
unify (TermOp1 (t1), TermOp1 (t2), tl, unify_combined_tup); return proceed
return; && unify (TermOp1 (t1), TermOp1 (t2), tl, unify_combined_tup);
} }
return; return proceed;
}
//! Subterm unification
/**
* Try to unify (a subterm of) tbig with tsmall.
*
* Callback is called with a list of substitutions, and a list of terms that
* need to be decrypted in order for this to work.
*
* E.g. subtermUnify ( {{m}k1}k2, m ) yields a list : {{m}k1}k2, {m}k1 (where
* the {m}k1 is the last added node to the list)
*
* The callback should return true for the iteration to proceed, or false to abort.
* The final result is this flag.
*/
int
subtermUnify (Term tbig, Term tsmall, Termlist tl, Termlist keylist,
int (*callback) (Termlist, Termlist))
{
int proceed;
int keycallback (Termlist tl)
{
return callback (tl, keylist);
}
proceed = true;
// Devar
tbig = deVar (tbig);
tsmall = deVar (tsmall);
// Three options:
// 1. simple unification
proceed = proceed && unify (tbig, tsmall, tl, keycallback);
// [2/3]: complex
// 2. interm unification
if (realTermTuple (tbig))
{
proceed = proceed
&& subtermUnify (TermOp1 (tbig), tsmall, tl, keylist, callback);
proceed = proceed
&& subtermUnify (TermOp2 (tbig), tsmall, tl, keylist, callback);
}
// 3. unification with encryption needed
if (realTermEncrypt (tbig))
{
// extend the keylist
keylist = termlistAdd (keylist, tbig);
proceed = proceed
&& subtermUnify (TermOp (tbig), tsmall, tl, keylist, callback);
// remove last item again
keylist = termlistDelTerm (keylist);
}
return proceed;
} }

View File

@ -20,6 +20,10 @@ int termMguInTerm (Term t1, Term t2, int (*iterator) (Termlist));
int termMguSubTerm (Term t1, Term t2, int (*iterator) (Termlist, Termlist), int termMguSubTerm (Term t1, Term t2, int (*iterator) (Termlist, Termlist),
Termlist inverses, Termlist keylist); Termlist inverses, Termlist keylist);
void termlistSubstReset (Termlist tl); void termlistSubstReset (Termlist tl);
void unify (Term t1, Term t2, Termlist tl, void (*callback) (Termlist));
// The new iteration methods
int unify (Term t1, Term t2, Termlist tl, int (*callback) (Termlist));
int
subtermUnify (Term tbig, Term tsmall, Termlist tl, Termlist keylist,
int (*callback) (Termlist, Termlist));
#endif #endif

View File

@ -17,6 +17,53 @@ extern Protocol INTRUDER;
extern int proofDepth; extern int proofDepth;
extern int max_encryption_level; extern int max_encryption_level;
//! Check locals occurrence
/*
* Returns true if the order is correct
*/
int
correctLocalOrder (const System sys)
{
int checkRun (int r1)
{
int checkTerm (Term t)
{
if (!isTermVariable (t))
{
int r2;
int e1, e2;
// t is a term from r2 that occurs in r1
r2 = TermRunid (t);
e1 = firstOccurrence (sys, r1, t, READ);
e2 = firstOccurrence (sys, r2, t, SEND);
// thus, it should not be the case that e1 occurs before e2
if (isDependEvent (r1, e1, r2, e2))
{
// That's not good!
if (switches.output == PROOF)
{
indentPrint ();
eprintf ("Pruned because ordering for term ");
termPrint (t);
eprintf
(" cannot be correct: the first send r%ii%i occurs after the read r%ii%i.\n",
r2, e2, r1, e1);
}
return false;
}
}
return true;
}
return iterateLocalToOther (sys, r1, checkTerm);
}
return iterateRegularRuns (sys, checkRun);
}
//! Check initiator roles //! Check initiator roles
/** /**
* Returns false iff an agent type is wrong * Returns false iff an agent type is wrong
@ -232,6 +279,11 @@ prune_theorems (const System sys)
} }
} }
/*
* Check for correct orderings involving local constants
*/
correctLocalOrder (sys);
/** /**
* Check whether the bindings are valid * Check whether the bindings are valid
*/ */

View File

@ -30,6 +30,9 @@ int globalLatex;
//! Global count of protocols //! Global count of protocols
int protocolCount; int protocolCount;
//! External
extern Protocol INTRUDER;
//! Switch for indent or not. //! Switch for indent or not.
static int indentState = 0; static int indentState = 0;
//! Current indent depth. //! Current indent depth.
@ -1513,3 +1516,140 @@ enoughAttacks (const System sys)
} }
return 0; return 0;
} }
//! Iterate over runs.
/**
* Callback should return true in order to continue.
*/
int
iterateRuns (const System sys, int (*callback) (int r))
{
int r;
for (r = 0; r < sys->maxruns; r++)
{
if (!callback (r))
{
return false;
}
}
return true;
}
//! Iterate over non-intruder runs.
/**
* Callback should return true in order to continue.
*/
int
iterateRegularRuns (const System sys, int (*callback) (int r))
{
int regular (int r)
{
if (sys->runs[r].protocol != INTRUDER)
{
return callback (r);
}
return true;
}
return iterateRuns (sys, regular);
}
// Iterate over events in a certain run (increasing through role)
int
iterateEvents (const System sys, const int run,
int (*callback) (Roledef rd, int ev))
{
int e;
Roledef rd;
rd = sys->runs[run].start;
for (e = 0; e < sys->runs[run].step; e++)
{
if (!callback (rd, e))
{
return false;
}
rd = rd->next;
}
return true;
}
// Iterate over event type in a certain run (increasing through role)
int
iterateEventsType (const System sys, const int run, const int evtype,
int (*callback) (Roledef rd, int ev))
{
int selectEvent (Roledef rd, int e)
{
if (rd->type == evtype)
{
return callback (rd, e);
}
return true;
}
return iterateEvents (sys, run, selectEvent);
}
// Iterate over all 'others': local variables of a run that are instantiated and contain some term of another run.
int
iterateLocalToOther (const System sys, const int myrun,
int (*callback) (Term t))
{
Termlist tlo, tls;
int addOther (Term t)
{
tlo = termlistAddNew (tlo, t);
return true;
}
tlo = NULL;
// construct all others occuring in the reads
for (tls = sys->runs[myrun].locals; tls != NULL; tls = tls->next)
{
iterateTermOther (myrun, tls->term, addOther);
}
// now iterate over all of them
for (tls = tlo; tls != NULL; tls = tls->next)
{
if (!callback (tls->term))
{
return false;
}
}
// clean up
termlistDelete (tlo);
return true;
}
//! Get first read/send occurrence (event index) of term t in run r
int
firstOccurrence (const System sys, const int r, Term t, int evtype)
{
int firste;
int checkOccurs (Roledef rd, int e)
{
if (termSubTerm (rd->message, t) || termSubTerm (rd->from, t)
|| termSubTerm (rd->to, t))
{
firste = e;
return false;
}
return true;
}
if (iterateEventsType (sys, r, evtype, checkOccurs))
{
globalError++;
eprintf ("Desired term ");
termPrint (t);
eprintf (" does not occur.\n");
globalError--;
error ("(in run %i in event type %i.)", r, evtype);
}
return firste;
}

View File

@ -224,6 +224,17 @@ int isAgentTrusted (const System sys, Term agent);
int isAgentlistTrusted (const System sys, Termlist agents); int isAgentlistTrusted (const System sys, Termlist agents);
int isRunTrusted (const System sys, const int run); int isRunTrusted (const System sys, const int run);
int iterateRuns (const System sys, int (*callback) (int r));
int iterateRegularRuns (const System sys, int (*callback) (int r));
int iterateEvents (const System sys, const int run,
int (*callback) (Roledef rd, int ev));
int iterateEventsType (const System sys, const int run, const int evtype,
int (*callback) (Roledef rd, int ev));
int iterateLocalToOther (const System sys, const int myrun,
int (*callback) (Term t));
int firstOccurrence (const System sys, const int r, Term t, int evtype);
//! Equality for run structure naming //! Equality for run structure naming
/** /**
* For the modelchecker, there was an index called step. In Strand Space * For the modelchecker, there was an index called step. In Strand Space

View File

@ -925,8 +925,8 @@ termOrder (Term t1, Term t2)
//! Generic term iteration //! Generic term iteration
int int
term_iterate (const Term term, int (*leaf) (), int (*nodel) (), term_iterate (const Term term, int (*leaf) (Term t), int (*nodel) (Term t),
int (*nodem) (), int (*noder) ()) int (*nodem) (Term t), int (*noder) (Term t))
{ {
if (term != NULL) if (term != NULL)
{ {
@ -977,8 +977,8 @@ term_iterate (const Term term, int (*leaf) (), int (*nodel) (),
//! Generic term iteration //! Generic term iteration
int int
term_iterate_deVar (Term term, int (*leaf) (), int (*nodel) (), term_iterate_deVar (Term term, int (*leaf) (Term t), int (*nodel) (Term t),
int (*nodem) (), int (*noder) ()) int (*nodem) (Term t), int (*noder) (Term t))
{ {
term = deVar (term); term = deVar (term);
if (term != NULL) if (term != NULL)
@ -1045,7 +1045,7 @@ term_iterate_deVar (Term term, int (*leaf) (), int (*nodel) (),
* well. It is up to func to decide wether or not to recurse. * well. It is up to func to decide wether or not to recurse.
*/ */
int int
term_iterate_leaves (const Term term, int (*func) ()) term_iterate_leaves (const Term term, int (*func) (Term t))
{ {
if (term != NULL) if (term != NULL)
{ {
@ -1069,13 +1069,13 @@ term_iterate_leaves (const Term term, int (*func) ())
//! Iterate over open leaves (i.e. respect variable closure) //! Iterate over open leaves (i.e. respect variable closure)
int int
term_iterate_open_leaves (const Term term, int (*func) ()) term_iterate_open_leaves (const Term term, int (*func) (Term t))
{ {
int testleaf (const Term t) int testleaf (const Term t)
{ {
if (substVar (t)) if (substVar (t))
{ {
return term_iterate_open_leaves (t, func); return term_iterate_open_leaves (t->subst, func);
} }
else else
{ {
@ -1427,3 +1427,22 @@ termHidelevel (const Term tsmall, Term tbig)
} }
} }
} }
// Iterate over subterm constants of other runs in a term
// Callback should return true to progress. This is reported in the final thing.
int
iterateTermOther (const int myrun, Term t, int (*callback) (Term t))
{
int testOther (Term t)
{
int run;
run = TermRunid (t);
if (run >= 0 && run != myrun)
{
return callback (t);
}
return true;
}
return term_iterate_deVar (t, testOther, NULL, NULL, NULL);
}

View File

@ -186,12 +186,14 @@ Term tupleProject (Term tt, int n);
int termSize (Term t); int termSize (Term t);
float termDistance (Term t1, Term t2); float termDistance (Term t1, Term t2);
int termOrder (Term t1, Term t2); int termOrder (Term t1, Term t2);
int term_iterate (const Term term, int (*leaf) (), int (*nodel) (), int term_iterate (const Term term, int (*leaf) (Term t),
int (*nodem) (), int (*noder) ()); int (*nodel) (Term t), int (*nodem) (Term t),
int term_iterate_deVar (Term term, int (*leaf) (), int (*nodel) (), int (*noder) (Term t));
int (*nodem) (), int (*noder) ()); int term_iterate_deVar (Term term, int (*leaf) (Term t),
int term_iterate_leaves (const Term t, int (*func) ()); int (*nodel) (Term t), int (*nodem) (Term t),
int term_iterate_open_leaves (const Term term, int (*func) ()); int (*noder) (Term t));
int term_iterate_leaves (const Term t, int (*func) (Term t));
int term_iterate_open_leaves (const Term term, int (*func) (Term t));
void term_rolelocals_are_variables (); void term_rolelocals_are_variables ();
int term_encryption_level (const Term term); int term_encryption_level (const Term term);
float term_constrain_level (const Term term); float term_constrain_level (const Term term);
@ -203,5 +205,6 @@ int isTermFunctionName (Term t);
Term getTermFunction (Term t); Term getTermFunction (Term t);
unsigned int termHidelevel (const Term tsmall, Term tbig); unsigned int termHidelevel (const Term tsmall, Term tbig);
int iterateTermOther (const int myrun, Term t, int (*callback) (Term t));
#endif #endif