Hi,

I had another look at this (using certificates and private keys from the
LOCAL_MACHINE certificate store) yesterday and made another small
discovery; in addition to passing the CERT_STORE_READONLY_FLAG to
CertOpenStore(),
it's also important to pass CRYPT_MACHINE_KEYSET in the 'dwFlags' parameter
to CryptAquireContext()[1] if the referenced key is provided by the
LOCAL_MACHINE certificate store or else you'll get a NTE_BAD_KEYSET
("Keyset does not exist") error. I've updated my wcsa[2] utility to account
for this.

FYI: If anyone wants to take a stab at modifying the underlying
libsunmscapi provided by OpenJDK to enable accessing of certificates and
keys in the LOCAL_MACHINE certificate store, you might find my
sunmscapi-build-helper[3] useful, as it enables building the sunmscapi.dll
(with debug symbols) in isolation without having to build the entire
OpenJDK.

References:
[1]
https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptacquirecontexta
[2] https://github.com/oddbjornkvalsund/wcsa
[3] https://github.com/oddbjornkvalsund/sunmscapi-build-helper

Best regards,
Oddbjørn Kvalsund

ons. 8. aug. 2018 kl. 23:19 skrev Oddbjørn Kvalsund <
oddbjornkvals...@gmail.com>:

> Thanks for the input, Bernd and Sean! I'm afraid submitting a patch for
> this directly is a bit beyond my ability, but I'll happily discuss the
> design of such a patch.
>
> Nelson D'Costa proposed a couple of possible solutions in JDK-6782021:
>
> > Either define a new store type like Windows-LOCALCOMPUTER,
> > or also list the computer local certificates when using the Windows-MY
> store type.
>
> My rudimentary understanding of the Windows certificate store architecture
> after reading [1] is that Windows comes with a predefined set of
> "collection stores" that can be opened with the WinCrypt function
> CertOpenStore() using identifier tuples such as
> CERT_SYSTEM_STORE_CURRENT_USER+MY, CERT_SYSTEM_STORE_LOCAL_MACHINE+CA etc.
> and that these collection stores aggregate a set of "physical stores",
> typically in the Windows registry. This model is thoroughly documented in
> [1] (although complex), but mapping this identifier scheme to something
> that can be used by JCA and KeyStore.getInstance(<identifier>) is slightly
> tricky because of at least two concerns:
>
> 1) The SunMSCAPI JCA provider is widely used and although its "Windows-MY"
> certificate store identifier scheme is flawed (it should have been
> something like "Windows-CurrentUser-MY") we can't easily change it without
> breaking things.
> 2) Opening any certificate stores involving the
> CERT_SYSTEM_STORE_LOCAL_MACHINE identifier (and most likely other
> identifiers) requires administrator privileges or specifically opening the
> store as read-only by passing CERT_STORE_READONLY_FLAG to CertOpenStore [2].
>
> To offer the full flexibility of CertOpenStore() through
> KeyStore.getInstance() seems like a grand undertaking involving an almost
> infinite number of magic string identifiers, so my suggestion is as follows:
>
> 1) Introduce the new identifiers Windows-CurrentUser-MY,
> Windows-CurrentUser-ROOT, Windows-LocalMachine-MY and
> Windows-LocalMachine-ROOT. These seem to be the most requested, but the
> identifier scheme allows for more esoteric additions such as
> Windows-Services-<ServiceName>-MY down the line.
> 2) Make Windows-MY and Windows-ROOT be aliases for Windows-CurrentUser-MY
> and Windows-CurrentUser-ROOT to maintain backward compatibility.
> 3) Attempt to open Windows-LocalMachine-MY and Windows-LocalMachine-ROOT
> in the default read-write mode, but fallback to read-only if read-write
> mode fails. This will transparently enable write operations for privileged
> users, while unprivileged users will get an exception when attempting to
> write to the store.
>
> References:
> [1]
> https://docs.microsoft.com/en-us/windows/desktop/seccrypto/system-store-locations
> [2]
> https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certopenstore
>
> Best regards,
> Oddbjørn Kvalsund
>
> ons. 8. aug. 2018 kl. 14:04 skrev Bernd Eckenfels <e...@zusammenkunft.net
> >:
>
>> Hello,
>>
>> What also should be mentioned is that the old CAPI clients cannot access
>> CNG Keys. Which is especially a pity since only the new keys benefit from
>> the cryptographic process isolation (not to mention the confusion that it’s
>> hard to see which provide hosts them)
>>
>> Gruss
>> Bernd
>>
>> Gruss
>> Bernd
>> --
>> http://bernd.eckenfels.net
>>
>> ------------------------------
>> *Von:* -980814368m Auftrag von
>> *Gesendet:* Mittwoch, August 8, 2018 12:35 PM
>> *An:* Oddbjørn Kvalsund; security-dev@openjdk.java.net
>> *Betreff:* Re: JDK-6782021
>>
>> Vinnie is not working on security-libs any more and I think the JBS
>> report should be marked as unassigned.  If any contributors want to suggest
>> a patch, then I think it can be reviewed on this list!
>>
>> regards,
>> Sean.
>>
>> On 07/08/2018 06:36, Oddbjørn Kvalsund wrote:
>>
>> Hi,
>>
>> I was just bit by this issue [JDK-6782021] It is not possible to read
>> local computer certificates with the SunMSCAPI provider
>> <https://bugs.openjdk.java.net/browse/JDK-6782021> and from
>> StackOverflow I notice that several other people (see [1][2][3]) have come
>> across the same problem. Coming up on the 10th anniversary for this issue;
>> any chance we'll see some love for it? Or at least a comment on the issue
>> on what timeline to expect and a list of workaround/alternative solutions
>> for the meantime?
>>
>> Background: I'm working with a company having primarily Microsoft
>> infrastructure and they have a routine where all Windows servers
>> automatically receive new certificates/keys when the old ones expire. These
>> certificates are installed in the "Local Computer → Private" certificate
>> store. They're quite fond of this system and hesitant to diverge from it,
>> so my preferred option is to just "get with the program". To temporarily
>> get around JDK-6782021 I created a small utility [5] that intercepts the
>> JDKs call to 'CertOpenSystemStore' [4] and presents a read-only virtual
>> certificate store combining all certificates and keys from the "Current
>> User" and "Local Computer" certificate stores, but this may have unexpected
>> implications that I've not yet uncovered, so I'd much prefer not having to
>> do this. A more thorough solution would be to use the commercial Pheox
>> JCAPI [6] product, but this is rather expensive and way overkill for what I
>> (and most others, it seems) need.
>>
>> References:
>> [1]
>> https://stackoverflow.com/questions/3612962/access-local-machine-certificate-store-in-java/51708360
>> [2]
>> https://stackoverflow.com/questions/51205158/access-windows-local-machine-personal-keystore-with-java-sunmscapi
>> [3]
>> https://stackoverflow.com/questions/51193143/use-jna-to-get-local-machine-certificate
>> [4]
>> http://hg.openjdk.java.net/jdk/jdk/file/tip/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp
>> [5] https://github.com/oddbjornkvalsund/wcsa
>> [6] https://pheox.com/products/jcapi/
>>
>> Best regards,
>> Oddbjørn Kvalsund
>>
>>
>>

Reply via email to