Donanımla sarmalanmış anahtarlar

Çoğu disk ve dosya şifreleme yazılımı gibi, Android'in depolama şifrelemesi de şifrelemenin yapılabilmesi için geleneksel olarak sistem belleğinde ham şifreleme anahtarlarının bulunmasına dayanır. Şifreleme yazılımla değil, özel donanımla yapılsa bile genellikle ham şifreleme anahtarlarının yazılımla yönetilmesi gerekir.

Geleneksel olarak bu durum bir sorun olarak görülmez. Bunun nedeni, anahtarların çevrimdışı saldırı sırasında mevcut olmamasıdır. Çevrimdışı saldırı, depolama şifrelemesinin korumayı amaçladığı temel saldırı türüdür. Ancak soğuk başlatma saldırıları gibi diğer saldırı türlerine ve saldırganın cihazı tamamen tehlikeye atmadan sistem belleğini sızdırabileceği online saldırılara karşı daha fazla koruma sağlamak istenmektedir.

Android 11, bu sorunu çözmek için donanım desteğinin olduğu yerlerde donanım sarmalı anahtarlar için destek sunar. Donanımla sarmalanmış anahtarlar, yalnızca özel donanım tarafından ham biçimde bilinen depolama anahtarlarıdır. Yazılım, bu anahtarları yalnızca sarmalanmış (şifrelenmiş) biçimde görür ve bu biçimde kullanır. Bu donanım, depolama anahtarları oluşturup içe aktarabilmeli, depolama anahtarlarını kısa ömürlü ve uzun vadeli biçimlerde sarmalayabilmeli, alt anahtarlar türetebilmeli, bir alt anahtarı doğrudan satır içi kripto motoruna programlayabilmeli ve yazılıma ayrı bir alt anahtar döndürebilmelidir.

Not: Satır içi kripto motoru (veya satır içi şifreleme donanımı), depolama cihazına giderken/gelirken verileri şifreleyen/şifresini çözen donanımı ifade eder. Bu genellikle, ilgili JEDEC spesifikasyonu tarafından tanımlanan kripto uzantılarını uygulayan bir UFS veya eMMC ana makine denetleyicisidir.

Tasarım

Bu bölümde, donanım sarmalı anahtarlar özelliğinin tasarımı ve bu özellik için hangi donanım desteğinin gerektiği açıklanmaktadır. Bu tartışmada dosya tabanlı şifreleme (FBE) ele alınmaktadır ancak çözüm meta veri şifreleme için de geçerlidir.

Sistem belleğinde ham şifreleme anahtarlarına ihtiyaç duymamak için bu anahtarları yalnızca satır içi kripto motorunun anahtar yuvalarında tutabilirsiniz. Ancak bu yaklaşım bazı sorunlara yol açar:

  • Şifreleme anahtarlarının sayısı, anahtar yuvalarının sayısını aşabilir.
  • Depolama alanı ana bilgisayar denetleyicisi sıfırlanırsa satır içi kripto motorları genellikle anahtar yuvalarının içeriğini kaybeder. Depolama alanı ana denetleyicisini sıfırlama, belirli depolama alanı hataları oluştuğunda yürütülen standart bir hata kurtarma prosedürüdür ve bu tür hatalar herhangi bir zamanda oluşabilir. Bu nedenle, satır içi şifreleme kullanılırken işletim sistemi, kullanıcı müdahalesi olmadan her zaman anahtar yuvalarını yeniden programlamaya hazır olmalıdır.
  • Satır içi kripto motorları yalnızca diskteki tam veri bloklarını şifrelemek/şifrelerini çözmek için kullanılabilir. Ancak FBE durumunda, yazılımın dosya adı şifreleme ve anahtar tanımlayıcıları türetme gibi diğer şifreleme işlemlerini yapabilmesi gerekir. Yazılımın bu diğer işi yapabilmesi için yine de ham FBE anahtarlarına erişmesi gerekir.

Bu sorunları önlemek için depolama anahtarları, yalnızca özel donanım tarafından sarmalaması açılıp kullanılabilecek donanım sarmalamalı anahtarlara dönüştürülür. Bu sayede sınırsız sayıda anahtar desteklenebilir. Ayrıca, anahtar hiyerarşisi değiştirilir ve kısmen bu donanıma taşınır. Bu sayede, satır içi şifreleme motorunun kullanılamadığı görevler için alt anahtarın yazılıma döndürülmesine olanak tanınır.

Anahtar hiyerarşisi

Anahtarlar, HKDF gibi bir anahtar türetme işlevi (KDF) kullanılarak diğer anahtarlardan türetilebilir. Bu işlem sonucunda anahtar hiyerarşisi oluşur.

Aşağıdaki şemada, donanım sarmalı anahtarların kullanılmadığı durumlarda FBE için tipik bir anahtar hiyerarşisi gösterilmektedir:

FBE anahtar hiyerarşisi (standart)
Şekil 1. FBE anahtar hiyerarşisi (standart)

FBE sınıf anahtarı, Android'in Linux çekirdeğine ilettiği ham şifreleme anahtarıdır. Bu anahtar, belirli bir Android kullanıcısının kimlik bilgileriyle şifrelenmiş depolama alanı gibi belirli bir şifrelenmiş dizin grubunun kilidini açar. (Çekirdekte bu anahtara fscrypt ana anahtarı denir.) Çekirdek, bu anahtardan aşağıdaki alt anahtarları türetir:

  • Anahtar tanımlayıcısı. Bu değer şifreleme için değil, belirli bir dosyanın veya dizinin korunduğu anahtarı tanımlamak için kullanılır.
  • Dosya içeriği şifreleme anahtarı
  • Dosya adları şifreleme anahtarı

Buna karşılık, aşağıdaki şemada donanım sarmalı anahtarlar kullanıldığında FBE için anahtar hiyerarşisi gösterilmektedir:

FBE anahtar hiyerarşisi (donanım sarmalı anahtarla)
Şekil 2. FBE anahtar hiyerarşisi (donanım sarmalı anahtarla)

Önceki duruma kıyasla anahtar hiyerarşisine ek bir düzey daha eklendi ve dosya içeriği şifreleme anahtarı yeniden konumlandırıldı. Kök düğüm, Android'in bir dizi şifrelenmiş dizinin kilidini açmak için Linux'a ilettiği anahtarı temsil etmeye devam eder. Ancak bu anahtar artık geçici olarak sarmalanmış biçimde olduğundan kullanılabilmesi için özel donanıma aktarılması gerekir. Bu donanım, geçici olarak sarmalanmış bir anahtar alan iki arayüzü uygulamalıdır:

  • inline_encryption_key değerini elde etmek ve doğrudan satır içi kripto motorunun bir anahtar yuvasına programlamak için tek bir arayüz. Bu sayede, dosya içerikleri, yazılımın ham anahtara erişimi olmadan şifrelenebilir/şifresi çözülebilir. Android ortak çekirdeklerinde bu arayüz, depolama sürücüsü tarafından uygulanması gereken blk_crypto_ll_ops::keyslot_program işlemine karşılık gelir.
  • Dosya içeriği şifrelemesi dışındaki her şey için alt anahtarları türetmek üzere Linux'un kullandığı anahtar olan sw_secret ("yazılım sırrı" -- daha önce "ham sır" olarak adlandırılıyordu) değerini türetip döndürmek için kullanılan bir arayüz. Android ortak çekirdeklerinde bu arayüz, depolama sürücüsü tarafından uygulanması gereken blk_crypto_ll_ops::derive_sw_secret işlemine karşılık gelir.

Donanım, ham depolama anahtarından inline_encryption_key ve sw_secret değerlerini türetmek için kriptografik olarak güçlü bir KDF kullanmalıdır. Bu KDF, kriptografiyle ilgili en iyi uygulamalara uymalıdır. En az 256 bitlik bir güvenlik gücüne sahip olmalıdır. Bu, daha sonra kullanılacak herhangi bir algoritma için yeterlidir. Ayrıca, her bir alt anahtar türünü türetirken farklı bir etiket ve bağlam kullanması gerekir. Böylece, ortaya çıkan alt anahtarların kriptografik olarak izole edilmesi (yani bir alt anahtarın bilinmesinin diğerlerini ortaya çıkarmaması) sağlanır. Ham depolama anahtarı zaten tek tip rastgele bir anahtar olduğundan anahtar uzatma gerekli değildir.

Teknik olarak, güvenlik şartlarını karşılayan herhangi bir KDF kullanılabilir. Ancak test amacıyla vts_kernel_encryption_test, diskteki şifreli metni yeniden oluşturmak ve doğru olduğunu doğrulamak için yazılımda aynı KDF'yi uygular. Testin kolaylığı ve güvenli, daha önce incelenmiş bir KDF'nin kullanılmasını sağlamak için donanımın, testin kontrol ettiği varsayılan KDF'yi uygulamasını öneririz. Farklı bir KDF kullanan donanımlarda testi buna göre yapılandırmak için Sarmalanmış anahtarları test etme başlıklı makaleyi inceleyin.

Anahtar sarmalama

Donanım sarmalı anahtarların güvenlik hedeflerini karşılamak için iki tür anahtar sarmalama tanımlanır:

  • Geçici sarmalama: Donanım, her başlatmada rastgele oluşturulan ve donanımın dışında doğrudan açığa çıkmayan bir anahtar kullanarak ham anahtarı şifreler.
  • Uzun süreli sarmalama: Donanım, ham anahtarı donanıma yerleştirilmiş ve doğrudan donanım dışında açığa çıkmayan benzersiz, kalıcı bir anahtar kullanarak şifreler.

Depolama alanının kilidini açmak için Linux çekirdeğine iletilen tüm anahtarlar geçici olarak sarmalanır. Bu, bir saldırganın sistem belleğinden kullanımda olan bir anahtarı çıkarabilmesi durumunda, bu anahtarın yalnızca cihaz dışında değil, yeniden başlatma işleminden sonra cihazda da kullanılamamasını sağlar.

Aynı zamanda, Android'in anahtarların şifrelenmiş bir sürümünü diskte saklayabilmesi gerekir. Böylece anahtarların kilidi açılabilir. Bu amaçla hamanahtarlar kullanılabilir. Ancak, ham anahtarların sistem belleğinde hiç bulunmaması, böylece önyükleme sırasında çıkarılsalar bile cihaz dışında kullanılmak üzere çıkarılamamaları tercih edilir. Bu nedenle, uzun vadeli sarmalama kavramı tanımlanır.

Bu iki farklı şekilde sarmalanmış anahtarların yönetilmesini desteklemek için donanımın aşağıdaki arayüzleri uygulaması gerekir:

  • Depolama anahtarlarını oluşturup içe aktarmak ve bunları uzun vadeli sarmalanmış biçimde döndürmek için kullanılan arayüzler. Oluştur arayüzü, vold tarafından Android'de kullanılacak yeni depolama anahtarları oluşturmak için kullanılır. İçe aktarma arayüzü, vts_kernel_encryption_test tarafından test anahtarlarını içe aktarmak için kullanılır.
  • Uzun süreli sarmalanmış bir depolama anahtarını kısa süreli sarmalanmış bir depolama anahtarına dönüştürmek için kullanılan arayüz. Bu arayüz, depolama alanının kilidini açmak için hem vold hem de vts_kernel_encryption_test tarafından kullanılır.

Anahtar sarmalama algoritması bir uygulama ayrıntısıdır ancak rastgele başlatma vektörleriyle AES-256-GCM gibi güçlü bir AEAD kullanmalıdır.

Yazılım değişiklikleri gerekiyor

AOSP'de, donanım tabanlı anahtarları desteklemek için temel bir çerçeve zaten mevcuttur. Bu, vold gibi kullanıcı alanı bileşenlerindeki desteğin yanı sıra blk-crypto, fscrypt ve dm-default-key'deki Linux çekirdek desteğini de içerir.

Linux çekirdeği değişiklikleri

Cihazın satır içi şifreleme destekli depolama denetleyicisi için Linux çekirdek sürücüsü, donanım tarafından sarmalanmış anahtarları destekleyecek şekilde değiştirilmelidir.

android17 ve sonraki çekirdekler için:

  • BLK_CRYPTO_KEY_TYPE_HW_WRAPPED değerini blk_crypto_profile::key_types_supported olarak ayarlayın.
  • blk_crypto_ll_ops::keyslot_program, donanım sarmalı anahtarları destekleyecek şekilde programlanmalıdır.
  • blk_crypto_ll_ops::keyslot_evict'nın donanım sarmalı anahtarları silmeyi desteklemesini sağlayın.
  • blk_crypto_ll_ops::derive_sw_secret, blk_crypto_ll_ops::import_key, blk_crypto_ll_ops::generate_key ve blk_crypto_ll_ops::prepare_key uygulayın.

android14, android15 ve android16 çekirdekleri için:

  • BLK_CRYPTO_KEY_TYPE_HW_WRAPPED değerini blk_crypto_profile::key_types_supported olarak ayarlayın.
  • blk_crypto_ll_ops::keyslot_program, donanım sarmalı anahtarları destekleyecek şekilde programlanmalıdır.
  • blk_crypto_ll_ops::keyslot_evict'nın donanım sarmalı anahtarları silmeyi desteklemesini sağlayın.
  • blk_crypto_ll_ops::derive_sw_secret uygulayın.

android12 ve android13 çekirdekleri için:

  • BLK_CRYPTO_FEATURE_WRAPPED_KEYS değerini blk_keyslot_manager::features olarak ayarlayın.
  • blk_ksm_ll_ops::keyslot_program, donanım sarmalı anahtarları destekleyecek şekilde programlanmalıdır.
  • blk_ksm_ll_ops::keyslot_evict'nın donanım sarmalı anahtarları silmeyi desteklemesini sağlayın.
  • blk_ksm_ll_ops::derive_raw_secret uygulayın.

android11 çekirdek için:

  • BLK_CRYPTO_FEATURE_WRAPPED_KEYS değerini keyslot_manager::features olarak ayarlayın.
  • keyslot_mgmt_ll_ops::keyslot_program, donanım sarmalı anahtarları destekleyecek şekilde programlanmalıdır.
  • keyslot_mgmt_ll_ops::keyslot_evict'nın donanım sarmalı anahtarları silmeyi desteklemesini sağlayın.
  • keyslot_mgmt_ll_ops::derive_raw_secret uygulayın.

KeyMint değişiklikleri (eski)

Donanım sarmalı anahtarların mevcut sürümünde (wrappedkey), donanım sarmalı anahtarların oluşturulması, içe aktarılması ve hazırlanması için Linux çekirdek ioctl'leri BLKCRYPTOGENERATEKEY, BLKCRYPTOIMPORTKEY ve BLKCRYPTOPREPAREKEY kullanılır. Bu ioctl'ler, struct blk_crypto_ll_ops içindeki yöntemlere karşılık gelir. Depolama sürücüsü bu yöntemleri uygular ve istenen işlemi gerçekleştirmek için anahtar sarmalama donanımıyla iletişim kurar. Bu ioctl'ler hakkında daha fazla bilgi için Linux çekirdeği belgelerine bakın.

Bu ioctl'ler Linux 6.16'da eklenmiştir. ioctl tabanlı çözümle kullanıma sunulmayan cihazlarda, Android KeyMint (veya daha önce KeyMaster) kullanan farklı bir çözüm kullanılır. Eski çözüm (wrappedkey_v0), ana Linux çekirdeğiyle veya mevcut çözümle uyumlu değil. Eski çözümde aşağıdaki KeyMint işlevleri kullanılır:

  • Hem anahtar oluşturma hem de içe aktarma için TAG_STORAGE_KEY desteği.
  • convertStorageKeyToEphemeral yöntemi için destek.

Bu KeyMint işlevi yalnızca fstab dosyasında wrappedkey_v0 ile eşleşen eski çözümü kullanan cihazlarda gereklidir.

fstab dosyasındaki wrappedkey ile eşleşen mevcut çözümü kullanan cihazlarda bu KeyMint işlevinin uygulanması gerekmez.

Sarmalanmış anahtarları test etme

Donanım sarmalı anahtarlarla şifrelemeyi test etmek, ham anahtarlarla şifrelemeyi test etmekten daha zor olsa da test anahtarı içe aktarıp donanımın yaptığı anahtar türetme işlemini yeniden uygulayarak test etmek mümkündür. Bu özellik, vts_kernel_encryption_test'de uygulanır. Bu testi çalıştırmak için: run:

atest -v vts_kernel_encryption_test

Test günlüğünü okuyun ve donanımla sarmalanmış anahtar testlerinin (örneğin, FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy ve DmDefaultKeyTest.TestHwWrappedKey) donanımla sarmalanmış anahtar desteği algılanmadığı için atlanmadığını doğrulayın. Bu durumda test sonuçları yine de "geçti" olarak gösterilir.

vts_kernel_encryption_test, varsayılan olarak donanımın kdf1 adını verdiği bir KDF'yi uyguladığını varsayar. Bu KDF, NIST SP 800-108'deki KDF'lerin sayaç modu ailesine aittir ve sözde rastgele işlev olarak AES-256-CMAC kullanır. CMAC hakkında daha fazla bilgi için CMAC spesifikasyonuna bakın. KDF, her alt anahtarı türetirken belirli bağlamları ve etiketleri kullanır. Donanım, her alt anahtarı türetirken bağlam, etiket ve sabit giriş dizesinin biçimlendirmesiyle ilgili kesin seçim de dahil olmak üzere bu KDF'yi uygulamalıdır.

Ancak vts_kernel_encryption_test, kdf4 aracılığıyla kdf2 ek KDF'ler de uygular. Bunlar kdf1 kadar güvenlidir ve yalnızca bağlam, etiket ve sabit giriş dizesinin biçimlendirilmesi seçiminde farklılık gösterir. Yalnızca farklı donanımları desteklemek için kullanılırlar.

Farklı bir KDF kullanan cihazlar için ro.crypto.hw_wrapped_keys.kdf sistem özelliğini PRODUCT_VENDOR_PROPERTIES içinde test kaynak kodunda tanımlanan KDF'nin adıyla ayarlayın. Bu durum, vts_kernel_encryption_test tarayıcısının kdf1 yerine söz konusu KDF'yi kontrol etmesine neden olur. Örneğin, kdf2 öğesini seçmek için şunu kullanın:

PRODUCT_VENDOR_PROPERTIES += ro.crypto.hw_wrapped_keys.kdf=kdf2

Testin desteklemediği bir KDF kullanan cihazlar için bu KDF'nin bir uygulamasını da teste ekleyin ve bu uygulamaya benzersiz bir ad verin.

Sarmalanmış anahtarları etkinleştirme

Cihazın donanım sarmalı anahtar desteği düzgün çalıştığında, Android'in FBE ve meta veri şifrelemesi için kullanmasını sağlamak üzere cihazın fstab dosyasında aşağıdaki değişiklikleri yapın:

  • FBE: wrappedkey (veya eski sürüm için wrappedkey_v0) işaretini fileencryption parametresine ekleyin. Örneğin, fileencryption=::inlinecrypt_optimized+wrappedkey kullanın. Daha fazla bilgi için FBE belgelerini inceleyin.
  • Meta veri şifreleme: wrappedkey parametresine wrappedkey işaretini (veya eski sürüm için wrappedkey_v0) ekleyin.metadata_encryption Örneğin, metadata_encryption=:wrappedkey kullanın. Daha fazla bilgi için meta veri şifreleme belgelerine bakın.

Her durumda, işaretin iki versiyonu vardır:

  • Android 17 ve sonraki sürümler tarafından desteklenen wrappedkey, donanım sarmalı anahtarların mevcut sürümünü etkinleştirir. Bu sürüm, ana Linux çekirdeğiyle uyumludur.
  • Android 11 ve sonraki sürümlerde desteklenen wrappedkey_v0, donanım sarmalı anahtarların eski sürümünü etkinleştirir. Bu sürüm, ana Linux çekirdeğiyle uyumlu değil. Belirli işlemleri KeyMint üzerinden proxy'ler ve standart olmayan bir disk içi biçim kullanır. Daha fazla bilgi için KeyMint değişiklikleri (eski) başlıklı makaleyi inceleyin.

Android 17 veya sonraki sürümlerle kullanıma sunulan cihazlarda wrappedkey tercih edilir.

wrappedkey_v0 ile kullanıma sunulmuş cihazlarda geriye dönük uyumluluk için wrappedkey_v0 kullanmaya devam edin.