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 dalla v2 alla 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 compatibilità con le versioni precedenti del formato APK v1, le firme APK v2 e v3 sono archiviate all'interno di un blocco firma APK, situato immediatamente prima della directory centrale ZIP.

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

Blocco schema firma APK v3

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 di prova di rotazione.

Formato

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

Il formato dell'APK Signature Scheme v3 Block segue quello della v2:

  • sequenza con prefisso di lunghezza del signer con prefisso di lunghezza:
    • signed data con prefisso di lunghezza:
      • sequenza con prefisso di lunghezza di digests con prefisso di lunghezza:
        • signature algorithm ID (4 byte)
        • digest (prefisso di lunghezza)
      • sequenza prefissata di lunghezza di 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 con prefisso di lunghezza:
        • ID (uint32)
        • value (lunghezza variabile: lunghezza dell'attributo aggiuntivo - 4 byte)
        • ID - 0x3ba06f8c
        • value - struct di 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 con prefisso di lunghezza di signatures con prefisso di lunghezza:
      • signature algorithm ID (uint32)
      • signature con lunghezza prefissata sui signed data
    • public key con prefisso di lunghezza (SubjectPublicKeyInfo, modulo ASN.1 DER)

Strutture Proof-of-rotation e self-trusted-old-certs

La struttura di prova di rotazione consente alle app di ruotare il proprio certificato di firma senza essere bloccate su altre app con cui comunicano. A tal fine, le firme delle app contengono due nuovi dati:

  • affermazione per terze parti che il certificato di firma dell'app può essere considerato attendibile ovunque siano attendibili i suoi predecessori
  • certificati di firma precedenti 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 con collegamenti singoli, 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 di dati concettuali della prova di rotazione e dei certificati vecchi di fiducia. L'elenco è ordinato per versione con il certificato di firma più vecchio corrispondente al nodo radice. La struttura dei dati di 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 quanto le chiavi più vecchie.

La struttura dati self-trusted-old-certs viene costruita aggiungendo flag a ciascun nodo che ne indica 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 è attendibile per l'ottenimento delle autorizzazioni di firma Android. Questo flag consente ad altre app firmate dal certificato precedente di ottenere ancora un'autorizzazione di firma definita da un'app firmata con il nuovo certificato di firma. Poiché l'intero attributo della prova di rotazione risiede nella sezione dei dati firmati del campo del 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 dei predecessori in uno (più nodi iniziali in un sink comune).

Formato

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

  • sequenza con prefisso di lunghezza di levels con prefisso di lunghezza:
    • signed data con prefisso di lunghezza (da certificato precedente - se esistente)
      • certificate X.509 con prefisso di lunghezza (modulo ASN.1 DER)
      • signature algorithm ID (uint32) - algoritmo utilizzato da cert 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 con lunghezza prefissata sui signed data

Certificati multipli

Attualmente Android considera un APK firmato con più certificati come se avesse un'identità di firma univoca separata dai certificati che lo compongono. Pertanto, l'attributo proof-of-rotation nella sezione dei dati con segno forma un grafo aciclico orientato, che potrebbe essere visto meglio come un elenco con collegamento singolo, con ciascun insieme di firmatari per una data versione che rappresenta un nodo. Ciò aggiunge ulteriore complessità alla struttura della prova di rotazione (versione per più firmatari di seguito). In particolare, l'ordine 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 può fare in modo che il firmatario B includa solo una firma di A o B, perché si tratta di un'identità di firma diversa da B e C. Ciò significherebbe significa che i firmatari devono coordinarsi prima di costruire tale struttura.

Attributo di prova di rotazione di più firmatari

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

Più antenati nella struttura di 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 ottenere lo stesso certificato, infrange molte delle ipotesi fatte nel progetto di rotazione delle chiavi.

Verifica

In Android 9 e versioni successive, gli APK possono essere verificati in base allo schema APK Signature Scheme v3, v2 o v1. Le piattaforme precedenti 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 dello schema di firma APK v3

  1. Individua il blocco firma APK e verifica che:
    1. Due campi di dimensioni del Blocco firma APK contengono lo stesso valore.
    2. ZIP Central Directory è immediatamente seguito dal record ZIP End of Central Directory.
    3. ZIP La fine della directory centrale non è seguita da altri dati.
  2. Individua il primo blocco APK Signature Scheme v3 all'interno del blocco 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 minima e massima dell'SDK che rientra nell'intervallo della piattaforma corrente:
    1. Scegli l' signature algorithm ID di firma più forte supportato dalle signatures . L'ordine di forza dipende da ciascuna versione di implementazione/piattaforma.
    2. Verificare la signature corrispondente dalle signatures rispetto ai signed data utilizzando public key . (Ora è sicuro analizzare signed data .)
    3. Verifica che le versioni minima e massima dell'SDK nei dati firmati corrispondano a quelle specificate per il signer .
    4. Verificare che l'elenco ordinato degli ID dell'algoritmo di firma nei digests e nelle signatures sia identico. (Questo serve per impedire 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 corrispondente digest 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 lo struct sia valido e che questo signer sia l'ultimo certificato nell'elenco.
  4. La verifica ha esito positivo se è stato trovato esattamente un signer nell'intervallo della piattaforma corrente e il passaggio 3 ha avuto esito positivo per quel signer .

Convalida

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