MS CryptoAPI - Machine Keystore with Error 0x80090

2019-08-04 02:32发布

Summary

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.

Goal

My goal is to get both the keys in MY and REQUEST. If I call CryptAcquireContextA() on any of those, it fails.

System

Windows 7 x64

Sample Source Code

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.

The error

If I run this, it fails with the output Error: 0x80090016. This means one of three things according to Microsoft:

  • Key container does not exist.
  • You do not have access to the key container.
  • The Protected Storage Service is not running.

What have I done so far?

  • Started service "Protected Storage"
  • Verified container exists with MMC & Certificate Snap-In for Local Computer
  • Ran the same code on the User store in user context - it worked

File System Permissions

After 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.

Different privilege levels

I tried to execute my program with the following privileges:

  • my local user account
  • admin prompt (cmd->start as administrator)
  • nt authority\system (whoami output)

To recieve a service prompt, I executed psexec.exe –ids cmd.exe according to a tip from MaaSters Center

Final words

Any help or guidance on how to further narrow this problem down will be greatly appreciated.

2条回答
▲ chillily
2楼-- · 2019-08-04 02:38

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

查看更多
萌系小妹纸
3楼-- · 2019-08-04 02:58

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.

查看更多
登录 后发表回答