Introduce ASN.1 SEQUENCE traversal API #263

Merged
hanno-becker merged 7 commits from asn1_traversal_api into development 2020-02-03 06:35:20 -06:00
hanno-becker commented 2019-09-17 07:23:04 -05:00 (Migrated from github.com)

Summary: This PR is a spin-out from the X.509 on demand parsing work https://github.com/ARMmbed/mbedtls/pull/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 and MBEDTLS_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.

__Summary:__ This PR is a spin-out from the X.509 on demand parsing work https://github.com/ARMmbed/mbedtls/pull/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` and `MBEDTLS_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.
Patater (Migrated from github.com) reviewed 2019-09-17 07:23:04 -05:00
yanesca (Migrated from github.com) reviewed 2019-09-17 07:23:04 -05:00
gilles-peskine-arm commented 2019-09-18 03:30:32 -05:00 (Migrated from github.com)

https://github.com/ARMmbed/mbed-crypto/pull/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.

https://github.com/ARMmbed/mbed-crypto/pull/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.
hanno-becker commented 2019-09-18 03:31:35 -05:00 (Migrated from github.com)

@gilles-peskine-arm It's not fully satisfactory, but because the PR reimplements mbedtls_asn1_get_sequence_of() in terms of the new traversal API, any tests for the former will also test the latter.
But of course, it'd be better to have standalone tests, too.

@gilles-peskine-arm It's not fully satisfactory, but because the PR reimplements `mbedtls_asn1_get_sequence_of()` in terms of the new traversal API, any tests for the former will also test the latter. But of course, it'd be better to have standalone tests, too.
Patater (Migrated from github.com) reviewed 2019-09-18 06:13:41 -05:00
@ -371,0 +423,4 @@
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
Patater (Migrated from github.com) commented 2019-09-18 06:08:58 -05:00

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?

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?
@ -371,0 +477,4 @@
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
Patater (Migrated from github.com) commented 2019-09-18 06:09:56 -05:00

Can the unsigned char be const unsigned char? I don't think we'd be modifying **p, only p or *p.

Can the `unsigned char` be `const unsigned char`? I don't think we'd be modifying `**p`, only `p` or `*p`.
@ -371,0 +482,4 @@
* - The length of the content of the current element.
* If the callback returns a non-zero value,
* the function stops immediately,
* forwarding the callback's return value.
Patater (Migrated from github.com) commented 2019-09-18 06:10:21 -05:00

Can start be made const?

Can `start` be made const?
Patater (Migrated from github.com) commented 2019-09-18 06:12:41 -05:00

Ah, too bad this is not const. I guess we can't have our callback with p const because of this.

Ah, too bad this is not const. I guess we can't have our callback with `p` const because of this.
gilles-peskine-arm commented 2019-10-30 13:59:05 -05:00 (Migrated from github.com)

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:

  • I removed most updates to existing documentation because they were largely superseded by #75.
  • I added tests for the new functions.
  • I tweaked the documentation of the new functions.
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: * I removed most updates to existing documentation because they were largely superseded by #75. * I added tests for the new functions. * I tweaked the documentation of the new functions.
gilles-peskine-arm (Migrated from github.com) reviewed 2019-10-30 13:59:38 -05:00
@ -371,0 +423,4 @@
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
gilles-peskine-arm (Migrated from github.com) commented 2019-10-30 13:59:37 -05:00

It isn't internal since it will be used by Mbed TLS.

It isn't internal since it will be used by Mbed TLS.
gilles-peskine-arm (Migrated from github.com) reviewed 2019-10-30 14:00:34 -05:00
@ -371,0 +477,4 @@
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
gilles-peskine-arm (Migrated from github.com) commented 2019-10-30 14:00:34 -05:00

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.

`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.
gilles-peskine-arm (Migrated from github.com) reviewed 2019-10-30 14:01:36 -05:00
@ -371,0 +482,4 @@
* - The length of the content of the current element.
* If the callback returns a non-zero value,
* the function stops immediately,
* forwarding the callback's return value.
gilles-peskine-arm (Migrated from github.com) commented 2019-10-30 14:01:36 -05:00

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.

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.
gilles-peskine-arm commented 2019-11-12 11:15:10 -06:00 (Migrated from github.com)

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

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
hanno-becker (Migrated from github.com) reviewed 2020-01-31 09:44:37 -06:00
@ -371,0 +423,4 @@
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
hanno-becker (Migrated from github.com) commented 2020-01-31 09:44:36 -06:00

@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.

@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.
gilles-peskine-arm (Migrated from github.com) reviewed 2020-01-31 09:49:30 -06:00
@ -371,0 +423,4 @@
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
gilles-peskine-arm (Migrated from github.com) commented 2020-01-31 09:49:30 -06:00

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.

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.
hanno-becker (Migrated from github.com) reviewed 2020-01-31 09:49:41 -06:00
@ -371,0 +477,4 @@
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
hanno-becker (Migrated from github.com) commented 2020-01-31 09:49:41 -06:00

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.

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.
gilles-peskine-arm (Migrated from github.com) reviewed 2020-01-31 09:51:50 -06:00
@ -371,0 +477,4 @@
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
gilles-peskine-arm (Migrated from github.com) commented 2020-01-31 09:51:50 -06:00

We can tweak the API in Mbed TLS 3. Until we get there, let's keep the API consistent.

We can tweak the API in Mbed TLS 3. Until we get there, let's keep the API consistent.
hanno-becker (Migrated from github.com) reviewed 2020-01-31 09:52:41 -06:00
@ -371,0 +482,4 @@
* - The length of the content of the current element.
* If the callback returns a non-zero value,
* the function stops immediately,
* forwarding the callback's return value.
hanno-becker (Migrated from github.com) commented 2020-01-31 09:52:41 -06:00

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.

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.
hanno-becker (Migrated from github.com) reviewed 2020-01-31 09:53:08 -06:00
@ -371,0 +477,4 @@
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
hanno-becker (Migrated from github.com) commented 2020-01-31 09:53:08 -06:00

Ok, no change here, then.

Ok, no change here, then.
hanno-becker (Migrated from github.com) reviewed 2020-01-31 09:54:06 -06:00
hanno-becker (Migrated from github.com) commented 2020-01-31 09:54:06 -06:00

This way it would work, but what doesn't work is calling parsing functions from within mbedtls_asn1_traverse_sequence_of().

This way it would work, but what doesn't work is calling parsing functions from within `mbedtls_asn1_traverse_sequence_of()`.
hanno-becker commented 2020-01-31 09:55:59 -06:00 (Migrated from github.com)

Rebased on top of development. The only conflict stemmed from @yanesca's introduction of default error codes and was easy to fix.

Rebased on top of `development`. The only conflict stemmed from @yanesca's introduction of default error codes and was easy to fix.
gilles-peskine-arm (Migrated from github.com) reviewed 2020-01-31 10:04:16 -06:00
mpg commented 2020-02-03 04:37:51 -06:00 (Migrated from github.com)

The CI found a problem, in test-ref-configs, with config-symmetric-only.h, the first error is:

/var/lib/build/include/mbedtls/asn1.h:504:5: error: unknown type name 'uint8_t'
     uint8_t tag_must_mask, uint8_t tag_must_val,
     ^

and the other errors look similar. I suggest including stdint.h directly in asn1.h - it probably happens to be included indirectly in some configurations including the default one, but apparently not all of them.

The CI found a problem, in `test-ref-configs`, with `config-symmetric-only.h`, the first error is: ``` /var/lib/build/include/mbedtls/asn1.h:504:5: error: unknown type name 'uint8_t' uint8_t tag_must_mask, uint8_t tag_must_val, ^ ``` and the other errors look similar. I suggest including `stdint.h` directly in `asn1.h` - it probably happens to be included indirectly in some configurations including the default one, but apparently not all of them.
hanno-becker commented 2020-02-03 04:38:54 -06:00 (Migrated from github.com)

Thank you @mpg, I'll fix that.

Thank you @mpg, I'll fix that.
hanno-becker commented 2020-02-03 04:41:08 -06:00 (Migrated from github.com)

@mpg @gilles-peskine-arm Fixed the issue by replacing uint8_t by unsigned char.

@mpg @gilles-peskine-arm Fixed the issue by replacing `uint8_t` by `unsigned char`.
mpg (Migrated from github.com) reviewed 2020-02-03 05:42:56 -06:00
@ -371,0 +423,4 @@
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
mpg (Migrated from github.com) commented 2020-02-03 05:42:55 -06:00

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.

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.
mpg (Migrated from github.com) approved these changes 2020-02-03 05:58:06 -06:00
mpg (Migrated from github.com) left a comment

LGTM

LGTM
gilles-peskine-arm (Migrated from github.com) approved these changes 2020-02-03 06:34:03 -06:00
gilles-peskine-arm commented 2020-02-03 06:35:01 -06:00 (Migrated from github.com)

CI passes except for the Mbed OS tests which are failing for unrelated reasons.

CI passes except for the Mbed OS tests which are failing for unrelated reasons.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-ARMmbed/mbed-crypto!263
No description provided.