windows - infineon - virtual trusted platform module



Como criptografar bytes usando o TPM(Trusted Platform Module) (2)

Chaves confiáveis ​​e criptografadas

Chaves confiáveis ​​e criptografadas são dois novos tipos de chave adicionados ao serviço de conjunto de chaves do kernel existente. Esses dois novos tipos são chaves simétricas de comprimento variável e, em ambos os casos, todas as chaves são criadas no kernel, e o espaço do usuário vê, armazena e carrega apenas blobs criptografados. As chaves confiáveis ​​exigem a disponibilidade de um chip TPM (Trusted Platform Module) para maior segurança, enquanto as chaves criptografadas podem ser usadas em qualquer sistema. Todos os blobs no nível do usuário são exibidos e carregados em hex ascii por conveniência e são verificados quanto à integridade.

Chaves confiáveis ​​use um TPM para gerar e selar as chaves. As chaves são seladas sob uma chave RSA de 2048 bits no TPM e, opcionalmente, seladas nos valores especificados de PCR (medição de integridade), e não seladas somente pelo TPM, se as verificações de integridade de PCRs e de correspondência corresponderem. Uma chave confiável carregada pode ser atualizada com novos valores de PCR (futuros), para que as chaves sejam facilmente migradas para novos valores de pcr, como quando o kernel e o initramfs são atualizados. A mesma chave pode ter muitos blobs salvos sob diferentes valores de PCR, para que várias inicializações sejam facilmente suportadas.

Por padrão, as chaves confiáveis ​​são seladas no SRK, que possui o valor de autorização padrão (20 zeros). Isso pode ser definido no momento da tpm_takeownership -u -z com o utilitário da calça: tpm_takeownership -u -z .

Usage:
    keyctl add trusted name "new keylen [options]" ring
    keyctl add trusted name "load hex_blob [pcrlock=pcrnum]" ring
    keyctl update key "update [options]"
    keyctl print keyid

    options:
    keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
    keyauth=   ascii hex auth for sealing key default 0x00...i
        (40 ascii zeros)
    blobauth=  ascii hex auth for sealed data default 0x00...
        (40 ascii zeros)
    blobauth=  ascii hex auth for sealed data default 0x00...
        (40 ascii zeros)
    pcrinfo=   ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
    pcrlock=   pcr number to be extended to "lock" blob
    migratable= 0|1 indicating permission to reseal to new PCR values,
                default 1 (resealing allowed)

keyctl print retorna uma cópia hexadecimal ascii da chave selada, que está no formato padrão TPM_STORED_DATA. O comprimento da chave para novas chaves está sempre em bytes. As chaves confiáveis ​​podem ter entre 32 e 128 bytes (256 - 1024 bits), o limite superior é o tamanho da chave SRK (RSA) de 2048 bits, com toda a estrutura / preenchimento necessário.

As chaves criptografadas não dependem de um TPM e são mais rápidas, pois usam o AES para criptografia / descriptografia. Novas chaves são criadas a partir de números aleatórios gerados pelo kernel e são criptografadas / descriptografadas usando uma chave 'mestre' especificada. A chave 'mestre' pode ser do tipo chave confiável ou chave do usuário. A principal desvantagem das chaves criptografadas é que, se não estiverem enraizadas em uma chave confiável, elas são tão seguras quanto a chave do usuário que as criptografa. A chave de usuário mestre deve, portanto, ser carregada da maneira mais segura possível, de preferência no início da inicialização.

A parte descriptografada das chaves criptografadas pode conter uma chave simétrica simples ou uma estrutura mais complexa. O formato da estrutura mais complexa é específico da aplicação, identificado por 'formato'.

Usage:
    keyctl add encrypted name "new [format] key-type:master-key-name keylen"
        ring
    keyctl add encrypted name "load hex_blob" ring
    keyctl update keyid "update key-type:master-key-name"

format:= 'default | ecryptfs'
key-type:= 'trusted' | 'user'

Exemplos de uso de chave confiável e criptografada

Crie e salve uma chave confiável chamada "kmk" de 32 bytes de comprimento:

$ keyctl add trusted kmk "new 32" @u
440502848

$ keyctl show
Session Keyring
       -3 --alswrv    500   500  keyring: _ses
 97833714 --alswrv    500    -1   \_ keyring: _uid.500
440502848 --alswrv    500   500       \_ trusted: kmk

$ keyctl print 440502848
0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
e4a8aea2b607ec96931e6f4d4fe563ba

$ keyctl pipe 440502848 > kmk.blob

Carregue uma chave confiável no blob salvo:

$ keyctl add trusted kmk "load `cat kmk.blob`" @u
268728824

$ keyctl print 268728824
0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
e4a8aea2b607ec96931e6f4d4fe563ba

Sele novamente uma chave confiável sob novos valores de pcr:

$ keyctl update 268728824 "update pcrinfo=`cat pcr.blob`"
$ keyctl print 268728824
010100000000002c0002800093c35a09b70fff26e7a98ae786c641e678ec6ffb6b46d805
77c8a6377aed9d3219c6dfec4b23ffe3000001005d37d472ac8a44023fbb3d18583a4f73
d3a076c0858f6f1dcaa39ea0f119911ff03f5406df4f7f27f41da8d7194f45c9f4e00f2e
df449f266253aa3f52e55c53de147773e00f0f9aca86c64d94c95382265968c354c5eab4
9638c5ae99c89de1e0997242edfb0b501744e11ff9762dfd951cffd93227cc513384e7e6
e782c29435c7ec2edafaa2f4c1fe6e7a781b59549ff5296371b42133777dcc5b8b971610
94bc67ede19e43ddb9dc2baacad374a36feaf0314d700af0a65c164b7082401740e489c9
7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8

O consumidor inicial de chaves confiáveis ​​é o EVM, que no momento da inicialização precisa de uma chave simétrica de alta qualidade para a proteção HMAC dos metadados do arquivo. O uso de uma chave confiável oferece fortes garantias de que a chave EVM não foi comprometida por um problema no nível do usuário e, quando selada para valores específicos de PCR de inicialização, protege contra ataques de inicialização e offline. Crie e salve uma chave criptografada "evm" usando a chave confiável acima "kmk":

opção 1: omitir 'formato'

$ keyctl add encrypted evm "new trusted:kmk 32" @u
159771175

opção 2: definir explicitamente 'formato' como 'padrão'

$ keyctl add encrypted evm "new default trusted:kmk 32" @u
159771175

$ keyctl print 159771175
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

$ keyctl pipe 159771175 > evm.blob

Carregue uma chave criptografada "evm" no blob salvo:

$ keyctl add encrypted evm "load `cat evm.blob`" @u
831684262

$ keyctl print 831684262
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

São previstos outros usos para chaves confiáveis ​​e criptografadas, como para criptografia de disco e arquivo. Em particular, o novo formato 'ecryptfs' foi definido para usar chaves criptografadas para montar um sistema de arquivos eCryptfs. Mais detalhes sobre o uso podem ser encontrados no arquivo 'Documentation / security / keys-ecryptfs.txt'.

Como criptografar bytes usando o módulo TPM de uma máquina?

CryptProtectData

O Windows fornece uma API (relativamente) simples para criptografar um blob usando a API CryptProtectData , que pode CryptProtectData uma função fácil de usar:

public Byte[] ProtectBytes(Byte[] plaintext)
{
   //...
}

Os detalhes do ProtectBytes são menos importantes do que a ideia de que você pode usá-lo facilmente:

  • Aqui estão os bytes que eu quero criptografados por uma chave secreta mantida no System
  • devolva o blob criptografado

O blob retornado é uma estrutura de documentação não documentation que contém tudo o que é necessário para descriptografar e retornar os dados originais (algoritmo de hash, algoritmo de cifra, salt, assinatura HMAC, etc.).

Para completar, aqui está a implementação de exemplo de pseudocódigo de ProtectBytes que usa a Crypt API para proteger bytes:

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.
}

Como fazer o mesmo com o TPM?

O código acima é útil para criptografar dados apenas para a máquina local. Os dados são criptografados usando a conta do System como gerador de chaves (os documentation ). O resultado final é que eu posso criptografar dados (por exemplo, uma chave mestra de criptografia do disco rígido) que só podem ser descriptografados pela máquina local.

Agora é hora de dar um passo adiante. Quero criptografar alguns dados (por exemplo, uma chave mestra de criptografia do disco rígido) que só podem ser descriptografados pelo TPM local. Em outras palavras, desejo substituir o TEE (Qualcomm Trusted Execution Environment) no diagrama de blocos abaixo para Android pelo TPM no Windows:

Nota : Percebo que o TPM não faz assinatura de dados (ou, se faz, não garante que a assinatura dos mesmos dados fornecerá sempre a mesma saída binária). É por isso que eu gostaria de substituir "assinatura RSA" por "criptografar um blob de 256 bits por uma chave vinculada a hardware" .

Então, onde está o código?

O problema é que a programação do TPM não está documentada no MSDN . Não há API disponível para executar nenhuma operação. Em vez disso, você precisa encontrar uma cópia da pilha de software do Trusted Computing Group (também conhecida como TSS) , descobrir quais comandos enviar para o TPM, com cargas úteis, em que ordem e chamar a função Tbsip_Submit_Command do Window para enviar comandos diretamente:

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
);

O Windows não possui API de nível superior para executar ações.

É o equivalente moral de tentar criar um arquivo de texto emitindo comandos de E / S SATA para o seu disco rígido .

Por que não usar apenas calças

O Trusted Computing Group (TCG) definiu sua própria API: TCB Software Stack (TSS) . Uma implementação dessa API foi criada por algumas pessoas e é chamada de TrouSerS . Um cara então transportou esse projeto para o Windows .

O problema com esse código é que ele não é portátil no mundo do Windows. Por exemplo, você não pode usá-lo no Delphi, nem no C #. Isso requer:

  • OpenSSL
  • pThread

Eu só quero que o código criptografe algo com o meu TPM.

O CryptProtectData acima requer nada além do que está no corpo da função.

Qual é o código equivalente para criptografar dados usando o TPM? Como outros observaram, você provavelmente precisará consultar os três manuais do TPM e construir os blobs por conta própria . Provavelmente envolve o comando TPM_seal . Embora eu ache que não queira selar dados, acho que quero vinculá- los:

Ligação - criptografa dados usando a chave de ligação do TPM, uma chave RSA exclusiva descendente de uma chave de armazenamento. Selagem - criptografa os dados de maneira semelhante à ligação, mas também especifica um estado no qual o TPM deve estar para que os dados sejam descriptografados (sem lacre)

Tento ler os três volumes necessários para encontrar as 20 linhas de código necessárias:

Mas não tenho ideia do que estou lendo. Se houvesse algum tipo de tutorial ou exemplo, eu poderia tentar. Mas estou completamente perdido.

Então, perguntamos ao Stackoverflow

Da mesma maneira, pude fornecer:

Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
   //...
   CryptProtectData(...); 
   //...
}

alguém pode fornecer o equivalente correspondente:

Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
   //...
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   //...snip...
   Tbsip_Submit_Command(...);
   //...
}

isso faz a mesma coisa, exceto que, em vez de uma chave bloqueada no System LSA, está bloqueado no TPM?

Início da Pesquisa

Não sei exatamente o que significa vincular . Mas olhando para o TPM Main - Parte 3 Comandos - Especificação Versão 1.2, há uma menção de bind :

10.3 TPM_UnBind

TPM_UnBind pega o blob de dados resultante de um comando Tspi_Data_Bind e o descriptografa para exportação para o Usuário. O chamador deve autorizar o uso da chave que descriptografará o blob recebido. O TPM_UnBind opera bloco por bloco e não tem noção de nenhuma relação entre um bloco e outro.

O que é confuso é que não há comando Tspi_Data_Bind .

Esforço de pesquisa

É horrível como ninguém nunca se incomodou em documentar o TPM ou sua operação. É como se eles passassem o tempo todo inventando algo legal para brincar, mas não quisessem lidar com o doloroso passo de torná-lo utilizável para alguma coisa.

Começando com o livro (agora) gratuito Um Guia Prático para o TPM 2.0: Usando o Módulo da Plataforma Confiável na Nova Era de Segurança :

Capítulo 3 - Tutorial rápido no TPM 2.0

O TPM tem acesso a uma chave privada gerada automaticamente, para criptografar chaves com uma chave pública e, em seguida, armazenar o blob resultante no disco rígido. Dessa forma, o TPM pode manter um número praticamente ilimitado de chaves disponíveis para uso, mas não desperdiçar armazenamento interno valioso. As chaves armazenadas no disco rígido podem ser apagadas, mas também podem ser copiadas, o que pareceu aos designers uma troca aceitável.

Como criptografar uma chave com a chave pública do TPM?

Capítulo 4 - Aplicativos existentes que usam TPMs

Aplicativos que devem usar o TPM, mas não

Nos últimos anos, o número de aplicativos baseados na Web aumentou. Entre eles estão o backup e armazenamento na Web. Um grande número de empresas agora oferece esses serviços, mas, até onde sabemos, nenhum dos clientes desses serviços permite ao usuário bloquear a chave do serviço de backup em um TPM. Se isso fosse feito, certamente seria bom se a própria chave do TPM fosse copiada em duplicada em várias máquinas. Parece ser uma oportunidade para os desenvolvedores.

Como um desenvolvedor bloqueia uma chave no TPM?

Capítulo 9 - Hierarquias

CASO DE USO: ARMAZENAMENTO DE SENHAS DE LOGIN

Um arquivo de senha típico armazena hashes salgados de senhas. A verificação consiste em salgar e hash uma senha fornecida e compará-la com o valor armazenado. Como o cálculo não inclui um segredo, está sujeito a um ataque offline no arquivo de senha.

Este caso de uso usa uma chave HMAC gerada pelo TPM. O arquivo de senha armazena um HMAC da senha salgada. A verificação consiste em salgar e HMACing a senha fornecida e compará-la com o valor armazenado. Como um invasor offline não possui a chave HMAC, o invasor não pode montar um ataque executando o cálculo.

Isso pode funcionar. Se o TPM tiver uma chave HMAC secreta e apenas o meu TPM conhecer a chave HMAC, eu poderia substituir "Sign (também conhecido como criptografia TPM com sua chave privada)" por "HMAC". Mas então, na linha seguinte, ele se inverte completamente:

TPM2_Create, especificando uma chave HMAC

Não é um segredo do TPM se for necessário especificar a chave HMAC. O fato de a chave HMAC não ser secreta faz sentido quando você percebe que este é o capítulo sobre utilitários criptográficos que o TPM fornece. Em vez de precisar escrever SHA2, AES, HMAC ou RSA, você pode reutilizar o que o TPM já possui.

Capítulo 10 - Chaves

Como dispositivo de segurança, a capacidade de um aplicativo usar chaves e mantê-las seguras em um dispositivo de hardware é a maior força do TPM. O TPM pode gerar e importar chaves geradas externamente. Ele suporta chaves assimétricas e simétricas.

Excelente! Como você faz isso!?

Gerador de chaves

Indiscutivelmente, a maior força do TPM é sua capacidade de gerar uma chave criptográfica e proteger seu segredo dentro de um limite de hardware. O gerador de chaves é baseado no próprio gerador de números aleatórios do TPM e não depende de fontes externas de aleatoriedade. Assim, elimina pontos fracos baseados em softwares fracos com uma fonte insuficiente de entropia.

O TPM tem a capacidade de gerar chaves criptográficas e proteger seus segredos dentro de um limite de hardware? É assim como?

Capítulo 12 - Registros de configuração da plataforma

PCRs para autorização

CASO DE USO: VEDANDO UMA CHAVE DE CRIPTOGRAFIA DE DISCO RÍGIDO PARA PLATAFORMA DO ESTADO

Os aplicativos de criptografia de disco completo são muito mais seguros se um TPM proteger a chave de criptografia do que se estiver armazenada no mesmo disco, protegido apenas por uma senha. Primeiro, o hardware do TPM possui proteção anti-hammering (consulte o Capítulo 8 para obter uma descrição detalhada da proteção contra ataques de dicionário do TPM), tornando impraticável um ataque de força bruta à senha. Uma chave protegida apenas por software é muito mais vulnerável a uma senha fraca. Segundo, uma chave de software armazenada no disco é muito mais fácil de roubar. Pegue o disco (ou um backup do disco) e você obterá a chave. Quando um TPM mantém a chave, toda a plataforma, ou pelo menos o disco e a placa-mãe, devem ser roubados.

A vedação permite que a chave seja protegida não apenas por uma senha, mas por uma política. Uma política típica bloqueia a chave dos valores de PCR (o estado do software) atuais no momento da vedação. Isso pressupõe que o estado na primeira inicialização não seja comprometido. Qualquer malware pré-instalado presente na primeira inicialização seria medido nas PCRs e, portanto, a chave seria selada para um estado de software comprometido. Uma empresa menos confiável pode ter uma imagem de disco padrão e selar para PCRs que representam essa imagem. Esses valores de PCR seriam pré-calculados em uma plataforma presumivelmente mais confiável. Uma empresa ainda mais sofisticada usaria TPM2_PolicyAuthorize e forneceria vários tickets autorizando um conjunto de valores de PCR confiáveis. Consulte o Capítulo 14 para obter uma descrição detalhada da política autorizada e sua aplicação para resolver o problema de fragilidade da PCR.

Embora uma senha também possa proteger a chave, há um ganho de segurança mesmo sem a senha da chave do TPM. Um invasor pode inicializar a plataforma sem fornecer uma senha do TPMkey, mas não pode efetuar login sem o nome de usuário e a senha do SO. O OSsecurity protege os dados. O invasor pode inicializar um sistema operacional alternativo, digamos, a partir de um DVD ao vivo ou pendrive ao invés do disco rígido, para ignorar a segurança de login do sistema operacional. No entanto, essa configuração e software de inicialização diferentes alterariam os valores de PCR. Como essas novas PCRs não correspondiam aos valores selados, o TPM não liberaria a chave de descriptografia e o disco rígido não pôde ser descriptografado.

Excelente! Esse é exatamente o caso de uso que eu desejo. Também é o caso de uso para o qual a Microsoft usa o TPM. Como eu faço isso!?

Então, li o livro inteiro e ele não forneceu nada de útil. O que é bastante impressionante, porque tem 375 páginas. Você quer saber o que o livro continha - e, olhando para trás, não faço ideia.

Portanto, desistimos do guia definitivo para programar o TPM e, em vez disso, recorremos a alguma documentação da Microsoft:

No Microsoft TPM Platform Crypto-Provider Toolkit . Menciona exatamente o que eu quero fazer:

A chave de endosso ou EK

O EK foi projetado para fornecer um identificador criptográfico confiável para a plataforma. Uma empresa pode manter um banco de dados das Chaves de Endosso pertencentes aos TPMs de todos os PCs em sua empresa, ou um controlador de malha do datacenter pode ter um banco de dados dos TPMs em todos os blades. No Windows, você pode usar o provedor NCrypt descrito na seção “Provedor de criptografia de plataforma no Windows 8” para ler a parte pública do EK.

Em algum lugar dentro do TPM há uma chave privada RSA. Essa chave está trancada lá dentro - para nunca ser vista pelo mundo exterior. Quero que o TPM assine algo com sua chave privada (ou seja, criptografe-o com sua chave privada).

Então, eu quero a operação mais básica que possa existir:

Criptografe algo com sua chave privada. Eu ainda nem estou pedindo coisas mais complicadas:

  • "selando" com base no estado da PCR
  • criando uma chave e armazenando-a em memroy volátil ou não volátil
  • criando uma chave simétrica e tentando carregá-la no TPM

Estou solicitando a operação mais básica que um TPM pode fazer. Por que é impossível obter informações sobre como fazê-lo?

Posso obter dados aleatórios

Suponho que estava sendo simplista quando disse que a assinatura do RSA era a coisa mais básica que o TPM pode fazer. A coisa mais básica que o TPM pode ser solicitado é fornecer bytes aleatórios. Que eu descobri como fazer:

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;
}

A coisa extravagante

Percebo que o volume de pessoas que usam o TPM é muito baixo. É por isso que ninguém no Stackoverflow tem uma resposta. Portanto, não posso ficar muito ganancioso ao encontrar uma solução para o meu problema comum. Mas o que eu realmente gostaria de fazer é "selar" alguns dados:

  • apresentar ao TPM alguns dados (por exemplo, 32 bytes de material chave)
  • fazer o TPM criptografar os dados, retornando alguma estrutura opaca de blob
  • depois peça ao TPM para descriptografar o blob
  • a descriptografia funcionará apenas se os registros de PCR do TPM forem iguais aos da criptografia.

Em outras palavras:

Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
   //...
}

Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
   //...
}

A próxima geração de criptografia (Cng, também conhecida como BCrypt) suporta o TPM

A API de criptografia original no Windows era conhecida como API de criptografia.

A partir do Windows Vista, a API Crypto foi substituída pela API Cryptography: Next Generation (conhecida internamente como BestCrypt , abreviada como BCrypt , para não ser confundida com o algoritmo de hash de senha ).

O Windows é fornecido com dois provedores BCrypt:

O provedor Platform Crypto não está documentado no MSDN, mas possui documentação de um site da Microsoft Research 2012:

Kit de ferramentas de provedor de criptografia da plataforma TPM

O provedor de criptografia da plataforma TPM e o Toolkit contêm código de amostra, utilitários e documentação para usar a funcionalidade relacionada ao TPM no Windows 8. Os subsistemas descritos incluem o provedor de criptografia da plataforma Crypto-Next-Gen (CNG) suportado pelo TPM e como provedores de serviços de atestado pode usar os novos recursos do Windows. Os sistemas baseados em TPM1.2 e TPM2.0 são suportados.

Parece que a intenção da Microsoft é apresentar a funcionalidade de criptografia TPM com o Microsoft Platform Crypto Provider da Cryptography NG API.

Criptografia de chave pública usando o Microsoft BCrypt

Dado que:

um caminho a seguir pode ser o de descobrir como fazer a assinatura digital usando a API de próxima geração do Microsoft Cryptography .

Meu próximo passo será criar o código para criptografia no BCrypt, com uma chave pública RSA, usando o provedor padrão ( MS_PRIMITIVE_PROVIDER ). Por exemplo:

  • 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 55
  • publicExponent : 65537

Com esse código em funcionamento, posso mudar para o provedor de TPM ( MS_PLATFORM_CRYPTO_PROVIDER ).

22/02/2016: E com a Apple sendo obrigada a descriptografar dados do usuário, há um interesse renovado em como fazer o TPM executar a tarefa mais simples que foi inventada - criptografar algo.

É aproximadamente equivalente a todos os proprietários de um carro, mas ninguém sabe como começar um. Pode fazer coisas realmente úteis e legais, se pudéssemos passar da Etapa 1 .

Leitura de bônus


Answer #1

Primer

Tudo o que se segue é sobre o TPM 1.2. Lembre-se de que a Microsoft exige um TPM 2.0 para todas as versões futuras do Windows. A geração 2.0 é fundamentalmente diferente da 1.2

Não há solução de uma linha por causa dos princípios de design do TPM. Pense no TPM como um microcontrolador com recursos limitados. Seu principal objetivo do projeto era ser barato, ainda seguro. Portanto, o TPM foi rasgado de toda a lógica que não era necessária para uma operação segura. Portanto, um TPM só funciona quando você possui pelo menos algum software mais ou menos gordo , emitindo muitos comandos na ordem correta. E essas seqüências de comandos podem ficar muito complexas. É por isso que o TCG especificou o TSS com uma API bem definida. Se você deseja seguir o caminho do Java, existe até uma API Java de alto nível. Não estou ciente de um projeto semelhante para C # / .net

Desenvolvimento

No seu caso, sugiro que você analise o software TPM da IBM.

No pacote você encontrará 3 componentes muito úteis:

  • um emulador de TPM de software
  • uma lib de tpm leve
  • alguns utilitários básicos de linha de comando

Você não precisa necessariamente do emulador de software TPM, também pode se conectar ao HW TPM da máquina. No entanto, você pode interceptar os comandos emitidos e examinar as respostas, aprendendo como elas são montadas e como correspondem à especificação do comando.

Alto nível

Pré-requisitos:

  1. TPM está ativado
  2. O driver TPM está carregado
  3. você tomou posse do TPM

Para selar um blob, você precisa fazer o seguinte:

  1. crie uma chave
  2. armazene o key-blob em algum lugar
  3. verifique se a chave está carregada no TPM
  4. selar a bolha

Para remover a vedação, você precisa:

  1. obtenha o key-blob
  2. carregue a chave no TPM
  3. retire o blob selado

Você pode armazenar o key-blob em sua estrutura de dados usada para armazenar os bytes protegidos.

A maioria dos comandos do TPM necessários é autorizada. Portanto, você precisa estabelecer sessões de autorização quando necessário. AFAIR essas são principalmente sessões OSAP.

Comandos do TPM

Atualmente, não posso executar uma versão de depuração, portanto não posso fornecer a sequência exata. Portanto, considere isso uma lista não ordenada de comandos que você precisará usar:

  • TPM_OSAP
  • TPM_CreateWrapKey
  • TPM_LoadKey2
  • TPM_Seal

Se você quiser ler também os valores atuais da PCR:

  • TPM_PCRRead