Typing for secrecy¶
This section describes the typing tactic enabled by
set securityTypes = true
.
The user must give types when declaring names and mutable states
describing which messages are public or secret.
Then, Squirrel will type-check all systems in the file
when they are defined.
Finally, the typing
tactic proves that a public term,
i.e., a message possibly known by the attacker,
cannot be equal to a secret term.
Note
This tactic implements the work published in [DHL25].
Types¶
Types used to express security guarantees are different from the usual
types defined by the @type
production. They do not replace them,
but are used in addition to them.
To typecheck a term, the user must have assigned a security type to some base elements of that term (i.e. names and mutable states). There are two kinds of security types: types for messages and types for keys.
message_type::=
Msg
|
High
|
Low
|
Bool
|
Cst fun_id
|
message_type * message_type
|
message_type + message_type
A message type describes the level of knowledge the attacker may have on a term with that type.
Msg
is the most general type: it does not give any guarantee.High
means the term is secret: its exact value cannot be computed from public values (except with negligible probility). However, some bits of information about it could be publicly available.Low
is the type of a value that may be published.Bool
is the type of a boolean value. These values are always public.Cst c
designates a term overwhelmingly interpreted as the constantc
. The identifier c must designate an abstract function with a type of the formindex ->* message
.T_1 * T_2
designates a pair of a term of typeT_1
and one of typeT_2
.T_1 + T_2
is a sum type: a term of this type will be a term of typeT_1
in some executions, and of typeT_2
in others.
::=
SK[fun_id, message_type]
|
AK[fun_id, message_type]
|
SSK[fun_id, message_type]
A key type describes an honest uncompromised key for encryption/signature:
SK[f, T]
is a symmetric encryption key.T
is the type of the plaintexts that can be encrypted with this key.f
must be the associated encryption function, declared usingsenc
.AK[f, T]
is an asymmetric encryption private key.T
is the type of the plaintexts that can be encrypted with this key by honest agent in the protocol.f
must be the associated encryption function, declared usingaenc
.SSK[f, T]
is a signature private key. A signature with this key ensures the signed message is of typeT
.f
must be the associated signature function, declared usingsignature
.
::=
message_type
|
key_type
|
Rand
A security type is either a message type, a key type,
or Rand
, a special type reserved for randomness used when encrypting.
To encrypt a message typed T
with a key typed SK[f, T]
or AK[f, T]
, the randomness given to the encryption function
must be typed Rand
.
The type system checks, among other conditions,
that the same random is not used twice.
Typing algorithm¶
The typing procedure does not support all features of Squirrel’s language. In particular, it cannot consider terms with user-defined types, higher-order, or names and mutable states with non-index arguments.
The typing procedure is sound w.r.t the type system described in
[DHL25], but it is not complete.
One notable source of incompleteness is a rule of the type system
that allows, when a variable is known to be of type T_1 + T_2
,
to perform a case disjunction, and continue the typechecking twice,
assuming first that the variable has type T_1
, and then T_2
.
One must be careful when applying that rule, since it may lead to the same
randomness being apparently used in different encryptions, once in each
branch of the proof.
Typing may thus require a subtle use of that rule to break sums.
The implemented algorithm relies on a heuristic to decide when to apply it,
which is not complete.
As much as possible, when typechecking fails because of the heuristic, the
error message reports it.
Declarations¶
The flag securityTypes
modifies the syntax and/or behaviour of some
declarations.
Once it is set to true
, the user can add security types
to name and mutable state declarations.
Name declarations¶
- Declaration Variant name name_id : type ->? type , security_type?
A name declaration
name name_id : typei ->? types
introduces a name symbolname_id
, with a user-definedsecurity_type
. The same constraints ontypei
andtypes
as on normal name declarations apply. A name can only be declared with typesLow
,High
,Rand
, or a@key type
. Additionally, a security type other thanLow
can only be declared if the type in which the name is sampled is taggedlarge
.
State declarations¶
- Declaration Variant mutable state_id binders : typesecurity_typetype, security_type? = term
Declares a mutable state with a user-defined @security_type. The same restrictions on
binders
andtype
as usual apply.When using a
security_type
,type
must bemessage
.If the
term
provided as initial value cannot be typed with the givensecurity_type
, then the mutable statestate_id
is not well-typed. Since, when declaring a state, actioninit
is updated in all systems to set its initial value, any past or future system immediately stops being well-typed as well, and a warning is displayed to the user.
Protocol declarations¶
The syntax for protocol declarations is unchanged.
However, each system is typechecked when it is declared.
The typechecker ensures all outputs are Low
,
all conditions are Bool
, and each update of a mutable state
sets it to a value of the expected type, provided at the state’s declaration.
These verifications are performed separately on each projection of the system, unless the
system does not use the diff
operator, in which case it is only typechecked once.
When declaring a system, some proof obligations may be opened. Indeed, to typecheck some terms, the type system may need to assume that some constants with different symbols are different – typically, constants used as tags to distinguish protocol messages. If the typechecker makes this assumption, and cannot automatically prove it holds, it opens a subgoal asking the user to prove it, before declaring the system to be well-typed.
The typing
tactic is enabled in all well-typed projections of a system, but
is unavailable in projections where the typechecking failed.
In that case, a message describing the action in which the error occurred is displayed.
Tactic¶
- Tactic typing hypothesis_id¶
This tactic applies to a hypothesis of the form
t_1 = t_2
. The current goal’ssystem_context
must specify a set consisting in a finite number of well-typed (projections of) systems. The tactic attempts to givet_1
the typeLow
andt_2
the typeHigh
, or vice-versa if that first attempt fails, in each system of the set. These typing derivations cannot use encryption randomness, of typeRand
.The
typing
tactic does not unfold macros, and it may thus be necessary to unfold global macros and conditions manually.Like for protocol declarations, typechecking can open subgoals:
Again, if typechecking
t_1
andt_2
requires the assumption that some constants are different, a proof obligation is generated for it.If a subterm of the form
output@tau
appears int_1
ort_2
, the user must prove that it appears under a condition that impliesexec@tau
.If a mutable state
s@tau
appears int_1
ort_2
, the user must prove that it appears under a condition that implieshappens(tau)
.
In these subgoals, not all hypotheses from the original proof context are sound to keep, according to the soundness proof of the type system in [DHL25]. The tactic only keeps global hypotheses, and local hypotheses that are either
[const]
or of typeBool
in the type system.If typechecking succeeds, the hypothesis
hypothesis_id
is contradictory, andtyping
closes the original goal. If typechecking fails in one or more systems, the tactic fails, and displays the errors obtained by both attempts at typing (t_1:Low
/t_2:High
and the converse).