Schema di firma dell'APK v3

Android 9 supporta la rotazione della chiave dell'APK, che consente alle app di modificare la chiave di firma nell'ambito di un aggiornamento dell'APK. Per rendere pratica la rotazione, gli APK devono indicare i livelli di affidabilità tra la nuova e la vecchia chiave di firma. Per supportare la rotazione delle chiavi, abbiamo aggiornato lo schema di firma dell'APK dalla versione 2 alla versione 3 per consentire l'utilizzo delle chiavi nuove e precedenti. La versione 3 aggiunge informazioni sulle versioni dell'SDK supportate e una struttura di prova della rotazione al blocco di firma dell'APK.

Blocco di firma dell'APK

Per mantenere la compatibilità con il formato APK v1, le firme APK v2 e v3 vengono memorizzate in un blocco di firma APK, situato immediatamente prima del directory centrale ZIP.

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

Blocco dello schema di firma dell'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, le stesse dimensioni delle chiavi e le stesse curve EC.

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

Formato

Il blocco dello schema di firma dell'APK v3 è archiviato all'interno del blocco di firma dell'APK nell'ID 0xf05368c0.

Il formato del blocco dello schema di firma dell'APK v3 segue quello della versione 2:

  • sequenza con prefisso di lunghezza di 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 di X.509 certificates:
        • X.509 con prefisso di lunghezza certificate (formato 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 proof-of-rotation
    • minSDK (uint32) - duplicato del valore minSDK nella sezione dei dati firmati - utilizzato per saltare la verifica di questa firma se la piattaforma corrente non rientra 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 di signatures con prefisso di lunghezza:
      • signature algorithm ID (uint32)
      • signature con prefisso di lunghezza su signed data
    • con prefisso di lunghezza public key (SubjectPublicKeyInfo, formato ASN.1 DER)

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

La struttura della prova della rotazione consente alle app di ruotare la propria firma senza essere bloccate su altre app con cui comunicano. Per farlo, le firme delle app contengono due nuovi dati:

  • affermazione per terze parti che il certificato di firma dell'app può essere considerato attendibile se i suoi predecessori sono considerati attendibili
  • le vecchie credenziali di firma dell'app che l'app stessa considera ancora attendibili

L'attributo proof-of-rotation nella sezione dei dati firmati è costituito da un elenco con un solo collegamento, in cui ogni nodo contiene un certificato di firma utilizzato per firmare le versioni precedenti dell'app. Questo attributo è destinato a contenere le strutture di dati concettuali proof-of-rotation e self-trusted-old-certs. L'elenco è ordinato per versione con il certificato di firma più antico corrispondente al nodo principale. La struttura di dati della prova della rotazione viene creata facendo in modo che il certificato in ogni nodo firme quello successivo nell'elenco e, di conseguenza, fornisca a ogni nuova chiave la prova che deve essere considerata attendibile quanto le chiavi precedenti.

La struttura di dati self-trusted-old-certs viene creata aggiungendo flag a ogni nodo che ne indicano l'appartenenza e le proprietà nell'insieme. 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 di 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 v3signer, è protetto dalla chiave utilizzata per firmare l'APK contenente.

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

Formato

La prova di rotazione è memorizzata all'interno del blocco dello schema di firma dell'APK v3 con ID 0x3ba06f8c. Il formato è il seguente:

  • sequenza con prefisso di lunghezza di levels con prefisso di lunghezza:
    • signed data con prefisso di lunghezza (dall'apposito certificato, se esistente)
      • X.509 con prefisso di lunghezza certificate (formato ASN.1 DER)
      • signature algorithm ID (uint32) - algoritmo utilizzato dal certificato nel livello precedente
    • flags (uint32) - flag che indica se questo certificato deve o meno essere 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.
    • lunghezza con prefisso signature rispetto a quanto sopra signed data

Più certificati

Non sono supportati più firmatari e Google Play non pubblica app firmate con più certificati.

Verifica

In Android 9 e versioni successive, gli APK possono essere verificati in base allo schema di firma dell'APK v3, v2 o v1. Le piattaforme meno recenti ignorano le firme v3 e tentano di verificare le firme v2 e poi v1.

Procedura di verifica della firma dell'APK

Figura 1. Procedura di verifica della firma dell'APK

Verifica dello schema di firma dell'APK v3

  1. Individua il blocco di firma dell'APK e verifica che:
    1. Due campi di dimensioni del blocco di firma dell'APK contengono lo stesso valore.
    2. Il Directory centrale ZIP è immediatamente seguito dal record Fine directory centrale ZIP.
    3. La fine del directory centrale ZIP non è seguita da altri dati.
  2. Individua il primo blocco dello schema di firma dell'APK v3 all'interno del blocco di firma dell'APK. Se il blocco v3 è presente, vai al passaggio 3. In caso contrario, torna alla verifica dell'APK utilizzando lo schema v2.
  3. Per ogni signer nel blocco dello schema di firma APK v3 con una versione minima e massima dell'SDK compresa nell'intervallo della piattaforma corrente:
    1. Scegli il signature algorithm ID più potente supportato da signatures. L'ordine di importanza dipende da ogni implementazione/versione della piattaforma.
    2. Verifica il signature corrispondente da signatures rispetto a signed data utilizzando public key. Ora è possibile analizzare signed data.
    3. Verifica che le versioni minime e massime dell'SDK nei dati firmati corrispondano a quelle specificate per signer.
    4. Verifica che l'elenco ordinato degli ID degli algoritmi di firma in digests e signatures sia identico. (Questo è per impedire la rimozione/l'aggiunta della firma).
    5. Calcola il digest dei contenuti dell'APK utilizzando lo stesso algoritmo di digest utilizzato dall'algoritmo di firma.
    6. Verifica che il digest calcolato sia identico al corrispondente digest di digests.
    7. Verifica che SubjectPublicKeyInfo del primo certificate di certificates sia identico a public key.
    8. Se l'attributo proof-of-rotation esiste per signer, verifica che la struttura sia valida e che signer sia l'ultimo certificato nell'elenco.
  4. La verifica è riuscita se è stato trovato esattamente un signer nell'intervallo della piattaforma corrente e il passaggio 3 è andato a buon fine per quel signer.

Convalida

Per verificare che il tuo dispositivo supporti correttamente la versione 3, esegui i PkgInstallSignatureVerificationTest.javatest CTS incts/hostsidetests/appsecurity/src/android/appsecurity/cts/.