3. Glamdring的設計
Glamdring的設計標的是:
1. 保護輸入資料的機密性和輸出資料的完整性
2. 適用於最少特權原則,是可以訪問敏感資料的程式碼最小化
3. 自動改變程式碼
4. 可接受的效能開銷
為了實現這些標的,Glamdring分成了4個階段:
(1)程式碼註釋:
(2)程式碼分析
(3) 程式碼劃分
(4) 程式碼生成
3.1 程式碼註釋階段
安全敏感的資料和具體的應用有關。為了識別它,開發者必須對原始碼進行註釋。當透過網路接受資料時,Glamdring要求客戶端對資料進行加密和簽名。客戶端和enclave都要使用對稱式AESGCM加密。秘鑰在建立enclave時生成。程式碼註釋是以預編譯指令pragma形式出現的,sensitive-source表示輸出資料,sensitive-sink表示輸出資料
3.2 程式碼分析階段
程式碼分析階段的目的是識別出所有對於已識別出的安全敏感型陳述句集合Sa有依賴的陳述句。Glamdring使用靜態程式分析去識別所有的安全敏感陳述句。靜態程式分析的重要部分是一個程式依賴圖PGD(Program dependence graph),下文中用P來表示。圖中的頂點表示陳述句,弧表示資料和陳述句間的控制依賴。
聯合集合Sa和依賴圖P,我們透過以下手段找到所有的安全敏感陳述句:
(1) 靜態資料流分析-實現機密性。透過Sa和P,Glamring利用圖的連通性,在圖P中找到一個子圖Pc,Pc中包含了對於Sa中的陳述句存在控制和資料依賴的陳述句(也就是說P中存在從這些陳述句所代表的頂點到Sa中頂點的弧)。
(2) 靜態反向切片-實現完整性。透過Sa和P,Glamring利用反向切片,在圖P中找到一個子圖Pi. Pi中包含了Sa中的陳述句所依賴的陳述句(也就是說,P中存在從Sa中到Pi中任意節點的弧,存在註意和上一個方法的區別)。最後,所有的安全敏感的陳述句集合Ss可以透過合併Pi和Pc實現。
3.3 程式碼劃分階段
雖然Ss按次序列舉出了所有的敏感陳述句。但是程式碼劃分是基於函式粒度的,而不是基於陳述句。這種粒度使得函式介面和enclave邊界是一致的(enclave邊界實際上就是一個介面檔案,該介面中宣告了一系列的介面函式,而函式粒度的程式碼劃分與介面檔案的粒度是一致的),這種粒度減輕了的程式碼生成步驟的負擔,並使得enclave尺寸最小化。
它生成一個劃分標準(partition specification),該標準包含一組安全敏感函式,記憶體分配,和需要保護的全域性變數.
函式:如果某個函式中至少有一條陳述句出現在Ss中,那麼PS就將其包含在內
記憶體分配:PS必須能夠識別出為安全敏感型資料分配的記憶體。Ss中所有呼叫malloc(或者類似函式)都被列舉在PS之中。
全域性變數:PS必須列出Ss中所有陳述句所訪問的全域性變數,並且這些全域性變數都是在enclave中分配的。不過,外部函式可能要使用enclave內部的全域性變數(ecalls)。PS必鬚根據全域性變數所處的集合來判斷,外部函式對於全域性變數的許可權(讀,寫,或無許可權).
Enclave界限重定向,enclave的界限可以是動態,在程式的實際執行中,可能出現由於enclave過大導致的enclave內部和外部的頻繁切換帶來的效能損失.這時,可以透過提高enclave界限,將enclave內部的一些函式轉移到外部,從而彌補效能的損失.
4 程式碼生成
Glamdring提供一個基於LLVM/Clang編譯工具鏈的程式碼生成器,該生成器負責重寫預處理過的原始碼.它使用clang庫生成一個原始碼的抽象語法樹(AST),遍歷AST去修改原始碼.去了生成enclave內的可信程式碼和enclave外的不可信程式碼,生成器還要輸出一個EDL(enclave definition )檔案.該檔案宣告了程式使用的所有的ecalls和ocalls.程式碼生成分成了三個階段:
(1) 程式碼載入階段:對於一個原始碼檔案,程式碼生成器會產生一個enclave版本和非enclave版本,對於enclave版本,生成器依據劃分標準PS將原始碼中沒有在PS中列出的陳述句刪除.類似的,對於非enclave版本,它將移除所有的enclave函式.
(2) 生成ecalls和ocalls:基於enclave函式集合,程式碼生成器識別出所有的ecalls和ocalls,這些ecalls和ocalls是enclave邊界介面的一部分.它遍歷每一個函式中包含的直接呼叫陳述句,如果呼叫者是一個不可信函式,而被呼叫的是一個enclave函式,那麼該enclave函式是一個ecalls. 類似的,如果被呼叫者是一個不可信函式,而呼叫者是一個enclave函式,那麼該enclave函式是一個ocall.
加解密操作:對於標記為 sensitive-source的資料,程式碼生成器會生成解密程式碼.同樣,對於標記為sensitive-sink的資料,生成器會生成加密程式碼.
處理c函式庫:不同於ecalls和ocalls,對於libc中的函式是分開處理的.在encalve內部存在個被SDK支援的libc版本.enclave程式碼和不可信程式碼分別呼叫不同版本的libc.
當函式指標作為介面引數:將函式指標作為函式引數傳遞給ecalls和ocalls可能會出現問題,因為在ecalls使用函式指標呼叫函式時,該函式可能並不存在.Glamdring使用靜態函式指標分析去識別傳遞給ecall和ocall的函式指標.程式碼生成器隨後建立標的函式(函式指標指向的函式),並建立一個trampoline函式,跳轉到正確的函式.如同以下程式碼所示
處理記憶體分配:程式碼生成器使用PS去決定記憶體的分配位置.對於列舉在PS中的記憶體分配操作,沒有額外的操作,因為enclave內部的malloc會在encalve內部分配記憶體.對於其他記憶體必須在enclave外分配,malloc也被替換成一次對於外界的ocall.這種情況發生在程式碼生成器將非敏感型程式碼放置到enclave中時.