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
OpenSSL backend code for CRLs #2315
Conversation
Looks like I have to change the test certs so that the 0.9.8 tests will not see a cert issuer extension marked as critical. Hopefully I can reuse some other cert for this, otherwise I might have to make a change to the vectors again. |
It looks like I'll have to change the test cert crl_all_reasons.pem so that the cert_issuer extension is not critical. Otherwise I would have to skip a bunch of tests in the 0.9.8 environments. |
6212bed
to
76902e8
Compare
Current coverage is
|
So I'm not sure what the coverage thing is complaining about, I guess it's because the for loop never runs completely through (intentionally).
|
Ended up completely changing the logic of the reason flag test. Coverage seems happy now. |
Jenkins, retest this please. |
c96b6ca
to
0511008
Compare
jenkins, retest this please |
Anybody could have a look at this? |
|
||
.. function:: load_pem_x509_crl(data, backend) | ||
|
||
.. versionadded:: 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be 1.1 now
It doesn't look like your merge captured all the commits (it's definitely missing the PR you opened earlier). |
Oh, please ignore this last push I merged my master and just did a push without specifying the branch so it updated this one unintentionally as well. I'm still testing my actual changes and will push once again once I('m done. |
1fd3f4b
to
dc57040
Compare
Now the PR is ready for review. If this gets a bit cluttered I can also create a new PR. |
return self.__last_update | ||
|
||
@property | ||
def revoked_certificates(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is in our current interface, but I'm wondering if it might be more consistent for us to just make CertificateRevocationList an iterable? That would look more like the way Extensions
, SubjectAlternativeName
, and several other x509 classes behave.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you just want me to get rid of revoked_certificates() and replace it with an iter() and len() function? I can do that, I just tried to stay as close to the OpenSSL specification because I think this makes it easier for people to find out how to access the revoked certs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that's consistent with our current approach for x509 objects.
… into crl_ossl_backend
Let's also discuss the caching in a separate PR since it'd be awesome to land this and caching is orthogonal to the vast majority of the work here. (Sorry to make you do some extra work!) |
It looks like the certificateIssuer revoked certificate extension is also something we can handle in 0.9.8. It's true that calling
|
@reaperhulk With the CRLExtensionOID I probably should have paid more attention when this change was made. This is unfortunate because it is basically wrong in the current form. They are not CRL extensions. Not sure if you would break anyones code yet since the backend support hasn't been in so the number of people using it is probably 0. However, I understand how complicated it is to change committed interfaces. Just one thing to keep in mind, if the backend code goes back, people might start using these extensions and then it gets even harder to change things around. |
The plan with the certificateIssuer sounds pretty nifty but how would we integrate this with the X509ExtensionParser which does run X509V3_EXT_d2i for us. We would have to shoehorn some extra code in there which seems ugly. Maybe we can look at this again if we find additional extensions which require newer OpenSSL versions to be properly supported. |
Before I forget it, I also changed the exception message for unsupported critical extensions so that it actually tells you that it is critical. Otherwise the message is confusing because the rule is that unknown exceptions are to be ignored unless they are marked critical. |
Right now there are no extensions that we parse conditionally on underyling OpenSSL version. I'd very much prefer to keep it that way since it's extremely difficult to explain to users how the "same" version of cryptography might exhibit significantly different behavior. At the very least we need to raise a warning. It is a shame that the naming is wrong (and that's on me!), but we can transition away from that name with our standard deprecation strategy without too much pain. We can put in a PR to change the name after this PR, update the docs to all point at the new name, but then keep the old name for compatibility for the next 2 releases. It would then be completely dropped in the 1.3 release. |
Ok, let me take a stab at the certIssuer custom parsing. I'll also remove the caching stuff for now and undo the naming change for CRLExtensionOID. |
undo name change of CRLExtensionOID use custom parsing mechanism for certIssuer entry extension add new crl to vectors for testing invalid certIssuer entry ext
Found a way to make this work, let me know what you think. |
Yeah if you wouldn't mind dropping those in separate PRs we can get them landed immediately :) |
backend | ||
) | ||
|
||
with pytest.raises(ValueError): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you walk me through the logic here? How was this extension encoded badly such that it should error? What makes the empty extension trigger the extension is invalid path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I did is I created a new custom extension which has the same OID as the certificate issuer extension but has a custom value. The way I did this is like that (in C using OpenSSL):
X509_REVOKED *r = X509_REVOKED_new();
int nid = OBJ_create("2.5.29.29", "Test", "Test Extension");
X509_REVOKED_add1_ext_i2d(r, nid, NULL, 0, 0);
Then when we get to _decode_cert_issuer(backend, ext)
we get a NULL pointer as data_ptr_ptr (or something else which isn't a GENERAL_NAMES
type) which goes into d2i_GENERAL_NAMES()
and returns a NULL pointer for which I explicitly test.
If that is not good enough, I could also create this CRL so that it sets an integer instead of a NULL value. Everything which is not GENERAL_NAMES
should trigger this. However, I think at that point we are fairly far out in terms of error cases, I expect this code to never be triggered in the real world. I just needed something to make coverage happy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm okay with this -- just wanted to make sure I understood the approach. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I think about this, I wonder if we should just silently ignore it. I mean for the other extensions we don't check if the values actually make sense and we can pass a NULL value to _decode_general_names()
, which just leads to an empty GeneralNames object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about just creating a bad extension (use an OID that doesn't make sense for the context, like EKU or KU)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I owe you a review of this updated code again. Will get to it tonight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks. I just wanted to see if we need to change the behavior again, because before we have decided on what should happen you might just waste your time reviewing code which needs to be changed anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, looking at this more I'd prefer it to ignore it like a normal NULL. We should already be triggering this code path with another test so we shouldn't need a special test case at all now that you're using the ExtensionParser class, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for everything which goes through the regular processing with X509V3_EXT_d2i
we already handle the NULL case and I haven't change any of that code. It would be just about the certIssuer extension parsing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave this as is with just an additional comment next to that value error that states it's present because we're parsing the extension ourselves and can't rely on the check in the extensionparser.
I've restarted the CI job in #2417. Once that merges you can rebase this and add the two comments and I'll do a final review. Once again, thanks for sticking with this! |
The vector has now merged. If you add those two comments I'll do a final paranoia-based review to make sure I haven't missed anything and we can get this merged! |
add __repr__ to x509.Extensions
… into crl_ossl_backend
Deserialize a certificate revocation list (CRL) from PEM encoded data. PEM | ||
requests are base64 decoded and have delimiters that look like | ||
``-----BEGIN X509 CRL-----``. This format is also known as | ||
PKCS#10. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PKCS10 defines CSRs -- is there anything about CRLs in there?
fix docs regarding CRL PEM format
I have a few small things I'd like to clean up but I'm satisfied that it's ready for merge now. Huge thanks @etrauschke. Be sure to send a PR adding yourself to |
OpenSSL backend code for CRLs
Changes Unknown when pulling cee79f8 on etrauschke:crl_ossl_backend into ** on pyca:master**. |
This is the backend code for the CRL objects. Looks like a bunch of additional automatic tests have been added so let me make sure they clear first.