-
Notifications
You must be signed in to change notification settings - Fork 96
Introduce ASN.1 SEQUENCE traversal API #263
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
Introduce ASN.1 SEQUENCE traversal API #263
Conversation
8950dc6
to
5d972e7
Compare
#75 fixes some edge cases in the ASN.1 library and adds tests. Can you please make sure that your X.509 code and tests are compatible with these fixes? This PR doesn't have tests; I'm willing to accept it without tests but the lack of tests needs to be filed as a separate bug. |
@gilles-peskine-arm It's not fully satisfactory, but because the PR reimplements |
* call a callback for each entry. | ||
* | ||
* \warning This function is still experimental and may change | ||
* at any time. |
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.
Why should this be experimental? When can it be non-experimental? Could we make asn1_internal.h and place it there if it's only for internal use for now?
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.
It isn't internal since it will be used by Mbed TLS.
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.
@gilles-peskine-arm @Patater What's your view on this? This function must be public, as @gilles-peskine-arm said, so what remains is to decide whether we want to declare it as experimental or not. I'm open either way. If you think the API is good as-is, I'm happy to remove the qualification.
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.
My preference is what you wrote: declare this function as experimental. We don't care about this function except as an internal detail of the implementation an X509 feature that we do care about. It has a complex API that I would prefer not to make official, but that I'm ok to include with the understanding that we're likely to modify it in the future.
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.
The situation should be temporary, since I think we're aiming at making the whole asn1.h
private in Mbed TLS 3.0 (or some point in the future at least) anyway.
* \p cb in case the latter returns a non-zero value. | ||
*/ | ||
int mbedtls_asn1_traverse_sequence_of( | ||
unsigned char **p, |
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 the unsigned char
be const unsigned char
? I don't think we'd be modifying **p
, only p
or *p
.
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.
const unsigned char **
and unsigned char **
do not mix. If this function used a different type, it couldn't be used with the other asn1 parsing functions.
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 agree with @Patater in that in principle the type of p
should be const unsigned char **
here. However, the rest of the ASN.1 parsing library unfortunately also uses unsigned char **
, which we can't change and which forces the use of unsigned char **
here, too (not just for consistency, but simply because this function calls e.g. mbedtls_asn1_get_tag()
which has a unsigned char **
argument). An alternative would be to extend the documentation of all ASN.1 parsing functions to explicitly mention that, despite the missing const
qualification, the **p
is never written to, and that it is hence safe to use the functions in a const unsigned char **
context. If we did that, we could start improving the API by using const unsigned char **
at least for this new API function, and doing a const-cast when calling the other parsing functions.
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.
We can tweak the API in Mbed TLS 3. Until we get there, let's keep the API consistent.
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.
Ok, no change here, then.
uint8_t tag_must_mask, uint8_t tag_must_val, | ||
uint8_t tag_may_mask, uint8_t tag_may_val, | ||
int (*cb)( void *ctx, int tag, | ||
unsigned char* start, size_t len ), |
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 start
be made const?
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 wondering about that. In 99% of the cases it would be const: parsing a read-only string. But it may be useful occasionally to modify an input in place.
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 agree that it should be const
. However, if we want to call other ASN.1 parsing functions from within the callback, then we can't have const
here because those parsing functions don't have const
qualification, as mentioned above.
/* | ||
* Parses and splits an ASN.1 "SEQUENCE OF <tag>" | ||
*/ | ||
int mbedtls_asn1_get_sequence_of( unsigned char **p, |
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.
Ah, too bad this is not const. I guess we can't have our callback with p
const because of this.
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 way it would work, but what doesn't work is calling parsing functions from within mbedtls_asn1_traverse_sequence_of()
.
5d972e7
to
f40fccf
Compare
I rebased this pull request on top of the current base branch. The previous content by Hanno is at https://github.com/gilles-peskine-arm/mbed-crypto/tree/asn1_traversal_api-1. Compared with the previous content:
|
New CI run now that the problems with the Cypress boards are fixed: https://jenkins-internal.mbed.com/job/mbed-crypto-pr/job/PR-263-merge/20/ → PASS |
Also fix a copypasta.
f40fccf
to
1505f63
Compare
Rebased on top of |
The CI found a problem, in
and the other errors look similar. I suggest including |
Thank you @mpg, I'll fix that. |
The rest of the ASN.1 API uses `unsigned char`, too.
@mpg @gilles-peskine-arm Fixed the issue by replacing |
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.
LGTM
CI passes except for the Mbed OS tests which are failing for unrelated reasons. |
* ARMmbed#352: Parse RSA parameters DP, DQ and QP from PKCS1 private keys * ARMmbed#263: Introduce ASN.1 SEQUENCE traversal API * ARMmbed#345: Fix possible error code mangling in psa_mac_verify_finish * ARMmbed#357: Update Mbed Crypto with latest Mbed TLS changes as of 2020-02-03 * ARMmbed#350: test_suite_asn1parse: improve testing of trailing garbage in parse_prefixes * ARMmbed#346: Improve robustness and testing of mbedtls_mpi_copy
Summary: This PR is a spin-out from the X.509 on demand parsing work Mbed-TLS/mbedtls#2478, one of the main drivers of which is to avoid dynamically allocated presentations of ASN.1 SEQUENCEs by traversing the raw ASN.1 in-place whenever needed. To this end, this PR introduces the ASN.1 API
mbedtls_asn1_traverse_sequence_of()
which can be used to traverse an ASN.1 SEQUENCE container, triggering a user-specified callback for each entry found.The PR also introduces two helper macros
MBEDTLS_ASN1_IS_STRING_TAG
andMBEDTLS_OID_CMP_RAW
. Those are technically unrelated to the SEQUENCE traversal API and are included here solely to keep the number of dependencies for the on demand parsing PR low.