熵品質測試

本文件說明 Google 如何測試用於安全漏洞的熵來源品質 找到了 Zircon CPRNG。

理論問題

簡單來說,有時候大家會很容易地學會一連串數字 而非透過辨識圖案來隨機傳回資料我們無法確定 完全是隨機的藝術作品的狀態似乎是在歷久彌新 資料統計測試,並希望能偵測任何可入侵的弱點。

如果隨機性參數測試的隨機性參數 數字不一定是隨機的 (如果分佈各不相同,或 )。A 罩杯 一連串不完美的隨機數字仍會有一些隨機性 也很難判斷兩者的隨機性

基於我們的目的,測量串流中所含的隨機性 非完全隨機數值為最小熵。這與 資訊理論中使用的 Shannon 熵,但值一定很小。 最小熵量決定可以安全可靠的隨機性擷取程度 熵來源;舉例來說 https://en.wikipedia.org/wiki/Randomness_extractor#Formal_definition_of_extractors

從實際的角度來看,我們可以使用美國 NIST 列出的測試套件 SP800-90B,分析來自熵來源的隨機樣本。原型 這些測試的實作 https://github.com/usnistgov/SP800-90B_EntropyAssessment.這套套件採用 樣本資料檔案 (例如隨機位元組的 1 MB) 做為輸入內容。最棒的是 測試套件可處理不完美的 RNG,並回報 計算隨機資料串流中每個位元組包含的最小值。

測試未處理資料的重要性

從我們的熵來源繪製熵後,我們會將該資訊混合使用 「安全無虞」這個方法通常會消除可偵測的相關性 熵原始隨機位元組流中的分佈不完美現象 來源。如果在實際產生隨機性參數時 但執行測試時,我們必須避免這個混合和處理階段 熵來源本身

以一個醒目的例子,測試未處理的資料為何如此重要 利用實際的熵來源進行測試Analytics 則應在任意位置 且新式 Linux 系統已安裝 OpenSSL。

head -c 1000000 /dev/zero >zero.bin
openssl enc -aes-256-ctr -in zero.bin -out random.bin -nosalt -k "password"

這項作業會從 /dev/0ro 擷取 100 萬位元組,並透過 AES-256 加密這些位元組, 但密碼強度不足且沒有加鹽 (當然是可怕的加密配置!)事實上 輸出看起來好像很好的隨機資料,代表 AES 會正常運作 但這證明瞭從 已處理的資料:一起,/dev/0ro 和「password」可提供約 0 位元的熵 但我們的測試對於產生的資料更樂觀!

如需更具體的 Zircon 範例,請考慮使用抖動器 (RNG) 這篇文章:http://www.chronox.de/jent/doc/CPU-Jitter-NPTRNG.html)。 而 Jitterentropy 會根據 CPU 時間的變化提取熵。未處理的資料 是指從佔用大量 CPU 和記憶體的特定區塊 執行特定區塊所需的時間 (以奈秒為單位)。這些時間資料並不一定是隨機的: 基準平均價值,但會有波動。每項 個別資料樣本可能是數個位元 (例如 64 位元整數),但只有 貢獻 1 位元以下的最小熵。

完整的抖動式 RNG 程式碼會採用數種原始時間資料樣本, 並轉換為單一隨機輸出內容 (方法是切換 LFSR、 其他事情)。如果我們測試處理過的輸出內容,則明顯出現隨機性參數 兩者的時間變化和「LFSR」指標我們希望將重點放在 所以我們應該測試原始時間樣本請注意, 您可以透過 kernel.jitterentropy.raw cmdline。

品質測試導入

如上所述,NIST 測試套件會從大量的隨機位元組擷取檔案, 。我們透過 Zircon 系統收集這些位元組 (可能搭配繁雜的 Fuchsia 系統) 通常匯出到更強大的工作站,以便執行 測試套件。

開機時間測試

系統會在啟動期間讀取部分熵來源,然後再開始啟動使用者空間。 為了在實際環境中測試這些熵來源,我們會執行測試 執行這些步驟相關程式碼位於 kernel/lib/crypto/entropy/quality\_test.cpp,但基本概念是 核心會分配大型靜態緩衝區,以便在早期啟動期間保留測試資料 (因此必須先分配 VMO 才能分配 VMO)。稍後 會將資料複製到 VMO,並將 VMO 傳遞至使用者啟動程序和 devmgr 在 /boot/kernel/debug/entropy.bin 中會以虛擬檔案的形式顯示。使用者空間 應用程式可讀取這個檔案並匯出資料 (將檔案複製到永久儲存空間,或 存取網路)。

理論上,應能使用熵收集器測試建構 Zircon 只要使用 scripts/entropy-test/make-parallel 啟用,應該就可以 使用指令碼執行單一啟動時間測試 scripts/entropy-test/run-boot-testrun-boot-test 指令碼主要用於 其實有點基本 邊緣 (例如,其大部分的引數是透過指令列選項傳遞) 例如 -a x86-64,但這些「選項」都是強制規定)

假設 run-boot-test 指令碼成功,則應在 輸出目錄:entropy.000000000.binentropy.000000000.meta。 第一種是從熵來源收集的原始資料 簡單的文字檔案,其中每一行都是鍵/值組合。關鍵在於單一字詞 比對符合 /[a-zA-Z0-9_-]+/,且值會以空格比對的方式分隔 /[ \t]+/。你可以透過 Bash 中的 read 輕鬆剖析這個檔案 Python 的 str.split(),或 (通常注意緩衝區超支情形) 以 C 表示:scanf

實務上,我對這些腳本感到不安,所以接下來幾對 這些章節記錄了指令碼的作用,方便您執行 來手動測試,或在指令碼中斷時修正指令碼。

開機時間測試:建構

因為啟動時間熵測試需要大量記憶體 永久保留 (用於暫時性的 VMM 緩衝區),我們通常不會建構 然後進入核心進行熵測試模式測試時只要傳送 ENABLE_ENTROPY_COLLECTOR_TEST 旗標 (例如:方法是新增

EXTERNAL_DEFINES += ENABLE_ENTROPY_COLLECTOR_TEST=1

local.mk。目前也有建構時間常數 ENTROPY_COLLECTOR_TEST_MAXLEN,其中 (如有提供) 是 靜態分配的緩衝區如未指定,則預設值為 1MiB。

開機時間測試:設定

啟動時間測試是透過核心 cmdlines 進行控制。相關 cmdline 是kernel.entropy-test.*,記錄在 kernel_cmdline.md

某些熵來源 (特別是抖動) 的參數值 您透過核心 cmdline 進行微調。另請參閱 kernel_cmdline.md。 ,進一步瞭解詳情

開機時間測試:執行中

只要正確設定,即可在開機時自動執行啟動期間測試 會通過核心 cmdlines (如果 cmdlines 有問題, 則改為列印)。這些測試會在 不久前發生在 LK_INIT_LEVEL_PLATFORM_EARLY 的 RNG 種子 VMM 也出現了堆積點執行大型測試時,啟動速度通常會變慢 會明顯下降例如,收集 128 KB 的資料 rpi3 可能需要約一分鐘的時間,實際情況視參數值而定。

執行階段測試

TODO(https://fxbug.dev/42098992):討論實際的使用者模式測試程序

目前的粗略概念:只有核心可以觸發 Hwrng 讀取。想要測試 使用者空間發出一個核心指令 (例如 k hwrng test),其中包含一些引數 請指定測試來源和長度核心會收集 位於 /boot/kernel/debug/entropy.bin 的現有 VMO 虛擬檔案 (假設) 可以安全寫入目前沒有導入;這是因為 userspace HWRNG 驅動程式庫可以先測試 VMO 重寫機制。

測試資料匯出功能

測試資料會儲存在 Zircon 系統的 /boot/kernel/debug/entropy.bin 中 測試中。到目前為止,我通常是透過 netcp 手動匯出資料檔案。 如果您使用正確的 Fuchsia 套件進行建構,其他選項包括 scp;或 儲存至永久儲存空間

執行 NIST 測試套件

注意:NIST 測試實際上並未反映在 Fuchsia 中。您現在需要 從存放區複製測試 https://github.com/usnistgov/SP800-90B_EntropyAssessment.

NIST 測試套件有三個進入點 (截至 10 月修訂的版本, 25、2016):iid_main.pynoniid_main.pyrestart.py。這兩個「主要」 執行大量工作iid_main.py 指令碼適用於 都會產生獨立且均勻分佈的資料樣本。 大部分的測試都是驗證 iid 條件。許多熵來源 並非 iid,因此 noniid_main.py 測試會實作數個熵估算器 不需要 iid 資料

請注意,NIST 存放區中的測試二進位檔是沒有指令 因此您可能需要在指令中明確呼叫 python

前兩個指令碼需要兩個引數,這些引數都是要讀取的資料檔案。 以及每個樣本的有效位元數 (如果小於 8,則只有 N 偏低, 位元會從每個位元組中使用)。他們可選擇接受 -v 旗標來建立 詳細輸出或 -h 來取得說明

noniid_main.py 也選擇性接受 -u <int> 旗標,可減少 低於第二個必要引數所傳遞 N 值的位元數。 我不太確定該標記提供的原因;它似乎功能 多餘的輸出內容,不過傳遞這類訊息確實會稍微改變詳細輸出內容。我猜測 是因為非馬可夫測試僅適用於 所以 7 或 8 位元資料集會縮減為低 6 位元 測試。相反地,所有 iid 測試都可以在 8 位元樣本上執行。

iid_main.py 指令碼叫用範例:

python2 -- $FUCHSIA_DIR/third_party/sp800-90b-entropy-assessment/iid_main.py -v /path/to/datafile.bin 8

restart.py 指令碼會使用相同的兩個引數,以及第三個引數: 前次執行 (iid_main.py) 或執行一次所需的最低熵預估值 noniid_main.py。本文件未說明重新啟動測試。目前,請參閱 詳情請參閱 NIST SP800-90B。

未來路線

自動化

建議將建構、設定和執行 品質測試首先,您將能輕鬆編寫殼層指令碼 執行這些步驟更好的方法就是使用測試基礎架構 自動執行熵收集器品質測試,主要是為了減少位元旋轉 。如果自動化系統故障,必須仰賴人類定期 執行測試 (或在測試中斷時進行修正)。