Capítulo 5: Diseño del módulo de control y configuración del sensor
5.2 Etapas de transmisión
As argued above, the low-level traces are not fully abstract because they not only capture all observable actions, but certain unobservable read-ins and write- outs as well. In this section, we will show that, while in general a low-level module can perform any of the low-level actions al, the low-level modules that
TRACES 55
result from the compilation of a high-level module using our secure compiler are more reserved in the kinds of interactions they engage in. This allows us to create a revised low-level trace semantics that is both simpler and fully abstract for securely compiled modules (it will not be fully abstract in general, for arbitrary modules, however). We make the following simplifications for our revised low-level traces.
• A securely compiled module never performs any reads from unprotected memory. Hence, read actions will never show up in low-level traces of a securely compiled module and thus we can discard them for our revised low-level traces.
• A securely compiled module never performs an outcall directly, but always passes through a function (named outcall_helper in the formalization in AppendixA) that (1) switches from the secure stack to the public stack, (2) places the address of the return entry point on the stack, (3) clears all flags and registers except the argument passing register R4 and the SP register, and finally (4) jumps to the call target using a jmp instruction. The call instruction is never used. Hence, the call p(r0, p0)! action will never show up in any low-level trace of a compiled module, but instead we will see a write (s, v)! followed by a jmp p(v0), where s is the top of the public stack, v is the address of the return entry point, p is the call target destination and v0 is the value of the argument passed in R4. For our revised low-level traces, we can hence discard the original call p(r0, p0)! action and we can replace sequences write (s, v)! · jmp p(v0) by a new action call p(v0). This new call action contains the same information as the sequence it replaces, even though it does not mention s or v. This is because s is always the top of the public stack (which is controlled completely by the context) and v is the address of the return entry point, which is constant for all protected modules and hence does not carry any information.
• Apart from the case described above, a securely compiled module never performs any write or jump to unprotected memory. Hence write and
jmp actions never show up in low-level traces, except in the above case,
where we have replaced them by the new call p(v0) action. Thus, we can discard jmp and write actions for our revised low-level traces.
• When a function of a securely compiled module returns, it will first return to the entry point through which it was called, which (1) switches from the secure stack back to the public stack, (2) checks that the return address (which is on the top of the stack) is a valid address in unprotected memory, (3) clears all flags and registers except R0 and SP, and finally (4) returns
back to unprotected code. Hence, for our revised low-level traces, we can replace each ret p(r)! action by a ret v! action, where v is the value of R0. We can discard the return location p, because it is controlled completely by the context and hence does not represent any information transferred from the module to the context. We also do not need to incorporate the value of SP into our traces, because it will point to the top of the public stack, which is also controlled completely by the context.
• When a securely compiled module receives a call from the context, the module never reads any of the values passed through the register and flag file, except the value of R4, which contains the call argument, and the value of SP, which is simply stored somewhere in protected memory such that the stack can be switched to the secure stack and later restored to the public stack. Thus, in our revised low-level traces, we can simplify
call p(r0)? actions to the format call p(v)?, where p is the call target address and v is value of R4.
• When a context returns back to a securely compiled module after an outcall, the protected module never reads any of the values passed through the register and flag file, except (1) the value of R0, which contains the return value, and (2) the value of SP, which is only stored temporarily, as described above. Thus, in our revised low-level traces, we can simplify
ret r? actions to the format ret v?, where v is value of R0.
Figure 3.8 formally defines these revised low-level traces and we give the definitions for trace sets and equivalence below.
Definition 3.5.5 (Revised low-level trace set). The revised set of traces of a
securely compiled low-level module M↓ is defined as:
TrR(M↓) = {α | ∃C, Θ. C|M↓=⇒αrΘ}
Definition 3.5.6 (Revised low-level trace equivalence). We say two securely
compiled low-level modules M1↓and M2↓are trace equivalent when their revised
trace sets are equal:
M1↓ 'RT M2↓ iff TrR(M1↓) = TrR(M2↓)
Lemma 3.5.4 (Full abstraction of revised low-level traces). For two securely
compiled low-level modules M1↓ and M2↓, we have:
M1↓ 'RT M2↓ ⇐⇒ M1↓ ' M2↓
Proof sketch. The above paragraphs have argued why no information is
TRACES 57 C|M −→ hp, r, mi C|M=⇒τ rhp, r, mi Tr-Init hp, r, mi −→ hp0, r0, m0i internalJmpδ(p, p 0 ) hp, r, mi=⇒τ rhp 0 , r0, m0i Tr-Internal hp, r, mi −→ hp0, r0, m0i exitJmpδ(p, p0) m(p) = jmp d v = r(R4) hp, r, micall p 0(v)! =⇒r hp 0 , r0, m0i Tr-OutCall hp, r, mi −→ hp0, r0, m0i exitJmpδ(p, p0) m(p) = ret v = r(R0) hp, r, mi=⇒ret v!rhp0, r0, m0i Tr-Return hp, r, mi −→ hp0, r0, m0i entryJmpδ(p, p0) ¬retEntryPointδ(p) v = r(R4) hp, r, micall p 0(v)? =⇒r hp0, r0, m0i Tr-InCall hp, r, mi −→ hp0, r0, m0i entryJmpδ(p, p0) retEntryPointδ(p 0 ) v = r(R0) hp, r, miret v?=⇒rhp0, r0, m0i Tr-RetBack Tr-Refl Θ− rΘ Tr-Silent Θ=⇒τ rΘ 0 Θ− rΘ0 Tr-Action Θ=⇒αrΘ0 Θ−[α]rΘ00 Tr-Trans Θ−αrΘ0 Θ0 α0 −rΘ00 Θ αα 0 −rΘ00
Figure 3.8: Definition of revised traces for our low-level assembly language. These traces are only fully abstract forsecurely compiled low-level modules.
compared to the original low-level traces. Hence we have M1↓ 'RTM2↓ =⇒ M1↓ 'LTM2↓ and based on Lemma 3.5.2, we thus have M1↓ 'RT M2↓ =⇒ M1↓ ' M2↓. The soundness of the revised low-level traces follows from the fact that any action that is part of a revised low-level trace is now observable in the corresponding low-level execution. This is because control is transferred from one component to the other (the context or the module) as part of each action, and any call destination, argument value or return value included in the action is directly observable by the destination component in the low-level execution. Hence we also have M1↓ ' M2↓ =⇒ M1↓ 'RT M2↓ and thus the