Android 4.4 ve üstü, blok cihazların şeffaf bütünlük kontrolünü sağlayan isteğe bağlı cihaz eşleyici-verity (dm-verity) çekirdek özelliği aracılığıyla Verified Boot'u destekler. dm-verity, kök ayrıcalıklarına sahip olabilen ve cihazları tehlikeye atabilen kalıcı rootkit'lerin önlenmesine yardımcı olur. Bu özellik, Android kullanıcılarının bir cihazı başlatırken en son kullanıldığı zamanki durumda olduğundan emin olmalarına yardımcı olur.
Kök ayrıcalıklarına sahip Potansiyel Olarak Zararlı Uygulamalar (PHA'lar), algılama programlarından gizlenebilir ve başka şekilde kendilerini maskeleyebilir. Kökleme yazılımı bunu yapabilir çünkü genellikle dedektörlerden daha ayrıcalıklıdır ve yazılımın algılama programlarına "yalan söylemesini" sağlar.
dm-verity özelliği, dosya sisteminin altında yatan depolama katmanı olan bir blok aygıtına bakmanıza ve beklenen yapılandırmasıyla eşleşip eşleşmediğini belirlemenize olanak tanır. Bunu kriptografik bir hash ağacı kullanarak yapar. Her blok için (tipik olarak 4k), bir SHA256 karması vardır.
Karma değerler bir sayfa ağacında saklandığından, ağacın geri kalanını doğrulamak için yalnızca üst düzey "kök" karmaya güvenilmelidir. Bloklardan herhangi birini değiştirme yeteneği, kriptografik karmayı kırmaya eşdeğer olacaktır. Bu yapının bir tasviri için aşağıdaki şemaya bakın.
Önyükleme bölümünde, aygıt üreticisi tarafından harici olarak doğrulanması gereken bir ortak anahtar bulunur. Bu anahtar, söz konusu hash için imzayı doğrulamak ve cihazın sistem bölümünün korunduğunu ve değişmediğini onaylamak için kullanılır.
Operasyon
dm-verity koruması çekirdekte yaşar. Bu nedenle, köklendirme yazılımı, çekirdek gelmeden önce sistemi tehlikeye atarsa, bu erişimi koruyacaktır. Çoğu üretici, bu riski azaltmak için, aygıta yazılan bir anahtar kullanarak çekirdeği doğrular. Cihaz fabrikadan çıktıktan sonra bu anahtar değiştirilemez.
Üreticiler bu anahtarı, birinci düzey önyükleyicideki imzayı doğrulamak için kullanırlar; bu da, sonraki düzeylerdeki, uygulama önyükleyicisindeki ve nihayetinde çekirdeğin imzasını doğrular. Doğrulanmış önyüklemeden yararlanmak isteyen her üretici, çekirdeğin bütünlüğünü doğrulamak için bir yönteme sahip olmalıdır. Çekirdeğin doğrulandığını varsayarsak, çekirdek bir blok aygıtına bakabilir ve monte edildiğinde onu doğrulayabilir.
Bir blok cihazını doğrulamanın bir yolu, içeriğine doğrudan hash uygulamak ve bunları saklanan bir değerle karşılaştırmaktır. Bununla birlikte, blok aygıtın tamamını doğrulamaya çalışmak uzun bir süre alabilir ve aygıtın gücünün çoğunu tüketebilir. Cihazların önyüklenmesi uzun sürer ve kullanımdan önce önemli ölçüde boşalır.
Bunun yerine dm-verity, blokları tek tek ve yalnızca her birine erişildiğinde doğrular. Belleğe okunduğunda, blok paralel olarak özetlenir. Karma daha sonra ağaçta doğrulanır. Bloğu okumak çok pahalı bir işlem olduğundan, bu blok düzeyinde doğrulamanın getirdiği gecikme nispeten nominaldir.
Doğrulama başarısız olursa, cihaz, bloğun okunamadığını belirten bir G/Ç hatası üretir. Beklendiği gibi, dosya sistemi bozulmuş gibi görünecektir.
Uygulamalar, örneğin bu sonuçların uygulamanın birincil işlevi için gerekli olmadığı durumlarda, sonuç verileri olmadan ilerlemeyi seçebilir. Ancak uygulama veri olmadan devam edemezse başarısız olur.
İleri hata düzeltmeAndroid 7.0 ve üstü, ileri hata düzeltme (FEC) ile dm-verity sağlamlığını geliştirir. AOSP uygulaması, ortak Reed-Solomon hata düzeltme koduyla başlar ve alan yükünü azaltmak ve kurtarılabilecek bozuk blok sayısını artırmak için serpiştirme adı verilen bir teknik uygular. FEC hakkında daha fazla ayrıntı için bkz. Hata Düzeltme ile Kesinlikle Zorunlu Doğrulanmış Önyükleme .
uygulama
Özet
- Bir ext4 sistem görüntüsü oluşturun.
- Bu görüntü için bir karma ağaç oluşturun .
- Bu hash ağacı için bir dm-verity tablosu oluşturun .
- Bir tablo imzası oluşturmak için bu dm-verity tablosunu imzalayın .
- Tablo imzasını ve dm-verity tablosunu verity meta verisinde bir araya getirin .
- Sistem görüntüsünü, doğrulama meta verilerini ve karma ağacı birleştirin.
Hash ağacı ve dm-verity tablosunun ayrıntılı açıklaması içinThe Chromium Projects - Verified Boot bölümüne bakın.
Hash ağacının oluşturulması
Giriş bölümünde açıklandığı gibi, hash ağacı dm-verity'nin ayrılmaz bir parçasıdır. Cryptsetup aracı sizin için bir hash ağacı oluşturacaktır. Alternatif olarak, uyumlu bir tanesi burada tanımlanır:
<your block device name> <your block device name> <block size> <block size> <image size in blocks> <image size in blocks + 8> <root hash> <salt>
Karmayı oluşturmak için sistem görüntüsü, katman 0'da her birine bir SHA256 özeti atanan 4k bloğa bölünür. Katman 1, yalnızca bu SHA256 karmalarının 4k bloklara birleştirilmesiyle oluşturulur ve çok daha küçük bir görüntü elde edilir. Katman 2, Katman 1'in SHA256 hash'leri ile aynı şekilde oluşturulur.
Bu, önceki katmanın SHA256 karmaları tek bir bloğa sığana kadar yapılır. Bu bloğun SHA256'sını aldığınızda, ağacın kök karmasına sahip olursunuz.
Karma ağacın boyutu (ve karşılık gelen disk alanı kullanımı), doğrulanan bölümün boyutuna göre değişir. Uygulamada, hash ağaçlarının boyutu küçük olma eğilimindedir, genellikle 30 MB'den azdır.
Bir katmanda bir önceki katmanın hash'leriyle tamamen doğal olarak doldurulmamış bir bloğunuz varsa, beklenen 4k'yı elde etmek için onu sıfırlarla doldurmanız gerekir. Bu, karma ağacın kaldırılmadığını ve bunun yerine boş verilerle tamamlandığını bilmenizi sağlar.
Karma ağacı oluşturmak için, katman 2 karmalarını katman 1'inkilerle, katman 3 karmalarını katman 2'ninkilerle vb. birleştirin. Bunların hepsini diskete yazın. Bunun, kök hash'in 0. katmanına referans vermediğini unutmayın.
Özetlemek gerekirse, karma ağacı oluşturmak için genel algoritma aşağıdaki gibidir:
- Rastgele bir tuz (onaltılık kodlama) seçin.
- Sistem görüntünüzü 4k bloklara bölün.
- Her blok için (tuzlu) SHA256 karmasını alın.
- Bir seviye oluşturmak için bu karmaları birleştirin
- Seviyeyi 0'larla 4k blok sınırına kadar doldurun.
- Düzeyi karma ağacınızla birleştirin.
- Yalnızca tek bir hash'iniz olana kadar bir önceki seviyeyi bir sonraki seviyenin kaynağı olarak kullanarak 2-6 arasındaki adımları tekrarlayın.
Bunun sonucu, kök karmanız olan tek bir karmadır. Bu ve tuzunuz, dm-verity eşleme tablonuzun oluşturulması sırasında kullanılır.
dm-verity eşleme tablosunu oluşturma
Çekirdek için blok aygıtını (veya hedefini) ve karma ağacın konumunu (aynı değerdir) tanımlayan dm-verity eşleme tablosunu oluşturun. Bu eşleme,
fstab oluşturma ve önyükleme için kullanılır. Tablo ayrıca blokların boyutunu ve karma ağacın başlangıç konumu olan hash_start'ı da tanımlar (özellikle, görüntünün başlangıcından itibaren blok numarası).
Doğruluk hedefi eşleme tablosu alanlarının ayrıntılı açıklaması için cryptsetup'a bakın.
dm-verity tablosunu imzalama
Bir tablo imzası oluşturmak için dm-verity tablosunu imzalayın. Bir bölümü doğrularken, önce tablo imzası doğrulanır. Bu, önyükleme görüntünüzdeki sabit bir konumdaki bir tuşa karşı yapılır. Anahtarlar, sabit bir konumdaki cihazlara otomatik olarak dahil edilmek üzere genellikle üreticilerin yapı sistemlerine dahil edilir.
Bölümü bu imza ve tuş bileşimi ile doğrulamak için:
-
/verity_keykonumunda
/bootbölümüne libmincrypt uyumlu biçimde bir RSA-2048 anahtarı ekleyin. Hash ağacını doğrulamak için kullanılan anahtarın konumunu tanımlayın.
- İlgili giriş için fstab'ta,
fs_mgrişaretlerine
verifyekleyin.
Tablo imzasını meta verilere gruplama
Tablo imzasını ve dm-verity tablosunu verity meta verisinde bir araya getirin. Tüm meta veri bloğu, ikinci bir tür imza eklemek veya bazı sıralamayı değiştirmek gibi genişletilebilecek şekilde sürümlendirilir.
Akıl sağlığı kontrolü olarak, tablonun tanımlanmasına yardımcı olan her bir tablo meta verisi grubuyla sihirli bir sayı ilişkilendirilir. Uzunluk, ext4 sistem görüntü başlığına dahil edildiğinden, bu, verilerin içeriğini bilmeden meta verileri aramak için bir yol sağlar.
Bu, doğrulanmamış bir bölümü doğrulamayı seçmediğinizden emin olmanızı sağlar. Eğer öyleyse, bu sihirli sayının olmaması doğrulama sürecini durduracaktır. Bu sayı şuna benzer:
0xb001b001
Onaltılı bayt değerleri şunlardır:
- ilk bayt = b0
- ikinci bayt = 01
- üçüncü bayt = b0
- dördüncü bayt = 01
Aşağıdaki diyagram, verity meta verilerinin dökümünü göstermektedir:
<magic number>|<version>|<signature>|<table length>|<table>|<padding> \-------------------------------------------------------------------/ \----------------------------------------------------------/ | | | | 32K block content
Ve bu tablo, bu meta veri alanlarını açıklar.
|Alan||Amaç||Boyut||Değer|
|sihirli sayı||fs_mgr tarafından akıl sağlığı kontrolü olarak kullanılır||4 bayt||0xb001b001|
|sürüm||meta veri bloğunu sürümlendirmek için kullanılır||4 bayt||şu anda 0|
|imza||PKCS1.5 dolgulu formda tablonun imzası||256 bayt|
|masa uzunluğu||bayt cinsinden dm-verity tablosunun uzunluğu||4 bayt|
|masa||daha önce açıklanan dm-verity tablosu||tablo uzunluğu bayt|
|dolgu malzemesi||bu yapı 0 dolgulu ila 32k uzunluğundadır||0|
dm-verity'yi optimize etme
dm-verity'den en iyi performansı almak için şunları yapmalısınız:
- Çekirdekte, ARMv7 için NEON SHA-2'yi ve ARMv8 için SHA-2 uzantılarını açın.
- Cihazınız için en iyi yapılandırmayı bulmak için farklı ileri okuma ve prefetch_cluster ayarlarıyla denemeler yapın.