How to Create a RSA Machine Key using CNG on Windows and Grant Access to All Users?
I’m using the Windows CNG API to create a TPM-stored (or MS KSP) RSA key and want to allow non-administrative users to access it. My goal is to generate a machine level key (non-exportable) which can be accessed without admin privileges by all the users. But creating and reading (public key) of machine level key fails unless app is run with admin privileges. I tried setting a security descriptor that grants full access to SYSTEM and Administrators, and Built-in Users. This way admin access would be required only once and then all other users could use the key. I attempted to do this using the following code:
/ Set a security descriptor granting full access to System, Administrators, and Users.
const char* sdString = "D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BU)";
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(sdString, SDDL_REVISION_1, &pSecurityDescriptor, NULL)) {
PrintErrorMessage(GetLastError());
NCryptFreeObject(hKey);
NCryptFreeObject(hProvider);
return GetLastError();
}
status = NCryptSetProperty(hKey, NCRYPT_SECURITY_DESCR_PROPERTY,
reinterpret_cast<PBYTE>(pSecurityDescriptor),
static_cast<DWORD>(GetSecurityDescriptorLength(pSecurityDescriptor)), 0);
LocalFree(pSecurityDescriptor);
if (status != ERROR_SUCCESS) {
PrintErrorMessage(status);
NCryptFreeObject(hKey);
NCryptFreeObject(hProvider);
return status;
}
The key is successfully created, but when I call NCryptFinalizeKey, it returns an “Access Denied” error if MS_PLATFORM_CRYPTO_PROVIDER (and Invalid key flags for MS_KSP), and non-admin users are unable to access the key.
My questions are:
- What is the correct SDDL string to use so that the key is owned by SYSTEM and non-admin users (BU) get at least read access?
- Are there any other considerations or known issues when applying a security descriptor with NCryptSetProperty on machine keys that could lead to “Access Denied” errors on finalization?
Any help or pointers would be appreciated!
I am trying to create a cryptographic device identifier which is accessible to all the users without admin access.