Cihaz üzerinde imzalama mimarisi

Android 12'den itibaren Android Çalışma Zamanı (ART) modülü bir Mainline modülüdür. Modülün güncellenmesi için ön derleme (AOT) derleme yapılarının bootclasspath jar'ları ve sistem sunucusunun yeniden oluşturulması gerekebilir. Bu yapı taşları güvenlik açısından hassas olduğundan Android 12, bu yapı taşlarının bozulmasını önlemek için cihaz üzerinde imzalama adlı bir özellik kullanır. Bu sayfada, cihaz üzerinde imzalama mimarisi ve diğer Android güvenlik özellikleriyle etkileşimleri ele alınmaktadır.

Üst düzey tasarım

Cihaz üzerinde imzalamanın iki temel bileşeni vardır:

  • odrefresh, ART Mainline modülünün bir parçasıdır. Çalışma zamanındaki yapıları oluşturmaktan sorumludur. Mevcut yapıların güncel olup olmadığını veya yeniden oluşturulup oluşturulmayacağını belirlemek için ART modülünün, bootclasspath jar'larının ve sistem sunucusu jar'larının yüklü sürümüyle karşılaştırmasını yapar. Yeniden oluşturulmaları gerekirse odrefresh bunları oluşturur ve depolar.

  • odsign, Android platformunun bir parçası olan bir ikili programdır. Bu komut dosyası, erken önyükleme sırasında /data bölümü bağlandıktan hemen sonra çalışır. Ana görevi, herhangi bir yapının oluşturulması veya güncellenmesi gerekip gerekmediğini kontrol etmek için odrefresh'ü çağırmaktır. odrefresh tarafından oluşturulan yeni veya güncellenmiş tüm yapı taşlarında odsign bir karma işlevi hesaplar. Bu tür bir karma oluşturma işleminin sonucuna dosya özeti denir. Mevcut yapı taşlarında odsign, mevcut yapı taşlarının özetlerinin odsign'ün daha önce hesapladığı özetlerle eşleşip eşleşmediğini doğrular. Bu, yapıların bozulmadığını gösterir.

Bir dosyanın özeti eşleşmediğinde olduğu gibi hata durumlarında odrefresh ve odsign, /data üzerindeki tüm mevcut yapıları atar ve yeniden oluşturmaya çalışır. Bu işlem başarısız olursa sistem JIT moduna geri döner.

odrefresh ve odsign, dm-verity tarafından korunur ve Android'in Doğrulanmış Başlatma zincirinin bir parçasıdır.

fs-verity ile dosya özetleri hesaplama

fs-verity, Linux çekirdeğinin dosya verilerini Merkle ağacı tabanlı olarak doğrulayan bir özelliğidir. Bir dosyada fs-verity'nin etkinleştirilmesi, dosya sisteminin SHA-256 karmaları kullanarak dosyanın verileri üzerinde bir Merkle ağacı oluşturmasına, bu ağacı dosyanın yanında gizli bir konumda depolamasına ve dosyayı salt okunur olarak işaretlemesine neden olur. fs-verity, dosyanın verileri okunurken gerektiğinde Merkle ağacıyla otomatik olarak doğrular. fs-verity, Merkle ağacının kök karmasını fs-verity dosya özeti adlı bir değer olarak kullanılabilir hale getirir ve dosyada okunan tüm verilerin bu dosya özüyle tutarlı olmasını sağlar.

odsign, cihaz üzerinde derlenmiş yapıların başlatma sırasındaki kriptografik kimlik doğrulamasını optimize ederek başlatma performansını artırmak için fs-verity'yi kullanır. Bir yapı oluşturulduğunda odsign, bu yapıda fs-verity'yi etkinleştirir. odsign bir yapıyı doğrularken tam dosya karması yerine fs-verity dosya özetini doğrular. Bu sayede, önyükleme sırasında yapının tüm verilerini okuma ve karma oluşturma ihtiyacı ortadan kalkar. Bunun yerine, yapı verileri, kullanıldıkça fs-verity tarafından blok bazında isteğe bağlı olarak karma oluşturma işlemine tabi tutulur.

Çekirdeği fs-verity'yi desteklemeyen cihazlarda odsign, dosya özetleri hesaplama işlemini kullanıcı alanında gerçekleştirir. odsign, fs-verity ile aynı Merkle ağacı tabanlı karma algoritmasını kullanır. Bu nedenle, her iki durumda da özetler aynıdır. fs-verity, Android 11 ve sonraki sürümlerle kullanıma sunulan tüm cihazlarda gereklidir.

Dosya özetleri depolama

odsign, yapıların dosya özetleri odsign.info adlı ayrı bir dosyada saklar. odsign.info'nin bozulmadığından emin olmak için odsign.info, önemli güvenlik özelliklerine sahip bir imzalama anahtarıyla imzalanır. Özellikle, anahtar yalnızca erken önyükleme sırasında oluşturulabilir ve kullanılabilir. Bu aşamada yalnızca güvenilir kod çalışır. Ayrıntılar için Güvenilir imzalama anahtarları bölümüne bakın.

Dosya özetleri doğrulaması

Her başlatma işleminde odrefresh, mevcut yapıların güncel olduğunu belirlerse odsign, dosyaların oluşturulduktan sonra değiştirilmediğinden emin olur. odsign, dosya özetleri doğrulanarak bunu yapar. Öncelikle odsign.info imzasını doğrular. İmza geçerliyse odsign, her dosyanın özetinin odsign.info'daki ilgili özetle eşleşip eşleşmediğini doğrular.

Güvenilir imzalama anahtarları

Android 12, aşağıdaki güvenlik sorunlarını gideren önyükleme aşaması anahtarları adlı yeni bir Keystore özelliğini kullanıma sunuyor:

  • Bir saldırganın, odsign.info sürümünü imzalamak için imzalama anahtarımızı kullanmasını ne engeller?
  • Bir saldırganın kendi imzalama anahtarını oluşturmasını ve bunu odsign.info sürümünü imzalamak için kullanmasını ne engeller?

Önyükleme aşaması anahtarları, Android'in önyükleme döngüsünü seviyelere ayırır ve bir anahtarın oluşturulmasını ve kullanılmasını şifreleme yoluyla belirli bir seviyeye bağlar. odsign, yalnızca güvenilir kod çalıştırıldığında ve dm-verity aracılığıyla korunduğunda erken bir aşamada imzalama anahtarını oluşturur.

Açılış aşaması seviyeleri 0 ile 1000000000 sihirli sayısı arasında numaralandırılır. Android'in önyükleme işlemi sırasında init.rc üzerinden bir sistem mülkü ayarlayarak önyükleme düzeyini artırabilirsiniz. Örneğin, aşağıdaki kodda önyükleme seviyesi 10 olarak ayarlanmıştır:

setprop keystore.boot_level 10

Anahtar mağazasının istemcileri, belirli bir önyükleme düzeyine bağlı anahtarlar oluşturabilir. Örneğin, 10. önyükleme seviyesi için bir anahtar oluşturursanız bu anahtar yalnızca cihaz 10. önyükleme seviyesindeyken kullanılabilir.

odsign, 30. önyükleme düzeyini kullanır ve oluşturduğu imzalama anahtarı bu önyükleme düzeyine bağlıdır. odsign, yapıları imzalamak için bir anahtar kullanmadan önce anahtarın 30. önyükleme düzeyine bağlı olduğunu doğrular.

Bu, bu bölümde daha önce açıklanan iki saldırıyı önler:

  • Saldırganlar, oluşturulan anahtarı kullanamaz. Bunun nedeni, saldırganın kötü amaçlı kod çalıştırma şansı bulduğunda önyükleme seviyesinin 30'un üzerine çıkması ve Keystore'un anahtarı kullanan işlemleri reddetmesidir.
  • Saldırganlar yeni bir anahtar oluşturamaz. Bunun nedeni, saldırganın kötü amaçlı kod çalıştırma şansı bulduğunda önyükleme düzeyinin 30'un üzerine çıkması ve Keystore'un bu önyükleme düzeyinde yeni bir anahtar oluşturmayı reddetmesidir. Bir saldırgan, 30. önyükleme düzeyine bağlı olmayan yeni bir anahtar oluşturursa odsign bunu reddeder.

Anahtar mağazası, önyükleme düzeyinin düzgün şekilde uygulanmasını sağlar. Aşağıdaki bölümlerde, bu işlemin farklı Keymaster sürümlerinde nasıl yapıldığı hakkında daha ayrıntılı bilgi verilmektedir.

Keymaster 4.0 uygulaması

Keymaster'ın farklı sürümleri, önyükleme aşaması anahtarlarının uygulanmasını farklı şekilde yönetir. Keymaster 4.0 TEE/Strongbox'un yüklü olduğu cihazlarda Keymaster, uygulamayı aşağıdaki şekilde yönetir:

  1. Keystore, ilk açılışta MAX_USES_PER_BOOT etiketi 1 olarak ayarlanmış bir simetrik anahtar K0 oluşturur. Bu, anahtarın her önyükleme için yalnızca bir kez kullanılabileceği anlamına gelir.
  2. Açılış sırasında açılış seviyesi artırılırsa HKDF işlevi kullanılarak K0'dan bu açılış seviyesi için yeni bir anahtar oluşturulabilir: Ki+i=HKDF(Ki, "some_fixed_string"). Örneğin, 0. önyükleme seviyesinden 10. önyükleme seviyesine geçerseniz HKDF, K0'dan K10'u türetmek için 10 kez çağrılır.
  3. Önyükleme seviyesi değiştiğinde önceki önyükleme seviyesinin anahtarı bellekten silinir ve önceki önyükleme seviyeleriyle ilişkili anahtarlar artık kullanılamaz.

    K0 anahtarı bir MAX_USES_PER_BOOT=1 anahtarıdır. Bu, her zaman en az bir önyükleme seviyesi geçişi (nihai önyükleme seviyesine) gerçekleştiği için bu anahtarın önyüklemenin ilerleyen aşamalarında da kullanılamaması anlamına gelir.

odsign gibi bir Keystore istemcisi, i önyükleme düzeyinde bir anahtar oluşturulmasını istediğinde, blob'u Ki anahtarıyla şifrelenir. Ki, i önyükleme seviyesinden sonra kullanılamadığından bu anahtar daha sonraki önyükleme aşamalarında oluşturulamaz veya şifresi çözülemez.

Keymaster 4.1 ve KeyMint 1.0 uygulaması

Keymaster 4.1 ve KeyMint 1.0 uygulamaları büyük ölçüde Keymaster 4.0 uygulamasıyla aynıdır. Temel fark, K0'nun MAX_USES_PER_BOOT anahtarı değil, Keymaster 4.1'de kullanıma sunulan EARLY_BOOT_ONLY anahtarı olmasıdır. EARLY_BOOT_ONLY anahtarı yalnızca güvenilmeyen kod çalıştırılmadığında, önyüklemenin ilk aşamalarında kullanılabilir. Bu, ek bir koruma düzeyi sağlar: Keymaster 4.0 uygulamasında, dosya sistemini ve SELinux'u tehlikeye atan bir saldırgan, yapıları imzalamak için kendi MAX_USES_PER_BOOT=1 anahtarını oluşturmak üzere Keystore veritabanını değiştirebilir. EARLY_BOOT_ONLY anahtarları yalnızca erken önyükleme sırasında oluşturulabildiği için Keymaster 4.1 ve KeyMint 1.0 uygulamalarında bu tür bir saldırı mümkün değildir.

Güvenilir imzalama anahtarlarının herkese açık bileşeni

odsign, imzalama anahtarının ortak anahtar bileşenini Keystore'dan alır. Ancak Keystore, bu ortak anahtarı ilgili özel anahtarı barındıran TEE/SE'den almaz. Bunun yerine, ortak anahtarı kendi disk üzerindeki veritabanından alır. Bu, dosya sisteminin güvenliğini ihlal eden bir saldırganın, anahtar deposu veritabanını, kontrolü altındaki bir ortak/özel anahtar çiftinin parçası olan bir ortak anahtar içerecek şekilde değiştirebileceği anlamına gelir.

odsign, bu saldırıyı önlemek için imza anahtarıyla aynı önyükleme düzeyine sahip ek bir HMAC anahtarı oluşturur. Ardından, imza anahtarını oluştururken odsign, bu HMAC anahtarını kullanarak ortak anahtarın imzasını oluşturur ve bu imzayı diskte depolar. Sonraki önyüklemelerde, imzalama anahtarının ortak anahtarı alınırken diskteki imzanın, alınan ortak anahtarın imzasıyla eşleştiğini doğrulamak için HMAC anahtarı kullanılır. Eşleşirse HMAC anahtarı yalnızca erken önyükleme seviyelerinde kullanılabildiğinden ve bu nedenle bir saldırgan tarafından oluşturulamayacak olduğundan ortak anahtar güvenilirdir.