Android 4.4 ve sonraki sürümler, blok cihazların şeffaf bütünlük kontrolünü sağlayan isteğe bağlı device-mapper-verity (dm-verity) çekirdek özelliği aracılığıyla Doğrulanmış Başlatma'yı destekler. dm-verity, root ayrıcalıklarını koruyabilen ve cihazların güvenliğini ihlal edebilecek kalıcı rootkit'lerin önlenmesine yardımcı olur. Bu özellik, Android kullanıcılarının cihazı açtıklarında cihazın en son kullanıldığındaki durumda olduğundan emin olmalarını sağlar.
Kök ayrıcalıklarına sahip Potansiyel Olarak Zararlı Uygulamalar (PHA'lar), tespit programlarından gizlenebilir ve kendilerini başka şekilde maskeleyebilir. Köklendirme yazılımı, genellikle algılayıcılardan daha ayrıcalıklı olduğu için bunu yapabilir. Bu da yazılımın algılama programlarına "yalan söylemesine" olanak tanır.
dm-verity özelliği, dosya sisteminin temel depolama katmanı olan bir blok cihaza bakmanızı ve beklenen yapılandırmayla eşleşip eşleşmediğini belirlemenizi sağlar. Bunu, şifreleme karma değeri ağacı kullanarak yapar. Her blok (genellikle 4k) için bir SHA256 karması vardır.
Karma oluşturma değerleri bir sayfa ağacında depolandığından, ağacın geri kalanını doğrulamak için yalnızca üst düzey "kök" karma oluşturma değerine güvenilmelidir. Bloklardan herhangi birini değiştirmek, kriptografik karmanın kırılmasıyla eşdeğerdir. Bu yapının tasviri için aşağıdaki şemaya bakın.

Şekil 1. dm-verity karma tablosu
Başlatma bölümüne, cihaz üreticisi tarafından harici olarak doğrulanması gereken bir ortak anahtar eklenir. Bu anahtar, ilgili karma oluşturma işleminin imzasını doğrulamak ve cihazın sistem bölümünün korunduğunu ve değiştirilmediğini onaylamak için kullanılır.
İşlem
dm-verity koruması çekirdekte bulunur. Bu nedenle, köklendirme yazılımı çekirdek başlatılmadan önce sistemi tehlikeye atarsa bu erişimi korur. Çoğu üretici, bu riski azaltmak için cihaza yerleştirilmiş bir anahtar kullanarak çekirdeği doğrular. Bu anahtar, cihaz fabrikadan çıktıktan sonra değiştirilemez.
Üreticiler bu anahtarı kullanarak ilk seviye önyükleyicideki imzayı doğrular. Bu da sonraki seviyelerdeki imzayı (uygulama önyükleyici ve nihayetinde çekirdek) doğrular. Doğrulanmış başlatma özelliğinden yararlanmak isteyen her üreticinin, çekirdeğin bütünlüğünü doğrulamak için bir yöntemi olmalıdır. Çekirdek doğrulanmışsa bir blok cihazı inceleyebilir ve monte edildiği sırada doğrulayabilir.
Bir blok cihazı doğrulamanın bir yolu, içeriğini doğrudan karma oluşturarak depolanan bir değerle karşılaştırmaktır. Ancak bir blok cihazın tamamını doğrulamaya çalışmak uzun sürebilir ve cihazın gücünün büyük bir kısmını tüketebilir. Cihazların başlatılması uzun sürer ve daha sonra kullanımdan önce pilleri önemli ölçüde tükenir.
Bunun yerine dm-verity, blokları tek tek ve yalnızca her birine erişildiğinde doğrular. Belleğe okunduğunda blok paralel olarak karma oluşturma işlemine tabi tutulur. Karma oluşturma işlemi daha sonra ağaçta doğrulanır. Ayrıca, bloğu okumak oldukça pahalı bir işlem olduğundan bu blok düzeyinde doğrulamanın neden olduğu gecikme nispeten önemsizdir.
Doğrulama başarısız olursa cihaz, bloğun okunamadığını belirten bir G/Ç hatası oluşturur. Beklenen gibi, dosya sisteminin bozulduğu görülüyor.
Uygulamalar, elde edilen veriler olmadan devam etmeyi seçebilir (ör. bu sonuçlar uygulamanın birincil işlevi için gerekli olmadığında). Ancak uygulama, veriler olmadan devam edemezse başarısız olur.
İleriye doğru hata düzeltme
Android 7.0 ve sonraki sürümler, ileri hata düzeltmesi (FEC) ile dm-verity'nin sağlamlığını artırır. AOSP uygulaması, yaygın Reed-Solomon hata düzeltme koduyla başlar ve alan yükü azaltmak ve kurtarılabilen bozuk blok sayısını artırmak için ardışık düzenleme adı verilen bir teknik uygular. FEC hakkında daha fazla bilgi için Hata Düzeltme ile Sıkı Denetimli Doğrulanmış Başlatma başlıklı makaleyi inceleyin.Uygulama
Özet
- ext4 sistem görüntüsü oluşturun.
- İlgili resim için karma ağacı oluşturun.
- Söz konusu karma ağacı için dm-verity tablosu oluşturun.
- Tablo imzası oluşturmak için bu dm-verity tablosunu imzalayın.
- Tablo imzasını ve dm-verity tablosunu Verity meta verilerine bağlayın.
- Sistem görüntüsünü, doğruluk meta verilerini ve karma ağacını birleştirin.
Karma ağacı ve dm-verity tablosunun ayrıntılı açıklaması için Chromium Projeleri - Doğrulanmış Başlatma başlıklı makaleyi inceleyin.
Karma ağacı oluşturma
Giriş bölümünde açıklandığı gibi, karma ağacı dm-verity'nin ayrılmaz bir parçasıdır. cryptsetup aracı sizin için bir karma ağacı oluşturur. Alternatif olarak, uyumlu bir sürüm burada tanımlanmıştı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>
Karma oluşturmak için sistem görüntüsü 0. katmanda 4K bloklara bölünür ve her birine bir SHA256 karması atanır. 1. katman, yalnızca bu SHA256 karmalarının 4K bloklar halinde birleştirilmesiyle oluşturulur. Bu da çok daha küçük bir resim elde edilmesini sağlar. 2. katman, 1. katmanın SHA256 karmalarıyla aynı şekilde oluşturulur.
Bu işlem, önceki katmanın SHA256 karma değerleri tek bir bloğa sığana kadar devam eder. Bu bloğun SHA256 değerini aldığınızda ağacın kök karmasına sahip olursunuz.
Karma ağacının boyutu (ve karşılık gelen disk alanı kullanımı), doğrulanmış bölümün boyutuna göre değişir. Uygulamada karma ağaçlarının boyutu genellikle küçüktür (genellikle 30 MB'tan az).
Bir katmanda, önceki katmanın karma oluşturma işlemleriyle doğal olarak tamamen doldurulmamış bir blok varsa beklenen 4K'ya ulaşmak için bu bloğu sıfırlarla doldurmanız gerekir. Bu sayede, karma ağacının kaldırılmadığını ve bunun yerine boş verilerle doldurulduğunu anlayabilirsiniz.
Karma oluşturma ağacını oluşturmak için 2. katman karmalarını 1. katman karmalarıyla, 3. katman karmalarını 2. katman karmalarıyla ve bu şekilde devam ederek birleştirin. Tüm bunları diske yazın. Bunun, kök karmasının 0. katmanına referans vermediğini unutmayın.
Özetlemek gerekirse karma ağacı oluşturmaya yönelik genel algoritma aşağıdaki gibidir:
- Rastgele bir tuz (on altılık kodlama) seçin.
- Sistem resminizi 4K bloklara ayırın.
- Her blok için (tuzlanmış) SHA256 karmasını alın.
- Bir seviye oluşturmak için bu karma oluşturma işlemlerini birleştirin
- Seviyeyi 4k blok sınırına kadar 0 ile doldurun.
- Seviyeyi karma ağacınızla birleştirin.
- Yalnızca tek bir karma oluşturana kadar önceki seviyeyi sonraki seviyenin kaynağı olarak kullanarak 2-6 arasındaki adımları tekrarlayın.
Bunun sonucunda tek bir karma oluşturma işlemi gerçekleşir. Bu karma, kök karmanızdır. Bu değer 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 cihazı (veya hedefi) ve karma ağacını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. Tabloda, blokların boyutu ve karma ağacının başlangıç konumu (özellikle, resmin başındaki blok numarası) olan hash_start da tanımlanır.
Verity hedef eşleme tablosu alanlarının ayrıntılı açıklaması için cryptsetup bölümüne bakın.
dm-verity tablosunu imzalama
Tablo imzası oluşturmak için dm-verity tablosunu imzalayın. Bir bölüm doğrulanırken önce tablo imzası doğrulanır. Bu işlem, önyükleme görüntünüzde sabit bir konumdaki bir anahtara göre yapılır. Anahtarlar genellikle sabit bir konumdaki cihazlara otomatik olarak dahil edilmek için üreticilerin derleme sistemlerine dahil edilir.
Bu imza ve anahtar kombinasyonuyla bölümü doğrulamak için:
/verity_key
adresindeki/boot
bölümüne libmincrypt uyumlu biçimde bir RSA-2048 anahtarı ekleyin. Karma ağacını doğrulamak için kullanılan anahtarın konumunu belirleyin.- İlgili girişin fstab dosyasında
fs_mgr
işaretlerineverify
ekleyin.
Tablo imzasını meta verilerle bir araya getirme
Tablo imzasını ve dm-verity tablosunu verity meta verilerine bağlayın. Meta veri bloğunun tamamı, ikinci bir imza türü eklemek veya bazı sıralamaları değiştirmek gibi genişletilebilir olması için sürümlendirilir.
Tablonun tanımlanmasına yardımcı olan her tablo meta verisi grubuyla bir sihirli sayı ilişkilendirilir. Uzunluk, ext4 sistem resmi başlığına dahil edildiğinden, verilerin içeriğini bilmeden meta verileri aramanın bir yolu sağlanır.
Bu sayede, doğrulanmamış bir bölümü doğrulamayı seçmemiş olursunuz. Bu durumda, bu sihirli numaranın olmaması doğrulama sürecini durdurur. Bu sayı 0xb001b001
değerine benzer.
Onaltılık sistemdeki bayt değerleri şunlardır:
- ilk bayt = b0
- ikinci bayt = 01
- üçüncü bayt = b0
- dördüncü bayt = 01
Aşağıdaki şemada, Verity meta verilerinin dökümü gösterilmektedir:
<magic number>|<version>|<signature>|<table length>|<table>|<padding> \-------------------------------------------------------------------/ \----------------------------------------------------------/ | | | | 32K block content
Bu tabloda söz konusu meta veri alanları açıklanmaktadır.
Tablo 1. Meta veri alanlarını doğrulama
Alan | Amaç | Boyut | Değer |
---|---|---|---|
sihirli numara | fs_mgr tarafından doğrulama kontrolü olarak kullanılır | 4 bayt | 0xb001b001 |
sürüm | Meta veri bloğunun sürümünü belirlemek için kullanılır. | 4 bayt | şu anda 0 |
signature | PKCS1.5 dolgulu biçimde tablonun imzası | 256 bayt | |
tablo uzunluğu | dm-verity tablosunun bayt cinsinden uzunluğu | 4 bayt | |
masa | Daha önce açıklanan dm-verity tablosu | tablo uzunluğu baytları | |
padding | Bu yapı, 32 bin uzunluğa kadar 0 ile doldurulur. | 0 |
dm-verity'yi optimize etme
dm-verity'den en iyi performansı elde etmek için:
- Çekirdekte, ARMv7 için NEON SHA-2 ve ARMv8 için SHA-2 uzantılarını etkinleştirin.
- Cihazınız için en iyi yapılandırmayı bulmak üzere farklı önceden okuma ve prefetch_cluster ayarlarıyla denemeler yapın.