Ç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 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:
Ö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_keydeğ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ı gerekenblk_crypto_ll_ops::keyslot_programiş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ı gerekenblk_crypto_ll_ops::derive_sw_secretiş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ü,
voldtarafından Android'de kullanılacak yeni depolama anahtarları oluşturmak için kullanılır. İçe aktarma arayüzü,vts_kernel_encryption_testtarafı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
voldhem devts_kernel_encryption_testtarafı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_WRAPPEDdeğeriniblk_crypto_profile::key_types_supportedolarak 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_keyveblk_crypto_ll_ops::prepare_keyuygulayın.
android14, android15 ve android16 çekirdekleri için:
BLK_CRYPTO_KEY_TYPE_HW_WRAPPEDdeğeriniblk_crypto_profile::key_types_supportedolarak 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_secretuygulayın.
android12 ve android13 çekirdekleri için:
BLK_CRYPTO_FEATURE_WRAPPED_KEYSdeğeriniblk_keyslot_manager::featuresolarak 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_secretuygulayın.
android11 çekirdek için:
BLK_CRYPTO_FEATURE_WRAPPED_KEYSdeğerinikeyslot_manager::featuresolarak 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_secretuygulayı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_KEYdesteği. convertStorageKeyToEphemeralyö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çinwrappedkey_v0) işaretinifileencryptionparametresine ekleyin. Örneğin,fileencryption=::inlinecrypt_optimized+wrappedkeykullanın. Daha fazla bilgi için FBE belgelerini inceleyin. - Meta veri şifreleme:
wrappedkeyparametresinewrappedkeyişaretini (veya eski sürüm içinwrappedkey_v0) ekleyin.metadata_encryptionÖrneğin,metadata_encryption=:wrappedkeykullanı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.