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 string downcast to PrintableString as issued in #1033 #1641

Merged
merged 31 commits into from
Nov 8, 2018

Conversation

thomas-dee
Copy link
Contributor

Description

Fix string downcast to PrintableString as issued in #1033.

  1. Implemented mbedtls_asn1_write_any_string allowing to write a string with any given tag
  2. Extended x509_attrs in x509_create.c to handle tag types correctly
  3. Fixed x509_write_name to use mbedtls_asn1_write_any_string using the tag types specified in x509_attrs

Status

READY

Requires Backporting

T.b.d.

@simonbutcher
Copy link
Contributor

Thanks for the contribution and welcome to the project!

This looks like it's your first contribution and I can't find you in our list of contributors. Unfortunately we have a policy of only accepting contributions with a Contributor’s Licence Agreement (CLA), signed or authorised by yourself, so to be able to accept your PR, we'll need your, or your company's approval of a CLA.

The easiest way to do this is if you create an mbed account and accept this click through agreement which is applicable if this is a personal contribution. Alternatively, you can find a slightly different agreement to sign here, which can be signed and returned to us, and is applicable if you don't want to create an mbed account or alternatively if this is a corporate contribution.

Thanks for your understanding!

@thomas-dee
Copy link
Contributor Author

Ok, I just agreed to the CLA with my new mbed account.

@simonbutcher
Copy link
Contributor

Thanks @thomas-dee! Could you please confirm that this is your profile? Thanks.

@thomas-dee
Copy link
Contributor Author

Yes it is. I just linked my GitHub account in the Mbed profile settings.

@simonbutcher simonbutcher added the needs-review Every commit must be reviewed by at least two team members, label Jun 14, 2018
@simonbutcher simonbutcher self-assigned this Aug 1, 2018
{ ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },

Choose a reason for hiding this comment

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

@thomas-dee Could you explain the varying choices of encodings here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned in line 45 I tried to default to the types given in RFC3280. For the given types it was not clear for me, so I defaulted to PrintableString.

Choose a reason for hiding this comment

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

@thomas-dee I overlooked the reference to RFC 3280, thanks for pointing that out.

Choose a reason for hiding this comment

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

We should reference the newer RFC 5280 here.

};

static const char *x509_at_oid_from_name( const char *name, size_t name_len )
static const x509_attr_descriptor_t *x509_at_oid_from_name( const char *name, size_t name_len )

Choose a reason for hiding this comment

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

The name of this function is no longer accurate when it returns the entire descriptor, and not only the OID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about x509_at_descr_from_name?

@@ -253,34 +253,37 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
return( (int) len );
}

int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
int mbedtls_asn1_write_any_string( unsigned char **p, unsigned char *start, int tag,

Choose a reason for hiding this comment

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

I don't like the name mbedtls_asn1_write_any_string - what about mbedtls_asn1_write_tagged_string, reflecting the flexibility in the tag?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mbedtls_asn1_write_tagged_string sounds nice.

Copy link

@hanno-becker hanno-becker left a comment

Choose a reason for hiding this comment

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

Overall the change looks good to me, thanks @thomas-dee for your work!

There are some issues that need to be addressed, though:

  • The name of the new API function mbedtls_asn1_write_any_string should be changed.
  • The default choice of string format for RDN's should be explained.
  • Multiple test suites fail because they compare the output of X.509 writing functions to hardcoded files. Since many RDNs now use the UTF8String format, as
    opposed to PrintableString previously, the resulting ASN.1 data is different, and the files containing the expected output need to be updated.

@hanno-becker hanno-becker added needs-work and removed needs-review Every commit must be reviewed by at least two team members, labels Sep 18, 2018
@thomas-dee
Copy link
Contributor Author

@hanno-arm Thanks for your review.

Do you have any ideas how to elaborate the choices of string formats besides referencing RFC3280?

 - renamed `mbedtls_asn1_write_any_string` to `mbedtls_asn1_write_tagged_string`
 - renamed `x509_at_oid_from_name` to `x509_attr_descr_from_name`
*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param tag the tag to write

Choose a reason for hiding this comment

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

Suggestion: The tag defining the character encoding used in \p text, e.g. #MBEDTLS_ASN1_UTF8_STRING or #MBEDTLS_ASN1_PRINTABLE_STRING.

* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param tag the tag to write
* \param text the text to write

Choose a reason for hiding this comment

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

Suggestion: The string to write, encoded according to \p tag.

* \param start start of the buffer (for bounds-checking)
* \param tag the tag to write
* \param text the text to write
* \param text_len length of the text

Choose a reason for hiding this comment

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

Suggestion: The length of \p text in bytes (not necessarily characters).

*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param text the text to write

Choose a reason for hiding this comment

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

Pre-existing, but in line with the above suggestion I'd find it clearer to write The string to write, in UTF-8 encoding. here.

* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param text the text to write
* \param text_len length of the text
Copy link

@hanno-becker hanno-becker Sep 19, 2018

Choose a reason for hiding this comment

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

Pre-existing, but in line with the above suggestion I'd find it clearer to write The length of \p text in bytes. here.

* \param text the text to write
* \param text_len length of the text
*
* \return the length written or a negative error code

Choose a reason for hiding this comment

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

Pre-existing, but it should be clarified that "length" refers to the entire ASN.1 data, so The number of bytes written to the target buffer \c *p on success. Also, a negative error code should be in a separate line, i.e. \return A negative error code on failure.

@thomas-dee Do you mind making these changes while at it?

* \return the length written or a negative error code
*/
int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len );

Choose a reason for hiding this comment

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

The indentation is wrong here.

@hanno-becker
Copy link

This PR includes #2167 which should be merged first.

@hanno-becker
Copy link

Travis CI failed because of an unlucky seed leading to the UDP proxy dropping too much - such failures should be rare but in principle expected as long as we don't set a limit on how much the UDP proxy may drop.

@hanno-becker
Copy link

retest

hanno-becker pushed a commit to hanno-becker/mbedtls that referenced this pull request Nov 5, 2018
This commit introduces variants test-ca_utf8.crt,
test-ca_printablestring.crt and test-ca_uppercase.crt
of tests/data_files/test-ca.crt which differ from
test-ca.crt in their choice of string encoding and
upper and lower case letters in the DN field. These
changes should be immaterial to the recovation check,
and three tests are added that crl.pem, which applies
to test-ca.crt, is also considered as applying to
test-ca_*.crt.

The test files were generated using PR Mbed-TLS#1641 which
- adds a build instruction for test-ca.crt to
  tests/data_files/Makefile which allows easy
  change of the subject DN.
- changes the default string format from `PrintableString`
  to `UTF8String`.

Specifically:
- `test-ca_utf8.crt` was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641.
- `test-ca_uppercase.crt`, too, was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641, after modifying the subject DN line in the build
   instruction for `test-ca.crt` in `tests/data_files/Makefile`.
-  `test-ca_printable.crt` is a copy of `test-ca.crt`
   because at the time of this commit, `PrintableString` is
   still the default string format.
Copy link
Contributor

@k-stachowiak k-stachowiak 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. I only have one minor remark about preexisting code, also I noticed one commit message claiming to add something, whereas it was actually added in another commit, but in my opinion that is irrelevant.

/*
* Like memcmp, but case-insensitive and always returns -1 if different
*/
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
Copy link
Contributor

@k-stachowiak k-stachowiak Nov 5, 2018

Choose a reason for hiding this comment

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

This doesn't maintain the law of trichotomy like memcmp does. Therefore, I'd change the documenting comment, or reimplement the function to return adequate values.

Choose a reason for hiding this comment

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

@k-stachowiak Thanks for remarking that - however, while I agree that the documentation could be more verbose, it does already remark that the function 'always returns -1 if different`.

hanno-becker pushed a commit to hanno-becker/mbedtls that referenced this pull request Nov 6, 2018
This commit introduces variants test-ca_utf8.crt,
test-ca_printablestring.crt and test-ca_uppercase.crt
of tests/data_files/test-ca.crt which differ from
test-ca.crt in their choice of string encoding and
upper and lower case letters in the DN field. These
changes should be immaterial to the recovation check,
and three tests are added that crl.pem, which applies
to test-ca.crt, is also considered as applying to
test-ca_*.crt.

The test files were generated using PR Mbed-TLS#1641 which
- adds a build instruction for test-ca.crt to
  tests/data_files/Makefile which allows easy
  change of the subject DN.
- changes the default string format from `PrintableString`
  to `UTF8String`.

Specifically:
- `test-ca_utf8.crt` was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641.
- `test-ca_uppercase.crt`, too, was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641, after modifying the subject DN line in the build
   instruction for `test-ca.crt` in `tests/data_files/Makefile`.
-  `test-ca_printable.crt` is a copy of `test-ca.crt`
   because at the time of this commit, `PrintableString` is
   still the default string format.
hanno-becker pushed a commit to hanno-becker/mbedtls that referenced this pull request Nov 6, 2018
This commit introduces variants test-ca_utf8.crt,
test-ca_printablestring.crt and test-ca_uppercase.crt
of tests/data_files/test-ca.crt which differ from
test-ca.crt in their choice of string encoding and
upper and lower case letters in the DN field. These
changes should be immaterial to the recovation check,
and three tests are added that crl.pem, which applies
to test-ca.crt, is also considered as applying to
test-ca_*.crt.

The test files were generated using PR Mbed-TLS#1641 which
- adds a build instruction for test-ca.crt to
  tests/data_files/Makefile which allows easy
  change of the subject DN.
- changes the default string format from `PrintableString`
  to `UTF8String`.

Specifically:
- `test-ca_utf8.crt` was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641.
- `test-ca_uppercase.crt`, too, was generated by running
      `rm test-ca.crt && make test-ca.crt`
   on PR Mbed-TLS#1641, after modifying the subject DN line in the build
   instruction for `test-ca.crt` in `tests/data_files/Makefile`.
-  `test-ca_printable.crt` is a copy of `test-ca.crt`
   because at the time of this commit, `PrintableString` is
   still the default string format.
k-stachowiak
k-stachowiak previously approved these changes Nov 6, 2018
Copy link
Contributor

@k-stachowiak k-stachowiak left a comment

Choose a reason for hiding this comment

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

The new commit looks good. As a side note, I can see, that the commit messages document the data files generation method; I wonder if these are documented equally well elsewhere. If not, then the commit messages could be published somewhere.

simonbutcher
simonbutcher previously approved these changes Nov 6, 2018
one using PrintableString and the other UTF8String) or
in the choice of upper and lower case. Reported by
HenrikRosenquistAndersson in #1784.

Copy link
Contributor

Choose a reason for hiding this comment

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

There needs to be credit to @thomas-dee here also as well as mention of his work in #1033!

* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param len the length to write
* \note This function works backwards in data buffer.
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a blocker, but it should be 'This function works backwards in the data buffer'.

@hanno-becker
Copy link

@sbutcher-arm Thanks for noticing, indeed this PR never got a ChangeLog entry. Are you adding it during merging?

Copy link
Contributor

@simonbutcher simonbutcher left a comment

Choose a reason for hiding this comment

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

LGTM

@simonbutcher
Copy link
Contributor

Jenkins CI failed (again) on the BSD timing test, which is a known issue and good enough to be a pass.

@simonbutcher simonbutcher added approved Design and code approved - may be waiting for CI or backports and removed needs-review Every commit must be reviewed by at least two team members, labels Nov 6, 2018
@simonbutcher simonbutcher merged commit f143a78 into Mbed-TLS:development Nov 8, 2018
mpg added a commit to mpg/mbedtls that referenced this pull request Feb 3, 2020
In the 2.7 branch, test-ca.crt has all the components of its Subject name
encoded as PrintableString, because it's generated with our cert_write
program, and our code writes all components that way until Mbed TLS 2.14.

But the default RSA SHA-256 certificate, server2-sha256.crt, has the O and CN
components of its Issuer name encoded as UTF8String, because it was generated
with OpenSSL and that's what OpenSSL does, regardless of how those components
were encoded in the CA's Subject name.

This triggers some overly strict behaviour in some libraries, most notably NSS
and GnuTLS (of interest to us in ssl-opt.sh) which won't recognize the trusted
root as a possible parent for the presented certificate, see for example:
Mbed-TLS#1033

Fortunately, we have at our disposal a version of test-ca.crt with encodings
matching the ones in server2-sha256.crt, in the file test-ca_utf8.crt. So
let's append that to gnutls-cli's list of trusted roots, so that it recognizes
certs signed by this CA but with the O and CN components as UTF8String.

Note: Since Mbed-TLS#1641 was merged (in Mbed
TLS 2.14), we changed how we encode those components, so in the 2.16 branch,
cert_write generates test-ca.crt with encodings that matches the ones used by
openssl when generating server2-sha256.crt, so the issue of gnutls-cli
rejecting server2-sha256.crt is specific to the 2.7 branch.
gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this pull request Aug 21, 2020
The test certificate used for clients in compat.sh, cert_sha256.crt,
had the issuer ON and CN encoded as UTF8String, but the corresponding
CA certificate test-ca_cat12.crt had them encoded as PrintableString.
The strings matched, which is sufficient according to RFC 5280 §7.1
and RFC 4518 §2.1. However, GnuTLS 3.4.10 requires the strings to have
the same encoding, so it did not accept that the certificate issued by
UTF8String "PolarSSL Test CA" was validly issued by the
PrintableString "PolarSSL Test CA" CA.

ebc1f40, merged via
Mbed-TLS#1641 and released in Mbed TLS
2.14, updated these certificates.
4f928c0 merged, via
Mbed-TLS#2418 fixed this in the 2.7 LTS
branch for the SHA-1 certificate which was used at the time. The
present commit applies the same fix for the SHA-256 certificate that
is now in use.

For uniformity, this commit regenerates all the cert_*.crt.

Signed-off-by: Gilles Peskine <[email protected]>
gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this pull request Aug 21, 2020
server2-sha256.crt had the issuer ON and CN encoded as UTF8String, but the
corresponding CA certificate test-ca_cat12.crt had them encoded as
PrintableString. The strings matched, which is sufficient according to RFC
5280 §7.1 and RFC 4518 §2.1. However, GnuTLS 3.4.10 requires the strings to
have the same encoding, so it did not accept that the
UTF8String "PolarSSL Test CA" certificate was signed by the
PrintableString "PolarSSL Test CA" CA.

Since Mbed TLS 2.14 (specifically ebc1f40
merged via Mbed-TLS#1641), server2-sha256.crt
is generated by Mbed TLS's own cert_write program, which emits a
PrintableString. In older versions, this file was generated by OpenSSL,
which started emitting UTF8String at some point.
4f928c0 merged via
Mbed-TLS#2418 fixed this for the SHA-1
certificate which was used at the time. The present commit applies the same
fix for the SHA-256 certificate that is now in use.

Signed-off-by: Gilles Peskine <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Design and code approved - may be waiting for CI or backports component-x509 enhancement needs-preceding-pr Requires another PR to be merged first
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants