Search code examples
c++windowsbcryptmingw-w64

BCryptGenRandom STATUS_INVALID_HANDLE


I am trying to generate cryptographically secure numbers in Windows. I have the following code:

#ifndef w64crypt
#define w64crypt
#include <windows.h>
#include <bcrypt.h>
unsigned long getSeed(ULONG buffer_size){ 
    NTSTATUS status=0;
    ULONG flags=0;
    PUCHAR c_seed;
    BCRYPT_ALG_HANDLE handle;
    status=BCryptOpenAlgorithmProvider(
            &handle,BCRYPT_RNG_ALGORITHM,NULL,0
    );
    if(!BCRYPT_SUCCESS(status)){
            cout << "BCryptOpenAlgorithmProvider";
            printf("%X",status);
    }
    status=BCryptGenRandom(
            handle,c_seed,128,0
    );
    if(!BCRYPT_SUCCESS(status)){
            cout << "Error in BCryptGenRandom";
            printf("%X",status);
    }
    status=BCryptCloseAlgorithmProvider(
            handle,0
    );
    if(!BCRYPT_SUCCESS(status)){
            cout << "BCryptCloseAlgorithmProvider";
            printf("%X",status);
    }
    unsigned long seedNo=(unsigned long)c_seed;
    return seedNo;
}
#endif

When I run this, I get Error in BCryptGenRandom C0000008, which is STATUS_INVALID_HANDLE. This is what the documentation calls for:

https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider

NTSTATUS BCryptOpenAlgorithmProvider(
  BCRYPT_ALG_HANDLE *phAlgorithm,
  LPCWSTR           pszAlgId,
  LPCWSTR           pszImplementation,
  ULONG             dwFlags
);

https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom

NTSTATUS BCryptGenRandom(
  BCRYPT_ALG_HANDLE hAlgorithm,
  PUCHAR            pbBuffer,
  ULONG             cbBuffer,
  ULONG             dwFlags
);

The above link also states that pszAlgId must be:

The handle of an algorithm provider created by using the BCryptOpenAlgorithmProvider function. The algorithm that was specified when the provider was created must support the random number generator interface.

Looking at https://learn.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-identifiers, BCRYPT_RNG_ALGORITHM is my ideal candidate.

I'm compiling this using mingw-w64, cross-compiling from Ubuntu 18.04.

Why am I receiving this NTSTATUS?


Solution

  • I know that I'm late, but hopefully this helps people who're having the same issue.

    The documentation doesn't mention it, but you can use one of the predefined pseudo-handles for common algorithms. Here's an example

    unsigned int GenAESKey(char* keyb) {
    NTSTATUS s;
    /*BCRYPT_ALG_HANDLE algh;
    s = BCryptOpenAlgorithmProvider(&algh, BCRYPT_RNG_ALGORITHM, MS_PLATFORM_CRYPTO_PROVIDER, 0);
    if (s != STATUS_SUCCESS)
        return (unsigned int)s;*/
    s = BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (PUCHAR)keyb, CABINET_AES_KEY_S, 0);
    if (s != STATUS_SUCCESS)
        return (unsigned int)s;
    return 0;
    

    You can see the list of all the predefined pseudo-handles here