-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ASN1 corrupted data while calling X509Store.Certificates on Mac #54336
Comments
Tagging subscribers to this area: @bartonjs, @vcsjones, @krwq, @GrabYourPitchforks Issue DetailsHi We are receiving the following exception from one of our customer (no contact information).
I don't know which certificate in the users' key chain is causing the exception, and if its really corrupted or not. I can suggest two alternatives (which would require introducing new API):
|
The easier answer might just be to teach this layer that things can fail and have it skip bad entries. Testing it will have to be on faith, unless someone can come up with a way to repro this. |
I am fine with that. But that might cause the caller to think that the certificate doesn't exist (and perhaps try add it) when in actuality it does, but is corrupted (in the case that the corrupted certificate is actually the one we are looking for). |
That seems to also apply to the suggested alternatives, though. e.g. here we failed in determining a certificate's thumbprint, so find by thumbprint wouldn't be able to find it. Find by name would have a similar "how are we determining the value?" question, particularly if there are any sorts of normalization differences between a macOS native version (assuming it exists) and the managed implementation we'd have elsewhere. |
I see. Makes sense to me. |
Alternatively, perhaps the Certificates collection should enumerate the entire list (and throw, when accessing a corrupted certificate so we don't affect existing functionality) lazily ? That is only when the collection is actually enumerated ? |
Hm. I can get similar results with the same underlying root cause. The public X.509 contents in a keychain file are mutable and keychain doesn't really do anything to stop the contents from changing and you can just flip bits in the file. In the example below I started flipping bits in the signature OID. It's a little tricky to get right because the wrong changes will just result in the keychain APIs ignoring the certificate all together and acting like it isn't there. Perhaps there is a legitimate way to import such a damaged file, but one could presume it is a flipped bit on a disk or similar. While I can make the issue occur, unit testing it seems difficult.
|
Okay, here is how to reproduce the above.
So, conceivably the person running in to this either A) was able to import a corrupt X.509 certificate since the keychain app seems to permit it, or used to, or B) they have just the right bit-flip on their disk. |
Hm. That makes some sense, but then I wonder if that would be problematic if the absence of a certificate would lead to some potential issues. Consider: X509Store store = new X509Store(StoreName.Disallowed);
store.Open(OpenFlags.ReadOnly); If someone is using the disallowed store on macOS (really just a separate keychain) to store known bad certificates, and somehow an incorrectly encoded certificate was added to the certificate store (or we assume a disk is flipping bits), I (personally) would prefer throwing behavior rather than potentially be in a situation where I am trusting something I shouldn't be (put another way, I am now in a situation where I cannot safely continue).
I'm a bit unsure how this would work. |
@vcsjones what would you tell the user of application when such an exception is thrown ? Please look at your keychain and find which item is offending ? We can't even tell you its name? Although its not even relevant to the key our application needs, you can't use our application, goodbye ? :) SecItemCopyMatching (the underlying MacOS API used) will return a list of matching items in the keychain. If one of those would be the offending item, then Find will still throw, but if not, then I don't see why we should break our entire app just because an item we don't even care about is corrupted. Note, that we are using SecItemCopyMatching today, to create the entire collection. And then we decode the entire list of items returned from this API. This is a costly operation. And then, we perform Find on top of that decoded array returned from before - on our own. But that is too late, because we have already thrown while trying to decode an item, we most probably don't even care about (or yes, we don't know at this point). My suggestion is to call SecItemCopyMatching each time we call Find, and refine the query arguments we pass into it. This should return a much smaller set of relevant certs, and only decode those - it will be faster, will still throw if one of the certs is corrupted, but will only return the relevant data we need.
|
Not exactly a proposal, just some idle thoughts. If I had any real "ideas" out of that thought then, perhaps we limit any new / additional behavior to well-known keychains/trust store like
I have two thoughts here, the first, is The second is, even if |
@vcsjones I agree that implementing Find using
This will at least give our users something to work with. Our app will break, but he will know which certificate to delete or fix in the keychain. If everyone is on board this proposal, I will create a PR |
Hi
We are receiving the following exception from one of our customer (no contact information).
I don't know which certificate in the users' key chain is causing the exception, and if its really corrupted or not.
However, it seems like even if one certificate in the store is corrupted, this will cause the entire System.Security.Cryptography.X509Certificates.X509Store.get_Certificates() to fail. And there is no method for a "Find" certificate. So even if the certificate I am looking for is fine, we can't reach it because we are enumerating all certificates.
I can suggest two alternatives (which would require introducing new API):
The text was updated successfully, but these errors were encountered: