Skip to content
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

Fix several bugs relating to OID encoding and decoding #4063

Merged
merged 4 commits into from
May 23, 2024
Merged

Conversation

randombit
Copy link
Owner

The handling for OID encoding did not correctly handle OIDs that begin with 2.x where x >= 40.

Fixes #4023

Copy link

@jdoubleu jdoubleu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall 👍.

I'm not sure if it helps to clarify, that Botan only really supports OIDs in the context of X.503v3 certificates. In theory OIDs can have infinitely large components, while RFC5280 (Appendix B) restricts them to only 28 bits.

I think negative tests would be beneficial as well: Using invalid encodings and seeing what happens (hopefully an exception). I found some test vectors on this page: https://misc.daniel-marschall.de/asn.1/oid_facts.html#chap3

Comment on lines +30 to +32
// This last is a limitation of using 32 bit integers when decoding
// not a limitation of ASN.1 object identifiers in general
BOTAN_ARG_CHECK(oid[1] <= 0xFFFFFFAF, "OID second arc too large");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where's that 0xFFFFFFAF constant coming from? The comment doesn't explain why that's the limit. I imagine it has something to do with the variable length encoding?

You can go even further and restrict it to just 28 bits (0x0FFF'FFFF), if you only want to support X.509v3:

This specification mandates support for OIDs that have arc elements
with values that are less than 2^28, that is, they MUST be between 0
and 268,435,455, inclusive.

-- RFC5280 Appendix B

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's (2**32-1) - 80 which ensures that we can hold the combined first + second in a single uint32_t

@randombit
Copy link
Owner Author

I'm not sure if it helps to clarify, that Botan only really supports OIDs in the context of X.503v3 certificates. In theory OIDs can have infinitely large components, while RFC5280 (Appendix B) restricts them to only 28 bits.

Indeed. In the short term we can't fix this because we have some APIs (which become deprecated in this PR) which return the OID components as 32 bit integers. So it's not possible for us to support anything larger that this in the meantime.

I think negative tests would be beneficial as well:

Good point thanks, I'll add this.

The handling for OID encoding did not correctly handle OIDs that
begin with 2.x where x >= 40.

Fixes #4023
Even BER requires that the first byte of a multibyte encoding be
greater than zero, so don't accept this.
Copy link
Collaborator

@reneme reneme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this on! Looks good to me, too. I added a few nits and a potential control flow simplification for the decoder.

src/lib/asn1/asn1_oid.cpp Outdated Show resolved Hide resolved
@@ -159,28 +170,33 @@ void OID::encode_into(DER_Encoder& der) const {
throw Invalid_Argument("OID::encode_into: OID is invalid");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: If we were able to get rid of the default constructor, we could simply assert that an OID object must be valid. All other constructors call oid_valid_check() and therefore throw during construction of an invalid OID.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately with how the ASN.1 library works right now any type you decode has to be default constructable. :/

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm working on a new ASN.1 library but this is a very long term project, Botan 4 at earliest)

src/lib/asn1/asn1_oid.cpp Outdated Show resolved Hide resolved
src/lib/asn1/asn1_oid.cpp Outdated Show resolved Hide resolved
src/lib/asn1/asn1_oid.cpp Outdated Show resolved Hide resolved
src/lib/asn1/asn1_oid.cpp Outdated Show resolved Hide resolved
Co-authored-by: René Meusel <github@renemeusel.de>
@randombit randombit merged commit 9e6c6da into master May 23, 2024
43 checks passed
@randombit randombit deleted the jack/fix-4023 branch May 23, 2024 14:30
@jdoubleu
Copy link

Thanks for fixing this! 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invalid BER decoding of OIDs
3 participants