Lectures onType Theory
Chapter 70
Chapter 70Optional

Information-Flow Type Systems and Noninterference

Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.

Preservation and progress cannot distinguish the following command from an ordinary well-typed conditional: (Leak)if h=0 then l:=0 else l:=1. Both branches assign integers. Nevertheless, an observer who may read the public variable l learns whether the secret h was zero. The missing invariant relates two runs: changing only secret inputs must not change public outputs. For the imperative language below, that relation is the exact termination-insensitive noninterference property to establish.

Stores, observations, and the security lattice

Fix a finite lattice (L,sec,,). A security environment Γ:VarL assigns a fixed label to every mutable variable. Expressions and commands are e::=kxe+e,b::=eee=e,c::=skipx:=ec;cif b then c else cwhile b do c. Stores map variables to integers. The deterministic big-step relation is c,sIFs; its assignment, sequence, conditional, and terminating-loop rules appear in appendix A. The theorem will quantify only over pairs of terminating derivations.

An observer at level o sees the variables labelled at most o.

Definition 70.1 — Low equivalence

s1Γos2x. Γ(x)secos1(x)=s2(x).

On the two-point lattice LsecH, stores agreeing on l:L are low-equivalent at L, regardless of their values at h:H. Taking s0(h)=0 and s1(h)=7 in (Leak) yields outputs with l=0 and l=1, so the command fails the relation.

Expression labels and command typing

The expression judgment Γe: assigns an upper bound to every variable read by e: constants have label , a variable has label Γ(x), and a compound expression joins the labels of its operands. Boolean guards use the same join.

Commands are checked under a program-counter label: ΓpIFc. The label p records the information already revealed by control flow. Γe:psecΓ(x)ΓpIFx:=eIFAssignΓpIFc1ΓpIFc2ΓpIFc1;c2IFSeq Γb:ΓpIFc1ΓpIFc2ΓpIFif b then c1 else c2IFIfΓb:ΓpIFcΓpIFwhile b do cIFWhile. The skip rule has no premise. In Leak, the branches are checked under H, but IF-Assign would require HsecL. The rejected derivation pinpoints the implicit flow.

Lemma 70.2 — Program-counter monotonicity

If psecp and ΓpIFc, then ΓpIFc.

Proof of Lemma 70.2 — Program-counter monotonicity

Proof. Induct on the typing derivation. In IF-Assign, psecpsecΓ(x). In IF-If and IF-While, monotonicity of join gives psecp; apply the induction hypothesis to the premises. Sequence and skip are immediate. ◻

Write c,sIFc,s for the deterministic small-step rules in appendix A. A conditional step removes a guard and thereby lowers the dynamic program counter. The preceding lemma supplies exactly the needed weakening.

Proposition 70.3 — Subject reduction

If ΓpIFc and c,sIFc,s, then ΓpIFc.

Proof of Proposition 70.3 — Subject reduction

Proof. By cases on the step. Assignment produces skip. A conditional selects a branch typed at p; since psecp, apply lemma 70.2. While unfolds to a conditional followed by the loop, whose premises follow from IF-While. Sequence uses the induction hypothesis for its left component and retains the right premise. ◻

Exercise 70.1

★☆☆ Erase p from IF-Assign while leaving the branch rule unchanged. Construct a derivation for Leak, then calculate the two low-equivalent runs that refute noninterference.

Agreement and confinement

Two lemmas divide the proof according to whether observed data are read or written.

Lemma 70.4 — Expression agreement, or simple security

If Γe:, seco, and s1Γos2, then [[e]]s1=[[e]]s2. The same holds for guards.

Proof of Lemma 70.4 — Expression agreement, or simple security

Proof. Induct on e. In the variable case, Γ(x)secseco, so low equivalence gives the equality. Constants agree. For addition, each operand label flows to their join and therefore to o; apply both induction hypotheses. Guard evaluation follows from the two expression cases. ◻

Lemma 70.5 — High-context confinement

If pseco, ΓpIFc, and c,sIFs, then sΓos.

Proof of Lemma 70.5 — High-context confinement

Proof. Induct on the evaluation derivation. For assignment to x, IF-Assign gives psecpsecΓ(x). If Γ(x)seco, transitivity would contradict pseco. Hence no observed variable changes. Sequence composes the two low-equivalences.

For a conditional, each selected branch is typed at p. Since psecp, that label also fails to flow to o; apply the induction hypothesis to the selected branch. The false-loop rule changes no store. In the true-loop rule, apply the induction hypothesis first to the body and then to the recursive loop derivation, and use transitivity of low equivalence. ◻

The original Volpano–Irvine–Smith calculus phrases these facts as simple security, confinement, and a two-store soundness theorem [VIS96]. Its printed syntax-directed system uses command security types rather than our explicit program-counter judgment. The proof above belongs to the book’s stated calculus; the historical theorem is comparison evidence, not an implementation transfer.

Exercise 70.2

★★☆ Prove that psecp implies psecp in any lattice. Use it to derive lemma 70.2 for IF-While in full.

Two runs

The central argument is an unwinding proof over two terminating derivations. The low-guard case synchronizes their control choices; the high-guard case allows different choices but confines both.

Theorem 70.6 — Termination-insensitive noninterference

Suppose ΓIFc, s1Γos2, and both runs terminate: c,s1IFs1,c,s2IFs2. Then s1Γos2.

Proof of Theorem 70.6 — Termination-insensitive noninterference

Proof. Prove the stronger statement for ΓpIFc, by induction on the first evaluation and case analysis on the second.

For x:=e, consider an observed target Γ(x)seco. IF-Assign gives psecΓ(x), hence seco. By lemma 70.4, both assignments store the same integer. Unobserved targets do not affect low equivalence. Sequence applies the induction hypothesis to the first commands and then to the second commands.

For a conditional with guard label , there are two cases. If seco, expression agreement makes both guards select the same branch. Apply the induction hypothesis to that branch, whose typing premise is at p. If seco, then pseco. Each run may select a different branch, but lemma 70.5 shows that each selected branch preserves its own initial low store. Transitivity through s1Γos2 relates the results.

For while with a low guard, expression agreement synchronizes zero iterations or one iteration. In the latter case, apply the induction hypothesis to the body and then to the two residual loop derivations. For a high guard, the whole terminating loop is confined: every body is typed at pseco, so each finite iteration preserves its run’s low projection. The runs may execute different numbers of iterations; their final low projections still equal their respective initial ones. Skip is immediate. Instantiate the stronger statement with p=. ◻

The theorem deliberately assumes that both evaluations terminate. A program may loop exactly when h=0; an observer who can detect termination learns a secret bit even though no low store cell changes. That is a termination-sensitive observation and is not covered by theorem 70.6.

Exercise 70.3

★★☆ Repair Leak in two ways: first by relabelling its destination, then by making the public result constant. Give the first typing derivation. Explain why the second program is semantically secure but still rejected by the syntax-directed rules when its assignments remain under a high guard.

A complete password calculation

Let Γ(pwd)=Γ(guess)=Γ(audit)=H and Γ(status)=L. Consider (PasswordAudit)if pwd=guess then audit:=1 else audit:=0;status:=1. The guard has label H. Both branch assignments satisfy HL=HsecH=Γ(audit). The final assignment is checked after the conditional, at program counter , so secL. For any two initial stores agreeing on status, the branches may disagree on audit, but confinement preserves the low projection; both final assignments then write 1 to status. Thus the complete two-run result is s1ΓLs2s1[status1]ΓLs2[status1]. Moving status:=1 into only the successful branch would make the program rejected and genuinely leaking when the initial status differs from 1.

The checker as a finite abstract interpretation

Only after fixing the two-run semantics can we compare the type checker to an analysis. For a finite set of variables, abstract an expression to the join of labels of variables it reads. Abstract a command at program point p to the predicate that every assignment x:=e on a control path satisfies pesecΓ(x), joining the guard label into p below conditionals and loop bodies. Structural recursion computes this finite predicate; IF-Assign, IF-If, and IF-While are exactly its local transfer conditions.

Soundness of this analysis is theorem 70.6, not merely termination of the checker. It is incomplete: the constant-branch program if h=0 then l:=0 else l:=0 is noninterfering but rejected because the abstraction retains the high control dependency and does not prove equality of branch results. The more flow- and path-sensitive analysis of Li and Zhang and the ownership-oriented Flowistry system refine different components of this abstraction [LZ17, CPAH22]. Neither paper’s theorem transfers to this fixed-variable calculus without an explicit translation.

Exercise 70.4

★★★ For each program below, decide whether it is accepted, semantically noninterfering, both, or neither. Justify each semantic answer with two runs or an unwinding argument. (a)l:=0;(b)if h=0 then l:=0 else l:=0;(c)if h=0 then l:=0 else l:=1;(d)h:=l+1.

A bounded DCC comparison

The Dependency Core Calculus protects a value at label with a type TA. This is a separate, functional theorem card. It does not replace the imperative two-run proof.

Algehed and Bernardy first prove a shallow relational-parametricity theorem. For their shallow DCC module dcc, a type A, observer ^, and protected label sec^, every f:(dcc:DCC)(T dcc  A)(T dcc ^ Bool) returns equal results on any two protected inputs. This is their Theorem 3.

Their Definition 4 interprets deep DCC types and terms in the shallow module. Theorem 5 says the translation preserves typing. Theorem 6 says one deep DCC step translates to definitional equality; its bind-return case assumes the right-unit law for the selected DCC module. Strong normalization and confluence then reflect equality at protected Boolean values.

Theorem 70.7 — Original-DCC noninterference

Let A be a DCC type, let sec^, and let e:TAT^Bool be a closed deep DCC term. For closed a0,a1:A, e(returna0)=βe(returna1).

Proof of Theorem 70.7 — Original-DCC noninterference

Proof. By translation type preservation, [[e]] has the shallow type needed by Theorem 3. Apply that theorem to [[a0]] and [[a1]]: [[e]](return[[a0]])[[e]](return[[a1]]). Definition 4 identifies these terms with the translations of the two deep applications. Theorem 6 carries each deep reduction to definitional equality. Strong normalization and confluence put the closed protected Booleans in canonical return forms; the Boolean reflection corollary makes their deep normal forms equal. One beta expansion on each side yields the displayed equation. This is precisely the route through Theorems 3, 5, and 6 used to derive Algehed–Bernardy Theorem 8 [AB19]. ◻

The pinned Agda fixture exposes its assumptions rather than hiding them: lattice structure is postulated in Definitions.agda; function extensionality, strong normalization of deep DCC, a separating observer, and shallow noninterference appear as named postulates in Translation.agda. The artifact is hole-free at its pinned commit, but the local environment used for this edition has no Agda executable, so Appendix E records hashes and a static hole scan rather than claiming a fresh typecheck.

This comparison covers the original DCC Boolean-observation theorem only. It does not establish termination-sensitive security, declassification, term-sensitive relations, quantitative leakage, or results for other DCC variants. The Haskell adaptation in the paper explicitly remains termination-insensitive because partiality exposes a termination channel.

Chapter seminar

The Kappa companion at artifacts/ch70-tini-checker/ implements the two-point instance, the syntax-directed checker, a fuel-bounded evaluator, and finite two-run tests. The finite enumeration tests the implementation; the proof of theorem 70.6 quantifies over every terminating derivation.

The first two tasks form the practical route. Later tasks change the observation and therefore require a new theorem statement.

Suggested first pass.

Run the leak and audit examples, then inspect why the secure constant-branch program is rejected before modifying the checker.

Exercise 70.5

★★★ Practical project.imperative-tini-checker Run the accepted corpus. Remove the program-counter join from conditional checking and confirm that the unchanged leak oracle fails. Add a third lattice point M with LsecMsecH, and test one permitted L-to-M assignment and one rejected H-to-M assignment.

Exercise 70.6

★★★ Write the complete high-guard while case of theorem 70.6, including the induction on each finite evaluation and the two transitivity steps for low equivalence.

Exercise 70.7

★★★ Give two low-equivalent stores for a program that terminates exactly when h=0. Define an observation that includes termination, and show precisely which premise or conclusion of theorem 70.6 must change.

Exercise 70.8

★★★ Design a command that intentionally releases the parity of h. State a declassification policy and a corresponding two-run relation. Explain why the original low-equivalence theorem cannot certify the program.

The principal result is termination-insensitive two-run noninterference for a sequential, deterministic, fixed-label store language. Concurrency, declassification, probabilistic observations, quantitative leakage, and termination-sensitive security require different observations and proof relations; they are not variants silently covered by the theorem above.

Search the book

Type to search the local edition.