龍蜥白皮書精選:基於 SM4 演算法的檔案加密(fscrypt)實踐

OpenAnolis小助手發表於2023-03-31

文/張天佳

通常我們會以檔案作為資料載體,使用磁碟,USB 快閃記憶體,SD 卡等儲存介質進行資料儲存,即便資料已經離線儲存,仍然不能保證該儲存介質不會丟失,如果丟失那麼對於我們來說有可能是災難性的事件。因此對這些離線儲存的重要資料檔案進行加密是非常有必要的,本節將介紹如何使用國密演算法加密檔案系統中的檔案。

01 fscrypt 簡介

核心中的 fscrypt 是一個庫,檔案系統可以使用它以支援檔案和目錄的透明加密。

與 dm-crypt 不同,fscrypt 在檔案系統級別而不是塊裝置級別執行。這允許它使用不同的金鑰加密不同的檔案,並在同一檔案系統上擁有未加密的檔案。這對於多使用者系統非常有用,在該系統中,每個使用者的靜態資料都需要與其他使用者進行加密隔離。除了檔名,fscrypt 不加密檔案系統的後設資料。

與作為棧式檔案系統的 eCryptfs 不同,fscrypt 是直接整合到支援的檔案系統中,目前支援 fscrypt 的檔案系統是 ext4、F2FS 和 UBIFS。fscrypt 允許讀取和寫入加密檔案,而無需在頁面快取中同時快取解密和加密頁面,從而將使用的記憶體幾乎減半並使其與未加密檔案保持一致。同樣,需要一半的 dentry 和 inode。eCryptfs 還將加密檔名限制為 143 位元組,從而導致應用程式相容性問題;fscrypt 允許完整的 255 個位元組 (NAME_MAX)長度的檔名。最後,與 eCryptfs 不同,fscrypt API 可以由非特權使用者使用,而無需依賴其它任何元件。

fscrypt 不支援就地加密檔案。相反,它支援將空目錄標記為已加密。然後,在使用者空間提供金鑰後,在該目錄樹中建立的所有常規檔案、目錄和符號連結都將被透明地加密。

02 支援的加密模式和用法

fscrypt 允許為檔案內容指定一種加密模式,為檔名指定一種加密模式。不同的目錄樹允許使用不同的加密方式。目前支援以下幾種加密方式對:

  • AES-256-XTS 演算法用於加密內容,AES-256-CTS-CBC 演算法用於加密檔名

  • AES-128-CBC 演算法用於加密內容,AES-128-CTS-CBC 演算法用於加密檔名

  • Adiantum 演算法同時用於加密檔案內容和檔名

  • AES-256-XTS 演算法用於加密內容,AES-256-HCTR2 演算法用於加密檔名(僅限 v2 策略)

  • SM4-XTS 演算法用於加密內容,SM4-CTS-CBC 演算法用於加密檔名(僅限 v2 策略)

AES-128-CBC 僅為具有不支援 XTS 模式的加速器的低功耗嵌入式裝置使用。要使用 AES-128-CBC,必須啟用 CONFIG_CRYPTO_ESSIV 和 CONFIG_CRYPTO_SHA256(或其他 SHA-256 實現)以便使用 ESSIV。

Adiantum 是一種基於流密碼的模式,即使在沒有專用加密指令的 CPU 上也很快。與 XTS 不同,它也是真正的寬塊模式。要使用 Adiantum,必須啟用 CONFIG_CRYPTO_ADIANTUM。此外,應啟用 ChaCha 和 NHPoly1305 的快速實現,例如 ARM 架構上的 CONFIG_CRYPTO_CHACHA20_NEON 和 CONFIG_CRYPTO_NHPOLY1305_NEON。

AES-256-HCTR2 是另一種真正的寬塊加密模式,旨在用於具有專用加密指令的 CPU。AES-256-HCTR2 具有明文中的位翻轉會更改整個密文的屬性。由於初始化向量在目錄中重複使用,因此此屬性使其成為檔名加密的理想選擇。要使用 AES-256-HCTR2,必須啟用 CONFIG_CRYPTO_HCTR2。此外,應啟用 XCTR 和 POLYVAL 的快速實現,例如 用於 ARM64 的 CRYPTO_POLYVAL_ARM64_CE 和 CRYPTO_AES_ARM64_CE_BLK。

最後是 SM4 演算法,目前僅在 fscrypt v2 策略中啟用。

03 使用 SM4 演算法加密檔案

? 準備工作

fscrypt 依賴核心配置 CONFIG_FS_ENCRYPTION=y,這裡作業系統選擇使用 ANCK 5.10 核心的 Anolis OS,其次,需要支援 fscrypt 特性的檔案系統,這裡以 ext4 為例,當然,F2FS 或者 UBIFS 也可以。

使用者空間是透過 fscrypt API 跟核心完成互動的,對於使用者來說,一般是透過 fscryptctl 或者 fscrypt 工具來下達加密策略。

本節內容以 fscryptctl() 工具為例來演示,目前這是一個第三方工具,需要手工安裝,按如下常規流程安裝:

git clone .git
cd fscryptctl
make
make install

其次,選擇一塊未用到的磁碟格式化為支援 fscrypt 的檔案系統 ext4,並掛載。

mkfs.ext4 -O encrypt /dev/vda3
mount /dev/vda3 /mnt

? 透明加密檔案

fscrypt 所用的加解金鑰是關聯在超級塊上的,執行時是跟掛載點相關聯的,新增刪除金鑰都是針對掛載點的操作,以下對金鑰操作的命令都會帶上掛載點。

按如下命令所示設定加密策略:

# 生成金鑰檔案,實際環境中應用使用更復雜的金鑰
> echo '1234567812345678' > /tmp/keyfile
# 新增該金鑰到檔案系統,返回金鑰ID,之後對金鑰的操作都使用這個ID來索引
> fscryptctl add_key /mnt < /tmp/keyfile
23086a13ed81fd75ca5fe9b8f2ff25c7
# 檢視金鑰狀態(不是必需)
> fscryptctl key_status 23086a13ed81fd75ca5fe9b8f2ff25c7 /mnt
Present (user_count=1, added_by_self)
# 建立加密目錄 endir,並設定加密策略
# 使用之前新增的金鑰和 SM4 演算法來加密該目錄中的檔案和子目錄
> mkdir /mnt/endir
> fscryptctl set_policy --contents=SM4-XTS \
        --filenames=SM4-CTS 23086a13ed81fd75ca5fe9b8f2ff25c7 /mnt/endir
# 檢視策略是否生效(不是必需)
> fscryptctl get_policy /mnt/endir
Encryption policy for /mnt/endir:
    Policy version: 2
    Master key identifier: 23086a13ed81fd75ca5fe9b8f2ff25c7
    Contents encryption mode: SM4-XTS
    Filenames encryption mode: SM4-CTS
    Flags: PAD_32

此時,endir 已經是支援透明加解密的一個目錄,可以像正常目錄一樣建立刪除檔案,在該目錄下進行一些常規的檔案操作,可以看到與普通目錄沒有區別:

> mkdir /mnt/endir/foo
> echo 'hello' > /mnt/endir/foo/hello
> cp -v /usr/include/curl/* endir
> tree /mnt/endir
/mnt/endir
├── curl.h
├── easy.h
├── foo
│   └── hello
└── websockets.h

? 鎖定加密目錄

之所以能像普通目錄一樣操作,是因為金鑰已經被新增到了檔案系統中。接下來刪除金鑰後,就能看到目錄被鎖定,裡面的所有路徑和內容都是加密狀態:

# 移除金鑰
> fscryptctl remove_key 23086a13ed81fd75ca5fe9b8f2ff25c7 /mnt
> fscryptctl key_status 23086a13ed81fd75ca5fe9b8f2ff25c7 /mnt
Absent
# 處於加密狀態的目錄樹
> tree /mnt/endir
/mnt/endir
├── 1H2e0BbS4MGZKAKEu6NVXniaYMWIrWDwbyzX6EVEWEN8tfWcWNgDyw
├── LvYw6Jl0a1jImKKOFPjtpG3hEDxjjuM6YIYqcMeXaWdzKUdaX0YCNQ
├── QBBz8_qGE4MJY6YVzfqVUkr6YeCSqtoQmbvG04BsR0lAr2oLwO0b2g
│   └── wOYdFlMRACjeBa-eSo3LuO4sE55q1YuFv-S_lVU-n498jdMjAt06JA
└── zoiobWxVG2DLjg8uMXfsVP11159zqQUjozJ8gmt1zyjayJlZ4awOhA
# 目錄被鎖定,無法進行常規檔案操作,即便拔盤,也不能得到明文內容
> cat /mnt/endir/1H2e0BbS4MGZKAKEu6NVXniaYMWIrWDwbyzX6EVEWEN8tfWcWNgDyw
cat: /mnt/endir/1H2e0BbS4MGZKAKEu6NVXniaYMWIrWDwbyzX6EVEWEN8tfWcWNgDyw: Required key not available
> mkdir /mnt/endir/hello
mkdir: cannot create directory ‘/mnt/endir/hello’: Required key not available

? 再次解鎖加密目錄

要解鎖目錄也很簡單,重新新增金鑰即可,檔案系統會搜尋到正確的金鑰並解鎖相應目錄:

> fscryptctl add_key /mnt < /tmp/keyfile
23086a13ed81fd75ca5fe9b8f2ff25c7
# 新增金鑰後檔案內容可正常訪問
> cat /mnt/endir/foo/hello
hello

04 後記

fscryptctl 是一個相對原生的工具,更接近核心,可以看到,該工具命令比較複雜,使用中需要記住很長一串金鑰 ID,使用者體驗並不好。

實際環境中,一般會使用 fscrypt 工具來完成加密策略操作,該工具由 Google 開發,用 Go 語言寫成,透過在使用者層面維護了一些後設資料來簡化使用者操作,命令更易於理解,也更接近使用者。

商密軟體棧 SIG 主頁:

附:商用密碼技術最 佳實踐白皮書

—— 完 ——


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004278/viewspace-2943208/,如需轉載,請註明出處,否則將追究法律責任。

相關文章