Schema di firma APK v3

Android 9 supporta la rotazione della chiave APK , che offre alle app la possibilità di modificare la chiave di firma come parte di un aggiornamento APK. Per rendere pratica la rotazione, gli APK devono indicare i livelli di fiducia tra la nuova e la vecchia chiave di firma. Per supportare la rotazione delle chiavi, abbiamo aggiornato lo schema di firma APK da v2 a v3 per consentire l'utilizzo delle chiavi nuove e vecchie. V3 aggiunge informazioni sulle versioni SDK supportate e una struttura di prova di rotazione al blocco di firma dell'APK.

Blocco firma APK

Per mantenere la retrocompatibilità con il formato APK v1, le firme APK v2 e v3 vengono archiviate all'interno di un blocco firme APK, situato immediatamente prima della directory centrale ZIP.

Il formato del blocco firma APK v3 è lo stesso di v2 . La firma v3 dell'APK è archiviata come coppia valore ID con ID 0xf05368c0.

APK Signature Scheme v3 Block

Lo schema v3 è progettato per essere molto simile allo schema v2 . Ha lo stesso formato generale e supporta gli stessi ID algoritmo di firma , dimensioni chiave e curve EC.

Tuttavia, lo schema v3 aggiunge informazioni sulle versioni SDK supportate e sulla struttura della prova di rotazione.

Formato

Il blocco APK Signature Scheme v3 è memorizzato all'interno del blocco di firma APK con ID 0xf05368c0 .

Il formato del blocco APK Signature Scheme v3 segue quello della v2:

  • sequenza con prefisso di lunghezza del signer prefisso di lunghezza:
    • signed data prefisso di lunghezza:
      • sequenza con prefisso di lunghezza di digests prefisso di lunghezza:
        • signature algorithm ID (4 byte)
        • digest (prefisso di lunghezza)
      • sequenza con prefisso di lunghezza dei certificates X.509:
        • certificate X.509 con prefisso di lunghezza (modulo ASN.1 DER)
      • minSDK (uint32): questo firmatario deve essere ignorato se la versione della piattaforma è inferiore a questo numero.
      • maxSDK (uint32): questo firmatario deve essere ignorato se la versione della piattaforma è superiore a questo numero.
      • Sequenza con prefisso di lunghezza di additional attributes prefisso di lunghezza:
        • ID (uint32)
        • value (lunghezza variabile: lunghezza dell'attributo aggiuntivo - 4 byte)
        • ID - 0x3ba06f8c
        • value - prova di rotazione
    • minSDK (uint32) - duplicato del valore minSDK nella sezione dei dati firmati - utilizzato per saltare la verifica di questa firma se la piattaforma corrente non è nell'intervallo. Deve corrispondere al valore dei dati con segno.
    • maxSDK (uint32) - duplicato del valore maxSDK nella sezione dei dati firmati - utilizzato per saltare la verifica di questa firma se la piattaforma corrente non è nell'intervallo. Deve corrispondere al valore dei dati con segno.
    • Sequenza di signatures prefisso di lunghezza:
      • signature algorithm ID (uint32)
      • signature prefisso di lunghezza sui signed data
    • public key prefisso di lunghezza (SubjectPublicKeyInfo, modulo ASN.1 DER)

Strutture a prova di rotazione e auto-fidate di vecchi certificati

La struttura della prova di rotazione consente alle app di ruotare il proprio certificato di firma senza essere bloccate su altre app con cui comunicano. A tale scopo, le firme delle app contengono due nuove parti di dati:

  • affermazione per terze parti secondo cui il certificato di firma dell'app può essere considerato attendibile ovunque sia attendibile il suo predecessore
  • i certificati di firma più vecchi dell'app di cui l'app stessa si fida ancora

L'attributo di prova di rotazione nella sezione dei dati firmati è costituito da un elenco collegato singolarmente, con ogni nodo contenente un certificato di firma utilizzato per firmare le versioni precedenti dell'app. Questo attributo ha lo scopo di contenere le strutture dati concettuali della prova di rotazione e dei vecchi certificati auto-affidabili. L'elenco è ordinato per versione con il certificato di firma più vecchio corrispondente al nodo radice. La struttura dei dati della prova di rotazione è costruita facendo in modo che il certificato in ogni nodo firmi il successivo nell'elenco, e quindi impregnando ogni nuova chiave con la prova che dovrebbe essere affidabile come le chiavi più vecchie.

La struttura dati self-trusted-old-certs viene costruita aggiungendo flag a ciascun nodo che ne indicano l'appartenenza e le proprietà nel set. Ad esempio, potrebbe essere presente un flag che indica che il certificato di firma in un determinato nodo è considerato attendibile per l'ottenimento delle autorizzazioni di firma Android. Questo flag consente ad altre app firmate dal certificato precedente di ricevere ancora un'autorizzazione di firma definita da un'app firmata con il nuovo certificato di firma. Poiché l'intero attributo di prova di rotazione risiede nella sezione dei dati firmati del campo signer v3, è protetto dalla chiave utilizzata per firmare l'apk che lo contiene.

Questo formato preclude più chiavi di firma e la convergenza di diversi certificati di firma antenati in uno (più nodi iniziali in un sink comune).

Formato

La prova di rotazione è archiviata nel blocco APK Signature Scheme v3 con ID 0x3ba06f8c . Il suo formato è:

  • sequenza con prefisso di lunghezza di levels prefisso di lunghezza:
    • signed data prefisso di lunghezza (dal certificato precedente - se esiste)
      • certificate X.509 con prefisso di lunghezza (modulo ASN.1 DER)
      • signature algorithm ID (uint32) - algoritmo utilizzato dal certificato nel livello precedente
    • flags (uint32) - flag che indicano se questo certificato deve essere o meno nella struttura self-trusted-old-certs e per quali operazioni.
    • signature algorithm ID (uint32): deve corrispondere a quello della sezione dei dati firmati nel livello successivo.
    • signature prefisso di lunghezza sopra i signed data sopra

Certificati multipli

Android attualmente considera un APK firmato con più certificati come avente un'identità di firma univoca separata dai certificati che lo compongono. Pertanto, l'attributo di prova di rotazione nella sezione dei dati con segno forma un grafo aciclico diretto, che potrebbe essere meglio visto come un elenco collegato singolarmente, con ciascun insieme di firmatari per una data versione che rappresenta un nodo. Ciò aggiunge ulteriore complessità alla struttura della prova di rotazione (versione multi-firmatario di seguito). In particolare, l'ordinazione diventa una preoccupazione. Inoltre, non è più possibile firmare gli APK in modo indipendente, perché la struttura della prova di rotazione deve avere i vecchi certificati di firma che firmano il nuovo set di certificati, anziché firmarli uno per uno. Ad esempio, un APK firmato dalla chiave A che desidera essere firmato da due nuove chiavi B e C non potrebbe avere il firmatario B semplicemente includere una firma di A o B, perché si tratta di un'identità di firma diversa da B e C. Ciò sarebbe significa che i firmatari devono coordinarsi prima di costruire una struttura del genere.

Attributo di prova di rotazione firmatari multipli

  • sequenza con prefisso di lunghezza di sets prefisso di lunghezza:
    • signed data con segno (dal set precedente - se esiste)
      • sequenza di certificates prefisso per lunghezza
        • certificate X.509 con prefisso di lunghezza (modulo ASN.1 DER)
      • Sequenza di signature algorithm IDs di signature algorithm IDs (uint32): uno per ogni certificato del set precedente, nello stesso ordine.
    • flags (uint32) - flag che indicano se questo insieme di certificati deve essere o meno nella struttura self-trusted-old-certs e per quali operazioni.
    • Sequenza di signatures prefisso di lunghezza:
      • signature algorithm ID (uint32): deve corrispondere a quello della sezione dei dati firmati
      • signature prefisso di lunghezza sopra i signed data sopra

Più antenati nella struttura della prova di rotazione

Lo schema v3 inoltre non gestisce due chiavi diverse che ruotano sulla stessa chiave di firma per la stessa app. Ciò è diverso dal caso di un'acquisizione, in cui la società acquirente vorrebbe spostare l'app acquisita per utilizzare la sua chiave di firma per condividere le autorizzazioni. L'acquisizione è vista come un caso d'uso supportato perché la nuova app si distinguerebbe per il nome del pacchetto e potrebbe contenere la propria struttura di prova di rotazione. Il caso non supportato, della stessa app con due percorsi diversi per arrivare allo stesso certificato, rompe molte delle ipotesi fatte nel design della rotazione delle chiavi.

Verifica

In Android 9 e versioni successive, gli APK possono essere verificati in base allo schema di firma APK v3, schema v2 o schema v1. Le piattaforme più vecchie ignorano le firme v3 e provano a verificare le firme v2, quindi v1.

Processo di verifica della firma APK

Figura 1. Processo di verifica della firma APK

Verifica APK Signature Scheme v3

  1. Individua il blocco firme APK e verifica che:
    1. Due campi di dimensione del blocco firma APK contengono lo stesso valore.
    2. ZIP Central Directory è immediatamente seguito dal record ZIP End of Central Directory.
    3. La fine della directory centrale ZIP non è seguita da altri dati.
  2. Individua il primo blocco APK Signature Scheme v3 all'interno del blocco di firma APK. Se è presente il blocco v3, vai al passaggio 3. In caso contrario, torna alla verifica dell'APK utilizzando lo schema v2 .
  3. Per ogni signer nel blocco APK Signature Scheme v3 con una versione SDK minima e massima compresa nell'intervallo della piattaforma corrente:
    1. Scegli l' signature algorithm ID più forte supportato dalle signatures . L'ordinamento della forza dipende da ciascuna implementazione / versione della piattaforma.
    2. Verificare la signature corrispondente dalle signatures rispetto ai signed data utilizzando public key . (Ora è sicuro analizzare i signed data .)
    3. Verificare che le versioni minime e massime dell'SDK nei dati firmati corrispondano a quelle specificate per il signer .
    4. Verificare che l'elenco ordinato degli ID degli algoritmi di firma nei digests e nelle signatures sia identico. (Questo serve per evitare la rimozione / aggiunta della firma.)
    5. Calcola il digest dei contenuti APK utilizzando lo stesso algoritmo digest dell'algoritmo digest utilizzato dall'algoritmo di firma.
    6. Verificare che il digest calcolato sia identico al digest corrispondente dai digests .
    7. Verificare che SubjectPublicKeyInfo del primo certificate di certificates sia identico alla public key .
    8. Se l'attributo di prova di rotazione esiste per il signer verificare che la struttura sia valida e che questo signer sia l'ultimo certificato nell'elenco.
  4. La verifica ha esito positivo se è stato trovato esattamente un signer nel raggio della piattaforma corrente e il passaggio 3 è riuscito per quel signer .

Validazione

Per verificare che il tuo dispositivo supporti correttamente v3, esegui i test PkgInstallSignatureVerificationTest.java CTS in cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ .