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