title: CryptoNextGeneration : Storing a key in the TPM
body: <p>I am currently working on a small sample program using Crypto Next Generation (Windows Crypto API) to generate a key, store it in the TPM on my computer, encrypt some data and then retrieve it and decrypt the data.</p>
  
  <p>My choice of RSA encryption is because it is the only algorithm my TPM supports.</p>
  
  <p>I understand I can access the TPM as a provider using:</p>
  
  <pre><code>// Open handle to TPM
  if (FAILED(secStatus = NCryptOpenStorageProvider(
      &amp;hProv,
      MS_PLATFORM_CRYPTO_PROVIDER,
      0)))
  {
      wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
      goto Cleanup;
  }
  </code></pre>
  
  <p>And that I can generate the key (which documentation states should save this in my provider):</p>
  
  <pre><code>    // Create a persistent key
      if (FAILED(secStatus = NCryptCreatePersistedKey(
          hProv,
          &amp;hKey,
          NCRYPT_RSA_ALGORITHM,
          L"RSAKey0",
          0,
          0)))
      {
          wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
          goto Cleanup;
      }
  </code></pre>
  
  <p>(and then set length, finalize, etc)</p>
  
  <p>And it appears my data is encrypted by running:</p>
  
  <pre><code>    // Encrypt Data
      if (!NT_SUCCESS(status = NCryptEncrypt(
          hKey,                    // hKey
          InputData,               // pbInput
          InputDataSize,           // cbInput
          NULL,                    // pPaddingInfo
          encryptedBuffer,         // pbOutput
          encryptedBufferSize,     // cbOutput
          &amp;encryptedBufferSize,    // pcbResult
          NCRYPT_PAD_PKCS1_FLAG))) // dwFlags
      {
          wprintf(L"**** Failed to encrypt data. Error 0x%x returned by NCryptEncrypt\n", status);
          goto Cleanup;
      }
  </code></pre>
  
  <p>This appears to work alright with no errors and the data looks encrypted. 
  (I fear I may be misunderstanding the function usage here with RSA encryption and generating a persistent key as opposed to a key pair, but because I am not looking to need to share a public key, I assume this should work)</p>
  
  <p>But, when trying to retrieve the key using:</p>
  
  <pre><code>    // Get key from TPM
      if (FAILED(secStatus = NCryptOpenKey(
          hProv,
          &amp;hKey,
          L"RSAKey0",
          0,
          0)))
      {
          wprintf(L"**** Error 0x%x returned by NCryptOpenKey\n", secStatus);
          goto Cleanup;
      }
  </code></pre>
  
  <p>I receive an error of NTE_BAD_KEYSET. Which indicates the key was not found.</p>
  
  <p>Potentially, the only function I see that I may be missing is <a href="https://docs.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptexportkey" rel="nofollow noreferrer">NCryptExportKey</a>, but if I understand it right that exports the key to a blob of memory and not to the TPM (which should have been saved upon <a href="https://docs.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptcreatepersistedkey" rel="nofollow noreferrer">CreatePersistedKey</a>).</p>
  
  <p>Am I missing a step to ensure the key is stored in my TPM?</p>
  
  <p>Also, I am using <a href="https://docs.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptdeletekey" rel="nofollow noreferrer">NCryptDeleteKey</a> as cleanup of my encryption function, but the documentation states that this just frees the key handle and not the actual stored key. How do you delete a key from the TPM after storing it there?</p>