Schema di firma APK v4

Android 11 supporta uno schema di firma compatibile con lo streaming con APK Signature Scheme v4. La firma v4 si basa sull'hash tree Merkle calcolato su tutti i byte dell'APK. Segue esattamente la struttura dell'albero hash fs-verity (ad esempio, zero-riempimento del sale e zero-riempimento dell'ultimo blocco). Android 11 memorizza la firma in un file separato, <apk name>.apk.idsig Una firma v4 richiede una firma v2 o v3 complementare.

Formato del file

Tutti i campi numerici sono in little endian. Tutti i campi occupano esattamente il numero di byte della loro dimensione di sizeof() , nessun riempimento o allineamento implicito aggiunto.

Di seguito è una struttura di supporto per semplificare le definizioni.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Contenuto del file principale:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info sono i parametri usati per la generazione di hash tree + l'hash di root:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info è la seguente struttura:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • apk_digest è preso dal blocco di firma v3 apk_digest o, se non presente, dal blocco v2 (vedi apk_digest )

Per creare e verificare un codice di signature , è necessario serializzare i seguenti dati in un BLOB binario e passarli all'algoritmo di firma / verifica come dati firmati :

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_tree è l' intero albero Merkle merkle_tree , calcolato come descritto nella documentazione di fs-verity .

Produttori e consumatori

apksigner strumento Android SDK di apksigner ora genera il file della firma v4 se lo esegui con i parametri predefiniti. La firma v4 può essere disabilitata allo stesso modo degli altri schemi di firma. Può anche verificare se la firma v4 è valida.

adb aspetta che il file .apk.idsig sia presente accanto a .apk durante l'esecuzione del comando adb install --incremental
Utilizzerà anche il file .idsig per provare l'installazione incrementale per impostazione predefinita e tornerà a un'installazione normale se mancante o non valida.

Quando viene creata una sessione di installazione, la nuova API di installazione di streaming nel PackageInstaller accetta la spogliato firma v4 come un argomento separato quando si aggiunge un file alla sessione. A questo punto, signing_info viene passato a incfs come un intero blob. Incfs estrae l'hash della radice dal BLOB.

Quando viene eseguito il commit della sessione di installazione, PackageManagerService esegue un ioctl per recuperare il blob signing_info da incfs, lo analizza e verifica la firma.

Si prevede che il componente Caricatore dati incrementale trasmetta in streaming la parte dell'albero Merkle della firma attraverso l'API nativa del caricatore dati.
package comando della shell del servizio package install-incremental accetta il file della firma v4 spogliato codificato come base64 come parametro per ogni file aggiunto. L'albero Merkle corrispondente deve essere inviato nello stdin del comando.

apk_digest

apk_digest è il primo digest di contenuti disponibile in ordine:

  1. V3, blocco da 1 MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, blocco 4KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, blocco da 1 MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. V2, SHA2-256.

Vedere la sequenza con prefisso di lunghezza delle firme con prefisso di lunghezza nello schema di firma APK v3.

processo di convalida apk v4
Figura 1 : processo di convalida APK v4

Validazione e test

Convalidare l'implementazione utilizzando Feature Unit Tests e CTS.

  • CtsIncrementalInstallHostTestCases
    • / android / cts / hostsidetests / incrementalinstall

Verifica del formato della firma

Per testare il formato della firma, configurare un ambiente di sviluppo ed eseguire i seguenti test manuali:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Test del formato della firma con Android SDK (ADB e apksigner)

Per testare il formato della firma con Android SDK, configura un ambiente di sviluppo e assicurati di aver completato l'implementazione di IncFS . Quindi esegui il flash della build su un dispositivo fisico o un emulatore di destinazione. È necessario generare o ottenere un APK esistente e quindi creare una chiave di firma di debug . Infine, firma e installa l'apk con il formato della firma v4 dalla cartella build-tools.

Cartello

$ ./apksigner sign --ks debug.keystore game.apk

Installare

$ ./adb install game.apk

Dove si possono trovare questi test?

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java