Ç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 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:
Ö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ı gerekenblk_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ı gerekenblk_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çinvold
tarafından kullanılırken "içe aktar" özelliği, test anahtarlarını içe aktarmak içinvts_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 hemvold
hem devts_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
parametresinefileencryption
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
parametresinemetadata_encryption
işaretini ekleyin. Örneğin,metadata_encryption=:wrappedkey_v0
kullanın. Daha fazla bilgi için meta veri şifreleme belgelerini inceleyin.