Como posso 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 CryptProtectData
API, que pode envolver uma função fácil de usar:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Os detalhes de ProtectBytes
são menos importantes do que a ideia de que você pode usá-lo com bastante facilidade:
- aqui estão os bytes que quero criptografados por uma chave secreta mantida no
System
- me devolva o blob criptografado
O blob retornado é uma documentação não documentada estrutura de 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á o exemplo de implementação de pseudocódigo ProtectBytes
que usa o Crypt API
para proteger os 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 System
conta como gerador de chave (os detalhes, embora interessantes, não são importantes ). O resultado final é que posso criptografar dados (por exemplo, uma chave mestra de criptografia de disco rígido) que só podem ser descriptografados pela máquina local.
Agora é hora de dar um passo adiante. Desejo 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 Qualcomm Trusted Execution Environment ( TEE ) no diagrama de blocos abaixo para Android, pelo TPM no Windows:
Nota : Eu percebo que o TPM não faz assinatura de dados (ou se faz, não garante que assinar os mesmos dados dará sempre a mesma saída binária). É por isso que eu estaria disposto a substituir "assinatura RSA" por "criptografar um blob de 256 bits com uma chave associada ao hardware" .
Onde está o código?
O problema é que a programação TPM não está documentada no MSDN . Não há API disponível para realizar qualquer 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 Windows 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 tem API de nível superior para realizar ações.
É o equivalente moral de tentar criar um arquivo de texto emitindo comandos SATA I / O para 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 portou esse projeto para o Windows .
O problema com esse código é que não é portátil para o mundo do Windows. Por exemplo, você não pode usá-lo do Delphi, você não pode usá-lo do C #. Isso requer:
- OpenSSL
- pThread
Só quero que o código criptografe algo com meu TPM.
O acima CryptProtectData
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 notaram, você provavelmente terá que consultar os três manuais do TPM e construir você mesmo os blobs . Provavelmente envolve o TPM_seal
comando. Embora eu ache que não quero lacrar dados, acho que quero vinculá- los:
Vinculação - criptografa os dados usando a chave de vinculação TPM, uma chave RSA exclusiva descendente de uma chave de armazenamento. Selagem - criptografa os dados de maneira semelhante à vinculação, mas, além disso, especifica um estado em que 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 de que preciso:
Mas eu não tenho idéia do que estou lendo. Se houvesse algum tipo de tutorial ou exemplo, eu poderia tentar. Mas estou completamente perdido.
Então pedimos Stackoverflow
Da mesma forma, fui capaz de 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(...);
//...
}
que faz a mesma coisa, exceto ao invés de uma chave trancada em System
LSA, é trancada no TPM?
Início da Pesquisa
Não sei exatamente o que significa ligar . Mas olhando para 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 que é o resultado 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 de entrada. TPM_UnBind opera bloco a bloco e não tem noção de qualquer relação entre um bloco e outro.
O que está confundindo está lá é nenhum Tspi_Data_Bind
comando.
Esforço de Pesquisa
É horrível como ninguém jamais se preocupou em documentar o TPM ou sua operação. É como se eles passassem o tempo todo inventando uma coisa legal para brincar, mas não quisessem lidar com a dolorosa etapa de torná-la utilizável para alguma coisa.
Começando com o livro (agora) gratuito A Practical Guide to TPM 2.0: Using the Trusted Platform Module in the New Age of Security :
Capítulo 3 - Tutorial rápido sobre TPM 2.0
O TPM tem acesso a uma chave privada gerada automaticamente, portanto, ele pode 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 virtualmente ilimitado de chaves disponíveis para uso, mas não desperdiça armazenamento interno valioso. As chaves armazenadas no disco rígido podem ser apagadas, mas também podem ser feitas cópias de segurança, o que pareceu aos projetistas uma troca aceitável.
Como posso 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 backup e armazenamento baseados na web. Atualmente, um grande número de empresas oferece esses serviços, mas, pelo que sabemos, nenhum dos clientes desses serviços permite que o usuário bloqueie a chave do serviço de backup para um TPM. Se isso fosse feito, certamente seria bom se a própria chave TPM fosse copiada, duplicando-a em várias máquinas. Esta parece ser uma oportunidade para desenvolvedores.
Como um desenvolvedor bloqueia uma chave para o TPM?
Capítulo 9 - Heirarquias
CASO DE USO: ARMAZENAMENTO DE SENHAS DE LOGIN
Um arquivo de senha típico armazena hashes salgados de senhas. A verificação consiste em fazer o sal e hash de uma senha fornecida e compará-la com o valor armazenado. Como o cálculo não inclui um segredo, ele está sujeito a um ataque offline ao arquivo de senha.
Este caso de uso usa uma chave HMAC gerada por TPM. O arquivo de senha armazena um HMAC da senha com salt. A verificação consiste em salting e HMAC a senha fornecida e compará-la com o valor armazenado. Como um invasor offline não tem 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 meu TPM souber a chave HMAC, eu poderia substituir "Assinar (também conhecido como criptografar 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 eu tiver que 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 escrever SHA2, AES, HMAC ou RSA por conta própria, você pode reutilizar o que o TPM já tem disponível.
Capítulo 10 - Chaves
Como um dispositivo de segurança, a capacidade de um aplicativo de usar chaves enquanto as mantém seguras em um dispositivo de hardware é a maior força do TPM. O TPM pode gerar e importar chaves geradas externamente. Ele oferece suporte a 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 fraquezas com base em softwares de software 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 ENCRIPTAÇÃO DE DISCO RÍGIDO PARA O ESTADO DA PLATAFORMA
Os aplicativos de criptografia de disco completo são muito mais seguros se um TPM proteger a chave de criptografia do que se ela estiver armazenada no mesmo disco, protegido apenas por uma senha. Primeiro, o hardware TPM tem proteção anti-hammering (consulte o Capítulo 8 para uma descrição detalhada da proteção contra ataques de dicionário do TPM), tornando um ataque de força bruta à senha impraticável. Uma chave protegida apenas por software é muito mais vulnerável a uma senha fraca. Em segundo lugar, uma chave de software armazenada em disco é muito mais fácil de roubar. Pegue o disco (ou um backup do disco) e você terá a chave. Quando um TPM detém a chave, toda a plataforma, ou pelo menos o disco e a placa-mãe, deve ser roubada.
O lacre 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 para os valores PCR (o estado do software) atuais no momento da selagem. Isso pressupõe que o estado na primeira inicialização não está comprometido. Qualquer malware pré-instalado presente na primeira inicialização seria medido nos 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 selo 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 tíquetes autorizando um conjunto de valores PCR confiáveis. Consulte o Capítulo 14 para obter uma descrição detalhada da política de autorização e sua aplicação para resolver o problema de fragilidade PCR.
Embora uma senha também possa proteger a chave, há um ganho de segurança mesmo sem uma senha de chave TPM. Um invasor pode inicializar a plataforma sem fornecer uma senha TPMkey, mas não pode fazer login sem o nome de usuário e a senha do sistema operacional. O OSsecurity protege os dados. O invasor pode inicializar um sistema operacional alternativo, digamos a partir de um DVD ao vivo ou pen drive, em vez do disco rígido, para contornar a segurança de login do sistema operacional. No entanto, essa configuração de inicialização e software diferentes mudariam os valores PCR. Como esses novos PCRs não corresponderiam aos valores lacrados, o TPM não liberaria a chave de descriptografia e o disco rígido não poderia ser descriptografado.
Excelente! Este é exatamente o caso de uso que desejo. É também o caso de uso para o qual a Microsoft usa o TPM. Como eu faço isso!?
Portanto, li o livro inteiro e não trouxe nada de útil. O que é bastante impressionante porque tem 375 páginas. Você se pergunta o que o livro continha - e, olhando para trás, não tenho ideia.
Portanto, desistimos do guia definitivo para programar o TPM e, em vez disso, recorremos a alguma documentação da Microsoft:
Do Microsoft TPM Platform Crypto-Provider Toolkit . Ele 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 data center 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 está uma chave privada RSA. Essa chave está trancada lá - 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 pode existir:
Criptografe algo com sua chave privada. Não estou nem (ainda) pedindo as coisas mais complicadas:
- "selando" com base no estado de PCR
- criar uma chave e armazená-la em uma memória volátil ou não volátil
- criar uma chave simétrica e tentar carregá-la no TPM
Estou pedindo a operação mais básica que um TPM pode fazer. Por que é impossível obter informações sobre como fazer isso?
Posso obter dados aleatórios
Acho 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 a fazer é me dar bytes aleatórios. Que 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;
}
The Fancy Thing
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 em encontrar uma solução para meu problema comum. Mas o que eu realmente quero fazer é "lacrar" alguns dados:
- apresentar ao TPM alguns dados (por exemplo, 32 bytes de material chave)
- fazer com que o TPM criptografe os dados, retornando alguma estrutura de blob opaca
- mais tarde, peça ao TPM para descriptografar o blob
- a descriptografia só funcionará se os registros PCR do TPM forem os mesmos que eram durante a criptografia.
Em outras palavras:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Cryptography Next Gen (Cng, aka BCrypt) suporta TPM
A API de criptografia original no Windows era conhecida como API de criptografia.
A partir do Windows Vista, a Crypto API foi substituída por Cryptography API: Next Generation (internamente conhecido como BestCrypt , abreviado como BCrypt , não deve ser confundido com o algoritmo de hash de senha ).
O Windows é fornecido com dois provedores BCrypt :
- Provedor Primitive Microsoft (
MS_PRIMITIVE_PROVIDER
) padrão : Implementação padrão software de todos os primitivos (hash, criptografia simétrica, assinaturas digitais, etc) - Provedor de criptografia da plataforma Microsoft (
MS_PLATFORM_CRYPTO_PROVIDER
): Provedor que fornece acesso TPM
O provedor Platform Crypto não está documentado no MSDN, mas possui a documentação de um site de pesquisa da Microsoft 2012:
TPM Platform Crypto-Provider Toolkit
O provedor de criptografia da plataforma TPM e o kit de ferramentas 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 de plataforma Crypto-Next-Gen (CNG) apoiado por TPM e como provedores de serviço de atestado pode usar os novos recursos do Windows. Ambos os sistemas baseados em TPM1.2 e TPM2.0 são suportados.
Parece que a intenção da Microsoft é trazer à tona a funcionalidade de criptografia TPM com o Microsoft Platform Crypto Provider da Cryptography NG API.
Criptografia de chave pública usando Microsoft BCrypt
Dado que:
- quero realizar criptografia assimétrica RSA (usando o TPM)
- Microsoft BestCrypt suporta criptografia assimétrica RSA
- Microsoft BestCrypt tem um provedor de TPM
um caminho a seguir poderia ser a de descobrir como fazer a assinatura digital usando a API Microsoft Cryptography Next Gen .
Meu próximo passo será chegar ao código para fazer a 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 55publicExponent
: 65537
Com esse código funcionando, posso passar a usar o Provedor TPM ( MS_PLATFORM_CRYPTO_PROVIDER
).
22/02/2016: E com a Apple sendo obrigada a ajudar a descriptografar os dados do usuário, há um interesse renovado em como fazer o TPM executar a tarefa mais simples para a qual foi inventado - criptografar algo.
É mais ou menos equivalente a todo mundo que possui um carro, mas ninguém sabe como dar partida em um. Ele pode fazer coisas realmente úteis e interessantes, se ao menos pudéssemos passar da Etapa 1 .
Leitura de bônus
fonte
Respostas:
Primer
Tudo o que se segue é sobre TPM 1.2. Lembre-se de que a Microsoft requer um TPM 2.0 para todas as versões futuras do Windows. A geração 2.0 é fundamentalmente diferente da 1.2
Não existe uma solução de uma linha devido aos princípios de design do TPM. Pense no TPM como um microcontrolador com recursos limitados. Seu principal objetivo de design era ser barato, mas ainda seguro. Portanto, o TPM foi retirado de toda a lógica que não era necessária para uma operação segura. Portanto, um TPM só funciona quando você tem pelo menos um software mais ou menos gordo , emitindo muitos comandos na ordem correta. E essas sequências de comandos podem ficar muito complexas. É por isso que TCG especificou o TSS com uma API bem definida. Se você gostaria de seguir o caminho do Java, existe até uma API Java de alto nível . Não conheço um projeto semelhante para C # / .net
Desenvolvimento
No seu caso, sugiro que você dê uma olhada no software TPM da IBM.
No pacote você encontrará 3 componentes muito úteis:
Você não precisa necessariamente do emulador de software TPM, você também pode se conectar ao HW TPM da máquina. No entanto, você pode interceptar os comandos emitidos e ver as respostas, aprendendo assim como eles são montados e como correspondem à especificação do comando.
Alto nível
Pré-requisitos:
Para selar um blob, você precisa fazer o seguinte:
Para retirar o lacre, você precisa:
Você pode armazenar o key-blob na estrutura de dados que usa para armazenar os bytes protegidos.
A maioria dos comandos TPM de que você precisa são autorizados. Portanto, você precisa estabelecer sessões de autorização quando necessário. AFAIR, essas são principalmente sessões OSAP.
Comandos TPM
Atualmente não consigo executar uma versão de depuração, portanto, não posso fornecer a sequência exata. Portanto, considere esta uma lista não ordenada de comandos que você terá que usar:
TPM_OSAP
TPM_CreateWrapKey
TPM_LoadKey2
TPM_Seal
Se você quiser ler os valores PCR atuais também:
TPM_PCRRead
fonte
Chaves confiáveis e criptografadas
Chaves confiáveis e criptografadas são dois novos tipos de chave adicionados ao serviço de anel de chaves do kernel existente. Ambos os 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 Trusted Platform Module (TPM) 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 têm sua integridade verificada.
Chaves confiáveis usam um TPM para gerar e lacrar as chaves. As chaves são lacradas com uma chave RSA de 2048 bits no TPM e, opcionalmente, seladas para valores de PCR (medição de integridade) especificados e apenas sem lacre pelo TPM, se as verificações de integridade de blob e PCR forem correspondentes. Uma chave confiável carregada pode ser atualizada com novos (futuros) valores PCR, de forma que as chaves sejam facilmente migradas para novos valores pcr, como quando o kernel e o initramfs são atualizados. A mesma chave pode ter muitos blobs salvos em diferentes valores de PCR, portanto, várias inicializações são facilmente suportadas.
Por padrão, as chaves confiáveis são seladas sob a SRK, que tem o valor de autorização padrão (20 zeros). Isso pode ser definida em tempo takeownership com a utilidade do calças:
tpm_takeownership -u -z
.keyctl print
retorna uma cópia hexadecimal ascii da chave lacrada, que está no formato TPM_STORED_DATA padrão. O comprimento da chave para novas chaves é sempre em bytes. Chaves confiáveis podem ter 32 - 128 bytes (256 - 1024 bits), o limite superior é para caber no comprimento de chave SRK (RSA) de 2048 bits, com toda a estrutura / preenchimento necessários.As chaves criptografadas não dependem de um TPM e são mais rápidas, pois usam AES para criptografar / descriptografar. Novas chaves são criadas a partir de números aleatórios gerados pelo kernel e são criptografadas / descriptografadas usando uma chave 'mestra' especificada. A chave 'mestra' pode ser uma chave confiável ou um tipo de chave de usuário. A principal desvantagem das chaves criptografadas é que, se não estiverem enraizadas em uma chave confiável, serão tão seguras quanto a chave do usuário que as criptografou. A chave mestra do usuário 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 do aplicativo, que é identificado por 'formato'.
Exemplos de uso de chave confiável e criptografada
Crie e salve uma chave confiável chamada "kmk" de 32 bytes de comprimento:
Carregue uma chave confiável do blob salvo:
Sele novamente uma chave confiável com novos valores pcr:
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 proteção HMAC de metadados de arquivo. O uso de uma chave confiável fornece 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 "kmk" acima:
opção 1: omitindo 'formato'
opção 2: definir explicitamente 'formato' como 'padrão'
Carregue uma chave criptografada "evm" do blob salvo:
Outros usos para chaves confiáveis e criptografadas, como para criptografia de disco e arquivo, são previstos. 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'.
fonte
Documentation/security/keys-ecryptfs.tx
Depende da sua intenção e circunstâncias:
Cada um desses casos de uso (e há mais) - ou uma combinação deles - apresenta um caminho de implementação diferente. Pense no TPM como um canivete suíço de dispositivos criptográficos: não há muito que você não possa fazer com ele, mas a facilidade de uso é prejudicada por sua versatilidade. A pergunta continua oscilando entre criptografar, assinar e bloquear a configuração do sistema, mas a parte principal desta resposta considerará o comando Seal para cobrir a maioria das necessidades descritas na pergunta.
É para isso que serve o comando Bind (substituído pelo comando Criar do TPM 2). Você carrega uma chave que deriva de uma chave associada ao TPM e criptografa com ela (ou diretamente com uma chave associada ao hardware). Dessa forma, os dados só podem ser descriptografados com acesso ao mesmo TPM.
Não tenho certeza se replicar todo esse processo é uma boa ideia. Por um lado, não há necessidade de usar uma operação de assinatura em qualquer parte do processo. Parece que, no momento em que o Android 5 estava sendo desenvolvido, a API Keystore estava limitada a operações de assinatura e verificação. Meu melhor palpite é que a equipe de criptografia de disco fez o melhor para trabalhar com o que tinha e desenvolveu um algoritmo em que uma das chaves intermediárias era derivada com uma operação de assinatura , usando uma chave TEE armazenada, amarrando assim todo o processo a um hardware. chave vinculada disponível apenas na plataforma - já que a assinatura era a única maneira de fazer isso no momento. No entanto, não há necessidade de se restringir dessa forma se você tiver acesso a um TPM, que oferece mais recursos do que você sabia que precisava!
Isso é falso, ambas as versões de TPM suportam assinatura.
Isso não faz sentido. Assinando os mesmos dados com a mesma chave vai produzir a mesma assinatura. Você pode estar confundindo a operação de assinatura com a operação de cotação, que se misturam em um nonce.
Esta deve ser a opção preferida, embora ambas sejam possíveis com um TPM. Veja acima.
Infelizmente, não há muito para documentar. A API do Win é limitada a algumas funções do TBS que são removidas de um nível do driver.
Na verdade, não, se você tivesse um TSS, não teria que usar
Tbsip_submit_Command()
. Esse é o objetivo de ter um TSS - os detalhes de baixo nível são abstraídos.Ainda verdadeiro para o TPM 1, mas para o TPM 2 há TSS.MSR .
Corrigir.
Não está claro se este é um desafio intransponível. Acessar TrouSerS por meio de uma interoperabilidade deve ser preferível a reescrever todo o código de estruturação de dados. Além disso, havia
doTSS
no momento de escrever a pergunta.A pergunta contém uma citação que descreve a diferença entre os dois comandos, portanto, não deve haver muita confusão. A vedação é semelhante à ligação, com a restrição adicional de que o estado do sistema deve ser o mesmo para que os dados sejam removidos.
Em primeiro lugar, vale ressaltar que existem duas versões principais do TPM, que são totalmente incompatíveis entre si. Portanto, praticamente nenhum código que você escreveu para o TPM 1 funcionará para o TPM 2. A API do TBS é o único código comum entre os dois e, para ser justo com a Microsoft, esse pode ter sido um dos motivos pelos quais essa API nunca cresceu. A parte principal da resposta apresentará o código para TPM 1 por dois motivos:
Em segundo lugar, vamos tornar a pergunta mais específica. Estou reinterpretando da seguinte maneira:
O comando Seal é mais adequado para isso, pois executa a mesma função que o comando Bind quando o tamanho de seleção de PCR é definido como zero, mas a seleção de PCR pode ser facilmente alterada para incluir quaisquer PCRs que você desejar. Isso faz com que se pergunte por que o comando Bind foi incluído na especificação e, como observado, ele foi removido na especificação TPM 2 e os dois foram combinados em um comando Create.
Aqui está o código C # para usar o comando TPM 1.2 Seal para criptografar dados apenas com funções TBS (nota: este código não foi testado e provavelmente não funcionará sem depuração) :
Análise de código:
Estas são algumas das poucas funções disponíveis em Tbs.h e as únicas que usaremos aqui. Eles basicamente permitem que você abra um identificador para o dispositivo e se comunique com ele enviando e recebendo bytes brutos.
TPM é big endian, o Windows é little endian. Portanto, a ordem dos bytes terá que ser revertida para todos os dados que estamos enviando. Precisamos apenas nos preocupar em reverter os ints não assinados de 32 bits e 16 bits aqui.
Aqui, usamos Tbsi_Context_Create () para abrir um identificador para falar com o TPM. O
TBS_CONTEXT_PARAMS
parâmetro é apenas uma estrutura C com um campo int de 32 bits sem sinal que deve ser definido como 1 para se comunicar com uma instância do TPM 1.2, e é isso que definimos.Isso é especificado como o tamanho mínimo do buffer em TPM PC Client Spec . Será mais do que suficiente para nossas necessidades aqui.
TPM 1.2 Spec Parte 3 diz o seguinte:
Precisamos criptografar com XOR esse parâmetro "secreto" usando um nonce gerado durante uma sessão OSAP. Um dos identificadores de entrada do comando Seal também é um identificador OSAP:
Portanto, precisamos primeiro estabelecer esta sessão OSAP. OSAP é descrito no TPM 1.2 Spec Parte 1, . OSAP, ou protocolo de autorização específico de objeto, foi inventado para lidar com o caso de uso em que você deseja usar um objeto TPM que requer autorização várias vezes, mas não deseja fornecer autorização a cada vez: uma sessão OSAP é usada em vez disso, que depende sobre o conceito de "segredo compartilhado", que é um HMACque mistura os dados de autorização do objeto com nonces gerados em cada lado para evitar ataques de resposta. Portanto, o "segredo compartilhado" só é conhecido pelos dois lados desta sessão: o lado que iniciou a sessão (usuário) e o lado que o aceitou (TPM); além disso, ambos os lados devem ter os mesmos dados de autorização de objeto para que o "segredo compartilhado" seja o mesmo; além disso, o "segredo compartilhado" usado em uma sessão será inválido em outra. Este diagrama da especificação descreve o processo:
Não usaremos várias sessões neste caso específico (na verdade, esse parâmetro é ignorado com o comando Seal!) E a chave que usaremos não requer autorização, mas infelizmente ainda estamos vinculados à especificação para estabelecer um OSAP sessão.
Os operandos do comando TPM_OSAP são:
Cada comando do TPM 1.2 é apresentado assim:
A tag é um valor de dois bytes que indica se o que se segue é entrada ou saída e se há algum valor de dados de autenticação seguindo os parâmetros de comando. Para TPM_OSAP, a tag deve ser TPM_TAG_RQU_COMMAND (0x00C1) conforme a especificação, o que significa "um comando sem autorização".
Tamanho é um valor de quatro bytes que especifica o tamanho do comando em bytes, incluindo a tag e o próprio tamanho. Vamos definir esse valor mais tarde, uma vez que o tenhamos calculado.
O código de comando é um valor de quatro bytes que serve como um ID de comando: ele informa ao TPM como interpretar o restante do comando. Nosso código de comando aqui é TPM_OSAP (0x0000000B).
As próximas duas coisas a definir são o tipo de entidade e o valor da entidade. Uma vez que queremos usar uma chave que já existe no TPM, usaremos o tipo de entidade "SRK" (0x0004) e, uma vez que estamos trabalhando sob a suposição de que o TPM já pertenceu, é seguro assumir que ele foi um SRK carregado sob o identificador permanente 0x40000000 de acordo com as especificações, portanto, usaremos esse valor de identificador permanente para nosso valor de entidade. (SRK significa "Storage Root Key" e é a chave raiz da qual derivam a maioria das outras chaves de propriedade do TPM)
Por fim, calculamos o tamanho do comando, definimos e enviamos o comando.
Os dados que devemos obter do TPM no TPM_OSAP são:
Então, voltamos:
Extraímos esses valores e os armazenamos em variáveis.
Em seguida, calculamos o "segredo compartilhado". De acordo com as especificações, os valores que entram no cálculo são os dois nonces OSAP (um gerado pelo usuário e outro gerado pelo TPM) e o valor de autorização para a chave que queremos usar - o SRK. Por convenção, o valor de autenticação SRK é a "autenticação bem conhecida": um buffer de 20 bytes zerado. Tecnicamente, pode-se alterar esse valor para outra coisa ao assumir a propriedade do TPM, mas isso não é feito na prática, portanto, podemos presumir com segurança que o valor "autenticação bem conhecida" é bom.
A seguir, vamos dar uma olhada no que se passa no comando TPM_Seal:
Muitos desses parâmetros são fáceis de construir, exceto por dois deles:
encAuth
epubAuth
. Vamos examiná-los um por um.encAuth
é "O AuthData criptografado para os dados lacrados." Nosso AuthData aqui é o "auth bem conhecido" de antes, mas ainda temos que criptografá-lo. Como estamos usando uma sessão OSAP, ela é criptografada de acordo com ADIP, ou Authorization-Data Insertion Protocol. Da especificação: "O ADIP permite a criação de novas entidades e a inserção segura da nova entidade AuthData. A transmissão do novo AuthData usa criptografia com a chave baseada no segredo compartilhado de uma sessão OSAP." Além disso: "Para o algoritmo de criptografia XOR obrigatório, o criador constrói uma chave de criptografia usando um hash SHA-1 do segredo compartilhado OSAP e um nonce de sessão. O criador XOR criptografa o novo AuthData usando a chave de criptografia como um teclado único e envia esses dados criptografados junto com a solicitação de criação para o TPM. "O diagrama a seguir explica como o ADIP opera:
pubAuth
é "O resumo da sessão de autorização para entradas e keyHandle." A parte 1 da especificação, em "Declarações de parâmetro para exemplos OIAP e OSAP", explica como interpretar a tabela de parâmetros TPM_Seal acima: "A coluna HMAC # detalha os parâmetros usados no cálculo HMAC. Os parâmetros 1S, 2S, etc. são concatenados e hash para inParamDigest ou outParamDigest, implicitamente denominado 1H1 e possivelmente 1H2 se houver duas sessões de autorização. Para a primeira sessão, 1H1, 2H1, 3H1 e 4H1 são concatenados e HMAC'ed. Para a segunda sessão, 1H2, 2H2, 3H2, e 4H2 são concatenados e HMAC'ed. " Então, teremos que fazer o hash do texto simples, seu tamanho, tamanho da informação de PCR,encAuth
de cima e do ordinal TPM_Seal, e então HMAC que com os dois nonces e o booleano "continue session" usando o OSAP "Juntando tudo em um diagrama:
Observe como definimos "PCR info size" como zero neste código, pois queremos apenas criptografar os dados sem bloqueá-los no estado do sistema. No entanto, é trivial fornecer uma estrutura de "informação de PCR" se necessário.
Finalmente, construímos o comando e o enviamos.
Usamos a função Tbsip_Context_Close () para fechar nosso identificador de comunicação.
Retornamos a resposta como está aqui. O ideal é reverter os bytes novamente e validá-los recalculando o
resAuth
valor para evitar ataques man-in-the-middle.Isso ocorre porque Tspi_Data_Bind é um comando TSS, não um comando TPM. A razão é porque não requer segredos (apenas a chave pública é usada), portanto, pode ser feito sem envolver o TPM. Isso causou confusão, no entanto, e até mesmo os comandos que não exigem segredos agora estão incluídos na especificação do TPM 2.
Depende da versão do TPM. Com o comando TPM_CreateWrapKey para TPM 1.2. Com o comando TPM2_Create para TPM 2.
Crie-o no TPM ou envolva-o ou use qualquer outro método disponível.
O texto do livro é confuso. Você não especifica a chave HMAC , você especifica que deseja uma chave HMAC .
Não, não faz sentido. A chave é secreta.
Existem comandos para criar chaves ou importá-las para ambas as versões do TPM. Para o TPM 1, havia apenas uma chave raiz - a SRK - a partir da qual você poderia estabelecer uma hierarquia de chaves criando chaves agrupadas. Com o TPM 2, você pode ter várias chaves primárias ou raiz.
Veja acima.
Provavelmente depende do tipo de unidade. No caso de unidades não SED, a chave de criptografia da unidade provavelmente está agrupada com uma chave TPM. No caso de unidades SED, a senha Admin1 (ou semelhante) é selada com o TPM.
O EK não é uma chave de assinatura - é uma chave de criptografia. No entanto, não é uma chave de criptografia de uso geral: ela só pode ser usada em determinados contextos .
Veja acima.
fonte
Quando diz
NÃO significa fornecer a chave HMAC - significa "apontar para a chave HMAC que deseja usar" .
Os TPMs podem usar um número virtualmente ilimitado de chaves HMAC, como é indicado no livro. Você tem que dizer ao TPM qual usar.
fonte