Zxcrypt

總覽

zxcrypt 是區塊裝置篩選器驅動程式庫,可透明地加密寫入區塊裝置的資料,並解密從區塊裝置讀取的資料。zxcrypt 裝置使用的基礎區塊裝置幾乎可以是任何區塊裝置,包括原始磁碟、ramdisk、GPT 分割區、FVM 分割區,甚至是其他 zxcrypt 裝置。唯一的限制是區塊大小必須與頁面對齊。繫結後,zxcrypt 裝置會在裝置樹狀架構中發布另一個區塊裝置,供消費者正常互動。

用量

zxcrypt 現已整合至 FVM 元件。 libzxcrypt.so 提供四項函式,用於管理 zxcrypt 裝置。每個函式都會採用一或多個 zxcrypt_key_t 鍵,將鍵資料、長度和位置 (如果有多個鍵) 建立關聯。

  • zxcrypt_format 函式會採用開放式區塊裝置,並寫入必要的加密中繼資料,使其成為 zxcrypt 裝置。提供的 zxcrypt 金鑰不會直接保護裝置上的資料,而是用來保護資料金鑰內容。
zx_status_t zxcrypt_format(int fd, const zxcrypt_key_t* key);
  • zxcrypt_bind 函式會指示驅動程式庫讀取已加密的中繼資料,並擷取資料金鑰素材,用於以透明方式轉換 I/O 資料。
zx_status_t zxcrypt_bind(int fd, const zxcrypt_key_t *key);
  • zxcrypt_rekey 函式會先使用舊金鑰讀取已加密的中繼資料,然後使用新金鑰將資料寫回。
zx_status_t zxcrypt_rekey(int fd, const zxcrypt_key_t* old_key, const zxcrypt_key_t* new_key);
  • zxcrypt_shred 函式會先使用提供的金鑰讀取加密中繼資料,驗證呼叫端是否可以存取資料。如果成功,系統就會銷毀含有資料金鑰材料的加密中繼資料。日後就無法再存取資料。
zx_status_t zxcrypt_shred(int fd, const zxcrypt_key_t* key);

技術詳細資料

DDKTL 驅動程式

zxcrypt 是以 DDKTL 裝置驅動程式的形式編寫,src/lib/ddktl 是 C++ 框架,用於在 Fuchsia 中編寫驅動程式庫。作者可使用範本化混合程式,自動提供 src/lib/ddk 函式指標和回呼。

有兩項小功能無法以 DDKTL 和 C++ 編寫:

  • 驅動程式繫結邏輯,使用 DDK 的 binding.h C 前置處理器巨集編寫。
  • ulib/sync 的完成常式,用於同步 I/O,與 C++ 原子不相容。

Superblock 格式

用來加密及解密資料的金鑰材料稱為資料金鑰,並儲存在裝置的保留部分,也就是 superblock。這個超級區塊至關重要,如果沒有這個區塊,就無法重新建立資料金鑰,也無法復原裝置上的資料。因此,超級區塊會複製到裝置上的多個位置,以確保資料備援。 zxcrypt 區塊裝置消費者看不到這些位置。每當 zxcrypt 驅動程式從某個位置成功讀取並驗證超級區塊時,就會將該超級區塊複製到所有其他超級區塊位置,藉此「自我修復」任何已損毀的超級區塊位置。

超級區塊格式如下,每個欄位都會依序說明:

+----------------+----------------+----+-----...-----+----...----+------...------+
| Type GUID      | Instance GUID  |Vers| Sealed Key  | Reserved  | HMAC          |
| 16 bytes       | 16 bytes       | 4B | Key size    |    ...    | Digest length |
+----------------+----------------+----+-----...-----+----...----+------...------+
  • 類型 GUID:將此識別為 zxcrypt 裝置。與 GPT 相容。
  • 執行個體 GUID:每個裝置的 ID,用做 KDF 鹽,如下所述。
  • 版本:用來指出要使用的加密編譯演算法。
  • 密封金鑰:資料金鑰,由包裝金鑰加密,詳情請見下文。
  • 保留:未使用的資料,可將超級區塊與區塊邊界對齊。
  • HMAC:超級區塊的鍵控摘要,直到這個時間點為止 (包括「保留」欄位)。

包裝金鑰、包裝 IV 和 HMAC 金鑰都是從 KDF 衍生而來。這個 KDF 是 RFC 5869 HKDF,會結合提供的金鑰、執行個體 GUID 的「鹽」和每次使用的標籤 (例如「wrap」或「hmac」)。KDF 不會嘗試進行任何速率限制。KDF 可降低金鑰重複使用的風險,因為新的隨機例項鹽會產生新的衍生金鑰。HMAC 可防止意外或惡意修改未遭偵測,且不會洩漏任何有關 zxcrypt 金鑰的實用資訊。

_注意:KDF「不會」執行任何「金鑰延展」。假設攻擊者可以移除裝置,並嘗試自行推導金鑰,藉此略過 HMAC 檢查和任何可能的速率限制。為避免發生這種情況,zxcrypt 消費者應在衍生 zxcrypt 金鑰時,納入適當的頻率限制裝置金鑰,例如來自 TPM 的金鑰。

後續工作

有許多領域可以、應該或必須進一步努力:

  • 隱藏介面繫結失敗

    目前,即使裝置無法初始化,zxcrypt_bind 也可能會指出成功。 執行繫結邏輯時,zxcrypt 不會將裝置同步新增至裝置樹狀結構。這個函式必須執行 I/O,且不得封鎖對 device_bind 的呼叫,因此會產生初始化子執行緒,並在完成時新增裝置。

    自 2017 年 10 月起,這項 DDK 開發作業已進入活躍期,政策也隨之變更,要求裝置必須先新增,才能傳回,之後可能還需要額外呼叫發布作業。因此,您可能希望呼叫 zxcrypt_bind 同步封鎖呼叫端,直到裝置準備就緒或明確無法繫結為止。

  • 使用 AEAD 取代 AES-XTS

    普遍認為 AEAD 可在解密前驗證資料完整性,提供更優異的加密保護。這是理想做法,但需要額外的每個區塊負擔。也就是說,消費者必須使用非頁面對齊的區塊 (移除內嵌負擔後),或 zxcrypt 必須儲存行外負擔並處理非原子寫入失敗

  • 支援多個金鑰

    為方便金鑰託管和/或復原,您可以輕鬆修改超級區塊格式,使其包含一系列加密信封。為此,libzxcrypt API 會採用可變數量的金鑰,但目前僅支援長度為 1 的金鑰,且唯一有效的時段為 0。

  • 調整工作人員人數

    目前有一個加密器和一個解密器。這些設計可搭配任意數量的執行緒運作,因此可能需要進行效能微調,找出可平衡 I/O 頻寬與排程器流失的最佳工作站數量。

  • 移除內部檢查

    目前,zxcrypt 程式碼會在內部界線檢查許多錯誤條件,如果不符合這些條件,就會傳回提供實用資訊的錯誤訊息。為提升效能,只有因程式設計師錯誤而產生的斷言 (而非來自要求者或基礎裝置的資料),可以轉換為「偵錯」斷言,並在發布模式中略過。