Comment puis-je chiffrer des octets à l'aide du module TPM d'une machine?
CryptProtectData
Windows fournit une API (relativement) simple pour chiffrer un objet blob à l'aide de l' CryptProtectData
API, que nous pouvons encapsuler dans une fonction facile à utiliser:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Les détails de ProtectBytes
sont moins importants que l'idée que vous pouvez l'utiliser assez facilement:
- voici les octets que je souhaite chiffrer par une clé secrète contenue dans le
System
- rendez-moi le blob chiffré
Le blob retourné est une structure de documentation non documentée qui contient tout le nécessaire pour décrypter et renvoyer les données d'origine (algorithme de hachage, algorithme de chiffrement, salt, signature HMAC, etc.).
Pour être complet, voici l'exemple d'implémentation de pseudocode de ProtectBytes
qui utilise le Crypt API
pour protéger les octets:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//Setup our n-byte plaintext blob
DATA_BLOB dataIn;
dataIn.cbData = plaintext.Length;
dataIn.pbData = Addr(plaintext[0]);
DATA_BLOB dataOut;
//dataOut = EncryptedFormOf(dataIn)
BOOL bRes = CryptProtectData(
dataIn,
null, //data description (optional PWideChar)
null, //optional entropy (PDATA_BLOB)
null, //reserved
null, //prompt struct
CRYPTPROTECT_UI_FORBIDDEN || CRYPTPROTECT_LOCAL_MACHINE,
ref dataOut);
if (!bRes) then
{
DWORD le = GetLastError();
throw new Win32Error(le, "Error calling CryptProtectData");
}
//Copy ciphertext from dataOut blob into an actual array
bytes[] result;
SetLength(result, dataOut.cbData);
CopyMemory(dataOut.pbData, Addr(result[0]), dataOut.cbData);
//When you have finished using the DATA_BLOB structure, free its pbData member by calling the LocalFree function
LocalFree(HANDLE(dataOut.pbData)); //LocalFree takes a handle, not a pointer. But that's what the SDK says.
}
Comment faire de même avec le TPM?
Le code ci-dessus est utile pour crypter les données de la machine locale uniquement. Les données sont cryptées en utilisant le System
compte comme générateur de clé (les détails, bien qu'intéressants, ne sont pas importants ). Le résultat final est que je peux crypter des données (par exemple une clé principale de cryptage du disque dur) qui ne peuvent être décryptées que par la machine locale.
Il est maintenant temps d'aller plus loin. Je souhaite chiffrer certaines données (par exemple, une clé principale de chiffrement du disque dur) qui ne peuvent être déchiffrées que par le TPM local. En d'autres termes, je souhaite remplacer le Qualcomm Trusted Execution Environment ( TEE ) dans le diagramme ci-dessous pour Android, par le TPM sous Windows:
Remarque : je me rends compte que le TPM ne fait pas de signature de données (ou s'il le fait, il ne garantit pas que la signature des mêmes données donnera la même sortie binaire à chaque fois). C'est pourquoi je serais prêt à remplacer «signature RSA» par «chiffrement d'un objet blob 256 bits avec une clé liée au matériel» .
Alors, où est le code?
Le problème est que la programmation TPM est complètement non documentée sur MSDN . Aucune API n'est disponible pour effectuer des opérations. Au lieu de cela, vous devez vous trouver une copie de la pile logicielle du Trusted Computing Group (alias TSS) , déterminer les commandes à envoyer au TPM, avec les charges utiles, dans quel ordre, et appeler la fonction Tbsip_Submit_Command de Windows pour soumettre des commandes directement:
TBS_RESULT Tbsip_Submit_Command(
_In_ TBS_HCONTEXT hContext,
_In_ TBS_COMMAND_LOCALITY Locality,
_In_ TBS_COMMAND_PRIORITY Priority,
_In_ const PCBYTE *pabCommand,
_In_ UINT32 cbCommand,
_Out_ PBYTE *pabResult,
_Inout_ UINT32 *pcbOutput
);
Windows n'a pas d'API de niveau supérieur pour effectuer des actions.
C'est l'équivalent moral d'essayer de créer un fichier texte en émettant des commandes d'E / S SATA sur votre disque dur .
Pourquoi ne pas simplement utiliser des pantalons
Le Trusted Computing Group (TCG) a défini sa propre API: TCB Software Stack (TSS) . Une implémentation de cette API a été créée par certaines personnes et s'appelle TrouSerS . Un gars a ensuite porté ce projet sur Windows .
Le problème avec ce code est qu'il n'est pas portable dans le monde Windows. Par exemple, vous ne pouvez pas l'utiliser depuis Delphi, vous ne pouvez pas l'utiliser depuis C #. Cela demande:
- OpenSSL
- pThread
Je veux juste que le code crypte quelque chose avec mon TPM.
Ce qui précède CryptProtectData
ne nécessite rien d'autre que ce qui est dans le corps de la fonction.
Quel est le code équivalent pour crypter des données à l'aide du TPM? Comme d'autres l'ont noté, vous devez probablement consulter les trois manuels TPM et créer vous-même les objets blob . Cela implique probablement la TPM_seal
commande. Bien que je pense que je ne veux pas sceller les données, je pense que je veux les lier :
Liaison - chiffre les données à l'aide de la clé de liaison TPM, une clé RSA unique descendant d'une clé de stockage. Scellement - crypte les données de la même manière que la liaison, mais spécifie en outre un état dans lequel le TPM doit être pour que les données soient décryptées (descellées)
J'essaye de lire les trois volumes requis afin de trouver les 20 lignes de code dont j'ai besoin:
Mais je n'ai aucune idée de ce que je lis. S'il y avait une sorte de tutoriel ou d'exemples, je pourrais avoir une chance. Mais je suis complètement perdu.
Nous demandons donc à Stackoverflow
De la même manière j'ai pu fournir:
Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
//...
CryptProtectData(...);
//...
}
quelqu'un peut-il fournir l'équivalent correspondant:
Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
//...
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
//...snip...
Tbsip_Submit_Command(...);
//...
}
qui fait la même chose, sauf plutôt qu'une clé enfermée dans System
LSA, est enfermée dans le TPM?
Début de la recherche
Je ne sais pas exactement ce que signifie bind . Mais en regardant TPM Main - Part 3 Commands - Specification Version 1.2, il y a une mention de bind :
10.3 TPM_UnBind
TPM_UnBind prend le blob de données qui est le résultat d'une commande Tspi_Data_Bind et le déchiffre pour l'exportation vers l'utilisateur. L'appelant doit autoriser l'utilisation de la clé qui décryptera l'objet blob entrant. TPM_UnBind fonctionne bloc par bloc et n'a aucune notion de relation entre un bloc et un autre.
Ce qui est déroutant, c'est qu'il n'y a pas de Tspi_Data_Bind
commande.
Effort de recherche
Il est horrible de voir que personne ne s'est jamais donné la peine de documenter le TPM ou son fonctionnement. C'est comme s'ils passaient tout leur temps à trouver ce truc sympa avec lequel jouer, mais ne voulaient pas faire face à l'étape douloureuse de le rendre utilisable pour quelque chose.
À partir du livre (maintenant) gratuit Un guide pratique de TPM 2.0: Utilisation du module Trusted Platform dans le nouvel âge de la sécurité :
Chapitre 3 - Tutoriel rapide sur TPM 2.0
Le TPM a accès à une clé privée auto-générée. Il peut donc chiffrer les clés avec une clé publique, puis stocker l'objet blob résultant sur le disque dur. De cette façon, le TPM peut conserver un nombre pratiquement illimité de clés disponibles pour une utilisation sans gaspiller de précieux stockage interne. Les clés stockées sur le disque dur peuvent être effacées, mais elles peuvent également être sauvegardées, ce qui a semblé aux concepteurs comme un compromis acceptable.
Comment puis-je chiffrer une clé avec la clé publique du TPM?
Chapitre 4 - Applications existantes utilisant des TPM
Applications qui devraient utiliser le TPM mais pas
Au cours des dernières années, le nombre d'applications Web a augmenté. Parmi eux, il y a la sauvegarde et le stockage sur le Web. Un grand nombre d'entreprises proposent désormais de tels services, mais à notre connaissance, aucun des clients de ces services ne permet à l'utilisateur de verrouiller la clé du service de sauvegarde sur un TPM. Si cela était fait, ce serait certainement bien si la clé TPM elle-même était sauvegardée en la dupliquant sur plusieurs machines. Cela semble être une opportunité pour les développeurs.
Comment un développeur verrouille-t-il une clé du TPM?
Chapitre 9 - Héritarchies
CAS D'UTILISATION: ENREGISTREMENT DES MOTS DE PASSE DE CONNEXION
Un fichier de mots de passe typique stocke des hachages salés de mots de passe. La vérification consiste à saler et hacher un mot de passe fourni et à le comparer à la valeur stockée. Étant donné que le calcul n'inclut pas de secret, il est soumis à une attaque hors ligne sur le fichier de mots de passe.
Ce cas d'utilisation utilise une clé HMAC générée par TPM. Le fichier de mot de passe stocke un HMAC du mot de passe salé. La vérification consiste à saler et HMACing le mot de passe fourni et à le comparer à la valeur enregistrée. Étant donné qu'un attaquant hors ligne n'a pas la clé HMAC, l'attaquant ne peut pas monter une attaque en effectuant le calcul.
Cela pourrait fonctionner. Si le TPM a une clé HMAC secrète et que seul mon TPM connaît la clé HMAC, alors je pourrais remplacer «Sign (aka TPM chiffrer avec sa clé privée)» par «HMAC». Mais alors dans la ligne suivante, il se renverse complètement:
TPM2_Create, spécification d'une clé HMAC
Ce n'est pas un secret TPM si je dois spécifier la clé HMAC. Le fait que la clé HMAC ne soit pas secrète a du sens lorsque vous réalisez qu'il s'agit du chapitre sur les utilitaires cryptographiques fournis par le TPM. Plutôt que de devoir écrire vous-même SHA2, AES, HMAC ou RSA, vous pouvez réutiliser ce que le TPM a déjà en place.
Chapitre 10 - Clés
En tant que dispositif de sécurité, la capacité d'une application à utiliser des clés tout en les gardant en sécurité dans un périphérique matériel est la plus grande force du TPM. Le TPM peut à la fois générer et importer des clés générées en externe. Il prend en charge les clés asymétriques et symétriques.
Excellent! Comment faites-vous!?
Générateur de clés
On peut soutenir que la plus grande force du TPM est sa capacité à générer une clé cryptographique et à protéger son secret dans une limite matérielle. Le générateur de clés est basé sur le propre générateur de nombres aléatoires du TPM et ne repose pas sur des sources externes d'aléa. Il élimine ainsi les faiblesses basées sur des logiciels faibles avec une source d'entropie insuffisante.
Le TPM a- t -il la capacité de générer des clés cryptographiques et de protéger ses secrets dans une limite matérielle? Est-ce vrai, comment?
Chapitre 12 - Registres de configuration de plate-forme
RAP pour autorisation
CAS D'UTILISATION: SCELLER UNE CLÉ DE CRYPTION DE DISQUE DUR À L'ÉTAT DE LA PLATEFORME
Les applications de chiffrement de disque complet sont beaucoup plus sécurisées si un TPM protège la clé de chiffrement que si elle est stockée sur le même disque, protégé uniquement par un mot de passe. Tout d'abord, le matériel TPM dispose d'une protection anti-marteau (voir le chapitre 8 pour une description détaillée de la protection contre les attaques par dictionnaire TPM), ce qui rend impossible une attaque par force brute sur le mot de passe. Une clé protégée uniquement par un logiciel est beaucoup plus vulnérable à un mot de passe faible. Deuxièmement, une clé logicielle stockée sur le disque est beaucoup plus facile à voler. Prenez le disque (ou une sauvegarde du disque) et vous obtenez la clé. Lorsqu'un TPM détient la clé, la plate-forme entière, ou au moins le disque et la carte mère, doit être volée.
Le scellement permet à la clé d'être protégée non seulement par un mot de passe, mais par une politique. Une politique typique verrouille la clé aux valeurs PCR (l'état du logiciel) en cours au moment du scellage. Cela suppose que l'état au premier démarrage n'est pas compromis. Tout logiciel malveillant préinstallé présent au premier démarrage serait mesuré dans les PCR, et ainsi la clé serait scellée à un état logiciel compromis. Une entreprise moins fiable peut avoir une image disque standard et être scellée aux PCR représentant cette image. Ces valeurs PCR seraient précalculées sur une plateforme vraisemblablement plus fiable. Une entreprise encore plus sophistiquée utiliserait TPM2_PolicyAuthorize et fournirait plusieurs tickets autorisant un ensemble de valeurs PCR fiables. Voir le chapitre 14 pour une description détaillée de la politique d'autorisation et de son application pour résoudre le problème de PCRbrittleness.
Bien qu'un mot de passe puisse également protéger la clé, il existe un gain de sécurité même sans mot de passe de clé TPM. Un attaquant pourrait démarrer la plateforme sans fournir de mot de passe TPMkey, mais ne pourrait pas se connecter sans le nom d'utilisateur et le mot de passe du système d'exploitation. La sécurité du système d'exploitation protège les données. L'attaquant pourrait démarrer un système d'exploitation alternatif, par exemple à partir d'un DVD ou d'une clé USB en direct plutôt qu'à partir du disque dur, pour contourner la sécurité de connexion du système d'exploitation. Cependant, cette configuration de démarrage et ce logiciel différents modifieraient les valeurs PCR. Étant donné que ces nouveaux PCR ne correspondraient pas aux valeurs scellées, le TPM ne libérerait pas la clé de déchiffrement et le disque dur ne pouvait pas être déchiffré.
Excellent! C'est exactement le cas d'utilisation que je souhaite. C'est également le cas d'utilisation pour lequel Microsoft utilise le TPM. Comment fait-on ça!?
J'ai donc lu tout ce livre, et il n'a rien fourni d'utile. Ce qui est assez impressionnant car il fait 375 pages. Vous vous demandez ce que contient le livre - et en y repensant, je n'en ai aucune idée.
Nous abandonnons donc le guide définitif de programmation du TPM et nous nous tournons plutôt vers une documentation de Microsoft:
À partir de la boîte à outils du fournisseur de chiffrement de la plate-forme Microsoft TPM . Il mentionne exactement ce que je veux faire:
La clé d'approbation ou EK
L'EK est conçu pour fournir un identifiant cryptographique fiable pour la plateforme. Une entreprise peut maintenir une base de données des clés d'approbation appartenant aux TPM de tous les PC de son entreprise, ou un contrôleur de structure de centre de données peut avoir une base de données des TPM dans toutes les lames. Sous Windows, vous pouvez utiliser le fournisseur NCrypt décrit dans la section «Platform Crypto Provider dans Windows 8» pour lire la partie publique de l'EK.
Quelque part à l'intérieur du TPM se trouve une clé privée RSA. Cette clé est enfermée là-dedans - pour ne jamais être vue par le monde extérieur. Je veux que le TPM signe quelque chose avec sa clé privée (c'est-à-dire le crypte avec sa clé privée).
Je veux donc l' opération la plus basique qui puisse exister:
Cryptez quelque chose avec votre clé privée. Je ne demande même pas (encore) les choses les plus compliquées:
- "sceller" il en fonction de l'état de la PCR
- créer une clé et la stocker dans une mémoire volatile ou non volatile
- créer une clé symétrique et essayer de la charger dans le TPM
Je demande l'opération la plus élémentaire qu'un TPM peut effectuer. Pourquoi est-il impossible d'obtenir des informations sur la façon de procéder?
Je peux obtenir des données aléatoires
Je suppose que j'étais désinvolte quand j'ai dit que la signature RSA était la chose la plus élémentaire que le TPM puisse faire. La chose la plus basique que l'on puisse demander au TPM est de me donner des octets aléatoires. Que j'ai compris comment faire:
public Byte[] GetRandomBytesTPM(int desiredBytes)
{
//The maximum random number size is limited to 4,096 bytes per call
Byte[] result = new Byte[desiredBytes];
BCRYPT_ALG_HANDLE hAlgorithm;
BCryptOpenAlgorithmProvider(
out hAlgorithm,
BCRYPT_RNG_ALGORITHM, //AlgorithmID: "RNG"
MS_PLATFORM_CRYPTO_PROVIDER, //Implementation: "Microsoft Platform Crypto Provider" i.e. the TPM
0 //Flags
);
try
{
BCryptGenRandom(hAlgorithm, @result[0], desiredBytes, 0);
}
finally
{
BCryptCloseAlgorithmProvider(hAlgorithm);
}
return result;
}
La fantaisie
Je me rends compte que le nombre de personnes utilisant le TPM est très faible. C'est pourquoi personne sur Stackoverflow n'a de réponse. Je ne peux donc pas vraiment devenir trop gourmand pour trouver une solution à mon problème commun. Mais ce que je voudrais vraiment faire est de «sceller» certaines données:
- présenter au TPM des données (par exemple 32 octets de matériel clé)
- faire crypter les données par le TPM, renvoyant une structure blob opaque
- demander plus tard au TPM de décrypter l'objet blob
- le décryptage ne fonctionnera que si les registres PCR du TPM sont les mêmes que lors du cryptage.
En d'autres termes:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Cryptography Next Gen (Cng, alias BCrypt) prend en charge le TPM
L'API de cryptographie d'origine de Windows était connue sous le nom d'API Crypto.
À partir de Windows Vista, l'API Crypto a été remplacée par l' API Cryptography: Next Generation (connue en interne sous le nom de BestCrypt , en abrégé BCrypt , à ne pas confondre avec l'algorithme de hachage de mot de passe ).
Windows est livré avec deux fournisseurs BCrypt :
- Microsoft Primitive Provider (
MS_PRIMITIVE_PROVIDER
) par défaut : implémentation logicielle par défaut de toutes les primitives (hachage, cryptage symétrique, signatures numériques, etc.) - Microsoft Platform Crypto Provider (
MS_PLATFORM_CRYPTO_PROVIDER
): fournisseur qui fournit un accès au TPM
Le fournisseur Platform Crypto n'est pas documenté sur MSDN, mais dispose de la documentation d'un site Microsoft Research 2012:
Boîte à outils du fournisseur de chiffrement de la plateforme TPM
Le fournisseur de chiffrement et la boîte à outils de la plate-forme TPM contient des exemples de code, des utilitaires et de la documentation pour l'utilisation des fonctionnalités liées au TPM dans Windows 8. Les sous-systèmes décrits incluent le fournisseur de chiffrement de la plate-forme Crypto-Next-Gen (CNG) soutenu par TPM et comment les fournisseurs de services d'attestation peut utiliser les nouvelles fonctionnalités de Windows. Les systèmes basés sur TPM1.2 et TPM2.0 sont pris en charge.
Il semble que l'intention de Microsoft soit de présenter la fonctionnalité de cryptage TPM avec le fournisseur de cryptage de plate-forme Microsoft de l' API Cryptography NG .
Chiffrement par clé publique à l'aide de Microsoft BCrypt
Étant donné que:
- je souhaite effectuer un cryptage asymétrique RSA (à l'aide du TPM)
- Microsoft BestCrypt prend en charge le cryptage asymétrique RSA
- Microsoft BestCrypt a un fournisseur TPM
une façon peut - être avant de savoir comment faire la signature numérique en utilisant l' API Microsoft Cryptography Next Gen .
Ma prochaine étape sera de trouver le code pour faire le cryptage dans BCrypt, avec une clé publique RSA, en utilisant le fournisseur standard ( MS_PRIMITIVE_PROVIDER
). Par exemple:
modulus
: 0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55publicExponent
: 65537
Avec ce code fonctionnant, je pourrai peut-être passer à l'utilisation du fournisseur TPM ( MS_PLATFORM_CRYPTO_PROVIDER
).
22/02/2016: Et avec Apple étant obligé d'aider à déchiffrer les données des utilisateurs, il y a un regain d'intérêt pour la façon dont le TPM exécute la tâche la plus simple pour laquelle il a été inventé - chiffrer quelque chose.
C'est à peu près l'équivalent du fait que tout le monde possède une voiture, mais personne ne sait comment en démarrer une. Cela peut faire des choses vraiment utiles et intéressantes, si seulement nous pouvions passer l' étape 1 .