Hardware-verpackte Schlüssel

Wie bei den meisten Softwarelösungen zur Laufwerk- und Dateiverschlüsselung setzt auch die Speicherverschlüsselung von Android traditionell darauf, dass sich die Rohverschlüsselungsschlüssel im Systemspeicher befinden, damit die Verschlüsselung durchgeführt werden kann. Auch wenn die Verschlüsselung durchgeführt wird nicht durch Software, sondern nur auf dedizierter Hardware, muss Software in der Regel um die Verschlüsselungsschlüssel zu verwalten.

Dies wird üblicherweise nicht als Problem angesehen, da die Schlüssel nicht vorhanden sind. während eines Offlineangriffs. Dies ist die Hauptart eines Angriffs, den der Speicher die Verschlüsselung vor. Es besteht jedoch der Wunsch, erhöhter Schutz vor anderen Arten von Angriffen, z. B. Kaltstart Angriffe und Onlineangriffe, bei denen Angreifer ohne die Geräte zu beeinträchtigen.

Um dieses Problem zu lösen, wurde mit Android 11 für hardwareverpackte Schlüssel, bei denen Hardwareunterstützung vorhanden ist. Hardware-verpackte Schlüssel sind Speicherschlüssel, die nur in Rohform für spezielle Hardware bekannt sind. Software sieht und arbeitet nur mit diesen Schlüsseln in verpackter (verschlüsselter) Form. Diese Hardware muss in der Lage sein, Daten zu generieren und zu importieren sowie die flüchtige und langfristige Verpackung von Speicherschlüsseln, Unterschlüssel direkt in eine Inline-Krypto-Engine programmieren und gibt einen separaten Unterschlüssel an die Software zurück.

Hinweis: Eine Inline-Krypto-Engine (oder Inline-Krypto-Engine Verschlüsselungshardware) bezieht sich auf Hardware, die Daten verschlüsselt/entschlüsselt, während er ist unterwegs zum/vom Speichergerät. Normalerweise ein UFS- oder eMMC-Host Controller, der die von der entsprechenden JEDEC-Spezifikation.

Design

In diesem Abschnitt wird das Design der Funktion für mit Hardware verpackte Schlüssel beschrieben, einschließlich: welche Hardware-Unterstützung dafür benötigt wird. In diesem Artikel geht es hauptsächlich um die dateibasierte Verschlüsselung (File-Based Encryption, FBE). Die Lösung gilt aber auch für die Verschlüsselung von Metadaten.

Um zu vermeiden, dass die unverarbeiteten Verschlüsselungsschlüssel im Systemspeicher erforderlich sind, können Sie nur in den Schlüsselslots einer Inline-Krypto-Engine. Dieses birgt einige Probleme:

  • Die Anzahl der Verschlüsselungsschlüssel überschreitet möglicherweise die Anzahl der Schlüsselslots.
  • Inline-Krypto-Engines können nur zum Ver-/Entschlüsseln vollständiger Daten auf der Festplatte. Bei FBE muss die Software jedoch Andere kryptografische Aufgaben erledigen, z. B. die Verschlüsselung von Dateinamen und das Ableiten von Schlüssel Kennzeichnungen. Software benötigt weiterhin Zugriff auf die Roh-FBE-Schlüssel, um diese anderen Aufgaben ausführen zu können.

Um diese Probleme zu vermeiden, werden die Speicherschlüssel mit Hardware verpackten Schlüsseln, die nur entpackt und verwendet werden können dedizierte Hardware. Dadurch kann eine unbegrenzte Anzahl von Schlüsseln unterstützt werden. In Außerdem wird die Schlüsselhierarchie geändert und teilweise auf diese Hardware verschoben. mit dem ein Unterschlüssel für Aufgaben an die Software zurückgegeben werden kann, für die kein Inline-Krypto-Engine.

Schlüsselhierarchie

Schlüssel können mithilfe einer KDF (Schlüsselableitungsfunktion) wie HKDF aus anderen Schlüsseln abgeleitet werden, was zu einer Schlüsselhierarchie führt.

Das folgende Diagramm zeigt eine typische Schlüsselhierarchie für die FBE, wenn keine hardwareverpackten Schlüssel verwendet werden:

FBE-Schlüsselhierarchie (Standard)
Abbildung 1. FBE-Schlüsselhierarchie (Standard)

Der FBE-Klassenschlüssel ist der Rohverschlüsselungsschlüssel, den Android an den Linux-Kernel weitergibt, um eine bestimmte Gruppe verschlüsselter Verzeichnisse zu entsperren, z. B. den mit Anmeldedaten verschlüsselten Speicher für einen bestimmten Android-Nutzer. Im Kernel wird als fscrypt-Masterschlüssel bezeichnet.) Aus diesem Schlüssel leitet der Kernel die folgenden Unterschlüssel ab:

  • Die Schlüsselkennung. Dieser Wert wird nicht für die Verschlüsselung verwendet, sondern dient dazu, den Schlüssel zu identifizieren, mit dem eine bestimmte Datei oder ein bestimmtes Verzeichnis geschützt ist.
  • Der Verschlüsselungsschlüssel für den Dateiinhalt
  • Der Verschlüsselungsschlüssel für Dateinamen

Im Gegensatz dazu zeigt das folgende Diagramm die Schlüsselhierarchie für die FBE, wenn hardwareverpackte Schlüssel verwendet werden:

FBE-Schlüsselhierarchie (mit hardwareverpacktem Schlüssel)
Abbildung 2: FBE-Schlüsselhierarchie (mit hardwareverpacktem Schlüssel)

Im Vergleich zum vorherigen Fall wurde der Schlüsselhierarchie eine zusätzliche Ebene hinzugefügt und der Verschlüsselungsschlüssel für den Dateiinhalt wurde verschoben. Der Stamm Knoten stellt immer noch den Schlüssel dar, den Android an Linux übergibt, um eine Reihe von verschlüsselten Verzeichnissen suchen. Dieser Schlüssel liegt jedoch ephemerisch verpackt vor und damit er verwendet werden kann, muss er an die entsprechende Hardware übergeben werden. Diese Hardware muss zwei Schnittstellen implementieren, die einen kurzlebig verpackten Schlüssel akzeptieren:

  • Eine Schnittstelle, um inline_encryption_key abzuleiten und direkt in einen Schlüsselschlitz der Inline-Krypto-Engine zu programmieren. So können Dateiinhalte verschlüsselt/entschlüsselt werden, ohne dass Software Zugriff auf den Rohschlüssel hat. In den gängigen Kerneln von Android entspricht diese Schnittstelle der blk_crypto_ll_ops::keyslot_program-Vorgang, der Folgendes sein muss: Speichertreiber implementiert wird.
  • Eine Schnittstelle zum Ableiten und Zurückgeben von sw_secret („Software Secret“, an manchen Stellen auch „Raw Secret“ genannt), dem Schlüssel, mit dem Linux die Unterschlüssel für alles andere als die Verschlüsselung des Dateiinhalts ableitet. In den gängigen Kerneln von Android entspricht diese Schnittstelle der blk_crypto_ll_ops::derive_sw_secret-Vorgang, der folgender Wert sein muss: Speichertreiber implementiert wird.

Zum Ableiten von inline_encryption_key und sw_secret aus dem Rohspeicherschlüssel verwendet wird, muss die Hardware einen kryptografisch starken KDF verwenden. Dieser KDF Best Practices für Kryptografie einhalten; Die Sicherheitsstufe muss 256 Bit, was für einen später verwendeten Algorithmus ausreicht. Außerdem muss beim Ableiten der einzelnen Arten von Unterschlüsseln ein eindeutiges Label, ein eindeutiger Kontext und ein app-spezifischer Informationsstring verwendet werden, um sicherzustellen, dass die resultierenden Unterschlüssel kryptografisch isoliert sind, d. h., dass das Wissen um einen von ihnen keine anderen preisgibt. Eine Schlüsselstreckung ist nicht erforderlich, da der Rohspeicherschlüssel bereits ein gleichmäßig zufälliger Schlüssel ist.

Technisch gesehen kann jeder KDF verwendet werden, der die Sicherheitsanforderungen erfüllt. Zu Testzwecken ist es jedoch notwendig, denselben KDF in und testen Sie den Code. Derzeit wurde ein KDF geprüft und implementiert. Es befindet sich im Quellcode für vts_kernel_encryption_test. Es wird empfohlen, für die Hardware diesen KDF zu verwenden, der NIST SP 800-108 „KDF im Counter Mode“ mit AES-256-CMAC als PRF verwendet. Hinweis: Für die Kompatibilität müssen alle Teile des Algorithmus identisch sein, einschließlich der Auswahl der KDF-Kontexte und Labels für jeden Unterschlüssel.

Key-Wrapping

Um die Sicherheitsziele von hardwareverpackten Schlüsseln zu erreichen, sind zwei Arten der Schlüsselverpackung definiert sind:

  • Sitzungsspezifisches Wrapping: Die Hardware verschlüsselt den Rohschlüssel mit einem Schlüssel, der bei jedem Starten zufällig generiert wird und nicht direkt außerhalb der Hardware freigegeben wird.
  • Langfristige Verschlüsselung: Die Hardware verschlüsselt den Rohschlüssel mit einem eindeutigen, persistenten Schlüssel, der in die Hardware integriert ist und nicht direkt außerhalb der Hardware freigegeben wird.

Alle Schlüssel, die zum Entsperren des Speichers an den Linux-Kernel übergeben werden, sind sitzungsbasiert verpackt. So wird sichergestellt, dass, wenn ein Angreifer in der Lage ist, ein bereits verwendeten Schlüssel aus dem Systemspeicher, und nach einem Neustart auch auf dem Gerät.

Gleichzeitig muss Android weiterhin eine verschlüsselte Version der Schlüssel auf dem Laufwerk speichern können, damit sie überhaupt entsperrt werden können. Die Rohschlüssel eignen sich dafür. Es ist jedoch wünschenswert, niemals die unbearbeiteten Schlüssel überhaupt im Systemspeicher vorhanden sind, sodass sie nie extrahiert werden können, kann außerhalb des Geräts verwendet werden, auch wenn es beim Start des Geräts extrahiert wurde. Aus diesem Grund ist das Konzept von langfristiger Wrapping-Funktion definiert.

Damit die Verwaltung von Schlüsseln auf diese beiden Arten unterstützt werden kann, muss die Hardware die folgenden Schnittstellen implementieren:

  • Schnittstellen zum Generieren und Importieren von Speicherschlüsseln, die in gekapselter Form für die Langzeitspeicherung zurückgegeben werden. Der Zugriff auf diese Schnittstellen erfolgt indirekt über KeyMint und entsprechen dem KeyMint-Tag TAG_STORAGE_KEY. Die Funktion „generieren“ wird von vold verwendet, um neue Speicherschlüssel für die Verwendung unter Android zu generieren. Die Funktion „importieren“ wird von vts_kernel_encryption_test verwendet, um Testschlüssel zu importieren.
  • Eine Schnittstelle zum Umwandeln eines langfristig verpackten Speicherschlüssels in einen sitzungsspezifischen verpackten Speicherschlüssel. Dies entspricht dem convertStorageKeyToEphemeral: KeyMint-Methode. Diese Methode wird sowohl von vold als auch von vts_kernel_encryption_test verwendet, um den Speicher zu entsperren.

Der Algorithmus zum Verpacken von Schlüsseln ist ein Implementierungsdetail, sollte aber einen starken AEAD wie AES-256-GCM mit zufälligen IVs verwenden.

Erforderliche Softwareänderungen

AOSP bietet bereits ein grundlegendes Framework für die Unterstützung von hardwareverpackten Schlüsseln. Dieses umfasst die Unterstützung in Userspace-Komponenten wie vold sowie als Linux-Kernel-Unterstützung in blk-crypto, fscrypt und dm-default-key.

Es sind jedoch einige implementierungsspezifische Änderungen erforderlich.

KeyMint-Änderungen

Die KeyMint-Implementierung des Geräts muss so geändert werden, dass TAG_STORAGE_KEY unterstützt und die Methode convertStorageKeyToEphemeral implementiert wird.

In Keymaster wurde exportKey anstelle von convertStorageKeyToEphemeral.

Änderungen am Linux-Kernel

Der Linux-Kernel-Treiber für die Inline-Krypto-Engine des Geräts muss so geändert werden, dass er hardwareverpackte Schlüssel unterstützt.

Für Kernel ab android14: Legen Sie BLK_CRYPTO_KEY_TYPE_HW_WRAPPED in blk_crypto_profile::key_types_supported fest, sorgen Sie dafür, dass blk_crypto_ll_ops::keyslot_program und blk_crypto_ll_ops::keyslot_evict die Programmierung/Auslagerung von hardwareverpackten Schlüsseln unterstützen, und implementieren Sie blk_crypto_ll_ops::derive_sw_secret.

Für android12- und android13-Kernel muss BLK_CRYPTO_FEATURE_WRAPPED_KEYS in blk_keyslot_manager::features festgelegt sein. blk_ksm_ll_ops::keyslot_program und blk_ksm_ll_ops::keyslot_evict müssen das Programmieren und Entfernen von hardwareverpackten Schlüsseln unterstützen und blk_ksm_ll_ops::derive_raw_secret muss implementiert sein.

Für android11-Kernel: BLK_CRYPTO_FEATURE_WRAPPED_KEYS festlegen in keyslot_manager::features, machen keyslot_mgmt_ll_ops::keyslot_program und keyslot_mgmt_ll_ops::keyslot_evict unterstützen das Programmieren/Entfernen von hardwareverpackten Schlüsseln, und keyslot_mgmt_ll_ops::derive_raw_secret implementieren.

Testen

Die Verschlüsselung mit hardwareverpackten Schlüsseln ist zwar schwieriger zu testen als die Verschlüsselung mit Standardschlüsseln, aber es ist trotzdem möglich, sie zu testen, indem Sie einen Testschlüssel importieren und die Schlüsselableitung der Hardware neu implementieren. Dies wird implementiert, in vts_kernel_encryption_test Führen Sie zum Ausführen dieses Tests Folgendes aus:

atest -v vts_kernel_encryption_test

Lesen Sie das Testprotokoll und prüfen Sie, ob die mit Hardware verpackten Schlüssel (z. B. FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy und DmDefaultKeyTest.TestHwWrappedKey) wurden aufgrund der Unterstützung nicht übersprungen für mit Hardware verpackte Schlüssel nicht erkannt, da die Testergebnisse noch vorhanden sind "bestanden" in diesem Fall.

Tasten aktivieren

Sobald die Unterstützung für hardwareverpackte Schlüssel des Geräts ordnungsgemäß funktioniert, können Sie die folgenden Änderungen an der fstab-Datei des Geräts vornehmen, damit Android sie für die FBE- und Metadatenverschlüsselung verwendet:

  • FBE: Fügen Sie das Flag wrappedkey_v0 zum fileencryption-Parameter. Verwenden Sie zum Beispiel fileencryption=::inlinecrypt_optimized+wrappedkey_v0. Weitere Informationen finden Sie in der FBE-Dokumentation.
  • Verschlüsselung von Metadaten: Fügen Sie dem Parameter metadata_encryption das Flag wrappedkey_v0 hinzu. Verwenden Sie zum Beispiel metadata_encryption=:wrappedkey_v0. Weitere Informationen finden Sie in der Metadaten Dokumentation zur Verschlüsselung.