-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Certificates created are not accepted by curl/firefox #1033
Comments
Hi @Moschn, thanks for raising this! Could you provide your curl version and the error you're receiving? I tried to reproduce the problem following your steps and noticed the following:
Looking into the differences between the OpenSSL and mbed TLS generated certificates, the crucial point seems to be the choice of string-encoding: OpenSSL uses Regards, |
Hi @hanno-arm I am using curl v7.47.0 and I get the same error message:
This is great news. Can you check if your changes also apply to firefox? I also tested with chromium but it is not accepting the certificates because chromium stopped accepting |
ARM Internal Ref: IOTSSL-1591 |
Hi @Moschn,
Yes, switching from I'm surprised by this behavior of Firefox and curl, as I interpreted RFC5280 as not mandating any particular choice of string format. Regards, |
I checked which ssl library curl is built against on my machine. It turns out curl is built against gnutls. So I tried to connect directly with gnutls (version 3.4.10) after adding the rootCA.pem to the root-ca-store: cert_mbedtls.pem:
cert_openssl.pem: works flawlessly. Firefox and chromium use NSS as their ssl library. It looks like gnutls and NSS do not accept |
Hi @Moschn, thanks for checking that! The following might be the problem: GnuTLS seems to store the trusted certificates in a hash-table, the index of a trusted certificate being the hash of the DER-encoded distinguished name it contains, modulo the fixed hash-index size (127). When GnuTLS verifies a certificate, it only considers those trusted certificates as a potential signer whose DN's have the same hash-index as the issuer DN in the certificate to verify. See https://github.com/gnutls/gnutls/blob/gnutls_3_5_x/lib/x509/verify-high.c#L1281 and https://github.com/gnutls/gnutls/blob/gnutls_3_5_x/lib/x509/verify-high.c#L1297. Now when mbed TLS's I manually changed the string types from Looking at https://tools.ietf.org/html/rfc5280#section-7.1, it seems that checking the DN's DER-encodings for raw equality is not valid and that instead some normalization on the strings should be performed - but this as well as my guess above will need more careful study. In any case, to increase compatibility and avoid such kinds of problems, one could make the certificate signing routine always use the same string format as the signing certificate. Regards, |
I believe that #468 is related |
A small update: While the analysis above still seems to apply to the case where all fields are using the character set of |
Just a side note: I stumbled across the exact same issue and patched mbed TLS accordingly. |
Improved bugfix to handle all string types correctly |
Since the given patch works great for me. Are there any plans on merging this into the main development branch? |
Besides String type issues there is another reason, Firefox does not accept created (and signed) certificates. char issuer_name[256];
mbedtls_x509write_cert crt;
mbedtls_x509_crt issuer_crt;
...
mbedtls_x509_crt_init( &issuer_crt );
mbedtls_x509write_crt_init( &crt );
...
mbedtls_x509_crt_parse(&issuer_crt, issuer_crt_data, issuer_crt_data_len);
mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name), &issuer_crt.subject );
...
mbedtls_x509write_crt_set_issuer_name(&crt, issuer_name);
... The then created PEM certificate will lead to an Unknown CA error in Firefox. The reason is that I'm not sure if this is a Firefox or an Mbed TLS bug. |
Hi @thomas-dee, I looked at the relevant functions in #2005, and while I think there is inconsistency in the way the ASN.1 - LinkedList - String conversions sometimes reverse the order and sometimes don't, it seems that when going from ASN.1 to String and vice versa - as your code does, too - the order should be kept; in other words, I currently cannot unify my understanding of the code with the failure you're observing, nor reproduce the latter. Could you perhaps provide a minimal reproducible example? Best, |
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.
Description
Bug
OS
linux
mbed TLS build:
Version: ab0a804
OS version: Ubuntu 16.04
Configuration: not modified. Directly from the development branch
Peer device TLS stack and version
Curl/Firefox
Expected behavior
Create a signed certificate from a given CA certificate (rootCA.key), CA key (rootCA.pem), key (test.key) and signing request (request.csr). Start a testserver with the new certificate. Connect to the testserver with various clients with the rootCA added to the trusted CAs
See that the certificate is accepted.
Actual behavior
Certificate is not accepted.
The certificate gets accepted by both curl and firefox if instead of using mbedtls, openssl is used to create the certificate.
Steps to reproduce
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem
openssl genrsa -out test.key 2048
openssl req -new -key test.key -out request.csr
openssl x509 -req -in request.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out cert_openssl.pem -days 500 -sha256
./cert_write request_file=request.csr issuer_crt=rootCA.pem issuer_key=rootCA.key output_file=cert_mbedtls.pem not_before=20170727125153 not_after=20181209125153
openssl s_server -accept 4433 -cert cert_mbedtls.pem -key test.key -www
openssl s_server -accept 4433 -cert cert_openssl.pem -key test.key -www
./ssl_server2 crt_file=cert_mbedtls.pem key_file=test.key
./ssl_server2 crt_file=cert_openssl.pem key_file=test.key
E.g.
curl -X GET "https://_hostname_:4433" --cacert rootCA.pem
Further information
It does not matter if a certificate is created using a signing request or not. All certificates that are created with
cert_write
are not accepted (even though the rootCA is supplied to the clients).It is also interesting to note that
openssl s_client
accepts both certificates.The text was updated successfully, but these errors were encountered: