RFR: 8313367: SunMSCAPI cannot read Local Computer certs w/o Windows elevation [v3]

rebarbora-mckvak duke at openjdk.org
Fri Mar 22 21:41:29 UTC 2024


On Wed, 20 Mar 2024 19:45:32 GMT, Weijun Wang <weijun at openjdk.org> wrote:

>> rebarbora-mckvak has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits:
>> 
>>  - 8313367: signHash finds a key in the local machine store
>>  - 8313367: Local Computer store is opened with max. allowed permissions
>
> src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp line 806:
> 
>> 804:             {
>> 805:                 // If the key is in a local machine store, we need to try again with CRYPT_MACHINE flag.
>> 806:                 // See https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/cryptacquirecontext-troubleshooting
> 
> Since you said "if the key is in a local machine store", do you need to check if this is true before retrying with the `CRYPT_MACHINE_KEYSET` flag?

I am fairly new to Windows crypto API, so I will try to describe what happens on my test system and hopefully it will help to answer your question:

> loading store: Windows-MY-LOCALMACHINE
> MSCAPI (483): --------------------------

my keystore has two private key pairs, the following is loaded using MSCAPI by `..._loadKeysOrCertificateChains`

> MSCAPI (542): CAPI hCryptProv=2599423712528 hUserKey=2599426935088
> MSCAPI (632): stepan-cert: 1.2.840.113549.1.1.1

the second key pair is loaded using CNG:

> MSCAPI (483): --------------------------
> MSCAPI (527): CNG 2599431325072
> MSCAPI (632): Stepan-user: 1.2.840.113549.1.1.1

Now I try to sign data using the first key (CAPI):

> Alias: stepan-cert
> testing private key on SHA256withRSA
> MSCAPI (779): CryptCreateHash error: 80090008 (hCryptProv=2599423712528, hCryptKey=2599426935088), will try PROV_RSA_AES container: {48A88AAD-5CC2-4BBB-A26B-D64BF6A07D21}

`..._signHash` called `CryptCreateHash`, but it failed (NTE_BAD_ALGID), because the provider does not support SHA256. The original code tries to get the name of a container using `CryptGetProvParam(..., PP_CONTAINER, ...)` and tries to acquire a context.

> MSCAPI (788): CryptAcquireContext error: 80090016, may try PROV_RSA_AES (CRYPT_MACHINE)

That fails again with _Keyset does not exist_ error. Here comes my code trying to acquire a context again now with `CRYPT_MACHINE_KEYSET` flag set and that finally succeeds and signs the data.

I did a bit more of digging in Crypto API and it seems we can call `CryptGetProvParam(..., PP_KEYSET_TYPE, ...)` to get the information where the key is stored (user/machine store). I will modify the code in that way.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/16687#discussion_r1536248403



More information about the security-dev mailing list