MQTTS Stockage Sécurisé
L'étape 3 implémente un Durcissement au Niveau Silicium en isolant l'identité cryptographique du dispositif dans un coprocesseur dédié. En utilisant le Secure Element ATECC608B, nous séparons physiquement la clé privée du firmware.
Le Concept du Secure Element
Transférer les secrets depuis l'intérieur du code, toujours falsifiable, vers un emplacement de stockage externe sécurisé.
Pipeline d'Authentification
Trajet de la confiance : du silicium au serveur.
Signataire
ATECC608BLa clé privée est hébergée dans le coffre-fort matériel (Slot 8) et n'est extraite qu'à la volée par le microcontrôleur pour l'authentification, garantissant un stockage sécurisé.
Transport
ESP32Assure l'encapsulation TLS 1.2 du trafic MQTT. Le microcontrôleur récupère temporairement la clé du Secure Element en mémoire volatile pour établir le tunnel chiffré, sans stockage persistant sur la flash.
Vérificateur
MosquittoValide l'identité du client via l'authentification mutuelle (mTLS). Le broker vérifie la signature cryptographique et la chaîne de certification X.509 avant d'autoriser la session MQTT.
Les limites du stockage Flash conventionnel
Sur un microcontrôleur standard, la mémoire flash ne dispose pas d'isolation matérielle contre les accès physiques directs.
- Dumping de firmware
- Clonage d'identité
L'Approche Coffre-Fort
L'ATECC608B est une chambre forte cryptographique. Il introduit une frontière physique que le logiciel ne peut franchir.
Note Technique : Bien que ce lab charge la clé en RAM pour la démo TLS, en production, la clé ne quitte jamais le chip (offloading TLS).
Schéma de câblage
M5Stack
PORT A (Red)ENV II Unit
ATECC608B Unit
Pourquoi les clés stockées matériellement améliorent la sécurité
Avantages fondamentaux par rapport au stockage logiciel.
Résistance aux Attaques Invasives
L'extraction de secrets exige des attaques physiques destructives (décapsulation chimique, micro-sondage FIB), nécessitant un équipement de laboratoire coûteux et une expertise avancée, rendant l'attaque économiquement non viable.
Immunité aux Canaux Auxiliaires (SCA)
Le composant intègre des contre-mesures actives pour lisser la consommation de courant et introduire du jitter d'horloge, neutralisant ainsi les attaques par analyse de puissance (SPA/DPA) et temporelles (Timing Attacks).
Injection et Formatage des Clés
La clé privée est générée hors-puce (OpenSSL), sérialisée au format binaire strict (PKCS#8 DER avec préfixe de longueur), puis provisionnée directement dans le slot sécurisé n°8 pour établir l'identité du dispositif.
Intégrité via Verrouillage OTP
Les zones de mémoire (Data Slots) utilisent la technologie One-Time Programmable (OTP). Une fois la zone verrouillée (Locked), la configuration devient irréversible, garantissant l'intégrité permanente des données provisionnées.
Architecture et Flux de données
La clé privée est confinée au sein du Secure Element. L'authentification s'établit directement entre le Broker et la racine de confiance matérielle (Hardware Root of Trust).
Publisher M5Go
Mosquitto
Terminal
- require_cert true
- use_identity_as_username true
Subscriber M5Stack
Vidéo de Démo
Utilisez cet enregistrement comme un contrôle rapide (il complète, mais ne remplace pas, les commandes reproductibles et les captures).
Carte des Slots ATECC608B
Explorez l'agencement mémoire du Secure Element ATECC608B Trust&GO. Cliquez sur une zone pour inspecter sa configuration, ses politiques d'accès et son contenu.
Agencement Silicium (Logique)
Note : Configuration ATECC608B-TNGTLSU Trust&GO
Logique d'Implémentation
La séquence d'initialisation établit la sécurité complète en cinq étapes distinctes, de la vérification matérielle au handshake TLS final.
// 1. Scan I2C pour trouver l'ATECC608B (adresse par défaut 0x35) Wire.beginTransmission(0x35); if (Wire.endTransmission() == 0) { Serial.println("ATECC608 détecté à l'adresse 0x35."); // Initialisation de la librairie SparkFun if (atecc.begin(0x35, Wire, Serial)) { // Lecture des registres de configuration atecc.readConfigZone(false); // Vérification des verrous (Locks) if (atecc.configLockStatus && atecc.dataOTPLockStatus) { Serial.println("Puce verrouillée et prête à l'emploi."); } else { Serial.println("Attention : Puce non verrouillée."); } } } else { Serial.println("Erreur : Secure Element introuvable."); }
// Tableau contenant la longueur (2 octets) + la clé DER brute // Exemple raccourci : [LEN_HI, LEN_LO, DER_BYTE_1, DER_BYTE_2...] const uint8_t key_blob[] = { 0x00, 0x8A, 0x30, 0x81... }; size_t offset = 0; uint8_t block = 0; // Index du bloc (0 à 12 pour le Slot 8) // Boucle d'écriture tant qu'il reste des données et qu'on ne dépasse pas le Slot 8 (13 blocs) while (offset < sizeof(key_blob) && block < 13) { uint8_t chunk32[32]; // Buffer de 32 octets memset(chunk32, 0, 32); // Initialisation à 0 (padding) // Copie par paquet de 32 octets max size_t toCopy = min((size_t)32, sizeof(key_blob) - offset); memcpy(chunk32, &key_blob[offset], toCopy); // Calcul de l'adresse : (Slot 8 << 3) | (Bloc << 8) uint16_t addr = (8 << 3) | (block << 8); // Écriture physique dans la zone DATA atecc.write(ZONE_DATA, addr, chunk32, 32); offset += toCopy; block++; }
uint8_t slotData[416]; // Buffer pour stocker l'intégralité du Slot 8 (13 * 32 octets) // Lecture séquentielle des 13 blocs du Slot 8 for (uint8_t b = 0; b < 13; b++) { // Calcul de l'adresse du bloc dans le Slot 8 uint16_t addr = (8 << 3) | (b << 8); // Lecture via la librairie SparkFun (zone DATA, adresse, 32 octets) if (atecc.read(ZONE_DATA, addr, 32, false)) { // La librairie stocke la réponse dans inputBuffer[1..32] // Copie ces données dans le buffer global memcpy(&slotData[b * 32], &atecc.inputBuffer[1], 32); } } // slotData contient maintenant : [Longueur (2 octets)] + [Clé DER] + [Padding zéros]
// Récupération de la longueur de la clé (Big Endian sur les 2 premiers octets) uint16_t derLen = (slotData[0] << 8) | slotData[1]; // Pointeur vers le début des données DER (juste après les 2 octets de longueur) const uint8_t *derPtr = &slotData[2]; // Encodage du flux binaire DER en Base64 (fonction utilitaire) String b64Key = base64Encode(derPtr, derLen); // Construction de la chaîne PEM finale String pemKey = "-----BEGIN PRIVATE KEY-----\n"; // Ajout du corps en Base64 (idéalement découpé tous les 64 caractères) pemKey += b64Key; pemKey += "\n-----END PRIVATE KEY-----\n";
WiFiClientSecure tlsClient; // Injection des certificats publics (CA et Client) stockés en Flash tlsClient.setCACert(ca_cert); tlsClient.setCertificate(client_cert); // Injection de la clé privée PEM récupérée dynamiquement depuis le Secure Element // Note : La clé n'est jamais écrite "en dur" dans le code source tlsClient.setPrivateKey(pemKey.c_str()); // Connexion MQTT sécurisée (Port 8883) PubSubClient mqtt(tlsClient); mqtt.setServer(MQTT_HOST, 8883); if (mqtt.connect("m5stack-client-id")) { // Connexion TLS établie avec authentification utuelle (mTLS) réussie }
Approfondissement Technique
Logique d'ingénierie derrière la gestion crypto du firmware.
DER vs PEM
Binaire (0s & 1s). Optimisé pour l'efficacité de stockage sur silicium.
Texte Base64. Requis par les en-têtes de la bibliothèque TLS ESP32.
Pourquoi une Longueur de 2 Octets ?
Les clés privées ECC varient légèrement en taille (~118-121 octets). Les slots de la puce sont des conteneurs à taille fixe.
Nous préfixons la longueur pour que le firmware sache exactement où finissent les données et où commence le remplissage.
Pourquoi 13 Blocs ?
Contrainte matérielle : L'ATECC608B lit/écrit strictement par blocs de 32 octets.
Nous ne pouvons pas lire 'juste 5 octets'. Nous devons lire les blocs complets et les analyser en RAM.
Vérification en Direct
Nous avons validé le système contre les modes de défaillance physiques et cryptographiques courants. Voici la preuve de résilience :
1. Test de Falsification Physique
Scénario : Secure Element Déconnecté
Résultat : Arrêt immédiat. Le firmware sonde le bus I2C à
l'adresse 0x35. Si l'ATECC608B ne répond pas, le dispositif refuse de poursuivre,
empêchant toute connectivité réseau.
2. Test de Clonabilité
Scénario : Secure Element contenant un mauvais certificat.
Résultat : Connexion Rejetée. Le mauvais Secure Element
branché génère une signature qui ne correspond pas à la clé publique enregistrée. Le broker renvoie
bad signature et ferme le socket.
3. Vérification d'Identité
Scénario : Matériel Valide Présent
Résultat : Authentifié. Le handshake TLS Mutuel réussit. Le
broker vérifie le certificat et le SUBSCRIBE au topic m5go/env est acquitté.
4. Opération Système
Scénario : Publisher et Subscriber
Résultat : Synchronisation Parfaite. Le Publisher (bas) pousse les données environnementales de manière sécurisée. Le Subscriber (haut) les reçoit instantanément via le canal chiffré.
Analyse des Menaces (STRIDE)
Avec l'implémentation du Secure Element, nous obtenons une Couverture Complète.
Usurpation (Spoofing)
Clé stockée dans le Secure Element (bien qu'exportée en RAM dans ce labo).
Nous pouvons prouver une liaison d'identité distincte à la puce (bien que l'extraction RAM soit un risque théorique).
Falsification (Tampering)
Vérifications d'Intégrité TLS.
Les attaques Man-in-the-Middle modifient les paquets, brisant la signature. Le broker coupe la connexion instantanément.
Répudiation (Repudiation)
Clé stockée dans le matériel (Exportée en RAM ici).
Preuve d'origine irréfutable. La signature cryptographique garantit que le message a été généré exclusivement par ce composant matériel unique.
Divulgation d'Info (Information Disclosure)
Session chiffrée TLS.
Les charges utiles sont opaques pour les sniffers réseau. La confidentialité est totalement préservée.
Déni de Service (Denial of Service)
L'authentification mutuelle (mTLS) agit comme un filtre strict au niveau transport.
Rejet précoce. Les connexions non autorisées sont coupées avant même d'atteindre et de saturer la logique applicative.
Élévation (Elevation of Privilege)
Cloisonnement matériel des secrets.
Même si un firmware est exploité (Buffer Overflow), l'attaquant ne peut pas extraire la clé permanente pour attaquer d'autres systèmes.
Limitations et considérations de sécurité
Passer de l'implémentation éducative au durcissement en production implique des choix architecturaux critiques. Comprenez ce que nous avons construit, et la suite.
Logique TLS Hybride
Dans ce labo, la clé privée est extraite en tant que chaîne et transmise à la pile logicielle. Cela démontre le Stockage Sécurisé mais manque l'étape finale d' Exécution Sécurisée.
Utilisez PKCS#11 ou des callbacks ECDSA (HAL) pour que la clé privée ne quitte jamais le silicium. La signature de handshake se fait entièrement dans le Secure Element.
Exposition RAM Éphémère
Bien que la clé soit effacée du Flash, elle existe brièvement dans la RAM de l'ESP32 durant la séquence de démarrage avant d'être passée au moteur mTLS.
Remettre à zéro les buffers après usage et activer le Secure Boot ESP32 pour empêcher l'extraction de RAM.
Potentiel Sniffing I2C
Le bus I2C entre le MCU et le SE n'est pas chiffré. Un attaquant dédié pourrait théoriquement intercepter la clé durant la transmission I2C.
Contre l'écoute physique, préférez les pistes enterrées ou le chiffrement de bus. L'idéal reste le M5Stack Core2 AWS : son Secure Element interne supprime tout câblage vulnérable et confine la clé.
L'Architecture de Référence
En combinant un TLS Mutuel avec un Secure Element, nous atteignons un niveau de sécurité IoT très élevé.
Identité Inoubliable
La clé privée est générée en externe, stockée dans la puce, et relue pour utilisation. Le clonage nécessiterait d'extraire la clé depuis le bus I2C ou la RAM durant la séquence d'initialisation.
Isolation Matérielle
Même si le firmware est compromis (Buffer Overflow), l'attaquant ne peut pas toucher aux clés stockées dans l'élément cryptographique séparé.
Résistance à la Falsification
L'intégration de maillages actifs (Active Shields) et l'obfuscation du layout confèrent à l'ATECC608B une immunité contre l'ingénierie inverse et les attaques invasives.
Prêt pour la Production
Cette architecture répond aux exigences de notre cahier des charges. C'est une référence de l'industrie pour les dispositifs connectés sécurisés.
Prêt à reproduire ?
Vous avez exploré la théorie et l'architecture. Maintenant, suivez la procédure étape par étape pour construire ce système vous-même.