CryptoNextGeneration: хранение ключа в доверенном платформенном модуле - PullRequest
2 голосов
/ 15 апреля 2020

В настоящее время я работаю над небольшой программой-примером, использующей Crypto Next Generation (Windows Crypto API) для генерации ключа, сохранения его в модуле TPM на моем компьютере, шифрования некоторых данных, а затем извлечения и дешифрования данных.

Мой выбор RSA-шифрования заключается в том, что это единственный алгоритм, который поддерживает мой TPM.

Я понимаю, что могу получить доступ к TPM как провайдеру, используя:

// Open handle to TPM
if (FAILED(secStatus = NCryptOpenStorageProvider(
    &hProv,
    MS_PLATFORM_CRYPTO_PROVIDER,
    0)))
{
    wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
    goto Cleanup;
}

И это Я могу сгенерировать ключ (какие состояния документации должны сохранить это в моем провайдере):

    // Create a persistent key
    if (FAILED(secStatus = NCryptCreatePersistedKey(
        hProv,
        &hKey,
        NCRYPT_RSA_ALGORITHM,
        L"RSAKey0",
        0,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
        goto Cleanup;
    }

(а затем установить длину, завершить и т. Д. c)

И, похоже, мои данные зашифровано с помощью команды:

    // Encrypt Data
    if (!NT_SUCCESS(status = NCryptEncrypt(
        hKey,                    // hKey
        InputData,               // pbInput
        InputDataSize,           // cbInput
        NULL,                    // pPaddingInfo
        encryptedBuffer,         // pbOutput
        encryptedBufferSize,     // cbOutput
        &encryptedBufferSize,    // pcbResult
        NCRYPT_PAD_PKCS1_FLAG))) // dwFlags
    {
        wprintf(L"**** Failed to encrypt data. Error 0x%x returned by NCryptEncrypt\n", status);
        goto Cleanup;
    }

Кажется, что все работает нормально, без ошибок, и данные выглядят зашифрованными. (Боюсь, что, возможно, я неправильно понимаю использование функции здесь с шифрованием RSA и генерацией постоянного ключа в отличие от пары ключей, но, поскольку я не ищу необходимости использовать общий ключ c, я предполагаю, что это должно работать)

Но при попытке извлечь ключ с помощью:

    // Get key from TPM
    if (FAILED(secStatus = NCryptOpenKey(
        hProv,
        &hKey,
        L"RSAKey0",
        0,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by NCryptOpenKey\n", secStatus);
        goto Cleanup;
    }

я получаю сообщение об ошибке NTE_BAD_KEYSET. Что указывает на то, что ключ не был найден.

Потенциально единственная функция, которую я вижу, что я могу пропустить, - это NCryptExportKey , но если я правильно понимаю, это экспортирует ключ в большой двоичный объект памяти. а не в доверенный платформенный модуль (который должен был быть сохранен при CreatePersistedKey ).

Я пропускаю шаг, чтобы убедиться, что ключ хранится в моем доверенном платформенном модуле?

Кроме того, Я использую NCryptDeleteKey в качестве очистки моей функции шифрования, но в документации говорится, что это просто освобождает дескриптор ключа, а не фактический сохраненный ключ. Как удалить ключ из доверенного платформенного модуля после его хранения там?

1 Ответ

1 голос
/ 16 апреля 2020

NCryptDeleteKey действительно удаляет ключ из вашего TPM, а также очищает дескриптор.

Это было обнаружено путем экспериментов с перечислением и перечислением ключей.

...