I create a PKCS#10 CSR with certreq and have set the option Exportable=TRUE. This successfully creates a key under the location REQUEST. I also have a valid certificate with key in MY. If I try to access any one of them the CryptoAPI reports error code 0x80090016.
Running under different access rights could not solve this problem so far.
My goal is to get both the keys in MY and REQUEST. If I call CryptAcquireContextA() on any of those, it fails.
Windows 7 x64
My complete code looks like this:
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "REQUEST");
pCert = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, "CERTIFICATE_SUBJECT", NULL);
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len);
pinfo = (CRYPT_KEY_PROV_INFO *) malloc(len);
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len);
provname = wide_to_asc(pinfo->pwszProvName);
contname = wide_to_asc(pinfo->pwszContainerName);
if(!CryptAcquireContextA(&hCryptProv, contname, provname, pinfo->dwProvType, 0)) {
err = GetLastError();
fprintf(stderr, "Error: 0x%x\n", err);
}
CryptGetUserKey(hCryptProv, pinfo->dwKeySpec, &hUserkey);
This code is mostly copied from the OpenSSL capi engine. Since the engine failed, I created the smallest possible code to search the error.
If I run this, it fails with the output Error: 0x80090016. This means one of three things according to Microsoft:
Local ComputerAfter some googling, I tried to change permissions on the file system. I found the files by looking at the contname variable of my code and searching for the file. I changed permissions on them (more accurate, I changed permissions on the parent folder). While this fixed the issue for MY, it seems I cannot change it for REQUEST.
One note here is that my container for MY seems to be here:
%APPDATA%\Microsoft\Crypto\RSA\S-1-5-21-1650336054-1974872081-316617838-545102
For REQUEST I found it under a different address:
%ALLUSERSPROFILE%\Microsoft\Crypto\RSA\MachineKeys
I am not sure on the workings here so I cannot explain why it would put them in different locations (one being user centric, the other one a system folder). The MY store was created with a regular administrator prompt and the command certreq -new inf_file.inf cert-csr.csr and after I received my certificate, I issued certreq -accept cert.pem. Then I created a new csr with the same command.
I tried to execute my program with the following privileges:
whoami output)To recieve a service prompt, I executed psexec.exe –ids cmd.exe according to a tip from MaaSters Center
Any help or guidance on how to further narrow this problem down will be greatly appreciated.
I was finally able to solve this problem and it is a lot simpler than I thought. I was sure that I would receive an unambiguous container name and don't need to be more specific but CryptAcquireContext actually requires me to pass a flag CRYPT_MACHINE_KEYSET.
So my function call has to look like this:
CryptAcquireContextA(&hCryptProv, contname, provname, pinfo->dwProvType, CRYPT_MACHINE_KEYSET)
Unfortunately this is not supported by the OpenSSL engine, so you would have to alter it yourself in the engine.
See MSDN: "A key container created without this flag by a user that is not an administrator can be accessed only by the user creating the key container and the local system account."
Complete details here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx
User contributions licensed under CC BY-SA 3.0