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 depolama şifrelemesinin koruması amaçlanan başlıca saldırı türü olan çevrimdışı saldırı sırasında mevcut olmaması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 çalışı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 ya da depolama cihazından gelirken verileri şifreleyen/şifrelerini çö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) üzerinde durulsa da çö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.
  • Satır içi kripto motorları, depolama alanı ana denetleyicisi sıfırlandığında genellikle anahtar yuvalarının içeriğini kaybeder. Depolama alanı ana denetleyicisini sıfırlamak, 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 her zaman kullanıcı müdahalesi olmadan anahtar yuvalarını yeniden programlamaya hazır olmalıdır.
  • Satır içi kripto motorları yalnızca diskteki tam veri bloklarını şifrelemek/şifre çö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şleri yapabilmesi için yine de ham FBE anahtarlarına erişmesi gerekir.

Bu sorunları önlemek için depolama anahtarları bunun yerine donanım sarmalı anahtarlar haline getirilir. Bu anahtarlar yalnızca özel donanım tarafından sarmalandan çıkarılıp kullanılabilir. 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)
1.şekil FBE anahtar hiyerarşisi (standart)

FBE sınıf anahtarı, Android'in belirli bir Android kullanıcısının kimlik bilgileriyle şifrelenmiş depolama alanı gibi belirli bir şifrelenmiş dizin grubunun kilidini açmak için Linux çekirdeğine ilettiği ham şifreleme anahtarıdır. (Çekirdekte bu anahtara fscrypt ana anahtarı adı verilir.) Ç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ımla sarılmış anahtarla)

Önceki duruma kıyasla anahtar hiyerarşisine ek bir düzey 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 kısa ömürlü olarak sarmalanmış biçimde bulunur ve 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, yazılımın ham anahtara erişimi olmadan dosya içerikleri şifrelenebilir/şifreleri çö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 şifreleme dışındaki her şey için alt anahtarları türetmek üzere Linux'un kullandığı anahtar olan sw_secret ("yazılım sırrı" -- bazı yerlerde "ham sır" olarak da adlandırılır) türetmek ve 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, inline_encryption_key ve sw_secret değerlerini ham depolama anahtarından türetmek için kriptografik olarak güçlü bir KDF kullanmalıdır. Bu KDF, kriptografiyle ilgili en iyi uygulamalara uygun olmalıdır. Güvenlik gücü en az 256 bit olmalıdır. Bu, daha sonra kullanılacak algoritmalar için yeterlidir. Ayrıca, ortaya çıkan alt anahtarların kriptografik olarak izole edilmesini (yani birinin bilinmesinin diğerini ortaya çıkarmamasını) sağlamak için her bir alt anahtar türünü türetirken farklı bir etiket ve bağlam kullanmalıdı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, önceden 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ımlar için testi buna göre nasıl yapılandıracağınızı öğrenmek istiyorsanız 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ş, benzersiz, kalıcı ve doğrudan donanım dışında açığa çıkmayan bir anahtarla şifreler.

Depolamanın kilidini açmak için Linux çekirdeğine iletilen tüm anahtarlar geçici olarak sarmalanır. Bu işlem, saldırganın sistem belleğinden kullanımda olan bir anahtarı çıkarması durumunda 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ç için ham anahtarlar kullanılabilir. Ancak, ham anahtarların sistem belleğinde hiç bulunmaması, önyükleme sırasında çıkarılsalar bile cihaz dışında kullanılmak üzere çıkarılamamaları açısından 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. Bu arayüzlere KeyMint üzerinden dolaylı olarak erişilir ve TAG_STORAGE_KEY KeyMint etiketiyle eşleşirler. "Oluştur" özelliği, Android tarafından kullanılacak yeni depolama anahtarları oluşturmak için vold tarafından kullanılırken "içe aktar" özelliği, test anahtarlarını içe aktarmak için vts_kernel_encryption_test tarafından 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, convertStorageKeyToEphemeral KeyMint yöntemine karşılık gelir. Bu yöntem, 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 sarmalı 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.

Ancak uygulamaya özel bazı değişiklikler yapılması gerekir.

KeyMint değişiklikleri

Cihazın KeyMint uygulaması, TAG_STORAGE_KEY destekleyecek ve convertStorageKeyToEphemeral yöntemini uygulayacak şekilde değiştirilmelidir.

Keymaster'da convertStorageKeyToEphemeral yerine exportKey kullanılıyordu.

Linux çekirdeği değişiklikleri

Cihazın satır içi kripto motoru için Linux çekirdek sürücüsü, donanım sarmalı anahtarları destekleyecek şekilde değiştirilmelidir.

android14 ve daha yeni çekirdekler için: blk_crypto_profile::key_types_supported içinde BLK_CRYPTO_KEY_TYPE_HW_WRAPPED'i ayarlayın, blk_crypto_ll_ops::keyslot_program'ü oluşturun, blk_crypto_ll_ops::keyslot_evict'i oluşturun, donanım sarmalı anahtarların programlanmasını/kaldırılmasını destekleyin ve blk_crypto_ll_ops::derive_sw_secret'ı uygulayın.

android12 ve android13 çekirdekleri için BLK_CRYPTO_FEATURE_WRAPPED_KEYS'yi blk_keyslot_manager::features'de ayarlayın, blk_ksm_ll_ops::keyslot_program'i oluşturun ve blk_ksm_ll_ops::keyslot_evict'ı programlama/kaldırma donanım sarmalı anahtarlarını destekleyecek şekilde ayarlayın ve blk_ksm_ll_ops::derive_raw_secret'yi uygulayın.

android11 çekirdekleri için BLK_CRYPTO_FEATURE_WRAPPED_KEYS değerini keyslot_manager::features içinde ayarlayın, keyslot_mgmt_ll_ops::keyslot_program değerini oluşturun, keyslot_mgmt_ll_ops::keyslot_evict değerini oluşturun, donanım sarmalı anahtarların programlanmasını/çıkarılmasını destekleyin ve keyslot_mgmt_ll_ops::derive_raw_secret değerini uygulayın.

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 test senaryolarının (ör. 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 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 etiketler kullanır. Donanım, her bir alt anahtarı türetirken sabit giriş dizesinin bağlam, etiket ve biçimlendirme seçimini de içeren bu KDF'yi uygulamalıdır.

Ancak vts_kernel_encryption_test, kdf4 aracılığıyla ek KDF'ler de uygular kdf2. Bunlar kdf1 kadar güvenlidir ve yalnızca bağlam, etiket ve sabit giriş dizesinin biçimlendirilmesi açısından 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 durumda vts_kernel_encryption_test, kdf1 yerine söz konusu KDF'yi kontrol eder. Ö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_v0 parametresine fileencryption işaretini ekleyin. Örneğin, fileencryption=::inlinecrypt_optimized+wrappedkey_v0 kullanın. Daha fazla bilgi için FBE belgelerini inceleyin.
  • Meta veri şifreleme: wrappedkey_v0 parametresine metadata_encryption işaretini ekleyin. Örneğin, metadata_encryption=:wrappedkey_v0 kullanın. Daha fazla bilgi için meta veri şifreleme belgelerini inceleyin.