Greboca  

Suport technique et veille technologique

Aujourd’hui, les grandes entreprises et administrations publiques hésitent entre continuer à utiliser des logiciels propriétaires ou basculer vers les Logiciels Libres. Pourtant, la plupart des logiciels libres sont capables de bien traiter les données issues des logiciels propriétaire, et parfois avec une meilleur compatibilité.

C’est alors la barrière de la prise en main qui fait peur, et pourtant...

Les logiciels libres

L’aspect « Logiciel Libre » permet une évolution rapide et une plus grande participation des utilisateurs. Les aides et tutoriels foisonnent sur Internet ou sont directement inclus dans le logiciel lui-même.

Enfin, les concepteurs sont plus proches des utilisateurs, ce qui rend les logiciels libres plus agréable à utiliser et conviviaux.

Grâce à la disponibilité des logiciels libres, vous trouverez facilement des services de support techniques et la licence n’est plus un frein à l’utilisation de ces logiciels par votre personnel.

Notre support technique concerne essentiellement les logiciels libres, que ce soit sous forme de services ponctuels ou de tutoriels.

DLFP - Dépêches  -  Utilisation d’un TPM pour l’authentification SSH

 -  Mai 2020 - 

Après son « Bien démarrer avec GnuPG », gouttegd nous livre un nouveau journal sur l’utilisation du Trusted Platform Module (TPM) pour s’authentifier auprès d’un serveur SSH. Ce journal a été converti en dépêche et enrichi des premiers commentaires.

Sommaire

J’ai récemment fait l’acquisition d’un nouveau PC portable équipé entre autres choses d’un Trusted Platform Module (TPM) — comme la plupart des PC portables de nos jours, puisqu’à ce qu’il me semble la présence d’un TPM est un prérequis pour vendre un PC avec une version récente de Windows). Je n’ai pas encore étudié tout ce qu’il serait possible de faire avec ce TPM, mais dans ce journal je vais décrire comment l’utiliser pour s’authentifier auprès d’un serveur SSH.

Prise en charge par le noyau

Vérifions d’abord à quel matériel j’ai affaire et s’il est bien reconnu par le noyau :

# dmesg | grep tpm
[   16.880645] tpm_tis IFX0783:00: 2.0 TPM (device-id 0x1B, rev-id 22)

C’est donc une puce Infineon (IFX), gérée par le module tpm_tis (et les modules associés tpm_tis_core, tpm_crb et tpm).

Si vous êtes de celles et ceux qui compilent leur propre noyau, assurez‑vous que toutes les options CONFIG_TCG_*, dans Devices Drivers > Characters devices > TPM Hardware Support, sont activées.

La pile logicielle

Ensuite, il nous faut un ensemble de bibliothèques et d’outils en espace utilisateur, ce que le Trusted Computing Group appelle la pile logicielle TPM (TPM Software Stack ou TSS). On aura pris soin de noter plus haut, dans la sortie de dmesg, que la puce TPM de ce portable est un TPM 2.0 ; cela signifie notamment qu’il est inutile d’essayer TrouSerS, qui est une pile logicielle TPM pour GNU/Linux ne gérant que les TPM ≤ 1.2 — c’est dommage, car la plupart des documents disponibles sur le Net concernant l’utilisation d’un TPM sous GNU/Linux ne parlent que de TrouSerS.

À la place de TrouSerS, il y a deux piles logicielles TPM 2.0 disponibles : une provenant d’IBM (IBM TPM 2.0 TSS), et une provenant de la « communauté logicielle tpm2 » (principalement poussée par Intel). J’ai choisi cette dernière, qui semble fournir davantage d’outils pour l’intégration dans un système GNU/Linux — par exemple un moteur OpenSSL et surtout une interface PKCS#11, dont on reparlera plus bas.1

La pile de base

Installons donc le cœur de la pile Intel, la bibliothèque tpm2-tss et les outils associés. La bibliothèque est peut‑être déjà disponible dans les dépôts de votre distribution (c’est le cas sous Debian), sinon, use the source, Luke :

$ wget https://github.com/tpm2-software/tpm2-tss/releases/download/2.4.1/tpm2-tss-2.4.1.tar.gz
$ tar xf tpm2-tss-2.4.1.tar.gz
$ cd tpm2-tss-2.4.1
$ ./configure --with-udevrulesdir=/lib/udev/rules.d \
    --with-udevrulesprefix=50- \
    --localstatedir=/var \
    --sysconfdir=/etc \
    --disable-weakcrypto
$ make
# make install-strip

Dans le reste de ce journal, nous installerons systématiquement tout à partir des sources. Il vous appartiendra de vérifier préalablement si des paquets sont disponibles pour votre distribution de prédilection et de privilégier cette voie le cas échéant. À l’heure où ces lignes sont écrites, Debian Buster par exemple fournit tpm2-tss, tpm2-tools, et tpm2-abrmd, mais tpm2-pkcs11 n’est disponible que dans Sid et tpm2-tss-engine n’est disponible dans aucune version.

Pour les utilisateurs de Slackware, je fournis des SlackBuilds pour tous les projets mentionnés ici : tpm2-tss, tpm2-tools, tpm2-abrmd, tpm2-pkcs11, et tpm2-tss-engine.

Installons ensuite les outils permettant de manipuler le TPM. Pour ce qu’on veut faire, on ne les utilisera pas directement, mais l’interface PKCS#11 que nous installerons plus en aura besoin.

$ wget https://github.com/tpm2-software/tpm2-tools/releases/download/4.2/tpm2-tools-4.2.tar.gz
$ tar xf tpm2-tools-4.2.tar.gz
$ cd tpm2-tools-4.2
$ ./configure
$ make
# make install-strip

Il faut ensuite décider de la méthode d’accès au TPM pour les utilisateurs de la machine, sachant qu’il y a trois options :

  • laisser les utilisateurs accéder au périphérique /dev/tpm0 directement ; ce n’est pas recommandé par les développeurs, et je confirme en effet que sur ma machine ça ne marche pas quand on veut utiliser l’interface PKCS#11, comme on le fera plus loin ;
  • laisser les utilisateurs accéder au périphérique /dev/tpmrm0 directement, il s’agit du gestionnaire de ressources (resources manager) du TPM fourni par le noyau ;
  • utiliser un gestionnaire de ressources en espace utilisateur, le TPM Access Broker and Resource Manager daemon (TABRMD) ; seul le démon utilisera le TPM directement, les autres programmes interagiront avec le démon, c’est l’approche recommandée.

Nous utiliserons le démon, donc installons le projet tpm2-abrmd :

$ wget https://github.com/tpm2-software/tpm2-abrmd/releases/download/2.3.2/tpm2-abrmd-2.3.2.tar.gz
$ tar xf tpm2-abrmd-2.3.2.tar.gz
$ cd tpm2-abrmd-2.3.2
$ ./configure --with-systemdsystemunitdir=/usr/lib/systemd/system \
    --with-systemdpresetdir=/usr/lib/systemd/system-preset \
    --sysconfdir=/etc \
    --localstatedir=/var
$ make
# make install-strip

Le démon a besoin d’un compte utilisateur dédié avec un accès en lecture‑écriture au périphérique /dev/tpm0. Si vous l’avez installé depuis les dépôts de votre distribution, l’auteur du paquet a probablement déjà fait le nécessaire et vous pouvez sauter le reste de cette section ; sinon, lisez ce qui suit.

Le projet tpm2-tss est fourni avec une règle udev donnant accès au TPM à un compte utilisateur appelé tss ; assurez‑vous qu’un tel compte existe, donnez‑lui les droits sur les dossiers dont aura besoin le démon (ces dossiers sont normalement créés lors du make install de tpm2-tss) puis rechargez et appliquez les règles udev :

# groupadd --system tss
# useradd --system --comment "TPM2 Software Stack" --home-dir /var/lib/tpm2-tss --gid tss tss
# chown -R tss:tss /var/lib/tpm2-tss /var/run/tpm2-tss
# chmod 755 /var/lib/tpm2-tss /var/run/tpm2-tss
# udevadm control --reload-rules
# udevadm trigger

Le projet tpm2-abrmd est fourni avec une « unité » systemd ; si votre distribution utilise systemd, vous ne devriez pas avoir besoin de faire quoi que ce soit (à part peut‑être un systemctl daemon-reload pour être sûr que la nouvelle unité est prise en compte). Dans le cas contraire, il vous appartient d’élaborer un script de démarrage qui convienne au système d’initialisation de votre distribution, quel qu’il soit. Prenez garde que tabrmd fait partie de cette nouvelle génération de démons qui ne connaissent rien d’autre que systemd : le démon considère comme acquis qu’il est géré par systemd et, du coup, ne prend pas la peine d’écrire son PID quelque part ou même de se détacher du terminal, votre script de démarrage devra se charger de ça.

L’interface PKCS#11

L’interface PKCS#11, fournie par le projet tpm2-pkcs11, est une couche qui permet d’utiliser le TPM comme si c’était un jeton cryptographique compatible avec la spécification PKCS#11. Elle rend le TPM utilisable par n’importe quel programme capable d’interagir avec un tel jeton, comme OpenSSH par exemple.

$ wget https://github.com/tpm2-software/tpm2-pkcs11/releases/download/1.2.0/tpm2-pkcs11-1.2.0.tar.gz
$ tar xf tpm2-pkcs11-1.2.0.tar.xf
$ cd tpm2-pkcs11-1.2.0
$ ./configure
$ make
# make install-strip

L’interface OpenSSL

Dernier composant de la pile Intel que nous installerons, le projet tpm2-tss-engine fournit un « moteur » OpenSSL, exposant les fonctions cryptographiques du TPM à travers OpenSSL. Elle n’est pas nécessaire pour SSH, mais je l’installe quand même puisqu’au‑delà de SSH, le but de tout ceci est d’explorer ce que je peux faire de mon TPM.

$ wget https://github.com/tpm2-software/tpm2-tss-engine/releases/download/v1.0.1/tpm2-tss-engine-1.0.1.tar.gz
$ tar xf tpm2-tss-engine-1.0.1.tar.gz
$ cd tpm2-tss-engine-1.0.1
$ ./configure --sysconfdir=/etc
$ make
# make install-strip

Configurer l’accès au TPM pour les différents composants

Comme nous avons décidé plus haut d’accéder au TPM par l’intermédiaire du gestionnaire de ressources en espace utilisateur (TABRMD), nous devons définir les variables d’environnement suivantes :

export TPM2TOOLS_TCTI=tabrmd:
export TPM2_PKCS11_TCTI=tabrmd:
export TPM2TSSENGINE_TCTI=tabrmd:

Cela indiquera respectivement à tpm2-tools, tpm2-pkcs11, et tpm2-tss-engine de ne pas chercher à accéder au TPM directement mais de passer par le gestionnaire de ressources (TCTI signifie TPM Control Transmission Interface) ; sans cela, les différents outils ne contacteraient le gestionnaire de ressources qu’après avoir bruyamment échoué à ouvrir le périphérique /dev/tpm0 eux‑mêmes. Ces variables ne sont pas strictement nécessaires, mais les définir permet d’éviter de polluer la console avec des messages d’erreur inutiles.

Pour information, la syntaxe de la valeur attendue par toutes ces variables est méthode:paramètres, où méthode peut être :

  • device, pour accéder au TPM directement ; dans ce cas paramètres indique le chemin d’accès au périphérique (p. ex. : device:/dev/tpm0) ;
  • tabrmd, pour accéder au TPM via le gestionnaire de ressources ; paramètres peut alors contenir l’adresse IP et le numéro de port où ledit gestionnaire attend ses clients (exemple : tabrmd:host=127.0.0.1,port=555), ou bien rester vide pour utiliser les valeurs par défaut ;
  • mssim, pour accéder à un émulateur logiciel de TPM comme ibmswtpm2 (pratique pour apprendre à utiliser un TPM ou développer et tester des logiciels faisant usage d’un TPM) ; paramètres peut alors contenir l’adresse IP et le numéro de port de l’émulateur, comme pour la méthode tabrmd.

Utilisation avec SSH

Créer un jeton PKCS#11

OpenSSH est nativement capable d’utiliser un jeton PKCS#11, nous utiliserons donc l’interface tpm2-pkcs11 installée plus haut. Il nous faut pour ça commencer par créer le dossier où tpm2-pkcs11 stockera la clef et les autres données dont il a besoin :

$ mkdir ~/.tpm2_pkcs11
$ tpm2_ptool init
action: Created
id: 1

(NdM: il est possible que pour utiliser le script python tpm2_ptool init présent dans le répertoire décompressé tools de tpm2-pkcs11-1.2.0, vous ayez besoin d'avoir python > 3.7 ; « sous Ubuntu 18.04, j'ai installé python3.8 ainsi que les package python3-pyasn1-modules python3-cffi puis simplement la commande: python3.8 tpm2_ptool init » (merci à ce commentaire de Ben pour les corrections)).

En effet, et de manière quelque peu contre‑intuitive, la clef privée que nous allons créer ne sera pas stockée dans le TPM. À la place, la clef sera stockée dans un fichier SQLite dans le dossier .tpm2_pkcs11, chiffrée de telle sorte qu’elle ne peut être déchiffrée que par le TPM. Chaque fois que la clef privée sera requise (par exemple, pour s’authentifier auprès d’un serveur SSH), la bibliothèque tpm2-pkcs11 enverra la clef chiffrée au TPM en même temps que les données à signer ; le TPM déchiffrera la clef et l’utilisera immédiatement pour signer les données, puis renverra à tpm2-pkcs11 le résultat de l’opération de signature.

Ce mode de fonctionnement a été conçu ainsi pour permettre d’utiliser un nombre illimité de clefs différentes avec un TPM dont la capacité de stockage est très réduite.

Nous pouvons maintenant créer un (pseudo) jeton PKCS#11 :

$ tpm2_ptool addtoken --pid=1 --label=mylabel --sopin=XXXX --userpin=YYYY

La valeur de --pid doit correspondre à l’identifiant de l’objet primaire renvoyé par la commande init un peu plus haut (id: 1). Le label peut être choisi librement, mais doit être unique parmi tous les jetons que vous créez (si jamais vous en créez plusieurs). Enfin, sopin et userpin sont respectivement le PIN administrateur du jeton (Security Officer PIN) et le PIN utilisateur.

Maintenant que nous avons un jeton, on peut y créer une clef, par exemple une clef ECC basée sur la courbe NIST P‑256 :

$ tpm2_ptool addkey --label=mylabel --userpin=YYYY --algorithm=ecc256

Utiliser le jeton avec SSH

Il nous faut obtenir la partie publique de la clef que nous venons de créer, afin d’autoriser cette clef sur le serveur SSH auquel on veut se connecter. On utilise pour ça la commande ssh-keygen standard d’OpenSSH, en lui indiquant d’obtenir la clef depuis notre jeton PKCS#11 :

$ ssh-keygen -D /usr/local/lib/pkcs11/libtpm2_pkscs11.so > key.pub

Ajustez le chemin d’accès au module libtpm2_pkcs11.so en fonction de votre système et de la manière dont vous avez installé le projet tpm2-pkcs11.

Ajoutez le contenu du fichier key.pub au fichier ~/.ssh/authorized_key de votre compte utilisateur sur le serveur SSH. Vous pouvez maintenant tenter de vous connecter à ce serveur en utilisant le jeton :

$ ssh -I /usr/local/lib/pkcs11/libtpm2-pkcs11.so myserver.example.org
Enter PIN for 'myabel': YYYY

Pour éviter d’avoir à spécifier le chemin vers le module libtpm2-pkcs11.so à chaque appel, vous pouvez utiliser l’option PKCS11Provider dans le fichier de configuration de SSH (globalement ou pour un hôte donné). Si vous utilisez en parallèle d’autres clefs SSH que vous chargez normalement dans un agent SSH, vous devez aussi désactiver l’utilisation de l’agent pour les hôtes pour lesquels vous comptez utiliser le jeton TPM (sinon SSH contactera systématiquement l’agent sans jamais essayer le jeton) :

Host myserver.example.org
  PKCS11Provider /usr/local/lib/pkcs11/libtpm2-pkcs11.so
  IdentityAgent none

Utilisation avec OpenSSL

Maintenant qu’on peut utiliser le TPM pour SSH, ce qui était l’objectif premier, voyons rapidement comment on peut aussi l’utiliser avec OpenSSL.

Confirmons d’abord que l’interface OpenSSL (tpm2-tss-engine) a été installée correctement et profitons‑en pour voir les fonctions du TPM que cette interface rend disponibles, en demandant à OpenSSL les capacités du moteur tpm2tss :

$ openssl engine -c tpm2tss
(tpm2tss) TPM2-TSS engine for OpenSSL
 [RSA, RAND]

Le moteur est donc effectivement bien installé, et donne accès aux fonctions relatives à RSA ainsi qu’au générateur de nombres aléatoires.

J’ignore pourquoi les fonctions ECDSA ne sont pas disponibles, alors que mon TPM les prend en charge (et que tpm2-pkcs11 les utilise sans problèmes). Il s’agit sans doute d’une limitation, voire d’un bogue, de tpm2-tss-engine.

On pourra donc obtenir du TPM, par exemple, vingt octets aléatoires (encodés en base64) via la commande suivante :

$ openssl rand -engine tpm2tss -base64 20
engine "tpm2tss" set.
cO1eoOMocHPlvUxFB9tTDzOwZyE=

Générons une clef RSA à présent :

$ tpm2tss-genkey -a rsa -s 2048 -p XXXXXXXX tpmkey.pem

La commande produit un fichier tpmkey.pem contenant la clef générée. Elle est sous forme chiffrée et ne peut être déchiffrée et utilisée que par le TPM ; XXXXXXXX est le mot de passe à présenter au TPM pour le déchiffrement.

L’utilisation de la clef passe par les commandes OpenSSL classiques, auxquelles on précise d’utiliser le moteur tpm2tss. Par exemple, pour chiffrer puis déchiffrer un fichier, on commence par extraire la partie publique de la clef :

$ openssl rsa -engine tpm2tss -inform engine -in tpmkey.pem -pubout -outform pem -out publickey.pem
engine "tpm2tss" set.
Enter password for user key: XXXXXXXX
writing RSA key

Le moteur tpm2tss envoie la clef chiffrée contenue dans le fichier tpmkey.pem vers le TPM, celui‑ci la déchiffre (si l’utilisateur fournit le bon mot de passe) et renvoie à OpenSSL la partie publique. Utilisons cette dernière pour chiffrer un fichier (le TPM n’est pas impliqué ici, le chiffrement ne faisant appel qu’à la clef publique) :

$ openssl pkeyutl -pubin -inkey publickey.pem -in cleartext.txt -encrypt -out ciphertext.dat

Pour déchiffrer, on utilise à nouveau le moteur tpm2tss :

$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey tpmkey.pem -decrypt -in ciphertext.dat -out deciphered.txt
engine "tpm2tss" set.
Enter password for user key: XXXXXXXX

Le moteur envoie au TPM à la fois la clef chiffrée tpmkey.pem et le fichier à déchiffrer ciphertext.dat. Le TPM commence par déchiffrer la clef elle‑même (encore une fois sous réserve que l’utilisateur saisisse le bon mot de passe), puis l’utilise pour déchiffrer le fichier et renvoie le texte clair correspondant à OpenSSL.

TPM et génération pseudo‑aléatoire

(ajouté tiré d’un fil de discussion dans le journal)

Le TPM est une des sources d’entropie possibles pour alimenter le périphérique /dev/hwrng, comme on peut le voir dans /sys/class/misc/hw_random :

# cat /sys/class/misc/hw_random/rng_available
tpm-rng-0 via

Et voici une machine sur laquelle c’est la source actuellement utilisée :

# cat /sys/class/misc/hw_random/rng_current
tpm-rng-0

Donc, lire depuis /dev/hwrng va directement taper dans le TPM, sans avoir besoin de passer par OpenSSL. Si l’on veut utiliser cette source pour alimenter le réserve d’entropie du noyau (celui qui est derrière les périphériques /dev/(u)random ou l’appel getrandom(2)), on peut utiliser des outils comme rngd(8).


  1. Une autre raison pour ne pas s’attarder sur le code d’IBM est que le fait que ledit code est fourni sous la forme d’une tar bomb… C’est con, mais je n’ai aucune envie d’utiliser un code écrit par quelqu’un qui ne sait pas utiliser tar correctement. 

Commentaires : voir le flux atom ouvrir dans le navigateur

par gouttegd, Davy Defaud, Benoît Sibaud, Ysabeau

DLFP - Dépêches

LinuxFr.org

Entretien avec GValiente à propos de Butano

 -  16 avril - 

GValiente développe un SDK pour créer des jeux pour la console Game Boy Advance : Butano.Cet entretien revient sur son parcours et les raisons (...)


Nouveautés d'avril 2024 de la communauté Scenari

 -  11 avril - 

Scenari est un ensemble de logiciels open source dédiés à la production collaborative, publication et diffusion de documents multi-support. Vous (...)


Annuaire de projets libres (mais pas de logiciels)

 -  9 avril - 

Les communs sont une source énorme de partage !S’il est plutôt facile dans le monde francophone de trouver des ressources logicielles (Merci (...)


Les enchères en temps réel, un danger pour la vie privée mais aussi pour la sécurité européenne

 -  7 avril - 

Les enchères en temps réel, ou Real-Time Bidding (RTB), sont une technologie publicitaire omniprésente sur les sites web et applications mobiles (...)


XZ et liblzma: Faille de sécurité volontairement introduite depuis au moins deux mois

 -  31 mars - 

Andres Freund, un développeur Postgres, s’est rendu compte dans les derniers jours que xz et liblzma ont été corrompus par l’un des mainteneurs du (...)