- Big change in the Arachne algorithm: decryptor sequences now get

expanded explicitly. This solves a long-standing issue with {k}k
  decryption to yield k. Needs some testing to ensure that it did not
  introduce any new errors.
This commit is contained in:
ccremers 2005-05-17 18:45:01 +00:00
parent 2110206d80
commit f22ce0dcb9
8 changed files with 581 additions and 325 deletions

View File

@ -7,6 +7,7 @@
* *
*/ */
#include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <float.h> #include <float.h>
#ifdef DEBUG #ifdef DEBUG
@ -48,6 +49,7 @@ static int attack_length;
Protocol INTRUDER; // Pointers, to be set by the Init Protocol INTRUDER; // Pointers, to be set by the Init
Role I_M; // Same here. Role I_M; // Same here.
Role I_RRS; Role I_RRS;
Role I_RRSD;
static int indentDepth; static int indentDepth;
static int proofDepth; static int proofDepth;
@ -125,6 +127,15 @@ arachneInit (const System mysys)
add_event (SEND, NULL); add_event (SEND, NULL);
I_RRS = add_role ("I_E: Encrypt"); I_RRS = add_role ("I_E: Encrypt");
add_event (READ, NULL);
add_event (READ, NULL);
add_event (SEND, NULL);
I_RRSD = add_role ("I_D: Decrypt");
num_regular_runs = 0;
num_intruder_runs = 0;
max_encryption_level = 0;
return; return;
} }
@ -621,9 +632,76 @@ iterate_role_sends (int (*func) ())
return iterate_role_events (send_wrapper); return iterate_role_events (send_wrapper);
} }
//! Create decryption role instance
/**
* Note that this does not add any bindings for the reads.
*
*@param term The term to be decrypted (implies decryption key)
*
*@returns The run id of the decryptor instance
*/
int
create_decryptor (const Term term, const Term key)
{
if (term != NULL && isTermEncrypt (term))
{
Roledef rd;
Term tempkey;
int run;
run = semiRunCreate (INTRUDER, I_RRSD);
rd = sys->runs[run].start;
rd->message = termDuplicateUV (term);
rd->next->message = termDuplicateUV (key);
rd->next->next->message = termDuplicateUV (TermOp (term));
sys->runs[run].step = 3;
proof_suppose_run (run, 0, 3);
return run;
}
else
{
globalError++;
printf ("Term for which a decryptor instance is requested: ");
termPrint (term);
printf ("\n");
error
("Trying to build a decryptor instance for a non-encrypted term.");
}
}
//! Get the priority level of a key that is needed for a term (typical pk/sk distinction)
int
getPriorityOfNeededKey (const System sys, const Term keyneeded)
{
int prioritylevel;
/* Normally, a key gets higher priority, but unfortunately this is not propagated at the moment. Maybe later.
*/
prioritylevel = 1;
if (realTermEncrypt (keyneeded))
{
/* the key is a construction itself */
if (inKnowledge (sys->know, TermKey (keyneeded)))
{
/* the key is constructed by a public thing */
/* typically, this is a public key, so we postpone it */
prioritylevel = -1;
}
}
return prioritylevel;
}
//! 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 key goals are bound to the goal.
*
*@todo This is currently NOT correct. The point is that the key chain
* 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 subterm determines whether it is a subterm unification or not. *@param subterm determines whether it is a subterm unification or not.
*/ */
int int
@ -635,7 +713,7 @@ bind_existing_to_goal (const Binding b, const int run, const int index)
int newgoals; int newgoals;
int found; int found;
int subterm_iterate (Termlist substlist, Termlist keylist) int subterm_iterate (Termlist substlist, Termlist cryptlist)
{ {
int flag; int flag;
@ -644,55 +722,148 @@ bind_existing_to_goal (const Binding b, const int run, const int index)
/** /**
* Now create the new bindings * Now create the new bindings
*/ */
if (goal_bind (b, run, index)) 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
#ifdef DEBUG
if (DEBUGL (4))
{ {
int newgoals; printf ("Trying to bind the small term ");
Termlist tl; termPrint (b->term);
printf (" as coming from the big send ");
proof_suppose_binding (b); termPrint (rd->message);
if (keylist != NULL && sys->output == PROOF) printf (" , binding ");
{ termPrint (b->term);
indentPrint (); printf ("\nCrypted list needed: ");
eprintf termlistPrint (cryptlist);
("This introduces the obligation to produce the following keys: "); printf ("\n");
termlistPrint (keylist);
eprintf ("\n");
}
newgoals = 0;
tl = keylist;
while (tl != NULL)
{
int keyrun;
int prioritylevel;
/* normally, a key gets higher priority */
prioritylevel = 1;
if (realTermEncrypt (tl->term))
{
/* the key is a construction itself */
if (inKnowledge (sys->know, TermKey (tl->term)))
{
/* the key is constructed by a public thing */
/* typically, this is a public key, so we postpone it */
prioritylevel = -1;
}
}
/* add the key as a goal */
newgoals =
newgoals + goal_add (tl->term, b->run_to, b->ev_to,
prioritylevel);
tl = tl->next;
}
indentDepth++;
flag = flag && iterate ();
indentDepth--;
goal_remove_last (newgoals);
} }
else #endif
if (cryptlist != NULL && sys->output == PROOF)
{ {
proof_cannot_bind (b, run, index); indentPrint ();
eprintf
("This introduces the obligation to decrypted 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--;
}
else
{
proof_cannot_bind (b, run, index);
}
}
goal_remove_last (newgoals);
while (newruns > 0)
{
semiRunDestroy ();
newruns--;
} }
goal_unbind (b); goal_unbind (b);
return flag; return flag;
@ -2754,7 +2925,8 @@ prune_claim_specifics ()
{ {
if (arachne_claim_niagree (sys, 0, sys->current_claim->ev)) if (arachne_claim_niagree (sys, 0, sys->current_claim->ev))
{ {
sys->current_claim->count = statesIncrease (sys->current_claim->count); sys->current_claim->count =
statesIncrease (sys->current_claim->count);
if (sys->output == PROOF) if (sys->output == PROOF)
{ {
indentPrint (); indentPrint ();
@ -2768,7 +2940,8 @@ prune_claim_specifics ()
{ {
if (arachne_claim_nisynch (sys, 0, sys->current_claim->ev)) if (arachne_claim_nisynch (sys, 0, sys->current_claim->ev))
{ {
sys->current_claim->count = statesIncrease (sys->current_claim->count); sys->current_claim->count =
statesIncrease (sys->current_claim->count);
if (sys->output == PROOF) if (sys->output == PROOF)
{ {
indentPrint (); indentPrint ();

View File

@ -47,7 +47,7 @@ binding_create (Term term, int run_to, int ev_to)
b->ev_from = -1; b->ev_from = -1;
b->run_to = run_to; b->run_to = run_to;
b->ev_to = ev_to; b->ev_to = ev_to;
goal_graph_destroy(); goal_graph_destroy ();
b->term = term; b->term = term;
b->level = 0; b->level = 0;
return b; return b;
@ -104,15 +104,15 @@ goal_graph_destroy ()
struct mallinfo mi_free; struct mallinfo mi_free;
int mem_free; int mem_free;
mi_free = mallinfo(); mi_free = mallinfo ();
mem_free = mi_free.uordblks; mem_free = mi_free.uordblks;
#endif #endif
memFree (graph, (nodes * nodes) * sizeof (int)); memFree (graph, (nodes * nodes) * sizeof (int));
graph = NULL; graph = NULL;
#ifdef DEBUG #ifdef DEBUG
mi_free = mallinfo(); mi_free = mallinfo ();
if (mem_free - mi_free.uordblks != graph_uordblks) if (mem_free - mi_free.uordblks != graph_uordblks)
error ("Freeing gave a weird result."); error ("Freeing gave a weird result.");
#endif #endif
graph_uordblks = 0; graph_uordblks = 0;
nodes = 0; nodes = 0;
@ -132,211 +132,217 @@ goal_graph_create ()
// Setup graph // Setup graph
nodes = node_count (); nodes = node_count ();
{ {
struct mallinfo create_mi; struct mallinfo create_mi;
int create_mem_before; int create_mem_before;
if (graph_uordblks != 0) if (graph_uordblks != 0)
error ("Trying to create graph stuff without 0 uordblks for it first, but it is %i.", graph_uordblks); error
create_mi = mallinfo(); ("Trying to create graph stuff without 0 uordblks for it first, but it is %i.",
create_mem_before = create_mi.uordblks; graph_uordblks);
graph = memAlloc ((nodes * nodes) * sizeof (int)); create_mi = mallinfo ();
create_mi = mallinfo(); create_mem_before = create_mi.uordblks;
graph_uordblks = create_mi.uordblks - create_mem_before; graph = memAlloc ((nodes * nodes) * sizeof (int));
} create_mi = mallinfo ();
graph_uordblks = create_mi.uordblks - create_mem_before;
}
{ {
graph_fill (graph, nodes, 0); graph_fill (graph, nodes, 0);
// Setup run order // Setup run order
run = 0; run = 0;
last_m = -1; // last I_M run last_m = -1; // last I_M run
while (run < sys->maxruns) while (run < sys->maxruns)
{ {
ev = 1; ev = 1;
//!@todo This now reference to step, but we intend "length" as in Arachne. //!@todo This now reference to step, but we intend "length" as in Arachne.
while (ev < sys->runs[run].step) while (ev < sys->runs[run].step)
{ {
graph[graph_nodes (nodes, run, ev - 1, run, ev)] = 1; graph[graph_nodes (nodes, run, ev - 1, run, ev)] = 1;
ev++; ev++;
} }
// Enforce I_M ordering // Enforce I_M ordering
if (sys->runs[run].protocol == INTRUDER && sys->runs[run].role == I_M) if (sys->runs[run].protocol == INTRUDER && sys->runs[run].role == I_M)
{ {
if (last_m != -1) if (last_m != -1)
{ {
graph[graph_nodes (nodes, last_m, 0, run, 0)] = 1; graph[graph_nodes (nodes, last_m, 0, run, 0)] = 1;
} }
last_m = run; last_m = run;
} }
// Next // Next
run++; run++;
} }
// Setup bindings order // Setup bindings order
bl = sys->bindings; bl = sys->bindings;
while (bl != NULL) while (bl != NULL)
{ {
Binding b; Binding b;
b = (Binding) bl->data; b = (Binding) bl->data;
if (valid_binding (b)) if (valid_binding (b))
{ {
#ifdef DEBUG #ifdef DEBUG
if (graph_nodes if (graph_nodes
(nodes, b->run_from, b->ev_from, b->run_to, (nodes, b->run_from, b->ev_from, b->run_to,
b->ev_to) >= (nodes * nodes)) b->ev_to) >= (nodes * nodes))
error ("Node out of scope for %i,%i -> %i,%i.\n", b->run_from, error ("Node out of scope for %i,%i -> %i,%i.\n", b->run_from,
b->ev_from, b->run_to, b->ev_to); b->ev_from, b->run_to, b->ev_to);
#endif #endif
graph[graph_nodes graph[graph_nodes
(nodes, b->run_from, b->ev_from, b->run_to, b->ev_to)] = 1; (nodes, b->run_from, b->ev_from, b->run_to, b->ev_to)] = 1;
} }
bl = bl->next; bl = bl->next;
} }
// Setup local constants order // Setup local constants order
run = 0; run = 0;
while (run < sys->maxruns) while (run < sys->maxruns)
{ {
if (sys->runs[run].protocol != INTRUDER) if (sys->runs[run].protocol != INTRUDER)
{ {
int run2; int run2;
run2 = 0; run2 = 0;
while (run2 < sys->maxruns) while (run2 < sys->maxruns)
{ {
if (sys->runs[run].protocol != INTRUDER && run != run2) if (sys->runs[run].protocol != INTRUDER && run != run2)
{ {
// For these two runs, we check whether run has any variables that are mapped // For these two runs, we check whether run has any variables that are mapped
// to constants from run2 // to constants from run2
Termlist tl; Termlist tl;
tl = sys->runs[run].locals; tl = sys->runs[run].locals;
while (tl != NULL) while (tl != NULL)
{ {
Term t; Term t;
t = tl->term; t = tl->term;
if (t->type == VARIABLE && TermRunid (t) == run if (t->type == VARIABLE && TermRunid (t) == run
&& t->subst != NULL) && t->subst != NULL)
{ {
// t is a variable of run // t is a variable of run
Termlist tl2; Termlist tl2;
tl2 = sys->runs[run2].locals; tl2 = sys->runs[run2].locals;
while (tl2 != NULL) while (tl2 != NULL)
{ {
Term t2; Term t2;
t2 = tl2->term; t2 = tl2->term;
if (realTermLeaf (t2) && t2->type != VARIABLE if (realTermLeaf (t2) && t2->type != VARIABLE
&& TermRunid (t2) == run2) && TermRunid (t2) == run2)
{ {
// t2 is a constant of run2 // t2 is a constant of run2
if (isTermEqual (t, t2)) if (isTermEqual (t, t2))
{ {
// Indeed, run depends on the run2 constant t2. Thus we must store this order. // Indeed, run depends on the run2 constant t2. Thus we must store this order.
// The first send of t2 in run2 must be before the first (read) event in run with t2. // The first send of t2 in run2 must be before the first (read) event in run with t2.
int ev2; int ev2;
int done; int done;
Roledef rd2; Roledef rd2;
done = 0; done = 0;
ev2 = 0; ev2 = 0;
rd2 = sys->runs[run2].start; rd2 = sys->runs[run2].start;
while (!done while (!done
&& ev2 < sys->runs[run2].step) && ev2 < sys->runs[run2].step)
{ {
if (rd2->type == SEND if (rd2->type == SEND
&& termSubTerm (rd2->message, && termSubTerm (rd2->message,
t2)) t2))
{ {
// Allright, we send it here at ev2 first // Allright, we send it here at ev2 first
int ev; int ev;
Roledef rd; Roledef rd;
ev = 0; ev = 0;
rd = sys->runs[run].start; rd = sys->runs[run].start;
while (!done while (!done
&& ev < && ev <
sys->runs[run].step) sys->runs[run].step)
{ {
if (termSubTerm if (termSubTerm
(rd->message, t2)) (rd->message, t2))
{ {
// Term occurs here in run // Term occurs here in run
if (rd->type == READ) if (rd->type == READ)
{ {
// It's read here first. // It's read here first.
// Order and be done with it. // Order and be done with it.
graph[graph_nodes graph[graph_nodes
(nodes, run2, (nodes,
ev2, run, run2, ev2,
ev)] = 1; run, ev)] =
1;
#ifdef DEBUG #ifdef DEBUG
if (DEBUGL (5)) if (DEBUGL (5))
{ {
eprintf eprintf
("* [local originator] term "); ("* [local originator] term ");
termPrint (t2); termPrint
eprintf (t2);
(" is bound using %i, %i before %i,%i\n", eprintf
run2, ev2, (" is bound using %i, %i before %i,%i\n",
run, ev); run2, ev2,
} run, ev);
}
#endif #endif
done = 1; done = 1;
} }
else else
{ {
// It doesn't occur first in a READ, which shouldn't be happening // It doesn't occur first in a READ, which shouldn't be happening
if (sys->output == if (sys->output ==
PROOF) PROOF)
{ {
eprintf eprintf
("Term "); ("Term ");
termPrint (t2); termPrint
eprintf (t2);
(" from run %i occurs in run %i, term ", eprintf
run2, run); (" from run %i occurs in run %i, term ",
termPrint (t); run2, run);
eprintf termPrint (t);
(" before it is read?\n"); eprintf
} (" before it is read?\n");
// Thus, we create an artificial loop }
if (sys->runs[0]. // Thus, we create an artificial loop
step > 1) if (sys->runs[0].
{ step > 1)
// This forces a loop, and thus prunes {
graph // This forces a loop, and thus prunes
[graph_nodes graph
(nodes, 0, 1, [graph_nodes
0, 0)] = 1; (nodes, 0,
} 1, 0,
} 0)] = 1;
} }
rd = rd->next; }
ev++; }
} rd = rd->next;
done = 1; ev++;
} }
rd2 = rd2->next; done = 1;
ev2++; }
} rd2 = rd2->next;
} ev2++;
} }
tl2 = tl2->next; }
} }
} tl2 = tl2->next;
tl = tl->next; }
} }
} tl = tl->next;
run2++; }
} }
} run2++;
run++; }
} }
} run++;
}
}
} }
@ -432,9 +438,6 @@ binding_print (const Binding b)
int int
goal_add (Term term, const int run, const int ev, const int level) goal_add (Term term, const int run, const int ev, const int level)
{ {
int sum;
sum = 0;
term = deVar (term); term = deVar (term);
#ifdef DEBUG #ifdef DEBUG
if (term == NULL) if (term == NULL)
@ -447,9 +450,8 @@ goal_add (Term term, const int run, const int ev, const int level)
#endif #endif
if (realTermTuple (term)) if (realTermTuple (term))
{ {
sum = sum + return goal_add (TermOp1 (term), run, ev, level) +
goal_add (TermOp1 (term), run, ev, level) + goal_add (TermOp2 (term), run, ev, level);
goal_add (TermOp2 (term), run, ev, level);
} }
else else
{ {
@ -479,24 +481,81 @@ goal_add (Term term, const int run, const int ev, const int level)
b = binding_create (term, run, ev); b = binding_create (term, run, ev);
b->level = level; b->level = level;
sys->bindings = list_insert (sys->bindings, b); sys->bindings = list_insert (sys->bindings, b);
sum = sum + 1; #ifdef DEBUG
if (DEBUGL (3))
{
eprintf ("Adding new binding for ");
termPrint (term);
eprintf (" to run %i, ev %i.\n", run, ev);
}
#endif
return 1;
} }
} }
return sum; return 0;
}
//! Add a goal, and bind it immediately.
// If the result is negative, no goals will have been added, as the resulting state must be pruned (cycle) */
int
goal_add_fixed (Term term, const int run, const int ev, const int fromrun,
const int fromev)
{
int newgoals, n;
List l;
int res;
newgoals = goal_add (term, run, ev, 0);
l = sys->bindings;
n = newgoals;
res = 1;
while (res != 0 && n > 0 && l != NULL)
{
Binding b;
b = (Binding) l->data;
if (b->done)
{
globalError++;
binding_print (b);
error (" problem with new fixed binding!");
}
res = goal_bind (b, fromrun, fromev); // returns 0 if it must be pruned
l = l->next;
n--;
}
if (res != 0)
{
return newgoals;
}
else
{
goal_remove_last (newgoals);
return -1;
}
} }
//! Remove a goal //! Remove a goal
void void
goal_remove_last (int n) goal_remove_last (int n)
{ {
while (n > 0 && (sys->bindings != NULL)) while (n > 0)
{ {
Binding b; if (sys->bindings != NULL)
{
Binding b;
b = (Binding) sys->bindings->data; b = (Binding) sys->bindings->data;
binding_destroy (b); binding_destroy (b);
sys->bindings = list_delete (sys->bindings); sys->bindings = list_delete (sys->bindings);
n--; n--;
}
else
{
error
("goal_remove_last error: trying to remove %i too many bindings.",
n);
}
} }
} }
@ -522,6 +581,8 @@ goal_bind (const Binding b, const int run, const int ev)
} }
else else
{ {
globalError++;
binding_print (b);
error ("Trying to bind a bound goal again."); error ("Trying to bind a bound goal again.");
} }
} }
@ -545,7 +606,8 @@ goal_unbind (const Binding b)
/** /**
* Especially made for tuple expansion * Especially made for tuple expansion
*/ */
int binding_block (Binding b) int
binding_block (Binding b)
{ {
if (!b->blocked) if (!b->blocked)
{ {
@ -559,7 +621,8 @@ int binding_block (Binding b)
} }
//! Unblock a binding //! Unblock a binding
int binding_unblock (Binding b) int
binding_unblock (Binding b)
{ {
if (b->blocked) if (b->blocked)
{ {
@ -630,12 +693,13 @@ labels_ordered (Termmap runs, Termlist labels)
} }
//! Check whether the binding denotes a sensible thing such that we can use run_from and ev_from //! Check whether the binding denotes a sensible thing such that we can use run_from and ev_from
int valid_binding (Binding b) int
valid_binding (Binding b)
{ {
if (b->done && !b->blocked) if (b->done && !b->blocked)
return 1; return 1;
else else
return 0; return 0;
} }
//! Prune invalid state w.r.t. <=C minimal requirement //! Prune invalid state w.r.t. <=C minimal requirement
@ -656,7 +720,19 @@ bindings_c_minimal ()
// Recompute closure; does that work? // Recompute closure; does that work?
if (!warshall (graph, nodes)) if (!warshall (graph, nodes))
{ {
// Hmm, cycle List l;
globalError++;
l = sys->bindings;
while (l != NULL)
{
Binding b;
b = (Binding) l->data;
binding_print (b);
eprintf ("\n");
l = l->next;
}
error ("Detected a cycle when testing for c-minimality"); error ("Detected a cycle when testing for c-minimality");
} }
} }
@ -669,7 +745,7 @@ bindings_c_minimal ()
b = (Binding) bl->data; b = (Binding) bl->data;
// Check for a valid binding; it has to be 'done' and sensibly bound (not as in tuple expanded stuff) // Check for a valid binding; it has to be 'done' and sensibly bound (not as in tuple expanded stuff)
if (valid_binding(b)) if (valid_binding (b))
{ {
int run; int run;
int node_from; int node_from;

View File

@ -43,6 +43,8 @@ int binding_print (Binding b);
int valid_binding (Binding b); int valid_binding (Binding b);
int goal_add (Term term, const int run, const int ev, const int level); int goal_add (Term term, const int run, const int ev, const int level);
int goal_add_fixed (Term term, const int run, const int ev, const int fromrun,
const int fromev);
void goal_remove_last (int n); void goal_remove_last (int n);
int goal_bind (const Binding b, const int run, const int ev); int goal_bind (const Binding b, const int run, const int ev);
void goal_unbind (const Binding b); void goal_unbind (const Binding b);

View File

@ -1018,9 +1018,13 @@ order_label_roles (const Claimlist cl)
int scan_label (void *data) int scan_label (void *data)
{ {
Labelinfo linfo; Labelinfo linfo;
Termlist tl;
linfo = (Labelinfo) data; linfo = (Labelinfo) data;
if (inTermlist (cl->prec, linfo->label)) if (linfo == NULL)
return 1;
tl = cl->prec;
if (inTermlist (tl, linfo->label))
{ {
if (linfo->protocol == cl->protocol) if (linfo->protocol == cl->protocol)
{ {

112
src/mgu.c
View File

@ -60,32 +60,32 @@ goodsubst (Term tvar, Term tsubst)
{ {
// function to test compatibility // function to test compatibility
__inline__ int compatibleTypes () __inline__ int compatibleTypes ()
{ {
if (tvar->stype == NULL) if (tvar->stype == NULL)
{ {
// If the variable type is unspecified, anything goes // If the variable type is unspecified, anything goes
return 1; return 1;
} }
else else
{ {
// There are variable types. // There are variable types.
// At least one of them should match a type of the constant. // At least one of them should match a type of the constant.
Termlist tl; Termlist tl;
tl = tvar->stype; tl = tvar->stype;
while (tl != NULL) while (tl != NULL)
{ {
if (inTermlist (tsubst->stype, tl->term)) if (inTermlist (tsubst->stype, tl->term))
{ {
// One type matches // One type matches
return 1; return 1;
} }
tl = tl->next; tl = tl->next;
} }
// No matches // No matches
return 0; return 0;
} }
} }
if (mgu_match == 2) if (mgu_match == 2)
{ {
@ -104,8 +104,7 @@ goodsubst (Term tvar, Term tsubst)
else else
{ {
// It's a leaf, but what type? // It's a leaf, but what type?
if (mgu_match == 1 if (mgu_match == 1 || compatibleTypes ())
|| compatibleTypes ())
{ {
return 1; return 1;
} }
@ -305,68 +304,69 @@ termMguInTerm (Term t1, Term t2, int (*iterator) (Termlist))
return flag; return flag;
} }
//! Most general subterm unifiers of t1 subterm t2 //! Most general subterm unifiers of smallterm subterm bigterm
/** /**
* Try to determine the most general subterm unifiers of two terms. * Try to determine the most general subterm unifiers of two terms.
*@returns Nothing. Iteration gets termlist of subst, and list of keys needed to decrypt. *@returns Nothing. Iteration gets termlist of subst, and list of keys needed
* to decrypt. This termlist does not need to be deleted, because it is handled
* by the mguSubTerm itself.
*/ */
int int
termMguSubTerm (Term t1, Term t2, int (*iterator) (Termlist, Termlist), termMguSubTerm (Term smallterm, Term bigterm,
Termlist inverses, Termlist keylist) int (*iterator) (Termlist, Termlist), Termlist inverses,
Termlist cryptlist)
{ {
int flag; int flag;
flag = 1; flag = 1;
t1 = deVar (t1); smallterm = deVar (smallterm);
t2 = deVar (t2); bigterm = deVar (bigterm);
if (t2 != NULL) if (bigterm != NULL)
{ {
Termlist tl; Termlist tl;
if (!realTermLeaf (t2)) if (!realTermLeaf (bigterm))
{ {
if (realTermTuple (t2)) if (realTermTuple (bigterm))
{ {
// 'simple' tuple // 'simple' tuple
flag = flag =
flag && termMguSubTerm (t1, TermOp1 (t2), iterator, inverses, flag
keylist); && termMguSubTerm (smallterm, TermOp1 (bigterm), iterator,
flag = inverses, cryptlist);
flag && termMguSubTerm (t1, TermOp2 (t2), iterator, inverses, flag = flag
keylist); && termMguSubTerm (smallterm, TermOp2 (bigterm), iterator,
inverses, cryptlist);
} }
else else
{ {
// Must be encryption // Must be encryption
// So, we need the key, and try to get the rest Term keyneeded;
Term newkey;
newkey = inverseKey (inverses, TermKey (t2)); keyneeded = inverseKey (inverses, TermKey (bigterm));
// We can never produce the TERM_Hidden key, thus, this is not a valid iteration. // We can never produce the TERM_Hidden key, thus, this is not a valid iteration.
if (!isTermEqual (newkey, TERM_Hidden)) if (!isTermEqual (keyneeded, TERM_Hidden))
{ {
Termlist keylist_new; cryptlist = termlistAdd (cryptlist, bigterm); // Append, so the last encrypted term in the list is the most 'inner' one, and the first is the outer one.
keylist_new = termlistShallow (keylist);
keylist_new = termlistAdd (keylist_new, newkey);
// Recurse // Recurse
flag = flag =
flag flag
&& termMguSubTerm (t1, TermOp (t2), iterator, inverses, && termMguSubTerm (smallterm, TermOp (bigterm), iterator,
keylist_new); inverses, cryptlist);
termlistDelete (keylist_new);
cryptlist = termlistDelTerm (cryptlist);
} }
termDelete (newkey); termDelete (keyneeded);
} }
} }
// simple clause or combined // simple clause or combined
tl = termMguTerm (t1, t2); tl = termMguTerm (smallterm, bigterm);
if (tl != MGUFAIL) if (tl != MGUFAIL)
{ {
// Iterate // Iterate
flag = flag && iterator (tl, keylist); flag = flag && iterator (tl, cryptlist);
// Reset variables // Reset variables
termlistSubstReset (tl); termlistSubstReset (tl);
// Remove list // Remove list
@ -375,7 +375,7 @@ termMguSubTerm (Term t1, Term t2, int (*iterator) (Termlist, Termlist),
} }
else else
{ {
if (t1 != NULL) if (smallterm != NULL)
{ {
flag = 0; flag = 0;
} }

View File

@ -101,6 +101,7 @@ systemInit ()
sys->roleeventmax = 0; sys->roleeventmax = 0;
sys->claimlist = NULL; sys->claimlist = NULL;
sys->labellist = NULL; sys->labellist = NULL;
sys->match = 0; // default matching
/* matching CLP */ /* matching CLP */
sys->constraints = NULL; // no initial constraints sys->constraints = NULL; // no initial constraints

View File

@ -683,7 +683,7 @@ tupleCount (Term tt)
//! Yield the projection Pi(n) of a term. //! Yield the projection Pi(n) of a term.
/** /**
*@param tt Term *@param tt Term
*@param n The index in the tuple. *@param n The index in the tuple [0..tupleCount-1]
*@return Returns either a pointer to a term, or NULL if the index is out of range. *@return Returns either a pointer to a term, or NULL if the index is out of range.
*\sa tupleCount() *\sa tupleCount()
*/ */
@ -1085,7 +1085,7 @@ term_encryption_level (const Term term)
if (t == NULL) if (t == NULL)
{ {
#ifdef DEBUG #ifdef DEBUG
if (DEBUGL(2)) if (DEBUGL (2))
{ {
eprintf ("Warning: Term encryption level finds a NULL for term "); eprintf ("Warning: Term encryption level finds a NULL for term ");
termPrint (term); termPrint (term);

View File

@ -272,7 +272,8 @@ termlistConcat (Termlist tl1, Termlist tl2)
//! Remove the pointed at element from the termlist. //! Remove the pointed at element from the termlist.
/** /**
* Easier because of the double linked list. * Easier because of the double linked list. Note: does not do termDelete on the term.
*
*@param tl The pointer to the termlist node to be deleted from the list. *@param tl The pointer to the termlist node to be deleted from the list.
*@return The possibly new head pointer to the termlist. *@return The possibly new head pointer to the termlist.
*/ */
@ -667,8 +668,7 @@ termlistLocal (Termlist tl, const Termlist fromlist, const Termlist tolist)
while (tl != NULL) while (tl != NULL)
{ {
newtl = newtl = termlistAdd (newtl, termLocal (tl->term, fromlist, tolist));
termlistAdd (newtl, termLocal (tl->term, fromlist, tolist));
tl = tl->next; tl = tl->next;
} }
return newtl; return newtl;