Découverte de la puce Titan M a.k.a Citadel

Magazine
Marque
MISC
Numéro
114
Mois de parution
mars 2021
Spécialité(s)


Résumé

La puce Titan M ou Citadel est une puce sécurisée sur laquelle repose en grande partie la sécurité des terminaux Android de Google, la gamme Pixel. Dans cet article, nous détaillerons le fonctionnement interne et les usages de ce composant pour lequel peu d’information publique est disponible à ce jour. Nous donnerons également plusieurs pistes pour aider le rétro-ingénieur à travailler sur ce projet.


Body

La puce Titan M (a.k.a Citadel) a été créée par Google et intégrée dans les smartphones de la gamme Pixel à compter du Pixel 3. D’après Google, cette puce améliore la sécurité de ses terminaux en réduisant leur surface d’attaque et en limitant l’impacte de vulnérabilités matérielles telles que Rowhammer ou Spectre.

Bien que la plupart des smartphones Android reposent aujourd’hui sur la ARM TrustZone pour garantir les fonctionnalités de sécurité critiques du système, Google a fait le choix, depuis le Pixel 2 avec une puce sécurisée de NXP, de s’abstraire de la TrustZone et d’utiliser une puce externe. En effet, plusieurs attaques ont démontré qu’il était possible d’extraire des secrets de la TrustZone, depuis une application Android non privilégiée via des fuites par canaux auxiliaires. On peut citer l’attaque TruSpy [1] qui permet d’extraire une clé AES de la TrustZone via une attaque sur le cache CPU.

Cette nouvelle puce utilise sa propre mémoire et son propre cache CPU, limitant ainsi l’impact de ces attaques. Elle embarque aussi plusieurs protections contre les attaques matérielles ce qui la rend résistante à la rétro-ingénierie matérielle et aux injections de fautes.

Lors de l’annonce de la puce, Google a annoncé que le firmware serait open source. Deux ans après, les sources n’ont toujours pas été publiées et ce composant reste bien mystérieux.

1. Spécification matérielle

La puce Titan M est un SoC (pour System on Chip) reposant sur un microprocesseur ARM Cortex-M3, disposant de 64 ko de RAM et d’une mémoire flash interne dont la taille reste inconnue. Elle dispose aussi d’accélération matérielle pour les algorithmes de cryptographie courants (AES, SHA, HMAC), d’un composant pour la manipulation des grands nombres, d’un générateur de nombres aléatoires, et d’un module permettant de générer et de gérer des clés cryptographiques. On note aussi la présence de protections contre les attaques matérielles telles qu’un shield (un maillage qui recouvre la puce) et des capteurs, notamment de température et de tension (Google n’a pas présenté de liste exhaustive) probablement destinés à détecter des attaques par glitch.

Cette puce peut communiquer sur plusieurs bus de données classiques. Sur le Pixel 3, le bus SPI est utilisé pour communiquer avec Android. Sur le bus UART, on va retrouver les logs ainsi qu’une console minimaliste. Le bus UART n’est pas accessible depuis Android, mais il est possible de le rediriger sur le bus USB via un câble de debug appelé SuzyQable [SUZYQ].

Le Titan M n’est pas la première puce sécurisée créée par Google. En effet, il en existe au moins une autre, le Titan H1. Ce composant a d’ailleurs été présenté par l’un de ses développeurs [2] et dispose d’une architecture matérielle très similaire à celle de Citadel. On apprend notamment qu’il dispose d’un processeur ARM SecurCore SC300, qui combine un Cortex-M3 et des fonctionnalités d’anti-tampering de la gamme ARM SecurCore. On notera d’ailleurs que ce type de processeurs est utilisé dans de nombreuses puces sécurisées du marché.

2. Usages dans Android

Le CPU principal du Pixel 3 communique avec Citadel via le bus SPI. Le pilote au niveau du noyau Linux est très simple et va envoyer les données reçues sur le périphérique /dev/citadel0 vers le bus SPI à destination de Citadel (voir partie 4).

software-arch-citadel-s

Fig. 1 : Schéma de communication entre les services HAL d’Android et Citadel

Côté userland, le démon CitadelProxy gère la communication avec le pilote. Différents services HAL implémentent les fonctionnalités reposant sur Citadel. Tous ces services communiquent avec CitadelProxy via le périphérique /dev/vndbinder. La partie applicative du protocole permettant de communiquer entre un service Android et une tâche Citadel est définie avec protobuf [PROTOBUF], un outil bien connu développé par Google. La définition de ces protocoles ainsi que les sources des services HAL se trouvent dans le projet external/nos (pour NuggetOS ?) dans les sources d’Android. Ainsi le parseur de paquets est généré par protobuf, limitant les risques d’introduire une erreur dans la manipulation des données.

2.1 Format des images

Sur le Pixel 3, Android utilise le programme citadel_updater pour mettre à jour le firmware de Citadel. On trouve d’ailleurs ce firmware dans le répertoire /vendor/firmware/citadel/ec.bin sur le téléphone. citadel_updater implémente un parseur des en-êtes du firmware, ce qui est bien utile pour comprendre comment celui-ci est structuré.

citadel_updater est aussi utilisé pour définir ou changer le mot de passe utilisateur dans Citadel. Ce mot de passe (il s’agit en réalité d’un hash dérivé du mot de passe) permet ensuite de déverrouiller des fonctionnalités du Titan, notamment les mises à jour.

La définition de l’en-tête est présente dans les sources d’Android dans le fichier external/nos/host/generic/nugget/include/signed_header.h.

typedef struct SignedHeader {
 
uint32_t magic; // -1 (thanks, boot_sys!)
uint32_t signature[96];
uint32_t img_chk_; // top 32 bit of expected img_hash
// --------------------- everything below is part of img_hash
uint32_t tag[7];   // words 0-6 of RWR/FWR
uint32_t keyid;    // word 7 of RWR
uint32_t key[96];  // public key to verify signature with
uint32_t image_size;
uint32_t ro_base;  // readonly region
uint32_t ro_max;
uint32_t rx_base;  // executable region
uint32_t rx_max;
uint32_t fusemap[FUSE_MAX / (8 * sizeof(uint32_t))];
uint32_t infomap[INFO_MAX / (8 * sizeof(uint32_t))];
uint32_t epoch_;  // word 7 of FWR
uint32_t major_;  // keyladder count
uint32_t minor_;
uint64_t timestamp_; // time of signing
uint32_t p4cl_;
[...]

Cet en-tête comporte des informations intéressantes parmi lesquelles les adresses de deux zones mémoire ro_base et rx_base ou encore la taille de l’image.

2.2 Version et dépendances du firmware

citadel_updater permet aussi de récupérer différentes informations du firmware du Titan M telles que la version du firmware, la version des images ainsi qu’une liste des dépendances logicielles du projet.

blueline:/ # /vendor/bin/hw/citadel_updater -l
Chip:   Google Citadel C2-PVT
Board:  0
RO_A:   0.0.3/d55cc99c ok
RO_B: * 0.0.3/874a9517 ok
 0.0.3/brick_v0.0.8164-97b23b2e4 ok
RW_B: * 0.0.3/brick_v0.0.8232-b1e3ea340 ok

On apprend notamment que la bibliothèque nanopb [NANOPB] est utilisée pour générer des parseurs à partir de définitions protobuf.

2.3 Format de la mémoire flash

Les sources d’Android comportent aussi des informations sur l’organisation de la flash interne dans le fichier external/nos/host/generic/nugget/include/flash_layout.h.

flash layout-s 0

Fig. 2 : Schéma de l’agencement de la mémoire flash interne du Titan M.
Comme pour la plupart des microcontrôleurs, le code est exécuté directement depuis la mémoire flash. En effet, plusieurs périphériques (la mémoire flash, la RAM, mais aussi les contrôleurs USB, UART et autres) sont mappés sur l’espace mémoire et peuvent être accédés directement par leur adresse.

Ainsi, un firmware comporte quatre images, deux de type RO et deux de type RW, chacune comportant un SignedHeader. Les images RO contiennent le bootloader chargé de vérifier puis de démarrer l’OS principal contenu dans les images RW. Il existe deux versions de chaque image, une version A et une version B. C’est le résultat de l’implémentation des mises à jour de type « A / B », permettant de mettre à jour le système sans coupure que l’on trouve aussi dans Android ou ChromeOS. Après analyse, il apparaît que le fichier de firmware ec.bin comporte ces quatre images et respecte le formatage de la mémoire flash.

Dans la description de la flash interne, il est aussi question de zones appelées Certs et Provisioning data que l'on ne trouve pas dans les images. En effet, ces zones ne peuvent être provisionnées qu’une fois à l’aide de commandes spéciales, probablement à l’usine.

Avec ces informations, il nous est donc possible de charger le firmware aux adresses indiquées dans notre désassembleur préféré.

3. Analyse du firmware

3.1 Nugget OS

Il s’agit de l’OS principal exécuté par Citadel (présent dans les images RW). Il repose sur Chrome EC (Chromium Embedded Controller) [ECSOURCES], un OS open source pour microcontrôleur, développé par Google, aussi utilisé par le Titan H1. Dans les sources d’EC, il y a d’ailleurs la définition d’un équipement cr50 qui correspond à la puce Titan H1. Dans l’implémentation du cr50, on trouve la définition associée à une mystérieuse puce g (pour Google ?). En comparant cette implémentation avec le firmware de Citadel, on note de nombreuses similitudes, mais aussi quelques différences. Par exemple, les registres de différents contrôleurs de bus de données (UART ou USB) sont mappés à des adresses différentes en mémoire. La majorité des tâches et l’implémentation de la communication sur le bus SPI présenté plus loin ne se trouvent pas dans les sources.

Il n’y a pratiquement pas d’allocation dynamique dans EC. Une implémentation minimaliste de malloc et free repose sur un mécanisme de mémoire partagée, mais est très peu utilisé dans les sources de EC (et ne semble pas utilisé dans le Titan M).

3.2 Les interruptions

L’architecture Cortex-M3 définit un registre dédié à l’initialisation du vecteur d’interruptions. Le registre VTOR (pour Vector Table Offset Register) est mappé sur l’espace mémoire à l’adresse 0xE000ED08. On retrouve ainsi la déclaration du vecteur d’interruptions dans notre désassembleur. Dans les images étudiées, il se trouve juste après l’en-tête de chaque image.

La table des vecteurs d’interruptions commence par l’adresse initiale de la pile (0x10400 pour RW et 0x20000 pour RO), puis l’adresse du point d’entrée des routines d’exceptions dont une partie est définie par l’architecture et les autres sont définies par le fabricant de la puce. On trouve ainsi l’adresse de la routine reset qui est appelée au démarrage de la puce, et qui va initialiser le système puis appeler la fonction main.

00044400 00 04 01 00     addr      DAT_00010400            init_stack_addr
00044404 e5 47 04 00     undefine reset+1                  reset
00044408 27 48 04 00     void _fu irq_fault_handler+1      field_0x8
 0004440c 27 48 04 00    void _fu irq_fault_handler+1      field_0xc
00044410 27 48 04 00     void _fu irq_fault_handler+1      field_0x10
00044414 5d 6a 04 00     addr      bus_fault_handler+1     bus_fault
 00044418 27 48 04 00    void _fu irq_fault_handler+1      field_0x18
0004441c 00 00 00 00     addr      00000000                field_0x1c
00044420 00 00 00 00     addr      00000000                field_0x20
00044424 00 00 00 00     addr      00000000                field_0x24
00044428 00 00 00 00     addr      00000000                field_0x28
0004442c 2b 48 04 00     addr      svc_handler+1           svc_helper_h
00044430 27 48 04 00     void _fu irq_fault_handler+1      field_0x30
00044434 00 00 00 00     addr      00000000                field_0x34
00044438 27 48 04 00     void _fu irq_fault_handler+1      field_0x38
0004443c 27 48 04 00     void _fu irq_fault_handler+1      field_0x3c
00044440 b9 88 04 00     undefine uart_tx_irq_handler+1    uart_console_tx
00044444 27 48 04 00     void _fu irq_fault_handler+1      field_0x44
00044448 27 48 04 00     void _fu irq_fault_handler+1      field_0x48
0004444c dd 88 04 00     undefine uart_rx_irq_handler      uart_console_rx

Cette table comprend des interruptions pour la gestion des bus SPI, USB et UART, la gestion des boutons (les boutons physiques du Pixel sont reliés au Titan M) et d’autres encore non identifiées.

L’interruption logicielle est déclenchée via l’instruction SVC. Ce mécanisme est utilisé pour changer le contexte d’exécution en passant du mode Thread au mode Handle. Les tâches sont exécutées en mode Thread et utilisent ce mécanisme pour donner la main à l’ordonnanceur qui s’exécute donc en mode Handle. L’ordonnanceur correspond à la routine des interruptions logicielles, svc_handler dont une implémentation se trouve dans les sources d’EC (voir le fichier core/cortex-m/task.c). Avant chaque changement de contexte, il va vérifier la valeur d’un canari au pied la pile de la tâche courante.

current = current_task;
if (*current_task->stack != 0xdeadd00d) {
  iVar3 = (int)&current_task[-0xe1a].runtime >> 3;
  panic_printf("\n\nStack overflow in %s task!\n",TASK_NAMES[iVar3 * 0x36db6db7]);
  software_panic(0xdead6661,iVar3 * -0x49249249);
}

Il existe donc un stack canari dans EC. Cependant, cette protection est assez limitée : en effet, elle ne protège que d’un dépassement complet de la pile d’une tâche. Par ailleurs, la valeur du canari est fixe comme on peut le voir dans le pseudo-code ci-dessus, obtenu avec un peu de reverse.

3.3 Les tâches

La majeure partie du code est exécutée dans des tâches. Une tâche dispose de sa propre pile de taille fixe et est associée à une priorité utilisée par l’ordonnanceur pour choisir la prochaine tâche à exécuter.

Dans les sources, les tâches sont définies par le fichier ec.tasklist. Dans le firmware, on peut facilement retrouver cette liste en recherchant le nom de la tâche « << idle >> ».

00068238 79 54 06 00     addr       s_<<_idle_>>_00065479      = "<< idle >>"
0006823c 84 54 06 00     addr       s_HOOKS_00065484           = "HOOKS"
00068240 8a 54 06 00     addr       s_NUGGET_0006548a          = "NUGGET"
00068244 91 54 06 00     addr       s_FACEAUTH_00065491        = "FACEAUTH"
00068248 9a 54 06 00     addr       s_AVB_0006549a             = "AVB"
0006824c 9e 54 06 00     addr       s_KEYMASTER_0006549e       = "KEYMASTER"
00068250 a8 54 06 00     addr       s_IDENTITY_000654a8        = "IDENTITY"
00068254 b1 54 06 00     addr       s_WEAVER_000654b1          = "WEAVER"
00068258 b8 54 06 00     addr       s_CONSOLE_000654b8         = "CONSOLE"

En remontant les références vers ce tableau, on retrouve la définition initiale de ces tâches ainsi qu’une fonction de journalisation appelée task_print_list. Il est aussi possible de retrouver cette dernière fonction en recherchant la chaîne « Task Ready Name ». Cette fonction va utiliser deux structures qui nous intéressent : le tableau de structures tasks_init qui est stocké dans la flash et contient des valeurs d’initialisation des tâches, et le tableau de structure tasks qui est stocké en RAM et est utilisé pour la gestion des tâches.

tasks init-s

Fig. 3 : Définition de tasks_inits vu dans Ghidra.

Chacune des structures du tableau tasks_init comprend les valeurs initiales pour les registres r0 (qui semble toujours valoir 0), pc ainsi qu’une taille maximale de pile. La valeur de pc nous intéresse particulièrement puisqu’elle correspond au point d’entrée d’une tâche.

On identifie ainsi neuf tâches présentes dans Nugget OS :

  • << idle >> : cette tâche est exécutée lorsqu’aucune autre tâche ne l’est ;
  • HOOKS : cette tâche gère les évènements et les timers ;
  • NUGGET : ici sont implémentées les vérifications du mot de passe utilisateur, les mises à jour du firmware, et d’autres commandes pouvant être appelées depuis le programme citadel_updater d’Android ;
  • AVB : implémente la fonctionnalité AVB (Android Verified Boot, les dernières étapes du démarrage sécurisé) d’Android ;
  • KEYMASTER : implémente la fonctionnalité Keymaster, aussi appelée Strongbox Keymaster et que l’on trouve derrière le Keystore d’Android. Elle permet de réaliser des opérations cryptographiques dans le Titan ;
  • WEAVER : implémente la fonctionnalité Weaver d’Android qui permet de stocker des secrets dans le Titan ;
  • CONSOLE : implémente une console minimaliste accessible depuis l’UART ou l’USB en utilisant le câble de débogage SuzyQable [SUZYQ].

Dans les versions récentes de Citadel, deux nouvelles tâches ont été introduites : IDENTITY et FACEAUTH. Elles semblent être liées à la fonctionnalité de reconnaissance faciale introduite dans les smartphones Pixel 4, mais n’ont pas encore été étudiées.

4. La communication entre Citadel et Android

4.1 Côté Android

4.1.1 Les commandes au niveau userland

Un service HAL qui souhaite envoyer une commande va encoder les données avec le parseur généré à l’aide de protobuf. Il va ensuite les envoyer au service CitadelProxy, accompagnées de l’identifiant de l’application (ou tâche) ciblée dans Citadel, et le numéro de commande.

Pour une commande reçue, CitadelProxy va envoyer plusieurs requêtes au driver noyau, via des appels IOCTL. Les données vont être découpées en buffers d’une taille maximale de 2044 octets.

Une requête est représentée par une structure appelée citadel_ioc_tpm_datagram comprenant l’adresse du buffer de données, sa taille ainsi qu’un mot de 32 bits appelé command.

struct citadel_ioc_tpm_datagram {
     __u64 buf;
     __u32 len;
     __u32 command;
};

Ce mot contient l’identifiant de l’application Citadel encodé sur un octet, la taille des données encodée sur deux octets et des flags de signalétiques.

Une dernière requête est envoyée au driver. Le mot command contiendra alors l’identifiant de tâche ainsi que le numéro de commande (provenant de la définition protobuf). La requête sera accompagnée d’une structure command_info contenant, entre autres une somme de contrôle CRC16 de l’ensemble de la commande telle que reçue depuis le service HAL.

comm android-s

Fig. 4 : Échange d’une commande entre CitadelProxy et le driver noyau.

Pour recevoir la réponse associée à la commande, CitadelProxy va envoyer une nouvelle requête au noyau, toujours en utilisant la structure citadel_ioc_tpm_datagram. Le champ command contiendra un flag indiquant qu’il s’agit d’une lecture. Le champ buf sera alors rempli par le noyau avec la réponse.

4.1.2 Les commandes au niveau noyau

spi msg-s

Fig. 5 : Échange d’une requête entre le noyau Linux et Citadel.

Au niveau du driver, la structure citadel_ioc_tpm_datagram est reçue depuis le userland. La fonction citadel_tpm_datagram se charge de l’envoyer à Citadel en deux temps.

Un premier message comprenant la commande est envoyé sur le bus. Lorsque Citadel est en mesure de recevoir la suite, un message spécifique (0xdfdfdfde) est envoyé au noyau. Le driver envoie alors le buffer provenant du userland sur le bus SPI.

4.2 Côté Citadel

Deux interruptions sont utilisées pour la communication avec Android : une interruption rx pour les requêtes et une interruption tx pour les réponses. Lorsqu’un message est reçu, la routine d’interruption rx va appeler une fonction dédiée au traitement des messages reçus. Elle lui donne en paramètre la variable de commande, les adresses d’un buffer (ici appelé rx_buf) et sa taille.

void handle_recv_msg(uint32_t command,uint32_t *rx_buf,uint32_t *size_max) {
[...]
  spi_task = struct_spi_msg_task_ARRAY;
  while( true ) {
[...]
    if ((uint)*(byte *)&spi_task->id == (command << 8) >> 0x18) break;
    spi_task = spi_task + 1;
[...]
    (*spi_task->recv_callback)
              (command,(uint32_t)rx_buf,(uint32_t)size_max,(int)spi_task->spi_msg_info);

Cette fonction va itérer sur un tableau de structures (ici appelé struct_spi_msg_task_ARRAY) correspondant à la liste des tâches pouvant recevoir des messages via SPI. Il apparaît donc que cinq tâches peuvent envoyer et recevoir des données de cette façon : les tâches Nugget Core, AVB, Keymaster, Weaver et Identity.

Les structures de struct_spi_msg_task_ARRAY comportent notamment un identifiant de tâche qui est comparé à celui provenant de la commande, une callback pour l’envoi et une autre pour la réception de message, ainsi que l’adresse d’une autre structure appelée ici spi_msg_info.

Cette dernière structure contient entre autres l’adresse d’une zone en RAM où sera reconstituée la commande complète en provenance d’Android et qui sera utilisée par la tâche correspondante pour parser le message reçu. La structure spi_msg_info comporte aussi une fonction qui est utilisée pour générer un évènement afin d’alerter la tâche lorsqu’une commande est reçue.

4.2.1 Réception d’une commande SPI dans une tâche

do {
  do {
    do {
      iVar1 = task_wait_event(0xffffffff);
      FUN_000554c4();
    } while (-1 < iVar1 << 2);
    iVar1 = crc_check(KM_SPI_CMD);
  } while (iVar1 != 0);
  nugget_app_keymaster_Keymaster(&STACK_START.keymaster_funcs);
} while( true );

Cet extrait de la tâche KEYMASTER nous montre que la tâche attend l’arrivée d’un évènement avant d’effectuer la vérification du CRC de la commande reçue, alors stockée dans la structure KM_SPI_CMD. Si la vérification est valide, la fonction nugget_app_keymaster_Keymaster est appelée et va identifier le numéro de commande.

Cette fonction prend en paramètre le pointeur d’un tableau de fonctions situé en RAM. En typant correctement ce tableau de fonctions, la fonction de parsing devient plus lisible.

pb_istream_init_from_buffer
            (&pb_istream,STACK_START.km_spi_cmd.cmd_request_buf,
             STACK_START.km_spi_cmd.request_length);
pb_ostream_init_from_buf
            (&pb_ostream,STACK_START.km_spi_cmd.cmd_response_buf,
             STACK_START.km_spi_cmd.response_length);
[...]
switch(STACK_START.km_spi_cmd.cmd) {
case 0:
  km_func = keymaster_func->keymaster_AddRngEntropy;
  if (km_func != 0x0) {
    fields_out = (struct_pb_msgdesc_s *)&DAT_000602be;
    fields_in = (dword *)&msgdesc[-2].submsg_info;
       goto exec_function;
[...]
case 1:
  km_func = keymaster_func->keymaster_GenerateKey;
    if (kfunc != 0x0) {
[...]
    goto exec_function;
[...]
exec_function:
    iVar1 = (*km_func)(&pb_istream,fields_in,dest_struct,&pb_ostream,fields_out,
                     src_struct);

Le numéro de commande est utilisé dans un switch pour identifier la commande (l’identifiant « 0 » correspond à la commande AddRngEntropy) et appeler ensuite la fonction correspondante.

Toutes les fonctions correspondant aux commandes ont la signature suivante :

uint32_t nugget_func(struct_pb_istream_s * request, struct_pb_msgdesc_s * fields, byte * dest_struct, struct_pb_ostream_s * response, struct_pb_msgdesc_s * fields, void* src_struct)

4.2.2 Implémentation des commandes

La définition des protocoles protobuf nous donne quelques indications sur le rôle fonctionnel de chacune des fonctions de la liste passée en argument à nugget_app_keymaster_Keymaster. Le numéro de commande nous permettra d’identifier exactement chaque fonction et le format des données échangées.

L’analyse de la définition du protocole de keymaster (le fichier nos/host/generic/nugget/proto/nugget/app/keymaster/keymaster.proto) met en évidence l’ensemble des commandes pour lesquelles une fonction est implémentée dans la tâche.

rpc AddRngEntropy (AddRngEntropyRequest) returns (AddRngEntropyResponse);
rpc GenerateKey (GenerateKeyRequest) returns (GenerateKeyResponse);
rpc GetKeyCharacteristics (GetKeyCharacteristicsRequest) returns (GetKeyCharacteristicsResponse);
rpc ImportKey (ImportKeyRequest) returns (ImportKeyResponse);
[...]

Les implémentations de ces fonctions sont assez similaires. L’extrait suivant provient de la fonction AddRngEntropy.

bVar1 = pb_decode_ex(istream,fields_in,dest_struct,ostream);
if (bVar1 == false) {
  return 1;
}
km_add_rng_entropy(dest_struct,src_struct);
bVar1 = pb_encode(ostream,fields_out,src_struct);

La fonction pb_decode_ex du projet nanopb va décoder les données provenant de la commande et les placer dans une structure dest_struct. Cette dernière est ensuite donnée en argument à km_add_rng_entropy qui va réaliser l’action de la commande. Les données en sortie sont placées dans la structure src_struct qui sera utilisée pour générer une réponse. La fonction pb_encode va convertir cette structure en réponse qui sera envoyée à Android lors de la prochaine requête de lecture.

Conclusion

Il est curieux qu’à ce jour si peu de recherches aient été publiées sur ce composant alors même que Google propose d’offrir jusqu’à un million de dollars en bug bounty pour des vulnérabilités sur ce projet. On se demande aussi pourquoi les sources du projet n’ont pas été ouvertes alors que Google avait annoncé que ce projet serait open source.

Bien que ce composant dispose d’une armada impressionnante de protection contre les attaques matérielles, on peut aussi s’étonner de ne trouver qu’un simple canari comme protection logicielle.

Bien entendu, l’architecture semble faite pour limiter l’introduction de bugs : le logiciel est simple, la plupart des buffers sont alloués statiquement en mémoire, et les parseurs sont générés avec protobuf. On imagine aussi que Google a fait auditer ce produit, au moins en interne. On note d’ailleurs la présence de fichiers dédiés aux tests et au fuzzing dans les sources d’EC. Faut-il en conclure que ce projet est exempt de bugs ? L’avenir le dira…

Remerciements

Je tiens à remercier d33d34rt et doegox pour leur relecture attentive et leurs conseils avisés.

Références

[1] N. Zhang, K. Sun, D. Shands, W. Lou, Y. T. Hou, « TruSpy: Cache Side-Channel Information Leakage from the Secure World on ARM Devices », IACR Cryptology, 2016

[2] V. Bendeb, « Google Security Chip H1, A member of the Titan family », Open Source Firmware Conference, 2018, https://2018.osfc.io/uploads/talk/paper/7/gsc_copy.pdf

[ECSOURCES] https://chromium.googlesource.com/chromiumos/platform/ec/

[SUZYQ] https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/ccd.md#suzyq-suzyqable

[PROTOBUF] https://developers.google.com/protocol-buffers

[NANOPB] https://github.com/nanopb/nanopb



Article rédigé par

Les derniers articles Premiums

Les derniers articles Premium

Bénéficiez de statistiques de fréquentations web légères et respectueuses avec Plausible Analytics

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Pour être visible sur le Web, un site est indispensable, cela va de soi. Mais il est impossible d’en évaluer le succès, ni celui de ses améliorations, sans établir de statistiques de fréquentation : combien de visiteurs ? Combien de pages consultées ? Quel temps passé ? Comment savoir si le nouveau design plaît réellement ? Autant de questions auxquelles Plausible se propose de répondre.

Quarkus : applications Java pour conteneurs

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Initié par Red Hat, il y a quelques années le projet Quarkus a pris son envol et en est désormais à sa troisième version majeure. Il propose un cadre d’exécution pour une application de Java radicalement différente, où son exécution ultra optimisée en fait un parfait candidat pour le déploiement sur des conteneurs tels que ceux de Docker ou Podman. Quarkus va même encore plus loin, en permettant de transformer l’application Java en un exécutable natif ! Voici une rapide introduction, par la pratique, à cet incroyable framework, qui nous offrira l’opportunité d’illustrer également sa facilité de prise en main.

De la scytale au bit quantique : l’avenir de la cryptographie

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Imaginez un monde où nos données seraient aussi insaisissables que le célèbre chat de Schrödinger : à la fois sécurisées et non sécurisées jusqu'à ce qu'un cryptographe quantique décide d’y jeter un œil. Cet article nous emmène dans les méandres de la cryptographie quantique, où la physique quantique n'est pas seulement une affaire de laboratoires, mais la clé d'un futur numérique très sécurisé. Entre principes quantiques mystérieux, défis techniques, et applications pratiques, nous allons découvrir comment cette technologie s'apprête à encoder nos données dans une dimension où même les meilleurs cryptographes n’y pourraient rien faire.

Les listes de lecture

11 article(s) - ajoutée le 01/07/2020
Clé de voûte d'une infrastructure Windows, Active Directory est l'une des cibles les plus appréciées des attaquants. Les articles regroupés dans cette liste vous permettront de découvrir l'état de la menace, les attaques et, bien sûr, les contre-mesures.
8 article(s) - ajoutée le 13/10/2020
Découvrez les méthodologies d'analyse de la sécurité des terminaux mobiles au travers d'exemples concrets sur Android et iOS.
10 article(s) - ajoutée le 13/10/2020
Vous retrouverez ici un ensemble d'articles sur les usages contemporains de la cryptographie (whitebox, courbes elliptiques, embarqué, post-quantique), qu'il s'agisse de rechercher des vulnérabilités ou simplement comprendre les fondamentaux du domaine.
Voir les 66 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous