Open meastp opened 2 years ago
Hi @meastp
Thank you for your interest in this library.
I don't think it is possible to use a Windows Certificate Store with the current implementation but it sounds like it should definitely be something that ought to be possible.
To be honest I don't know much about how Windows handles certificates apart from the work I've done with this library,, so since this is something that has to be implemented I would very much appreciate you input on which kind of interface you would like for this.
If you have an idea of how you would like the interface to look we can discuss that and hopefully I'll have some time to implement it at some point. Otherwise, pull requests are of course very welcome if you want to try and implement it yourself.
@laudrup I see. I'm just a user, unfortunately with no expertise on tls or CryptoAPI, so I can't really help much.
The ideal interface would be to be able to point to a certificate in the Windows Certificate Store by using it's thumbprint (it's the usual and a sound way to pick a specific certificate on windows, at least). If this could be a certificate with a non-exportable private key, it would be the most secure (but requiring an exportable private key is also ok).
Hi again @meastp,
This library is very much modeled after how the existing asio::ssl
implementation which uses OpenSSL
works so that's why I initially implemented it this way.
I don't use Windows myself but most often things are quite a bit different/complicated on that platform so any user input is very much appreciated.
I've looked a bit into it and it seems like the certificate could be provided by adding an overload to the use_certificate function that takes an additional HCERTSTORE
parameter to the store containing the certificate.
I think that ought to work if you call such a function with the handle to the "Personal Certificate Store" in addition to the CERT_CONTEXT
pointer for the certificate to use from that store. Hopefully that should work even with a non-exportable private key. It should also be fairly simple for me to add a test for that functionality.
I don't think using a thumbprint is the correct approach here. A thumbprint is most often used for validating whether a certficiate/key matches the expected one. Of course on Windows things are quite often different from the norm though.
What do you think about adding such a function the the context class?
@laudrup
So, what you are suggesting is an overload use_certificate(HCERTSTORE*, CERT_CONTEXT*)
? The user is required to both acquire the HCERTSTORE*
(with CertOpenStore, which is flexible and can also open e.g. Personal and Web Hosting in the same HCERTSTORE*
, which is perfect) and the CERT_CONTEXT*
- finding the exact certificate (CERT_CONTEXT
) in the Windows Certificate Store using CertFindCertificateInStore or CertEnumCertificatesInStore - the user can choose freely how to locate the certificate (e.g. by thumbprint, issuer, subject etc.).
I think that would be a very nice interface. If there is a particular method that is more common, you can provide overload(s) that does the heavy lifting in boost-wintls as future additions (e.g use_certificate("MY" /* Personal cert store name */, "Cert_subject_1" /* certificate subject, used as argument to CertFindCertificateInStore */)
.
If this also works with certificates in the store that have a non-exportable private key, that's a nice bonus (but not a hard requirement, imho).
@meastp That's exactly what I'm suggesting. Good to hear you like that interface. Of course the most important aspect of designing APIs is that they are easy for the users to use correctly.
I'm working on implementing that and will update this issue once I have something working (or not).
@meastp
I've looked more into this and it seems like I've been a bit confused. As far as I can tell there's no need to add another member function to the context. If you have a CERT_CONTEXT
which has an associated private key you should be able to simply use the code as it is.
I'm looking into extending the tests to verify that and the documentation should definitely be updated to make it more clear that this is the case.
I'm also looking into whether it's possible to verify that the CERT_CONTEXT
has a usable private key associated and make the function fail if not. Currently the handshake will simply timeout if the certificate doesn't have a private key associated which is not very intuitive.
But please do feel free to use the code as it now and please do let me know if you experience any issues.
@laudrup That's great news - and I think, like you, that a documentation update is really needed ;)
which has an associated private key Have you been able to confirm if the (associated) private key has to be exportable?
@meastp
I've added some code for ensuring that a private key is referenced when setting the certificate using use_certificate
. It will now fail if the certificate doesn't reference a private key or the private key doesn't match the public key used in the certificate.
I've also added some tests for ensuring that as well as for using a certificate created by CertCreateSelfSignCertificate which I think should create a certificate similar to the one you're trying to use. I'm fairly certain this also works with a non-exportable private key.
Additionally I've tried to clarify the documentation for use_certificate
a bit. Do you think you could have a look at that here and see if that makes things clearer?
Of course feel free to have a look at the branch in general and let me know what you think.
Thanks.
@laudrup Great work, thank you! :) I'm on parental leave, will get back to this when I return to work (easter, next year) :)
I have a few questions when trying to evaluate if we can use this library for our http server (written in Boost.Beast):
CERT_CONTEXT*
from Windows Certificate Store (using the CryptoAPI perhaps?) directly, and then use it withcontext::use_certificate
without having to separately import a private key (after all, it is stored in the Windows Certificate Store on the system)?Lots of questions... :) I'm missing a server example using the Windows Certificate Store...