解析FrozenCache抵內(nèi)存威脅

字號(hào):

Cold boot 攻擊對(duì)全磁盤(pán)加密解決方案所提供的數(shù)據(jù)安全保護(hù)是一個(gè)重大威脅,大部分計(jì)算機(jī)都容易受到這種攻擊,而到目前為止還沒(méi)有通用方法可以解決這個(gè)問(wèn)題。
    為什么這篇文章名為“凍結(jié)緩存(Frozen Cache)”呢?因?yàn)槲覀儧Q定采用CPU緩存來(lái)抵御Cold boot 攻擊(至少對(duì)于所有X86系統(tǒng))。
    這個(gè)概念很簡(jiǎn)單:將緩存切換到特殊模式,該模式下可以強(qiáng)迫數(shù)據(jù)在緩存中而不是被寫(xiě)入支持RAM位置。因此,加密密鑰不能從RAM提取,其實(shí)這種技術(shù)并不新鮮:LinuxBIOS/CoreBoot將這種技術(shù)稱(chēng)為Cache-as-RAM,并使用這種技術(shù)來(lái)允許“RAM訪問(wèn)”,即使是在初始化內(nèi)存控制器前。
    下列步驟加載并維護(hù)CPU緩存中的256位的加密密鑰,并假定加密密鑰存放在RAM的線(xiàn)性地址X中:
    1. 從RAM將加密密鑰加載到一些CPU注冊(cè)器中(如SSE注冊(cè)器):
    movq [X], %xmm0
    movq [X+8], %xmm1
    movq [X+16], %xmm2
    movq [X+24], %xmm3
    2. 使用0值復(fù)寫(xiě)RAM中加密密鑰
    movq 0, [X]
    movq 0, [X+8]
    movq 0, [X+16]
    movq 0, [X+24]
    3. 刷新緩存(從而真正覆蓋RAM中的加密密鑰)
    wbinvd
    4. 添加需要的RAM區(qū)域到CPU的MTRR(4K部分包含密鑰)
    movl (X | MEMORY_TYPE_WRITEBACK), %eax
    xorl %edx, %edx
    movl 0x200, %ecx
    wrmsr
    movl ( ~(1) | MTRR_VALID ), %eax
    movl 0x1, %edx
    movl 0x201, %ecx
    wrmsr
    5. 禁用/凍結(jié)CPU的緩存(CR0.CD=1)
    movl %cr0, %eax
    orl 0x40000000, %eax
    movl %eax, %cr0
    6. 從CPU注冊(cè)器向RAM寫(xiě)入加密密鑰(數(shù)據(jù)仍然在緩存中,不會(huì)寫(xiě)入內(nèi)存)
    movq %xmm0, [X]
    movq %xmm1, [X+8]
    movq %xmm2, [X+16]
    movq %xmm3, [X+24]
    “禁用/凍結(jié)”CPU的緩存嚴(yán)重降低了性能,但是,這似乎也是可以接受的,因?yàn)榭紤]到只需在屏幕鎖定時(shí)設(shè)置特殊模式(如果筆記本被盜,那么所以努力都毫無(wú)意義)。在Linux系統(tǒng)的首次概念證明測(cè)試結(jié)果表明,需要對(duì)解鎖GUI進(jìn)行很多必要的性能優(yōu)化(從性能/可用性角度考慮)。
    這段文字只是描述了基本的概念,下面將涉及多CPU/Core問(wèn)題、性能考慮和優(yōu)化等問(wèn)題。
    性能方面
    如上所述,性能問(wèn)題是將緩存切換到“凍結(jié)”模式的主要關(guān)注問(wèn)題,CPU架構(gòu)的廣泛范圍(多CPU、多核和多線(xiàn)程)和各自的緩存配置讓問(wèn)題變得更加復(fù)雜。
    首先:只有一個(gè)CPU緩存需要“凍結(jié)”以有效保護(hù)加密密鑰。其他CPU允許執(zhí)行政策緩存模式。只要每個(gè)(邏輯或者虛擬的)CPU完全使用自己的緩存:采用線(xiàn)程技術(shù)(如英特爾的超線(xiàn)程HyperThreading)CPU會(huì)作為兩個(gè)(或者可能更多)邏輯CPU,但是這兩個(gè)CPU共享相同的緩存,而它們必須同時(shí)切換至凍結(jié)緩存模式。對(duì)于多核CPU,可能情況更加復(fù)雜,如果內(nèi)核都有自己的(L1和L2)緩存。
    加密密鑰僅位于單個(gè)CPU的緩存中,只有這個(gè)CPU必須執(zhí)行加密和解密線(xiàn)程,在全磁盤(pán)加密解決方案中最常見(jiàn)的架構(gòu)就是采用內(nèi)核模塊,它會(huì)產(chǎn)生一個(gè)為加密和解密邏輯指定的內(nèi)核線(xiàn)程,內(nèi)核線(xiàn)程是可調(diào)度實(shí)體,因此可以綁定在CPU上,CPU緩存中有加密密鑰。
    回到更加“傳統(tǒng)的”性能考慮,怎樣做可以減少凍結(jié)CPU緩存帶來(lái)的影響呢?將最常用的內(nèi)存區(qū)域加載到緩存(凍結(jié)前)是個(gè)不錯(cuò)的開(kāi)始,其中最適合的包括:系統(tǒng)調(diào)用入口端點(diǎn)、計(jì)時(shí)器中斷線(xiàn)程及其“幫助”功能,以及內(nèi)核線(xiàn)程執(zhí)行的加密/解密功能。目前L2緩存通??梢匀菁{所有這些代碼,但是同時(shí)還需要考慮緩存的結(jié)合問(wèn)題,以避免相關(guān)問(wèn)題。另一個(gè)好辦法就是將所有其他進(jìn)程的時(shí)間表分配給其他可用的CPU(不使用凍結(jié)緩存的CPU):這樣可以以正常的速度執(zhí)行,另一個(gè)很重要的原因就是,我們能獲得更多時(shí)間。
    現(xiàn)在已經(jīng)很明顯了,將需要部署確定具體(運(yùn)行中的)CPU/緩存組件的程序并有針對(duì)性的管理他們。
    缺乏緩存控制
    一旦緩存被凍結(jié),對(duì)這些緩存內(nèi)容的管理就沒(méi)有結(jié)束:同樣重要的是,緩存中的數(shù)據(jù)(加密密鑰)并沒(méi)有寫(xiě)回內(nèi)存。不幸的是,英特爾架構(gòu)只允許非常少的緩存控制:
    · 啟用/禁用緩存(系統(tǒng)范圍:CR0.CD,每個(gè)內(nèi)存區(qū)域:MTRR,每頁(yè):PAT)
    · 清除緩存(wbinvd
    就是如此,根本沒(méi)有查詢(xún)緩存狀態(tài)(目前在單個(gè)緩存線(xiàn)中的RAM位置)處理器指示或者其他先進(jìn)的緩存管理功能。因此,根本可能驗(yàn)證加密密鑰真正只出現(xiàn)在CPU緩存中。隨著凍結(jié)緩存設(shè)置,幾乎可以肯定密鑰將出現(xiàn)在緩存中,但是這并不意味著數(shù)據(jù)將同步到RAM中。不管wbinvd指示何時(shí)執(zhí)行都會(huì)發(fā)生(在凍結(jié)緩存步驟中),該指示可以由任何在ring 0(內(nèi)核)運(yùn)行的代碼執(zhí)行。因此,有必要盡量減少在CPU(加密密鑰在其緩存中)運(yùn)行的內(nèi)核模式,這也是為什么綁定其他可調(diào)度實(shí)體(至少是所有其他內(nèi)核線(xiàn)程)到其他CPU(如果有的話(huà))的原因。
    減少“無(wú)意的”緩存清除帶來(lái)的影響的方法是重復(fù)緩存凍結(jié)程序以減輕“無(wú)意”緩存清除(wbinvd)的影響。對(duì)于Linux而言有個(gè)更好的解決方法:修改執(zhí)行/包裝在內(nèi)核中觸發(fā)重新執(zhí)行緩存凍結(jié)的invd/wbinvd指示的函數(shù)/宏。
    保護(hù)加密密鑰
    加密密鑰不是需要保存在CPU緩存的數(shù)據(jù)類(lèi)型。
    密鑰調(diào)度是現(xiàn)代密碼加密的典型:加密和解秘例程并不直接使用加密密鑰,而是采用“輪流密鑰”,這些都來(lái)自加密密鑰(根據(jù)密碼算法)并且用于不同算*次的加密與解密。
    AES標(biāo)準(zhǔn)定義了128位的AES密鑰用于生成/獲得10輪128位的密鑰,可以推測(cè)這些輪密鑰通過(guò)某些不可逆的類(lèi)似哈希的函數(shù)從加密密鑰中計(jì)算出,不過(guò)這對(duì)于AES標(biāo)準(zhǔn)是不正確的:加密密鑰很容易從任何10/12/14輪密鑰中重新計(jì)算出。因此,這些輪密鑰也需要保存在CPU緩存中(至少對(duì)于經(jīng)常使用的AES是這樣的)。
    理論上聽(tīng)起來(lái)簡(jiǎn)單,但找到一個(gè)好的架構(gòu)方法確實(shí)是挑戰(zhàn),特別對(duì)于Linux系統(tǒng)。
    鎖定屏幕
    另一個(gè)重要問(wèn)題就是,只有當(dāng)屏幕被鎖定時(shí)才會(huì)凸顯對(duì)性能造成的影響,不過(guò)也可能在鎖定屏幕的情況下而不受到性能的影響。
    有兩個(gè)策略可以維持原有系統(tǒng)性能:
    1. 配置選項(xiàng),確定緩存何時(shí)不應(yīng)該被凍結(jié)
    2. 屏幕鎖定后的時(shí)間窗口允許用戶(hù)防止緩存凍結(jié)以進(jìn)行用戶(hù)交互操作等
    配置選項(xiàng)可以是“當(dāng)系統(tǒng)在充電時(shí)不要凍結(jié)緩存”或者名為gcc的程序正在運(yùn)行的時(shí)候不要凍結(jié)緩存等。
    時(shí)間窗口的方法有點(diǎn)像倒數(shù)計(jì)時(shí),從屏幕鎖定開(kāi)始(用戶(hù)可能仍然在電腦前)。在倒計(jì)時(shí)點(diǎn)擊“不凍結(jié)緩存”可以使密鑰安全受到威脅,不點(diǎn)擊可以繼續(xù)保護(hù)密鑰安全(因此當(dāng)計(jì)算機(jī)自動(dòng)鎖定屏幕時(shí),只會(huì)增加一個(gè)加密密鑰的額外窗口詢(xún)問(wèn)用戶(hù)是否凍結(jié)緩存)。
    保護(hù)所有需要保密的數(shù)據(jù)
    本來(lái)我的建議是將加密密鑰從RAM移到CPU緩存中進(jìn)行保護(hù),然而情況并非如此。另外,輪密鑰也需要保存在CPU緩存中。
    很明顯,加密密鑰需要受到保護(hù),其次,密鑰時(shí)間表(前文所說(shuō)的輪密鑰)也需要保護(hù),密鑰時(shí)間表是直接從加密密鑰提取的,可以看作是加密密鑰的“擴(kuò)張版”。第三,應(yīng)該保護(hù)“Initialization Vector(IV,初始化向量)”,IV是否需要獲得保護(hù)取決于IV的生成方式。例如,“Encrypted Salt-Sector Initialization Vector(ESSIV)”就必須獲得保護(hù),ESSIV是加密密鑰的hash,是Linux系統(tǒng)中dm-crpt默認(rèn)使用的IV。第四,任何包含解密內(nèi)容的緩沖都需要保護(hù),以避免已知的純文本攻擊,然而保護(hù)這種內(nèi)存緩沖非常麻煩。最后,在加密解密過(guò)程中計(jì)算的數(shù)據(jù)值必須安全地存儲(chǔ)在CPU緩存中以避免密鑰分析。
    控制失控的緩存
    失控緩存是指不確定CPU緩存中的數(shù)據(jù)是否被清除到RAM,這種清除可能是由CPU指示(如invd、wbinvd和clflush,或者外部事件等)。
    以下方法可以避免這種失控緩存問(wèn)題的發(fā)生:
    減少無(wú)意緩存清除的方法之一就是定期重復(fù)緩存凍結(jié)程序以消除這種無(wú)意緩存清除的影響。
    有個(gè)新方法可以將這種風(fēng)險(xiǎn)一起消除,不過(guò)還沒(méi)有證實(shí)這種方法是否可以部署。大家有必要理解物理/線(xiàn)性和虛擬內(nèi)存位置的區(qū)別。
    這種新想法其實(shí)很簡(jiǎn)單:將數(shù)據(jù)存儲(chǔ)在物理/線(xiàn)性位置(不是由系統(tǒng)RAM支持的),這能夠保證數(shù)據(jù)不會(huì)離開(kāi)CPU緩存,即使觸發(fā)緩存清除。
    雖然還沒(méi)有證實(shí)過(guò)是否能執(zhí)行,可能的安裝程序如下:
    1. 加載數(shù)據(jù)到CPU注冊(cè)器
    2. 重寫(xiě)RAM的數(shù)據(jù)
    3. 將虛擬地址的虛擬-線(xiàn)性映射更改為物理/線(xiàn)性地址(通過(guò)修改相應(yīng)的頁(yè)面表?xiàng)l目)
    4. 將CPU緩存切換至凍結(jié)模式
    5. 將數(shù)據(jù)從CPU注冊(cè)器移到CPU緩存
    還不確定的事情是:第三步或者第四步中CPU是否會(huì)發(fā)生故障,這使這一想法無(wú)法進(jìn)行,畢竟,這不太符合CPU內(nèi)存管理的邏輯。不過(guò)很快將會(huì)有辦法解決這一問(wèn)題。
    最后說(shuō)明:很明顯,如果你有4GB的RAM,將不會(huì)有無(wú)效線(xiàn)性地址。