Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

Các phím được bọc phần cứng

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Giống như hầu hết các phần mềm mã hóa đĩa và tệp, mã hóa lưu trữ của Android theo truyền thống dựa vào các khóa mã hóa thô có trong bộ nhớ hệ thống để quá trình mã hóa có thể được thực hiện. Ngay cả khi mã hóa được thực hiện bằng phần cứng chuyên dụng chứ không phải bằng phần mềm, phần mềm nói chung vẫn cần quản lý các khóa mã hóa thô.

Theo truyền thống, điều này không được coi là một vấn đề vì các khóa sẽ không xuất hiện trong một cuộc tấn công ngoại tuyến, đây là kiểu tấn công chính mà mã hóa lưu trữ nhằm bảo vệ chống lại. Tuy nhiên, có mong muốn cung cấp khả năng bảo vệ tăng cường chống lại các loại tấn công khác, chẳng hạn như các cuộc tấn công khởi động lạnh và các cuộc tấn công trực tuyến trong đó kẻ tấn công có thể làm rò rỉ bộ nhớ hệ thống mà không ảnh hưởng hoàn toàn đến thiết bị.

Để giải quyết vấn đề này, Android 11 đã giới thiệu hỗ trợ cho các phím được bọc phần cứng, nơi hỗ trợ phần cứng. Khóa bọc phần cứng là khóa lưu trữ chỉ được biết đến ở dạng thô đối với phần cứng chuyên dụng; phần mềm chỉ nhìn thấy và hoạt động với các khóa này ở dạng được bọc (mã hóa). Phần cứng này phải có khả năng tạo và nhập các khóa lưu trữ, gói các khóa lưu trữ ở dạng tạm thời và lâu dài, tạo ra các khóa con, lập trình trực tiếp một khóa con vào một công cụ mã hóa nội tuyến và trả lại một khóa con riêng biệt cho phần mềm.

Lưu ý : Công cụ mã hóa nội tuyến (hoặc phần cứng mã hóa nội tuyến ) đề cập đến phần cứng mã hóa / giải mã dữ liệu khi nó đang trên đường đến / từ thiết bị lưu trữ. Thông thường, đây là bộ điều khiển máy chủ lưu trữ UFS hoặc eMMC triển khai các phần mở rộng tiền điện tử được xác định bởi đặc tả JEDEC tương ứng.

Thiết kế

Phần này trình bày thiết kế của tính năng các phím được bao bọc bởi phần cứng, bao gồm những hỗ trợ phần cứng nào cần thiết cho nó. Cuộc thảo luận này tập trung vào mã hóa dựa trên tệp (FBE), nhưng giải pháp cũng áp dụng cho mã hóa siêu dữ liệu .

Một cách để tránh cần các khóa mã hóa thô trong bộ nhớ hệ thống là chỉ giữ chúng trong các khe khóa của một công cụ mã hóa nội tuyến. Tuy nhiên, cách tiếp cận này gặp phải một số vấn đề:

  • Số lượng khóa mã hóa có thể vượt quá số lượng khe cắm khóa.
  • Công cụ mã hóa nội tuyến chỉ có thể được sử dụng để mã hóa / giải mã toàn bộ khối dữ liệu trên đĩa. Tuy nhiên, trong trường hợp của FBE, phần mềm vẫn cần có khả năng thực hiện các công việc mật mã khác như mã hóa tên tệp và lấy mã định danh khóa. Phần mềm vẫn cần quyền truy cập vào các khóa FBE thô để thực hiện công việc khác này.

Để tránh những vấn đề này, thay vào đó, các khóa lưu trữ được làm thành các khóa bọc phần cứng , chỉ có thể được mở và sử dụng bằng phần cứng chuyên dụng. Điều này cho phép số lượng khóa không giới hạn được hỗ trợ. Ngoài ra, hệ thống phân cấp khóa được sửa đổi và chuyển một phần sang phần cứng này, cho phép một khóa con được trả về phần mềm cho các tác vụ không thể sử dụng công cụ mã hóa nội tuyến.

Hệ thống phân cấp chính

Khóa có thể được lấy từ các khóa khác bằng cách sử dụng KDF (chức năng dẫn xuất khóa) như HKDF , dẫn đến phân cấp khóa .

Sơ đồ sau mô tả một hệ thống phân cấp khóa điển hình cho FBE khi các khóa được bọc phần cứng không được sử dụng:

Hệ thống phân cấp khóa FBE (tiêu chuẩn)
Hình 1. Hệ thống phân cấp khóa FBE (tiêu chuẩn)

Khóa lớp FBE là khóa mã hóa thô mà Android chuyển tới nhân Linux để mở khóa một tập hợp các thư mục được mã hóa cụ thể, chẳng hạn như bộ nhớ được mã hóa thông tin xác thực cho một người dùng Android cụ thể. (Trong hạt nhân, khóa này được gọi là khóa chính fscrypt .) Từ khóa này, hạt nhân dẫn xuất các khóa con sau:

  • Mã định danh chính. Giá trị này không được sử dụng để mã hóa, mà là một giá trị được sử dụng để xác định khóa mà một tệp hoặc thư mục cụ thể được bảo vệ.
  • Khóa mã hóa nội dung tệp
  • Khóa mã hóa tên tệp

Ngược lại, sơ đồ sau mô tả hệ thống phân cấp khóa cho FBE khi các khóa được bọc phần cứng được sử dụng:

Hệ thống phân cấp khóa FBE (với khóa được bọc phần cứng)
Hình 2. Phân cấp khóa FBE (với khóa được bọc phần cứng)

So với trường hợp trước đó, một cấp bổ sung đã được thêm vào phân cấp khóa và khóa mã hóa nội dung tệp đã được chuyển vị trí. Nút gốc vẫn đại diện cho chìa khóa mà Android chuyển sang Linux để mở khóa một tập hợp các thư mục được mã hóa. Tuy nhiên, bây giờ chìa khóa đó ở dạng gói gọn gàng và để được sử dụng, nó phải được chuyển cho phần cứng chuyên dụng. Phần cứng này phải triển khai hai giao diện có khóa được bọc tạm thời:

  • Một giao diện để lấy inline_encryption_key và trực tiếp lập trình nó thành một keylot của công cụ mã hóa nội tuyến. Điều này cho phép nội dung tệp được mã hóa / giải mã mà phần mềm không có quyền truy cập vào khóa thô. Trong các hạt nhân chung của Android, giao diện này tương ứng với thao tác blk_ksm_ll_ops::keyslot_program , thao tác này phải được thực thi bởi trình điều khiển lưu trữ.
  • Một giao diện để lấy và trả về sw_secret ("bí mật phần mềm" - còn được gọi là "bí mật thô" ở một số nơi), là khóa mà Linux sử dụng để lấy ra các khóa con cho mọi thứ khác ngoài mã hóa nội dung tệp. Trong các hạt nhân chung của Android, giao diện này tương ứng với hoạt động blk_ksm_ll_ops::derive_raw_secret , phải được thực thi bởi trình điều khiển lưu trữ.

Để lấy được inline_encryption_keysw_secret từ khóa lưu trữ thô, phần cứng phải sử dụng KDF mạnh về mặt mật mã. KDF này phải tuân theo các phương pháp hay nhất về mật mã; nó phải có độ bền bảo mật ít nhất là 256 bit, tức là đủ cho bất kỳ thuật toán nào được sử dụng sau này. Nó cũng phải sử dụng một nhãn riêng biệt, ngữ cảnh và / hoặc chuỗi thông tin dành riêng cho ứng dụng khi lấy từng loại khóa con để đảm bảo rằng các khóa con kết quả được phân lập bằng mật mã, tức là kiến ​​thức về một trong số chúng không tiết lộ bất kỳ khóa con nào khác. Không cần kéo dài khóa, vì khóa lưu trữ thô đã là một khóa ngẫu nhiên đồng nhất.

Về mặt kỹ thuật, bất kỳ KDF nào đáp ứng các yêu cầu bảo mật đều có thể được sử dụng. Tuy nhiên, đối với mục đích thử nghiệm, cần phải triển khai lại cùng một KDF trong mã thử nghiệm. Hiện tại, một KDF đã được xem xét và triển khai; nó có thể được tìm thấy trong mã nguồn cho vts_kernel_encryption_test . Phần cứng được khuyến nghị sử dụng KDF này, sử dụng NIST SP 800-108 "KDF trong Chế độ Bộ đếm" với AES-256-CMAC làm PRF. Lưu ý rằng để tương thích, tất cả các phần của thuật toán phải giống hệt nhau, bao gồm cả việc lựa chọn các ngữ cảnh và nhãn KDF cho mỗi khóa con.

Bọc chìa khóa

Để đáp ứng các mục tiêu bảo mật của khóa được bọc bằng phần cứng, hai loại gói khóa được xác định:

  • Gói tạm thời: phần cứng mã hóa khóa thô bằng cách sử dụng khóa được tạo ngẫu nhiên tại mỗi lần khởi động và không được tiếp xúc trực tiếp bên ngoài phần cứng.
  • Bao lâu dài : phần cứng mã hóa khóa thô bằng cách sử dụng một khóa bền vững, duy nhất được tích hợp trong phần cứng mà không được tiếp xúc trực tiếp bên ngoài phần cứng.

Tất cả các khóa được chuyển đến nhân Linux để mở khóa bộ nhớ đều được bọc tạm thời. Điều này đảm bảo rằng nếu kẻ tấn công có thể trích xuất một khóa đang sử dụng từ bộ nhớ hệ thống, thì khóa đó sẽ không thể sử dụng được không chỉ ngoài thiết bị mà còn trên thiết bị sau khi khởi động lại.

Đồng thời, Android vẫn cần có khả năng lưu trữ phiên bản mã hóa của các khóa trên đĩa để chúng có thể được mở khóa ngay từ đầu. Các phím thô sẽ hoạt động cho mục đích này. Tuy nhiên, điều mong muốn là không bao giờ có các khóa thô trong bộ nhớ hệ thống để chúng không bao giờ có thể được trích xuất để sử dụng ngoài thiết bị, ngay cả khi được giải nén tại thời điểm khởi động. Vì lý do này, khái niệm gói dài hạn được định nghĩa.

Để hỗ trợ quản lý các khóa được bao bọc theo hai cách khác nhau này, phần cứng phải triển khai các giao diện sau:

  • Các giao diện tạo và nhập khóa lưu trữ, trả lại chúng ở dạng được bọc lâu dài. Các giao diện này được truy cập gián tiếp thông qua KeyMint và chúng tương ứng với thẻ TAG_STORAGE_KEY KeyMint. Khả năng "tạo" được vold sử dụng để tạo khóa lưu trữ mới để Android sử dụng, trong khi khả năng "nhập" được vts_kernel_encryption_test sử dụng để nhập khóa kiểm tra.
  • Một giao diện để chuyển đổi khóa lưu trữ được bao bọc lâu dài thành khóa lưu trữ được bao bọc tạm thời. Điều này tương ứng với phương thức convertStorageKeyToEphemeral KeyMint. Phương pháp này được cả voldvts_kernel_encryption_test sử dụng để mở khóa bộ nhớ.

Thuật toán gói khóa là một chi tiết triển khai, nhưng nó phải sử dụng AEAD mạnh như AES-256-GCM với các IV ngẫu nhiên.

Yêu cầu thay đổi phần mềm

AOSP đã có một khung cơ bản để hỗ trợ các khóa được bọc phần cứng. Điều này bao gồm hỗ trợ trong các thành phần không gian người dùng như vold , cũng như hỗ trợ nhân Linux trong blk-crypto , fscryptdm-default-key .

Tuy nhiên, một số thay đổi cụ thể về triển khai là bắt buộc.

KeyMint thay đổi

Việc triển khai KeyMint của thiết bị phải được sửa đổi để hỗ trợ TAG_STORAGE_KEY và triển khai phương thức convertStorageKeyToEphemeral .

Trong Keymaster, exportKey đã được sử dụng thay vì convertStorageKeyToEphemeral .

Thay đổi nhân Linux

Trình điều khiển nhân Linux cho công cụ mã hóa nội tuyến của thiết bị phải được sửa đổi để đặt BLK_CRYPTO_FEATURE_WRAPPED_KEYS , làm cho các hoạt động keyslot_program()keyslot_evict() hỗ trợ lập trình / loại bỏ các khóa được bọc phần cứng và triển khai hoạt động derive_raw_secret() .

Thử nghiệm

Mặc dù mã hóa bằng khóa được bọc phần cứng khó kiểm tra hơn so với mã hóa bằng khóa tiêu chuẩn, nhưng vẫn có thể kiểm tra bằng cách nhập khóa kiểm tra và triển khai lại dẫn xuất khóa mà phần cứng thực hiện. Điều này được thực hiện trong vts_kernel_encryption_test . Để chạy thử nghiệm này, hãy chạy:

atest -v vts_kernel_encryption_test

Đọc nhật ký kiểm tra và xác minh rằng các trường hợp kiểm tra khóa được bọc phần cứng (ví dụ: FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicyDmDefaultKeyTest.TestHwWrappedKey ) không bị bỏ qua do hỗ trợ cho các khóa được bọc phần cứng không được phát hiện, vì kết quả kiểm tra sẽ vẫn được "thông qua" trong trường hợp.

Cho phép

Sau khi hỗ trợ khóa được bao bọc bằng phần cứng của thiết bị hoạt động bình thường, bạn có thể thực hiện các thay đổi sau đối với tệp fstab của thiết bị để khiến Android sử dụng tệp này cho FBE và mã hóa siêu dữ liệu:

  • FBE: thêm cờ wrappedkey_v0 vào tham số fileencryption . Ví dụ: sử dụng fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Để biết thêm chi tiết, hãy xem tài liệu FBE .
  • Mã hóa siêu dữ liệu: thêm cờ wrappedkey_v0 vào tham số metadata_encryption . Ví dụ: sử dụng metadata_encryption=:wrappedkey_v0 . Để biết thêm chi tiết, hãy xem tài liệu mã hóa siêu dữ liệu .