Proof Carrying Code (PCC) Vedi: Necula-Lee www.cs.unibo.it/~laneve/html/metodi1/paper3.ps visione tradizionale: il software è codice eseguibile visione più appropriata: il software è codice eseguibile e verificabile A tal fine: il software porta con se un certificato (la prova) con il quale è possibile verificare la sua correttezza dinamica 1
33
Embed
Proof Carrying Code (PCC) - cs.unibo.itbabaoglu/courses/security05-06/lucidi/pcc.pdf · il processo PCC: 1. definizione formale della politica di correttezza. Il produttore di codice
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
visione tradizionale: il software è codice eseguibile
visione più appropriata: il software è codice eseguibile e verificabile
A tal fine:
il software porta con se un certificato (la prova) con il quale è possibile verificare la sua correttezza dinamica
1
i certificati sono già presenti nella tecnologia attuale: con le firme digitali
software
firma digitale
server
verifica della firma digitale
CPU
vantaggio: veloce, semplice, sicuro
svantaggio: non c’ è alcuna garanzia sulla correttezza del codice (ma solo sulla provenienza)
2
la verifica di codice in Java:
Interpreter JIT Compiler
CPU
Java Bytecode Verifier
software
server
vantaggio: general purpose
svantaggio: il JBV è limitato nelle verifiche, l’Interpreter/JIT è costoso e/o grande
3
il desiderata :
CPU
Theorem Prover
software
server
vantaggio: potente
svantaggio: difficile da implementare
4
la visione pcc: Prove Esplicite
vantaggi: server
software
prova di correttezza
verificatore di correttezza
CPU
dimostratore di correttezza
1. le prove hanno una dimensione ragionevole (0-10% del codice)
2. il verificatore di correttezza è semplice e piccolo ( 50KB)
3. non è necessario che il dimostratore di correttezza sia “affidabile”
Questioni a cui bisogna rispondere:
1. come funziona il “dimostratore di correttezza” ?
2. come si verifica la “correttezza” ?
3. cosa dimostra la “prova di correttezza” ? 5
il processo PCC:
1. definizione formale della politica di correttezza. Il produttore di codice definisce in maniera formale e pubblicizza una politica di correttezza (ad esempio, il proprio codice termina, oppure non produce memory leaks, etc.) che desidera venga rispettata dal codice che intende eseguire.
2. certificazione. Il produttore compila il codice e dimostra che il proprio codice è corretto rispetto alla politica pubblicizzata.
3. invio. La dimostrazione viene inviata assieme al codice ad ogni consumatore.
4. validazione. Il consumatore verifica che il codice è corretto secondo la certificazione allegata.
6
esempio: sicurezza della memoria
A è un array (il primo indirizzo) di n elementi di tipo booleano.
correttezza: - A memorizza soltanto booleani - se la funzione termina allora restituisce un booleano - 0 e 1 sono i soli booleani - le letture e le scritture sono ammesse tra A+1 e A + n
politica di correttezza pubblicizzata dal produttore: (assiomi e regole di inferenza)
A : array(T,L) I > 0 I ≤ L A : array(T,L) I > 0 I ≤ L E : T
L0 : INV : r: bool && i ≤ nif i ≤ 0 goto L1t := a + i t := *t r := r && t i := i –1 goto L0
L1 : return r POST : r : bool
8
9
osservazione: il codice contiene annotazioni all’inizio ed alla fine e in prossimità dei
cicli (vedremo poi chi inserisce tali annotazioni).
le annotazioni (interessanti) – gli invarianti – sono generati da salti all’indietro (cicli)
lo scheletro di prova è una sequenza di regole (determinismo e assenza di backtracking – cf. programmazione logica)
Generazione delle Condizioni di Verifica (Verification Condition – VC)
il codice viene scandito da una procedura. Quando si incontra una annotazione, la procedura genera un predicato (assunzione) che viene utilizzato dal verificatore per dimostrare la politica di correttezza. Il verificatore consta di due parti:
1. politiche di correttezza
2. assunzioni precedentemente verificate.
graficamente:
Ricostruttore di ProveVerificatore
producer user
software annotazione
prova di correttezza
n CVVCGe
Assiomatizzazione (Politica di Correttezza)
il generatore di condizioni di verifica (VCGen) è una procedura che deriva predicati secondo lo stile di Floyd-Hoare (che è dettagliato in seguito)
il verificatore è un programma logico (scritto in Prolog)
10
comportamento di VCGen e del verificatore
registri simbolici a : a0
n : n0 i : i0 r : r0 t : t0
assunzioni
PRE: a: array(bool,n) r := 1 i := n
L0 : INV : r: bool && i ≤ n if i ≤ 0 goto L1t := a + i t := *t r := r && t i := i –1 goto L0
L1 : return r POST : r : bool
11
registri simbolici a : a0
n : n0 i : i0 r : r0 t : t0
assunzioni (IP0) a0 : array(bool, n0)
PRE: a: array(bool,n) r := 1 i := n
L0 : INV : r: bool && i ≤ n if i ≤ 0 goto L1t := a + i t := *t r := r && t i := i –1 goto L0
L1 : return r POST : r : bool
12
registri simbolici a : a0
n : n0 i : n0 r : 1 t : t0
assunzioni (IP0) a0 : array(bool, n0)
PRE: a: array(bool,n) r := 1 i := n
L0 : INV : r: bool && i ≤ n if i ≤ 0 goto L1t := a + i t := *t r := r && t i := i –1 goto L0
L1 : return r POST : r : bool
osservazione: I valori simbolici di i ed r sono cambiati.
osservazione: ad L0 si incontra una annotazione di tipo INV
occorre invocare il verificatore per dimostrarne la validità
13
il verificatore: Assiomi e Regole di Inferenza
a0 : array(bool, n0)
Verificatore
(Scheletro di) Prova
bool1 leqid typerd IP0
IP2
IP3
. . . .
osservazione: Il verificatore tenta di derivare l’invariante INV attraverso la politica di correttezza e lo scheletro di prova.
INV è istanziato come: 1 : bool && n0 ≤ n0
che segue utilizzando (bool1) e (leqid), come specificato nello scheletro di prova.
14
la verifica continua con il generatore di condizioni di verifica:
osservazione: sel(a0 + i1) segue da (typerd) con ipotesi IP0, IP2 e IP3.
la verifica continua in questo modo alla fine della verifica il codice è pronto per essere eseguito
18
la logica di Floyd-Hoare
è il cuore del generatore di condizioni di verifica (VCGen).
la logica di Floyd-Hoare (1967) è un sistema definito per verificare la correttezza di programmi scritti con diagrammi di flusso.
con questa tecnica si derivano triple:
φ P ψ
dove P è il programma da verificare, mentre φ e ψ sono formule (di solito in logica dei predicati). Il significato di questa tripla è il seguente:
correttezza parziale: se il programma P inizia in una configurazione che soddisfa la proprietà φ e la sua esecuzione termina, allora la configurazione finale verifica la proprietà ψ
osservazione: il programma può non terminare
19
Le regole seguenti sono una istanziazione della tecnica di Floyd-Hoare a bytecode come quello dell’esempio precedente P[i] = x := e φi P[i] φi+1 dom(P)=1..n
φ { e/x } P[i] φ φ1 P φn+1 (φ && e) P[L] ψ P[i] = if e goto L
esempio. La somma di due numeri con le operazioni di incremento e decremento.
1 if (x = 0) goto 5 2 y := y+1 3 x := x-1 4 goto 1 5 return
proprietà da dimostrare: (P è il programma di sopra) { x + y = m + n && x ≥ 0 } P { y = m+n && x = 0 }
annotazioni: { x + y = m + n && x ≥ 0 } if (x = 0) goto 5
{ x + y = m + n && x > 0 } y := y+1 { x + y = m + n + 1 && x > 0 } x := x-1 { x + y = m + n && x ≥ 0 } goto 1 { x = 0 && x + y = m + n} return { x = 0 && x + y = m + n}
due problemi: 1. come individuare le formule
2. la regola φ ψ ψ P[i] χ χ ξ φ P ξ
21
1. L’ individuazione delle formule della logica di Floyd-Hoare la tecnica standard è di procedere dalla conclusione (la proprietà che si vuole dimostrare) verso la premessa (cf. Dijkstra weakest preconditions) osservazione: questa tecnica funziona bene se non ci sono salti
in caso di salti: . . .
instr_h . . . instr_k = goto h instr_k+1
. . . ed occorre che φ = ξ ciò può richiedere diverse iterazioni per individuare la formula corretta
Ad esempio, nel caso di sopra, si voleva dimostrare la proprietà:
POST { x = 0 && y = m + n}
Quindi i passi sono i seguenti:
22
if (x = 0) goto 5y := y+1 x := x-1 goto 1 return
{ x = 0 && x + y = m + n }
PASSO 1
if (x = 0) goto 5 y := y+1 x := x-1 goto 1
{ x = 0 && x + y = m + n}
return
{ x = 0 && x + y = m + n}
PASSO 2
φ if (x = 0) goto 5 y := y+1 x := x-1
φ goto 1
{ x = 0 && x + y = m + n}
return
{ x = 0 && x + y = m + n}
PASSO 3 23
φ if (x = 0) goto 5
φ { x-1/x }{ y+1/y }
y := y+1
φ { x-1/x } x := x-1
φ goto 1
{ x = 0 && x + y = m + n }
return
{ x = 0 && x + y = m + n }
PASSO 5
φ if (x = 0) goto 5 y := y+1
φ { x-1/x } x := x-1
φ goto 1
{ x = 0 && x + y = m + n }
return
{ x = 0 && x + y = m + n }
PASSO 4
24
per eseguire il prossimo passo, si osservi che deve esistere una ψ tale che:
ψ if (x = 0) goto 5 { ψ && x ≥ 0 }
osservazione: questa ψ deve soddisfare le seguenti due condizioni:
1. { ψ && x = 0} { x = 0 && x + y = m + n}
2. { ψ && x > 0 } φ { x-1/x }{ y+1/y }
ne segue che
ψ {x + y = m + n && x ≥ 0}
φ {x + y = m + n && x ≥ 0}
dunque otteniamo:
25
{ x + y = m + n && x ≥ 0 }
if (x = 0) goto 5
{ x + y = m + n && x ≥ 0 }{ x-1/x }{ y+1/y }
y := y+1
{ x + y = m + n && x ≥ 0 } { x-1/x } x := x-1
{ x + y = m + n && x ≥ 0 }
goto 1
{ x = 0 && x + y = m + n}
return
{ x = 0 && x + y = m + n}
PASSO 6
in questo semplice caso, il calcolo delle annotazioni termina senza ulteriori iterazioni (perchè φ ψ). In generale occorre iterare.
26
ossevazione: nel contesto PCC, il problema del calcolo delle annotazioni non è rilevante per quanto riguarda il server, visto che esso riceve il codice con le formule (le annotazioni).
verificare una prova è tanto semplice quanto fare type-checking
al contrario, il problema suddetto è rilevante dal punto di vista del produttore, che deve specificare le formule e fornire una prova.
2. La regola φ ψ ψ P[i] χ χ ξ
φ P ξ questa è la regola problematica del sistema di Floyd-Hoare perchè ci sono sistemi logici, ad esempio la logica dei predicati, per cui non esiste alcun algoritmo in grado di decidere “φ ψ”
in generale la verifica non è completamente automatica
27
esempio (performance dei filtri di pacchetti di rete): i filtri di pacchetti di rete sono delle procedure che controllano se un pacchetto in entrata (dalla rete) può essere interessante per l’applicazione utente o meno Questi filtri sono stati implementati utilizzando la tecnica PCC con i seguenti risultati:
lunghezza del codice annotato : 3-4 volte maggiore del bytecode
overhead per la verifica delle prove : 5% (minore delle firme digitali)
tempo per produrre la prova : 1-3 ms (che è ammortizzato presto)