mardi 30 mars 2010

tutoriel trusted platforms (TPM), openssl et ecryptfs

Une puce TPM (pour trusted platform) est un processeur cryptographique pouvant équiper une machine (serveur, ordinateur personnel ou mobile). Le but est de fournir un ensemble de services de chiffrement et d'authentification dont les clés sont conservées matériellement. Il devient alors difficile, pour un utilisateur malveillant, de les extraire. Dans un intérêt pédagogique, en l'absence de puce, il est possible d'émuler son fonctionnement. Ce tutoriel complète l'article de Noémie Floissac [3]. Il décrit l'utilisation d'une puce TPM sous linux, et son implémentation avec openssl et ecryptfs.



installation

possédons nous une puce TPM?

Jetons un oeil au bios de notre ordinateur. Si la puce TPM existe, nous l'activons.

Quel type de TPM possédons nous?

passons root:
~$ sudo passwd root
~$ su -
~#
installons les outils tpm et trousers. Ils nous seront utiles plus tard.
~# apt-get install tpm-tools trousers
jetons un oeil à la table ACPI
~# apt-get install acpidump iasl vim
~# acpidump -b -t DSDT -o dsdt.asml
~$ iasl -d dsdt.asml
~$ vim dsdt.dsl
/TPM
  Device(TPM)
  {
    Name (_HID,EisaId("IFX0102"))
  (...)
:q
Le type de la puce, ici, est IFX0102, c'est à dire une Infineon TPM 1.2.

Si la recherche de chaîne de caractère TPM ne donne rien, c'est que notre ordinateur ne comporte pas de puce.

une puce (activée dans le bios) est présente sur notre ordinateur


listons les drivers disponibles:
~# modprobe -l | grep tpm
kernel/drivers/char/tpm/tpm.ko
kernel/drivers/char/tpm/tpm_bios.ko
kernel/drivers/char/tpm/tpm_tis.ko
kernel/drivers/char/tpm/tpm_nsc.ko
kernel/drivers/char/tpm/tpm_atmel.ko
kernel/drivers/char/tpm/tpm_infineon.ko
chargeons le module TPM et le driver de notre puce dans le module
~# modprobe -a tpm tpm_infineon
remarque: à la fin du tutoriel, pour que ces modules soient chargés au démarrage, nous les ajouterons à /etc/modules
~# vim /etc/modules
tpm
tpm_infineon

émulation d'une puce

Si notre ordinateur ne possède pas de puce TPM, nous allons installer un daemon qui la simulera.

Commencons par installer les outils qui nous seront nécessaires
~# apt-get install libgmp3c2 libgmp3-dev cmake subversion
~# exit
~$
Téléchargeons les sources de tpm-emulator
~$ svn checkout svn://svn.berlios.de/tpm-emulator/trunk tpm-emulator
Suivons les consignes de compilation du fichier README
~$ cd tpm-emulator
~/tpm-emulator$ mkdir build
~/tpm-emulator$ cd build
~/tpm-emulator/build$ cmake ../
~/tpm-emulator/build$ sudo make
~/tpm-emulator/build$ sudo make install
copions le driver généré dans notre répertoire de drivers
~/tpm-emulator/build$ sudo cp tpmd_dev/linux/tpmd_dev.ko /lib/modules/2.6.31-xxx/kernel/drivers/char/tpm/
rechargons la liste de nos modules et chargeons les modules tpm dans notre noyau linux
~# depmod
~# modprobe -a tpm
~# modprobe -a tpmd_dev
vérifions que nos modules sont bien chargés
~# lsmod | grep tpm
tpm                    15680  0
tpm_bios                6268  1 tpm
tpmd_dev                4176  1
pour que ces modules soient chargés au démarrage, ajoutons les à /etc/modules
~# vim /etc/modules
tpm
tpmd_dev

initialisation de la puce

réinitialisation

Si nous émulons la puce, lancons le daemon.
Remarque: nous devrons le faire à chaque redémarrage. Il faut être root.
~$ sudo tpmd
lançons les tpm-tools
~$ sudo tcsd
vérifions que notre puce tpm fonctionne. A partir de là, il n'est pas nécessaire d'être root.
~$ tpm_version
  TPM 1.2 Version Info:
  Chip Version:        1.2.0.7
  Spec Level:          2
  Errata Revision:     1
  TPM Vendor ID:       ETHZ
  TPM Version:         01010000
  Manufacturer Info:   4554485a
Remarque: si nous travaillons dans un OS virtualisé, nous prenons maintenant un snapshot. Cela évite de tout refaire si nous sommes confrontés au bug ci après.

Une puce émulée est déjà enable et active. Nous passons alors directement au paragraphe suivant.

Pour une puce physique (non émulée), il est nécessaire de l'initialiser:
~$ tpm_clear --force
TPM Successfuly Cleared.  You need to reboot to complete this operation.  After reboot the TPM will be in the default state: unowned, disabled and inactive.
~$ tpm_setenable --enable --force
~$ tpm_setactive --active
Action requires a reboot to take affect
remarque: pour une puce émulée, le message suivant, apparait quand nous faisons la manipulation clear - setenable - setactive. Dans ce cas, il est nécessaire de tout recommencer: réinstaller les modules tpm et tpmd_dev d'origine, puis relancer les processus tpmd et tcsd! La commande kill utilise les pid obtenus avec la commande ps.
~$ tpm_takeownership -z -y
Tspi_TPM_TakeOwnership failed: 0x00000008 - layer=tpm, code=0008 (8), The TPM target command has been disabled
~$ ps -e | grep tpm
~$ ps -e | grep tcsd
~# kill 4335
~# kill 4336
~# modprobe -r tpmd_dev
~# modprobe -r tpm
~# apt-get remove tpm-tools trousers

le TPM maître des clés

La puce TPM ne stocke que quelques clés. Toutes les autres sont stockées chiffrées sur le disque. [8]

L'Endorsement Key (EK) est la paire de clés RSA de la puce. Elle est créée par le fabricant et peut parfois être modifiée par l'utilisateur. 

La Storage Root Key (SRK) est la paire de clés RSA racine. C'est l'utilisateur de la puce qui la crée.
Elle est utilisée pour chiffrer:
- les Storage Keys (SK),
- les Attestation Identity Keys (AIK).

Les Storage Keys (SK) servent à chiffrer et signer les Binding Keys (BK).

Les Binding Keys (BK) sont utilisées pour chiffrer de petits morceaux de données.

Les Attestation Identity Keys (AIK) servent à signer les échanges avec le TPM. Elles permettent donc aux applications d'authentifier la TPM.

création de la SRK

Jetons un oeil à la commande tpm_takeownership
~$ tpm_takeownership -h
Usage: tpm_takeownership [options]
    -h, --help
        Display command usage info.
    -v, --version
        Display command version info.
    -l, --log [none|error|info|debug]
        Set logging level.
    -u, --unicode
        Use TSS UNICODE encoding for passwords to comply with applications using TSS popup boxes
    -y, --owner-well-known
        Set the owner secret to all zeros (20 bytes of zeros).
    -z, --srk-well-known
        Set the SRK secret to all zeros (20 bytes of zeros).
nous créons une SRK. Attention! Ne rien noter dans le champ SRK password, tapons simplement la touche ENTREE. En effet, le mot de passe SRK est utilisé pour restreindre la création de clés par des utilisateurs. Ici nous n'en avons pas l'utilité. De plus, la création d'un mot de passe nécessiterait ensuite de modifier le code source de la librairie libengine-tpm-openssl.
Nous ne créons pas de mot de passe propriétaire (option -y) non plus.
~$ tpm_takeownership -u -y
Enter SRK password:
Confirm password:

tpm et openssl

Nous pouvons utiliser notre TPM avec openssl.

Installons les librairies
~$ sudo apt-get install libengine-tpm-openssl libtspi-dev
Voici le readme de la librairie assurant la liaison avec openssl: libengine-tpm-openssl

 README for the OpenSSL 0.9.8 TPM engine

 Author: Kent Yoder
 Report bugs: trousers-users@lists.sf.net


ABOUT

  This package contains 2 sets of code, a command-line utility used to
generate a TSS key blob and write it to disk and an OpenSSL engine which
interfaces with the TSS API.

BUILDING

 Requirements: OpenSSL 0.9.8

 By default, the build will assume that you have a custom openssl installed
in /usr/local/ssl.

 $ configure [--enable-debug] [--with-openssl=/path/to/custom/openssl]
 $ make
 # make install

RUNNING

create_tpm_key

        create_tpm_key: create a TPM key and write it to disk
        usage: create_tpm_key [options]

        Options:
                -e|--enc-scheme encryption scheme to use [PKCSV15] or OAEP
                -q|--sig-scheme signature scheme to use [DER] or SHA1
                -s|--key-size   key size in bits [2048]
                -a|--auth       require a password for the key [NO]
                -p|--popup      use TSS GUI popup dialogs to get the password
                for the key [NO] (implies --auth)

  Key type:  The TPM key type of the key created will be legacy, so that it can
be used for both signing and encryption.

  Padding schemes:  Choosing the encryption and signature schemes
at key creation time is mandatory because of the structure of a TPM key blob.
Once a key is created by the TPM, the encryption and signature schemes are set
in store and cannot be changed without corrupting the key (making it unloadable
into a TPM). Here are the trade-offs:

* PKCSV15 encryption scheme - all encrypted data will be padded using the
    PKCSv1.5 padding algorithm. OAEP padding is considered more secure, but
    many legacy apps will require PKCSv1.5 (most notably openssl). PKCSV15
    padding will also allow a slightly larger chunk of data to be encrypted in
    one operation.
  OAEP encryption scheme - all encrypted data will be padded using the OAEP
    padding algorithm.

* DER signature scheme - assumes data to be signed is DER encoded (although
    this is not required). Will allow signatures to be made of arbitrary
    size, up to the size the padding will allow.
  SHA1 signature scheme - assumes *all* data to be signed is a SHA1 hash.
    This restricts the data size to be signed to 20 bytes, always.

  * default

  Key sizes: Default=2048 bits. Other valid sizes are 512 and 1024 bits.

  Key auth: Default=none. if -a is specified, you will be prompted on the
command line using OpenSSL for a passphrase. This passphrase is SHA1 hashed
by the TSS and used as the key's password. At key load time, you'll be
prompted for the passphrase again by OpenSSL. If -p is specified, you'll get
a GUI  prompt for password.
  In order to make the TPM engine prompt you for your password, add the
following code to your app:

  To set the SRK password explicitly in your code, do:

  ENGINE_ctrl_cmd(e, "PIN", 0, SRK_password, NULL, 0);

  The default secret mode is TSS_SECRET_MODE_PLAIN, so the above code will
always work with a plaintext SRK secret.  If you have the hash of your secret,
do this:

  ENGINE_ctrl_cmd(e, "SECRET_MODE", TSS_SECRET_MODE_SHA1, NULL, NULL, 0);
  ENGINE_ctrl_cmd(e, "PIN", 0, SRK_password_hash, NULL, 0);

  To force the TSS to popup a dialog prompting you for your SRK password:

  ENGINE_ctrl_cmd(e, "SECRET_MODE", TSS_SECRET_MODE_POPUP, NULL, NULL, 0);


OpenSSL TPM engine

  Included in this package is a sample openssl.cnf file, which can be used
to turn on use of the TPM engine in apps where OpenSSL config support is
compiled in.


USE CASES

  If there's a use case for the TPM engine that you'd like to see it support,
please drop a line to trousers-users@lists.sf.net.

USES

Create a self-signed cert using the TPM engine:

1. Generate a TPM key and write it to a file:
 $ create_tpm_key

2. Make the openssl certificate request:
 $ openssl req -keyform engine -engine tpm -key -new -x509 -days 365 -out

3. Test using openssl:
 $ openssl s_server -cert -www -accept 4433 -keyform engine -engine tpm -key
 $ konqueror https://localhost:4433
Suivons donc ces conseils:

Nous créons une paire de clés
~$ create_tpm_key -a maclef
créons un certificat autosigné
~$ openssl req -keyform engine -engine tpm -key ./maclef -new -x509 -days 365 -out moncert
testons ce certificat
$ openssl s_server -cert moncert -www -accept 4433 -keyform engine -engine tpm -key maclef
$ firefox https://localhost:4433


ecryptfs

installation

installons ecryptfs-utils
~# apt-get install ecryptfs-utils
lancons le daemon ecryptfsd. Il est nécessaire pour gérér les clés publiques
~# ecryptfsd

utilisation

créons un répertoire qui contiendra nos documents chiffrés
~# mkdir /secret
montons le système de fichiers chiffré avec ecrypts:
~# mount -t ecryptfs /secret /secret -o key=openssl_keyfile=~/maclef -o ecryptfs_cipher=aes -o ecryptfs_key_bytes=32 -o no_sig_cache -o ecryptfs_enable_filename_crypto=y -o ecryptfs_passthrough=n

Passphrase:

Filename Encryption Key (FNEK) Signature [72da151dc29cf399]:

Attempting to mount with the following options:
  ecryptfs_unlink_sigs
  ecryptfs_fnek_sig=72da151dc29cf399
  ecryptfs_key_bytes=32
  ecryptfs_cipher=aes
  ecryptfs_sig=72da151dc29cf399
Mounted eCryptfs
créons un fichier dans le répertoire /secret
~# cd /secret
/secret# echo "bonjour" > ./essai
/secret# cat essai
bonjour
démontons notre répertoire secret
/secret# cd ~
~# umount /secret
voyons à présent à quoi il ressemble


Le nom de fichier (et le contenu) ont bien été chiffrés avec notre clef.

accédons à notre répertoire chiffré (veillons à garder les mêmes passphrase et FNEK)
~# mount -t ecryptfs /secret /secret -o key=openssl_keyfile=~/maclef -o ecryptfs_cipher=aes -o ecryptfs_key_bytes=32 -o no_sig_cache -o ecryptfs_enable_filename_crypto=y -o ecryptfs_passthrough=n
Passphrase:
Filename Encryption Key (FNEK) Signature [72da151dc29cf399]:
Attempting to mount with the following options:
  ecryptfs_unlink_sigs
  ecryptfs_fnek_sig=72da151dc29cf399
  ecryptfs_key_bytes=32
  ecryptfs_cipher=aes
  ecryptfs_sig=72da151dc29cf399
Mounted eCryptfs
effectivement ca marche:
~# cat /secret/essai
bonjour

références:

1) tpm tools - http://sourceforge.net/projects/trousers/
2) how to use a tpm with linux - https://www.grounation.org/index.php?post/2008/07/04/8-how-to-use-a-tpm-with-linux
3) Emmanuel Fleury et Noémie Floissac - quelle confiance accorder au trusted platforms - MISC n° 45 septembre/octobre 2009
4) Noémie Floissac - quel avenir pour les trusted platforms
5) Hans Brandl - infineon technologies - Trusted computing: the TCG trusted platform module specification
6) Windows trusted platform module management step-by-step guide - http://technet.microsoft.com/en-us/library/cc749022%28WS.10%29.aspx
7) SRK - http://docs.hp.com/en/5991-7466/ch01s03.html
8) tpm keys - http://www.cs.bham.ac.uk/~mdr/teaching/modules/security/lectures/TrustedComputingTCG.html
9) installer ecryptfs - http://publib.boulder.ibm.com/infocenter/lnxinfo/v3r0m0/index.jsp?topic=/liaai/ecrypts/liaaiecryptfstroub.htm
10) IBM embedded security subsystem - http://www.thinkwiki.org/wiki/Embedded_Security_Subsystem
11) ecryptfs faq - http://ecryptfs.sourceforge.net/ecryptfs-faq.html

1 commentaire:

  1. Bonsoir,
    Merci pour votre article, il est clair et bien rédigé. Cependant la secondes partie sur ecryptfs pourrait être refaite car là nous n'utilisons pas la TPM mais une simple passPhrase. Il aurais fallut si nécessaire expliquer comment rebuild ecryptfs-utils, intégrer le module de keyring pour openssl(qui n'est pas embarqué de base dans ecryptfs car basé sur du code proprio il me semble)...bref, vous en avez déjà dis beaucoup, et il est encore possible de creuser.
    Merci,
    Korigan

    RépondreSupprimer