Donanımla sarmalanmış anahtarlar

Çoğu disk ve dosya şifreleme yazılımı gibi Android'in depolama şifrelemesi de geleneksel olarak şifrelemenin yapılabilmesi için sistem belleğinde bulunan ham şifreleme anahtarlarını kullanır. Şifreleme yazılım yerine özel donanım tarafından gerçekleştirilse bile yazılımın genellikle ham şifreleme anahtarlarını yönetmesi gerekir.

Depolama alanı şifrelemenin amacının, çevrimdışı saldırılara karşı koruma sağlamak olduğu için anahtarlar çevrimdışı saldırı sırasında mevcut olmayacağından bu durum genellikle sorun olarak görülmez. Bununla birlikte, soğuk başlatma saldırıları gibi diğer saldırı türlerine ve saldırganın cihazın güvenliğini tamamen ihlal etmeden sistem belleğini sızdırabileceği online saldırılara karşı daha fazla koruma sağlamak istiyoruz.

Android 11, bu sorunu çözmek için donanım desteğinin bulunduğu donanımla sarmalanmış anahtarlara yönelik destek sunmuştur. Donanımla sarmalanmış anahtarlar, yalnızca özel donanım tarafından ham biçimde bilinen depolama anahtarlardır. Yazılımlar bu anahtarları yalnızca sarmalanmış (şifrelenmiş) biçimde görür ve bu biçimde işler. Bu donanım, depolama anahtarları oluşturma ve içe aktarma, depolama anahtarlarını geçici ve uzun süreli biçimlere sarmalama, alt anahtarlar türetme, bir alt anahtarı doğrudan satır içi şifreleme motoruna programlama ve yazılıma ayrı bir alt anahtar döndürme işlemlerini yapabilmelidir.

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

Tasarım

Bu bölümde, donanımla sarmalanmış anahtarlar özelliğinin tasarımı ve bu özellik için gereken donanım desteği açıklanmaktadır. Bu tartışmada dosya tabanlı şifreleme (FBE) ele alınsa da çözüm meta veri şifrelemesi için de geçerlidir.

Sistem belleğindeki ham şifreleme anahtarlarına ihtiyaç duymamaktan kaçınmanın bir yolu, bunları yalnızca satır içi kripto motorunun anahtar gruplarında tutmaktır. Ancak bu yaklaşımın bazı sorunları vardır:

  • Şifreleme anahtarlarının sayısı, anahtar yuvası sayısını aşabilir.
  • Satır içi şifreleme motorları, depolama denetleyicisi (genellikle UFS veya eMMC) sıfırlanırsa genellikle anahtar yuvalarının içeriğini kaybeder. Depolama alanı denetleyicisinin sıfırlanması, belirli depolama alanı hatası türleri oluştuğunda uygulanan standart bir hata kurtarma prosedürüdür. Bu tür hatalar herhangi bir zamanda ortaya çıkabilir. Bu nedenle, satır içi şifreleme kullanılırken işletim sistemi her zaman kullanıcı müdahalesi olmadan anahtar alanlarını yeniden programlamaya hazır olmalıdır.
  • Satır içi şifreleme motorları yalnızca diskteki tam veri bloklarını şifrelemek veya bunların şifresini çözmek için kullanılabilir. Ancak FBE söz konusu olduğunda yazılımın dosya adı şifreleme ve anahtar tanımlayıcıları türetme gibi diğer şifreleme işlerini yapabilmesi gerekir. Yazılımın bu diğer işlemleri yapabilmesi için ham FBE anahtarlarına erişmesi gerekir.

Bu sorunları önlemek için depolama alanı anahtarları, yalnızca özel donanım tarafından açılıp kullanılabilen donanımla sarmalanmış anahtarlar haline getirilir. Bu sayede sınırsız sayıda anahtar desteklenir. Ayrıca, anahtar hiyerarşisi değiştirilir ve kısmen bu donanıma taşınır. Bu sayede, satır içi şifreleme motoru kullanılamayan görevler için bir alt anahtarın yazılıma döndürülmesi sağlanır.

Anahtar hiyerarşisi

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

Aşağıdaki şemada, donanımla sarmalanmış anahtarlar kullanılmadığında 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 belirli bir Android kullanıcısının kimlik bilgisiyle ş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ı denir.) Çekirdek bu anahtardan aşağıdaki alt anahtarları türetmektedir:

  • 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 adı şifreleme anahtarı

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

FBE anahtar hiyerarşisi (donanımla sarmalanmış anahtarla)
Şekil 2. FBE anahtar hiyerarşisi (donanımla sarmalanmış anahtarla)

Önceki duruma kıyasla anahtar hiyerarşisine ek bir düzey eklendi ve dosya içeriği şifreleme anahtarı taşındı. Kök düğüm, şifrelenmiş bir dizi dizinin kilidini açmak için Android'in Linux'a ilettiği anahtarı temsil etmeye devam eder. Ancak bu anahtar artık geçici olarak sarmalanmış biçimdedir 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 türetmek 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şmesi gerekmeden dosya içeriklerinin şifrelenmesine/şifre çözülmesine olanak tanınabilir. 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.
  • Linux'un dosya içeriği şifrelemeden başka her şey için alt anahtarları türetmek amacıyla kullandığı sw_secret ("yazılım gizlisi", bazı yerlerde "ham gizli" olarak da adlandırılır) anahtarını 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ın, ham depolama anahtarından inline_encryption_key ve sw_secret'yi türetmesi için kriptografik olarak güçlü bir KDF kullanması gerekir. Bu KDF, kriptografiyle ilgili en iyi uygulamaları izlemelidir. En az 256 bit güvenlik gücüne sahip olmalıdır. Yani daha sonra kullanılacak herhangi bir algoritma için yeterli olmalıdır. Ayrıca, elde edilen alt anahtarların kriptografik olarak izole edilmesini (yani, bunlardan birinin bilinmesi diğerinin açığa çıkmasını) sağlamak için her alt anahtar türünü türetirken farklı bir etiket, bağlam ve uygulamaya özgü bilgi dizesi kullanmalıdır. Ham depolama anahtarı zaten tekdüze rastgele bir anahtar olduğundan anahtar uzatma işlemi gerekli değildir.

Teknik olarak, güvenlik şartlarını karşılayan herhangi bir KDF kullanılabilir. Ancak, test amacıyla aynı KDF'nin test kodunda yeniden uygulanması gerekir. Şu anda bir KDF incelendi ve uygulandı. Bu KDF'yi vts_kernel_encryption_test için kaynak kodunda bulabilirsiniz. Donanımın, PRF olarak AES-256-CMAC ile NIST SP 800-108 "Karşı Modda KDF" kullanan bu KDF'yi kullanması önerilir. Her bir alt anahtarın KDF bağlamlarının ve etiketlerin seçimi de dahil olmak üzere algoritmanın tüm bölümlerinin uyumlu olması için aynı olması gerektiğini unutmayın.

Anahtar sarmalama

Donanımla sarmalanmış anahtarların güvenlik hedeflerini karşılamak için iki tür anahtar sarmalama tanımlanmıştır:

  • Geçici sarmalama: Donanım, her önyüklemede rastgele oluşturulan ve donanımın dışında doğrudan gösterilmeyen bir anahtar kullanarak ham anahtarı şifreler.
  • Uzun süreli sarmalama: Donanım, ham anahtarı donanıma yerleştirilmiş ve doğrudan donanımın dışında gösterilmeyen 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 sayede, bir saldırgan sistem belleğinden kullanılan bir anahtarı çıkarsa bu anahtar yalnızca cihaz kapalıyken değil, yeniden başlatıldıktan sonra da kullanılamaz.

Aynı zamanda, Android'in kilitlerinin açılabilmesi için anahtarların şifrelenmiş bir sürümünü diskte saklayabilmesi gerekir. Ham anahtarlar bu amaçla kullanılabilir. Ancak, ham anahtarların sistem belleğinde hiç bulunmaması arzu edilir. Böylece, önyükleme sırasında ayıklanmış olsalar bile cihaz dışında kullanılmak üzere hiçbir zaman ayıklanamazlar. Bu sebeple uzun vadeli sarmalama kavramı tanımlanmıştır.

Anahtarları bu iki farklı şekilde sarmalamak için donanımın aşağıdaki arayüzleri uygulaması gerekir:

  • Depolama alanı anahtarları oluşturmak ve içe aktarmak için uzun süreli sarmalanmış biçimde döndüren arayüzler. Bu arayüzlere KeyMint aracılığıyla dolaylı olarak erişilir ve TAG_STORAGE_KEY KeyMint etiketine karşılık gelirler. "Oluşturma" özelliği, Android tarafından kullanılacak yeni depolama alanı anahtarları oluşturmak için vold tarafından kullanılır. "İçe aktarma" özelliği ise 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ı geçici olarak sarmalanmış bir depolama anahtarına dönüştüren bir 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 IV'ler içeren AES-256-GCM gibi güçlü bir AEAD kullanılmalıdır.

Yazılım değişiklikleri gerekiyor

AOSP'de donanımla sarmalanmış anahtarları destekleyen temel bir çerçeve zaten mevcuttur. Buna vold gibi kullanıcı alanı bileşenlerindeki destek ve blk-crypto, fscrypt ve dm-default-key'deki Linux çekirdeği desteği dahildir.

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

KeyMint değişiklikleri

Cihazın KeyMint uygulaması, TAG_STORAGE_KEY yöntemini desteklemek ve uygulamak için değiştirilmelidir.convertStorageKeyToEphemeral

Keymaster'da convertStorageKeyToEphemeral yerine exportKey kullanıldı.

Linux çekirdeği değişiklikleri

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

android14 ve sonraki sürüm çekirdekler için BLK_CRYPTO_KEY_TYPE_HW_WRAPPEDblk_crypto_profile::key_types_supported'de ayarlayın, blk_crypto_ll_ops::keyslot_program ve blk_crypto_ll_ops::keyslot_evict'i oluşturun, donanımla sarmalanmış anahtarların programlanmasını/kaldırılmasını destekleyin ve blk_crypto_ll_ops::derive_sw_secret'i uygulayın.

android12 ve android13 çekirdekleri için blk_keyslot_manager::features'te BLK_CRYPTO_FEATURE_WRAPPED_KEYS'yi ayarlayın, blk_ksm_ll_ops::keyslot_program ve blk_ksm_ll_ops::keyslot_evict'i oluşturun, donanımla sarmalanmış anahtarların programlanmasını/çıkarılmasını destekleyin ve blk_ksm_ll_ops::derive_raw_secret'yi uygulayın.

android11 çekirdeklerinde, keyslot_manager::features içinde BLK_CRYPTO_FEATURE_WRAPPED_KEYS'ü ayarlayın, keyslot_mgmt_ll_ops::keyslot_program ve keyslot_mgmt_ll_ops::keyslot_evict'i oluşturun, donanımla sarmalanmış anahtarların programlanmasını/çıkarılmasını destekleyin ve keyslot_mgmt_ll_ops::derive_raw_secret'i uygulayın.

Test

Donanımla sarmalanmış anahtarlarla şifrelemeyi test etmek, standart anahtarlarla şifrelemeden daha zor olsa da bir test anahtarını içe aktararak ve donanımın kullandığı anahtar türevini yeniden uygulayarak test etmek mümkündür. Bu, vts_kernel_encryption_test'te uygulanır. Bu testi çalıştırmak için:

atest -v vts_kernel_encryption_test

Test günlüğünü okuyun ve donanım destekli anahtar test durumlarının (ör. FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy ve DmDefaultKeyTest.TestHwWrappedKey), donanım destekli anahtar desteğinin algılanmaması nedeniyle atlanmadığından emin olun. Bu durumda test sonuçları yine de "geçti" olarak görünür.

Anahtarları etkinleştirme

Cihazın donanımla sarmalanmış anahtar desteği düzgün şekilde çalışmaya başladıktan sonra, Android'in FBE ve meta veri şifrelemesi için kullanması amacıyla cihazın fstab dosyasında aşağıdaki değişiklikleri yapabilirsiniz:

  • FBE: wrappedkey_v0 işaretini fileencryption parametresine ekleyin. Örneğin, fileencryption=::inlinecrypt_optimized+wrappedkey_v0 değerini kullanın. Ayrıntılı bilgi için FBE belgelerine bakın.
  • Meta veri şifrelemesi: metadata_encryption parametresine wrappedkey_v0 işaretini ekleyin. Örneğin, metadata_encryption=:wrappedkey_v0 değerini kullanın. Daha fazla bilgi için meta veri şifreleme dokümanlarını inceleyin.