Estoy aprendiendo sobre la protección dm-verity de Android y trato de entender cómo utiliza dm-verity de Android el árbol hash para la validación de "bloque único".
https://source.android.com/security/verifiedboot/dm-verity dice:
En lugar de ello, dm-verity verifica bloques individualmente y solo cuando cada uno es accedido. Cuando se lee en memoria, el bloque se hashea en paralelo. El hash es verificado luego en el árbol. Y dado que leer el bloque es una operación costosa, la latencia introducida por esta verificación a nivel de bloque es comparativamente nominal.
Después de que el bloque es leído y hasheado, se verifica en el árbol. Pero ¿cómo puedo verificar el hash root, cuando no he leído todos los bloques?? Solo puedo verificar la parte del árbol que he leído, y eso significa que no tengo que llegar hasta el hash root.
No entiendo por qué usamos un árbol hash. La publicación en StackOverflow dice que la razón principal para usar árboles hash es cuando se calcula el hash para cada bloque y luego para el archivo completo nuevamente, no entiendo por qué se usa aquí.
Entonces ¿cómo se implementa en realidad?? Mi suposición es que cuando el bloque se carga en la memoria, Android simplemente verifica la rama particular y el resto de los valores se toman del árbol hash precalculado. Pero luego no veo la razón para usar el árbol. Solo almacenaría los valores hash de bloque y después de leer el bloque y hashear, compararía solo el hash.
¡Editemos: Supongamos esta implementación:
- dividir todo el dispositivo de bloque en bloques de tamaño 4K.
- hashear cada bloque en particular y concatenar los hashes (crear la capa 0 de dm-verity)
- almacenar los hashes (capa 0) al final del dispositivo de bloque Ahora, cuando quiero verificar el bloque 4K cargado en la memoria, encuentro la posición del bloque y comparo el hash del bloque cargado con el hash almacenado.
En situaciones como esta tiene sentido usar un árbol, porque solo tienes disponible la root de Merkle, pero en Android, tenemos el árbol completo, entonces ¿por qué no usar solo la capa 0 (implementación anterior) y descartar el resto?
Y mientras escribo, creo que he llegado a una respuesta. Android almacena todo el árbol hash al final. Pero el árbol no está firmado, solo la tabla dm-verity (metadatos) que contiene el hash root. Entonces, en mi implementación, tendría que firmar toda la capa 0. Y eso probablemente sea un desperdicio de recursos, así que es mejor usar el árbol.