2006-01-02 18:43:25 +00:00
/**
*
* @ file prune_theorems . c
*
* Prune stuff based on theorems .
* Pruning leaves complete results .
*
*/
# include "system.h"
# include "list.h"
# include "switches.h"
# include "binding.h"
# include "specialterm.h"
2006-02-28 13:41:36 +00:00
# include "hidelevel.h"
2006-01-02 18:43:25 +00:00
extern Protocol INTRUDER ;
extern int proofDepth ;
extern int max_encryption_level ;
2006-02-27 16:08:17 +00:00
//! Check locals occurrence
/*
* Returns true if the order is correct
*/
int
correctLocalOrder ( const System sys )
{
2006-02-28 13:41:36 +00:00
int flag ;
2006-02-27 16:08:17 +00:00
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 ) ;
2006-02-28 15:33:12 +00:00
e1 = firstOccurrence ( sys , r1 , t , ANYEVENT ) ;
2006-02-28 13:41:36 +00:00
if ( e1 > = 0 )
2006-02-27 16:08:17 +00:00
{
2006-02-28 15:33:12 +00:00
if ( roledef_shift ( sys - > runs [ r1 ] . start , e1 ) - > type = = READ )
2006-02-27 16:08:17 +00:00
{
2006-02-28 15:33:12 +00:00
e2 = firstOccurrence ( sys , r2 , t , SEND ) ;
if ( e2 > = 0 )
2006-02-28 13:41:36 +00:00
{
2006-02-28 15:33:12 +00:00
// thus, it should not be the case that e1 occurs before e2
if ( isDependEvent ( r1 , e1 , r2 , e2 ) )
2006-02-28 13:41:36 +00:00
{
2006-02-28 15:33:12 +00:00
// That's not good!
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because ordering for term " ) ;
termSubstPrint ( t ) ;
eprintf
( " cannot be correct: the first send r%ii%i occurs after the read r%ii%i. \n " ,
r2 , e2 , r1 , e1 ) ;
}
flag = false ;
return false ;
2006-02-28 13:41:36 +00:00
}
}
2006-02-28 15:33:12 +00:00
else
{
globalError + + ;
eprintf ( " Error: term " ) ;
termSubstPrint ( t ) ;
eprintf
( " from run %i should occur in run %i, but it doesn't. \n " ,
r2 , r2 ) ;
globalError - - ;
error ( " Abort " ) ;
}
}
else
{
2006-03-15 08:33:09 +00:00
// not a read first? That's definitely impossible (can be caused by choices
2006-02-28 15:33:12 +00:00
globalError + + ;
eprintf ( " Error: term " ) ;
termSubstPrint ( t ) ;
eprintf
2006-03-15 08:33:09 +00:00
( " from run %i should occur in run %i first in a READ event, but it occurs first in event %i. \n " ,
r2 , r1 , e1 ) ;
eprintf ( " It occurs first in " ) ;
roledefPrint ( eventRoledef ( sys , r1 , e1 ) ) ;
eprintf ( " \n " ) ;
eprintf ( " which starts with " ) ;
roledefPrint ( eventRoledef ( sys , r1 , 0 ) ) ;
eprintf ( " \n " ) ;
2006-02-28 15:33:12 +00:00
globalError - - ;
error ( " Abort " ) ;
2006-02-27 16:08:17 +00:00
}
}
2006-02-28 15:33:12 +00:00
else
{
globalError + + ;
eprintf ( " Error: term " ) ;
termSubstPrint ( t ) ;
eprintf
( " from run %i should occur in run %i, but it doesn't. \n " , r2 ,
r1 ) ;
globalError - - ;
error ( " Abort " ) ;
}
return true ;
2006-02-27 16:08:17 +00:00
2006-02-28 15:33:12 +00:00
}
2006-02-27 16:08:17 +00:00
}
2006-02-28 13:41:36 +00:00
2006-02-27 16:08:17 +00:00
return iterateLocalToOther ( sys , r1 , checkTerm ) ;
}
2006-02-28 13:41:36 +00:00
flag = true ;
iterateRegularRuns ( sys , checkRun ) ;
return flag ;
2006-02-27 16:08:17 +00:00
}
2006-01-02 20:18:47 +00:00
//! Check initiator roles
/**
* Returns false iff an agent type is wrong
*/
int
initiatorAgentsType ( const System sys )
{
int run ;
run = 0 ;
while ( run < sys - > maxruns )
{
// Only for initiators
if ( sys - > runs [ run ] . role - > initiator )
{
Termlist agents ;
2006-03-15 21:30:19 +00:00
agents = sys - > runs [ run ] . rho ;
2006-01-02 20:18:47 +00:00
while ( agents ! = NULL )
{
if ( ! goodAgentType ( agents - > term ) )
{
return false ;
}
agents = agents - > next ;
}
}
run + + ;
}
return true ; // seems to be okay
}
2006-01-02 18:43:25 +00:00
//! Prune determination because of theorems
/**
* When something is pruned because of this function , the state space is still
* considered to be complete .
*
* @ returns true iff this state is invalid because of a theorem
*/
int
prune_theorems ( const System sys )
{
Termlist tl ;
List bl ;
int run ;
// Check all types of the local agents according to the matching type
if ( ! checkAllSubstitutions ( sys ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf
( " Pruned because some local variable was incorrectly subsituted. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
// Check if all actors are agents for responders (initiators come next)
run = 0 ;
while ( run < sys - > maxruns )
{
if ( ! sys - > runs [ run ] . role - > initiator )
{
Term actor ;
actor = agentOfRun ( sys , run ) ;
if ( ! goodAgentType ( actor ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because the actor " ) ;
termPrint ( actor ) ;
eprintf ( " of run %i is not of a compatible type. \n " , run ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
}
run + + ;
}
// Prune if any initiator run talks to itself
/**
* This effectively disallows Alice from talking to Alice , for all
* initiators . We still allow it for responder runs , because we assume the
* responder is not checking this .
*/
2006-03-31 09:24:41 +01:00
if ( switches . initUnique )
2006-01-02 18:43:25 +00:00
{
2006-03-28 15:45:02 +01:00
if ( selfInitiators ( sys ) > 0 )
2006-01-02 18:43:25 +00:00
{
2006-03-28 15:45:02 +01:00
// XXX TODO
// Still need to fix proof output for this
//
// Pruning because some agents are equal for this role.
return true ;
2006-01-02 18:43:25 +00:00
}
}
2006-03-31 09:24:41 +01:00
if ( switches . respUnique )
{
if ( selfResponders ( sys ) > 0 )
{
// XXX TODO
// Still need to fix proof output for this
//
// Pruning because some agents are equal for this role.
return true ;
}
}
2006-01-02 18:43:25 +00:00
// Prune wrong agents type for initators
2006-01-02 20:18:47 +00:00
if ( ! initiatorAgentsType ( sys ) )
2006-01-02 18:43:25 +00:00
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf
( " Pruned: an initiator role does not have the correct type for one of its agents. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
// Check if all agents of the main run are valid
if ( ! isRunTrusted ( sys , 0 ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf
( " Pruned because all agents of the claim run must be trusted. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
// Check if the actors of all other runs are not untrusted
if ( sys - > untrusted ! = NULL )
{
int run ;
run = 1 ;
while ( run < sys - > maxruns )
{
if ( sys - > runs [ run ] . protocol ! = INTRUDER )
{
2006-03-15 21:30:19 +00:00
if ( sys - > runs [ run ] . rho ! = NULL )
2006-01-02 18:43:25 +00:00
{
Term actor ;
actor = agentOfRun ( sys , run ) ;
if ( actor = = NULL )
{
error ( " Agent of run %i is NULL " , run ) ;
}
if ( ! isAgentTrusted ( sys , actor ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf
( " Pruned because the actor of run %i is untrusted. \n " ,
run ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
}
else
{
Protocol p ;
globalError + + ;
eprintf ( " Run %i: " , run ) ;
role_name_print ( run ) ;
eprintf ( " has an empty agents list. \n " ) ;
eprintf ( " protocol->rolenames: " ) ;
p = ( Protocol ) sys - > runs [ run ] . protocol ;
termlistPrint ( p - > rolenames ) ;
eprintf ( " \n " ) ;
error ( " Aborting. " ) ;
globalError - - ;
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
}
run + + ;
}
}
// Check for c-minimality
{
if ( ! bindings_c_minimal ( ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because this is not <=c-minimal. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
}
2006-02-27 16:08:17 +00:00
/*
* Check for correct orderings involving local constants
*/
2006-02-28 13:57:38 +00:00
if ( ! ( switches . experimental & 8 ) )
2006-02-27 22:27:09 +00:00
{
2006-02-28 13:41:36 +00:00
if ( ! correctLocalOrder ( sys ) )
{
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf
( " Pruned because this does not have the correct local order. \n " ) ;
}
return true ;
}
2006-02-27 22:27:09 +00:00
}
2006-02-27 16:08:17 +00:00
2006-01-02 18:43:25 +00:00
/**
* Check whether the bindings are valid
*/
bl = sys - > bindings ;
while ( bl ! = NULL )
{
Binding b ;
b = bl - > data ;
2006-02-28 13:57:38 +00:00
// Check for "Hidden" interm goals
2006-03-08 12:38:39 +00:00
//! @todo in the future, this can be subsumed by adding TERM_Hidden to the hidelevel constructs
2006-02-28 13:57:38 +00:00
if ( termInTerm ( b - > term , TERM_Hidden ) )
2006-01-02 18:43:25 +00:00
{
2006-02-28 13:57:38 +00:00
// Prune the state: we can never meet this
if ( switches . output = = PROOF )
2006-01-02 18:43:25 +00:00
{
2006-02-28 13:57:38 +00:00
indentPrint ( ) ;
eprintf ( " Pruned because intruder can never construnct " ) ;
termPrint ( b - > term ) ;
eprintf ( " \n " ) ;
2006-02-28 13:41:36 +00:00
}
2006-02-28 13:57:38 +00:00
return true ;
2006-02-28 13:41:36 +00:00
}
if ( switches . experimental & 4 )
{
// Check for SK-type function occurrences
//!@todo Needs a LEMMA, although this seems to be quite straightforward to prove.
// The idea is that functions are never sent as a whole, but only used in applications.
2006-03-08 12:38:39 +00:00
//! @todo Subsumed by hidelevel lemma later
2006-02-28 13:41:36 +00:00
if ( isTermFunctionName ( b - > term ) )
{
if ( ! inKnowledge ( sys - > know , b - > term ) )
{
// Not in initial knowledge of the intruder
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because the function " ) ;
termPrint ( b - > term ) ;
eprintf ( " is not known initially to the intruder. \n " ) ;
}
return true ;
}
2006-01-02 18:43:25 +00:00
}
}
// Check for encryption levels
/*
* if ( switches . match < 2
2006-03-08 12:38:39 +00:00
* ! @ todo Doesn ' t work yet as desired for Tickets . Prove lemma first .
2006-01-02 18:43:25 +00:00
*/
2006-02-28 13:41:36 +00:00
if ( switches . experimental & 2 )
2006-01-02 18:43:25 +00:00
{
2006-01-17 16:18:26 +00:00
if ( ! hasTicketSubterm ( b - > term ) )
2006-01-02 18:43:25 +00:00
{
2006-01-17 16:18:26 +00:00
if ( term_encryption_level ( b - > term ) > max_encryption_level )
{
// Prune: we do not need to construct such terms
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because the encryption level of " ) ;
termPrint ( b - > term ) ;
eprintf ( " is too high. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-17 16:18:26 +00:00
}
2006-01-02 18:43:25 +00:00
}
}
2006-04-13 13:43:13 +01:00
// To be on the safe side, we currently limit the encryption level. This is not a problem for known attacks, but should be addressed more carefully at some point.
2006-03-31 11:12:58 +01:00
/**
* @ todo Fix untyped variables reasoning
*/
2006-04-13 13:43:13 +01:00
if ( term_encryption_level ( b - > term ) > max_encryption_level )
2006-03-31 11:12:58 +01:00
{
2006-04-13 13:43:13 +01:00
// Prune: we do not need to construct such terms
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because the encryption level of " ) ;
termPrint ( b - > term ) ;
eprintf ( " is too high. \n " ) ;
}
2006-03-31 11:12:58 +01:00
return true ;
}
2006-02-28 13:41:36 +00:00
/**
* Prune on the basis of hidelevel lemma
*/
if ( hidelevelImpossible ( sys , b - > term ) )
2006-01-02 18:43:25 +00:00
{
2006-02-28 13:41:36 +00:00
// Prune: we do not need to construct such terms
if ( switches . output = = PROOF )
2006-01-02 18:43:25 +00:00
{
2006-02-28 13:41:36 +00:00
indentPrint ( ) ;
eprintf ( " Pruned because the hidelevel of " ) ;
termPrint ( b - > term ) ;
eprintf ( " is impossible to satisfy. \n " ) ;
2006-01-02 18:43:25 +00:00
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
bl = bl - > next ;
}
/* check for singular roles */
run = 0 ;
while ( run < sys - > maxruns )
{
if ( sys - > runs [ run ] . role - > singular )
{
// This is a singular role: it therefore should not occur later on again.
int run2 ;
Term rolename ;
rolename = sys - > runs [ run ] . role - > nameterm ;
run2 = run + 1 ;
while ( run2 < sys - > maxruns )
{
Term rolename2 ;
rolename2 = sys - > runs [ run2 ] . role - > nameterm ;
if ( isTermEqual ( rolename , rolename2 ) )
{
// This is not allowed: the singular role occurs twice in the semitrace.
// Thus we prune.
if ( switches . output = = PROOF )
{
indentPrint ( ) ;
eprintf ( " Pruned because the singular role " ) ;
termPrint ( rolename ) ;
eprintf ( " occurs more than once in the semitrace. \n " ) ;
}
2006-02-28 13:41:36 +00:00
return true ;
2006-01-02 18:43:25 +00:00
}
run2 + + ;
}
}
run + + ;
}
2006-02-28 13:41:36 +00:00
return false ;
2006-01-02 18:43:25 +00:00
}