PKI hors ligne avec 3 YubiKeys et une carte ARM

Vincent Bernat

Une PKI hors ligne ren­force la sé­cu­rité en iso­lant phy­si­que­ment l’au­to­rité de cer­ti­fi­ca­tion des me­naces ré­seau. Une Yubi­Key est une so­lu­tion éco­no­mique pour sto­cker un cer­ti­fi­cat ra­cine. Vous avez éga­le­ment be­soin d’un en­vi­ron­ne­ment isolé pour les opé­ra­tions sur l’au­to­rité de cer­ti­fi­ca­tion racine.

PKI s'appuyant sur un ensemble de 3 YubiKeys : 2 pour l'autorité de
certification racine et 1 pour l'autorité de certification
intermédiaire.
PKI hors ligne sauvegardée par 3 YubiKeys

Ce billet dé­crit un sys­tème PKI hors ligne uti­li­sant les com­po­sants suivants :

  • 2 Yubi­Keys pour l’au­to­rité de cer­ti­fi­ca­tion ra­cine (avec une va­li­dité de 20 ans) ;
  • 1 Yubi­Key pour l’au­to­rité de cer­ti­fi­ca­tion in­ter­mé­diaire (avec une va­li­dité de 5 ans) ;
  • 1 carte Libre Com­pu­ter Sweet Po­tato comme nano-or­di­na­teur isolé.

Si né­ces­saire, il est pos­sible d’ajou­ter plus de Yubi­Keys comme sau­ve­garde de l’au­to­rité de cer­ti­fi­ca­tion ra­cine. Ce n’est pas utile pour l’au­to­rité de cer­ti­fi­ca­tion in­ter­mé­diaire car vous pou­vez en gé­né­rer une nou­velle si l’ac­tuelle est détruite.

La partie logicielle#

offline-pki est une pe­tite ap­pli­ca­tion Py­thon pour gé­rer une PKI hors ligne. Elle s’ap­puie sur yu­bi­key-ma­na­ger pour gé­rer les Yubi­Keys et sur cryp­to­gra­phy pour les opé­ra­tions cryp­to­gra­phiques non exé­cu­tées par les Yubi­Keys. L’ap­pli­ca­tion a cer­tains choix de concep­tion opi­niâtres. No­tam­ment, la cryp­to­gra­phie est co­dée en dur pour uti­li­ser la courbe el­lip­tique NIST P-384.

La pre­mière étape consiste à ré­ini­tia­li­ser toutes vos YubiKeys :

$ offline-pki yubikey reset
This will reset the connected YubiKey. Are you sure? [y/N]: y
New PIN code:
Repeat for confirmation:
New PUK code:
Repeat for confirmation:
New management key ('.' to generate a random one):
WARNING[pki-yubikey] Using random management key: e8ffdce07a4e3bd5c0d803aa3948a9c36cfb86ed5a2d5cf533e97b088ae9e629
INFO[pki-yubikey]  0: Yubico YubiKey OTP+FIDO+CCID 00 00
INFO[pki-yubikey] SN: 23854514
INFO[yubikit.management] Device config written
INFO[yubikit.piv] PIV application data reset performed
INFO[yubikit.piv] Management key set
INFO[yubikit.piv] New PUK set
INFO[yubikit.piv] New PIN set
INFO[pki-yubikey] YubiKey reset successful!

En­suite, gé­né­rez l’au­to­rité de cer­ti­fi­ca­tion ra­cine et créez au­tant de co­pies que vous voulez :

$ offline-pki certificate root --permitted example.com
Management key for Root X:
Plug YubiKey "Root X"...
INFO[pki-yubikey]  0: Yubico YubiKey CCID 00 00
INFO[pki-yubikey] SN: 23854514
INFO[yubikit.piv] Data written to object slot 0x5fc10a
INFO[yubikit.piv] Certificate written to slot 9C (SIGNATURE), compression=True
INFO[yubikit.piv] Private key imported in slot 9C (SIGNATURE) of type ECCP384
Copy root certificate to another YubiKey? [y/N]: y
Plug YubiKey "Root X"...
INFO[pki-yubikey]  0: Yubico YubiKey CCID 00 00
INFO[pki-yubikey] SN: 23854514
INFO[yubikit.piv] Data written to object slot 0x5fc10a
INFO[yubikit.piv] Certificate written to slot 9C (SIGNATURE), compression=True
INFO[yubikit.piv] Private key imported in slot 9C (SIGNATURE) of type ECCP384
Copy root certificate to another YubiKey? [y/N]: n

Vous pou­vez exa­mi­ner le résultat :

$ offline-pki yubikey info
INFO[pki-yubikey]  0: Yubico YubiKey CCID 00 00
INFO[pki-yubikey] SN: 23854514
INFO[pki-yubikey] Slot 9C (SIGNATURE):
INFO[pki-yubikey]   Private key type: ECCP384
INFO[pki-yubikey]   Public key:
INFO[pki-yubikey]     Algorithm:  secp384r1
INFO[pki-yubikey]     Issuer:     CN=Root CA
INFO[pki-yubikey]     Subject:    CN=Root CA
INFO[pki-yubikey]     Serial:     1
INFO[pki-yubikey]     Not before: 2024-07-05T18:17:19+00:00
INFO[pki-yubikey]     Not after:  2044-06-30T18:17:19+00:00
INFO[pki-yubikey]     PEM:
-----BEGIN CERTIFICATE-----
MIIBcjCB+aADAgECAgEBMAoGCCqGSM49BAMDMBIxEDAOBgNVBAMMB1Jvb3QgQ0Ew
HhcNMjQwNzA1MTgxNzE5WhcNNDQwNjMwMTgxNzE5WjASMRAwDgYDVQQDDAdSb290
IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAERg3Vir6cpEtB8Vgo5cAyBTkku/4w
kXvhWlYZysz7+YzTcxIInZV6mpw61o8W+XbxZV6H6+3YHsr/IeigkK04/HJPi6+i
zU5WJHeBJMqjj2No54Nsx6ep4OtNBMa/7T9foyMwITAPBgNVHRMBAf8EBTADAQH/
MA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAwNoADBlAjEAwYKy/L8leJyiZSnn
xrY8xv8wkB9HL2TEAI6fC7gNc2bsISKFwMkyAwg+mKFKN2w7AjBRCtZKg4DZ2iUo
6c0BTXC9a3/28V5aydZj6rvx0JqbF/Ln5+RQL6wFMLoPIvCIiCU=
-----END CERTIFICATE-----

En­suite, vous pou­vez créer un cer­ti­fi­cat in­ter­mé­diaire avec offline-pki yubikey intermediate et l’uti­li­ser pour si­gner des cer­ti­fi­cats en four­nis­sant leur CSR à offline-pki certificate sign. Soyez pru­dent et ins­pec­tez la CSR avant de la si­gner, car seul le nom du su­jet peut être rem­placé. Consul­tez la do­cu­men­ta­tion pour plus de dé­tails. Ob­te­nez les op­tions dis­po­nibles en uti­li­sant l’op­tion --help.

La partie matérielle#

Pour ga­ran­tir que les opé­ra­tions sur les au­to­ri­tés de cer­ti­fi­ca­tion ra­cine et in­ter­mé­diaire sont iso­lées du ré­seau, une so­lu­tion éco­no­mique consiste à uti­li­ser une carte ARM64. Le Libre Com­pu­ter Sweet Po­tato est une al­ter­na­tive plus ou­verte au cé­lèbre Rasp­berry Pi1.

Ordinateur monocarte Libre Computer Sweet Potato s'appuyant sur le SOC Amlogic
S905X
SBC Libre Computer Sweet Potato, alimenté par le SOC AML-S905X

J’in­ter­agis avec lui via un conver­tis­seur USB vers série :

$ tio /dev/ttyUSB0
[16:40:44.546] tio v3.7
[16:40:44.546] Press ctrl-t q to quit
[16:40:44.555] Connected to /dev/ttyUSB0
GXL:BL1:9ac50e:bb16dc;FEAT:ADFC318C:0;POC:1;RCY:0;SPI:0;0.0;CHK:0;
TE: 36574

BL2 Built : 15:21:18, Aug 28 2019. gxl g1bf2b53 - luan.yuan@droid15-sz

set vcck to 1120 mv
set vddee to 1000 mv
Board ID = 4
CPU clk: 1200MHz
[…]

L’assemblage Nix#

Pour col­ler tout en­semble, j’uti­lise Nix avec un Flake four­nissant :

  • un pa­quet pour l’ap­pli­ca­tion offline-pki, avec la com­plé­tion pour le shell ;
  • un shell de dé­ve­lop­pe­ment, in­cluant une ver­sion édi­table de l’ap­pli­ca­tion offline-pki ;
  • un mo­dule NixOS pour confi­gu­rer la PKI, ré­ini­tia­li­sant le sys­tème à chaque dé­marrage ;
  • une image QEMU pour les tests ;
  • une image de carte SD à uti­li­ser sur le Sweet Po­tato ou une autre carte ARM64.
# Exécuter localement l'application
nix run github:vincentbernat/offline-pki -- --help
# Exécuter l'application dans une machine virtuelle QEMU
nix run github:vincentbernat/offline-pki\#qemu
# Construire l'image d'une carte SD pour Sweet Potato ou un Raspberry Pi
nix build --system aarch64-linux github:vincentbernat/offline-pki\#sdcard.potato
nix build --system aarch64-linux github:vincentbernat/offline-pki\#sdcard.generic
# Obtenir un shell de développement avec l'application
nix develop github:vincentbernat/offline-pki