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. La 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 vengono archiviate all'interno di un blocco di firma APK, situato immediatamente prima della directory centrale ZIP.

Il formato del blocco firma APK v3 è uguale a quello v2 . La firma v3 dell'APK viene archiviata come coppia ID-valore con ID 0xf05368c0.

Blocco v3 dello schema di firma APK

Lo schema v3 è progettato per essere molto simile allo schema v2 . Ha lo stesso formato generale e supporta gli stessi ID dell'algoritmo di firma , dimensioni delle chiavi 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 nel blocco firma APK con ID 0xf05368c0 .

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

  • sequenza con prefisso di lunghezza 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 (con prefisso di lunghezza)
      • sequenza con prefisso di lunghezza dei certificates X.509:
        • certificate X.509 con prefisso di lunghezza (modulo DER ASN.1)
      • 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 - Struttura prova di rotazione
    • minSDK (uint32) - duplicato del valore minSDK nella sezione dati firmati - utilizzato per saltare la verifica di questa firma se la piattaforma corrente non è nell'intervallo. Deve corrispondere al valore dei dati firmati.
    • 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 firmati.
    • sequenza con prefisso di lunghezza signatures con prefisso di lunghezza:
      • signature algorithm ID (uint32)
      • signature con prefisso di lunghezza sui signed data
    • public key con prefisso di lunghezza (SubjectPublicKeyInfo, modulo ASN.1 DER)

Strutture di prova di rotazione e vecchi certificati affidabili

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 tale scopo, 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
  • i certificati di firma più vecchi dell'app di cui l'app stessa si fida ancora

L'attributo proof-of-rotation nella sezione Signed-Data è costituito da un elenco collegato singolarmente, in cui ciascun nodo contiene un certificato di firma utilizzato per firmare versioni precedenti dell'app. Questo attributo è destinato a contenere le strutture dati concettuali della prova di rotazione e dei vecchi certificati auto-attendibili. L'elenco è ordinato per versione con il certificato di firma più vecchio corrispondente al nodo radice. La struttura dei dati di prova di rotazione viene costruita facendo in modo che il certificato in ciascun nodo firmi il successivo nell'elenco e quindi conferendo a ciascuna nuova chiave la prova che dovrebbe essere affidabile quanto le chiavi precedenti.

La struttura dati self-trust-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 su un determinato nodo è attendibile per ottenere le autorizzazioni di firma Android. Questo flag consente ad altre app firmate dal certificato precedente di continuare a ricevere un'autorizzazione di firma definita da un'app firmata con il nuovo certificato di firma. Poiché l'intero attributo proof-of-rotation risiede nella sezione dei dati firmati del campo signer v3, è protetto dalla chiave utilizzata per firmare l'apk che lo contiene.

Questo formato impedisce più chiavi di firma e la convergenza di diversi certificati di firma antenati in uno solo (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 (dal certificato precedente - se esiste)
      • certificate X.509 con prefisso di lunghezza (modulo DER ASN.1)
      • 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 con prefisso di lunghezza sui 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 prova di rotazione nella sezione dei dati con segno forma un grafico aciclico diretto, che potrebbe essere meglio visto come un elenco concatenato 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 multifirmatario di seguito). In particolare, l'ordinazione diventa una preoccupazione. Inoltre, non è più possibile firmare gli APK in modo indipendente, perché la struttura di 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 fare in modo che il firmatario B includa semplicemente 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 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 esiste)
      • sequenza di certificates con lunghezza prefissata
        • certificate X.509 con prefisso di lunghezza (modulo DER ASN.1)
      • Sequenza di signature algorithm IDs (uint32): uno per ciascun 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 signatures con prefisso di lunghezza:
      • signature algorithm ID (uint32): deve corrispondere a quello della sezione dei dati firmati
      • signature con prefisso di lunghezza sui signed data sopra

Antenati multipli 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 propria 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, in cui la stessa app ha due percorsi diversi per ottenere lo stesso certificato, infrange molti dei presupposti formulati nella progettazione della rotazione delle chiavi.

Verifica

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

  1. Individua il blocco firma APK e verifica che:
    1. Due campi dimensione 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 di firma APK. Se è presente il blocco v3, procedi al passaggio 3. Altrimenti, 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 compresa nell'intervallo della piattaforma corrente:
    1. Scegli l' signature algorithm ID supportato più potente tra signatures . L'ordine di forza dipende da ciascuna versione di implementazione/piattaforma.
    2. Verificare la signature corrispondente dalle signatures rispetto signed data utilizzando public key . (Ora è sicuro analizzare signed data .)
    3. Verificare 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 signatures sia identico. (Questo per evitare la rimozione/aggiunta di firme.)
    5. Calcola il digest dei contenuti APK utilizzando lo stesso algoritmo digest utilizzato dall'algoritmo di firma.
    6. Verificare che il digest calcolato sia identico al corrispondente digest dei digests .
    7. Verificare che ObjectPublicKeyInfo del primo certificate di certificates sia identico alla public key .
    8. Se esiste l'attributo prova di rotazione 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 nell'intervallo della piattaforma corrente e il passaggio 3 ha avuto esito positivo per quel signer .

Validazione

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