Mbed TLS is now part of TrustedFirmware.org.

All flags set if certificate verification fails


Feb 22, 2018 10:28
Marian Kechlibar

Hello all,

Recently, I updated mbedTLS to 2.7.0 and my application started behaving strangely if the cert of the remote party was rejected.

I was able to narrow the cause of the problem down to GitHub commit from Jun 22, 2017. Namely, to the line

*flags = (uint32_t) -1;

in the function function mbedtls_x509_crt_verify_with_profile in x509_crt.c.

This sets all the error flag bits to 1. From the commit message, it is obviously intended to do so.

However, I relied on the flags to inform the end user in the GUI about detected problems of the certificate, and now that all the flags are set "just in case", the message is massively misleading (and untrue), for example, the user is informed that the certificate is expired, while it is not.

I can get rid of my problem by just commenting out this line from the source and recompiling mbedTLS, but I would suggest reconsidering (and reverting) this change.

In my opinion, setting false-positive flags about errors that were not positively detected, is not really an improvement over the previous implementation. Usually, the certificate gets rejected for one particular reason and the user/administrator/root/whoever may be concerned should rather receive truthful, even if incomplete, feedback from the library, than a "shotgun blast".

Best regards

Marian Kechlibar, Prague, CZ

 
Feb 22, 2018 16:27
Ron Eldor

Hi Marian,
Thank you for raising our attention to this issue. I believe you are correct, and opened a github issue on your name, to track it.
Regards,
Mbed TLS Team member
Ron

 
Feb 22, 2018 16:39
Ron Eldor

Hi Marian,
Although I believe you are correct and thus opened an issue for it, I tried to reproduce it, and couldn't reproduce the issue.
Could you please comment on the github issue steps to reproduce the issue?
Regards,
Mbed TLS Team member
Ron

 
Mar 2, 2018 12:12
Marian Kechlibar

Hello, I can reproduce the problem always when I attempt to connect to a SSL server whose server certificate is in any way invalid or has unknown CA.

I made a screenshot of the trace in my MSVC, but it seems that I cannot add any attachment to my message.

 
Mar 2, 2018 12:15
Marian Kechlibar

So the trace is

mbedtls_ssl_handshake_step(mbedtls_ssl_context * ssl) Line 6627
mbedtls_ssl_handshake_client_step(mbedtls_ssl_context * ssl) Line 3370
mbedtls_ssl_parse_certificate(mbedtls_ssl_context * ssl) Line 4619
mbedtls_x509_crt_verify_with_profile(...) Line 2325

My line numbers may vary slightly, because I change some typedefs.

 
Mar 13, 2018 11:19
Ron Eldor

Hi Mariane,
Thank you for your explanation. Let me rephrase my previous answer, when I try to verify an invalid certificate, I get correct verification flags error. Could you please elaborate on what Mbed TLS version you are using, and complete steps to reproduce?
Regards,
Mbed TLS Team member
Ron

 
Mar 13, 2018 13:16
Marian Kechlibar

Hi Ron,

I am using mbedTLS 2.7.0 within a fairly complex project whose total line count exceeds two million. I cannot share a test case with you easily.

However, I think the source is pretty straightforward. As long as you can hit a breakpoint on the line

*flags = (uint32_t) -1;

in the function function mbedtls_x509_crt_verify_with_profile in x509_crt.c, you should have the same results as I have.

Try using mbedtls_ssl_conf_verify during initialization of your context to set a custom verification routine.

 
Mar 13, 2018 13:19
Fredrik Axelsson

I agree with the original poster. I run into this problem when the call to f_vrfy in x509_crt_verify_top returns an error in. My f_vrfy-function sets flags to reflect the cause of the error but when the error ends up in mbedtls_x509_crt_verify_with_profile, *flags is set to -1 and the cause of the error is lost. The error code is also changed from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED to MBEDTLS_ERR_X509_FATAL_ERROR which further obscures the original error cause.

 
Mar 13, 2018 14:47
Ron Eldor

Hi guys,
I don't disagree with you. I am trying to reproduce this issue, with an invalid CA, using the cert_app reference application, on my Linux machine, and I get correct verification flags. Any additional information would assist. No need to post full program, only the Mbed TLS related code (especially conf setting functions )For example, are you working on Windows?
Regards,
Mbed TLS Team member
Ron

 
Mar 13, 2018 14:51
Marian Kechlibar

The code I am working on is used on Windows, Linux, Android and Symbian. (Yes, that is not a typo. There are still quite a few people with old Nokias running around, and old Nokias do not support anything above TLS 1.0 natively).

I believe that the key step to reproduce the issue is to set up your own f_vrfy function.

 
Mar 15, 2018 07:12
Fredrik Axelsson

Provide a f_vrfy function that returns an error code and sets flags. Upon return from my_vrfy to mbedtls_x509_crt_verify_with_profie, *flags is set to -1 and the error code is changed to MBEDTLS_ERR_X509_FATAL_ERROR

int my_vrfy(void* /*ctx*/, mbedtls_x509_crt* /*crt*/,
            int /*certificate_depth*/, uint32_t* flags)
{
  /* ... */
  *flags = MBEDTLS_X509_BADCRL_NOT_TRUSTED;
  return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}

void setup()
{
  /* ... */
  mbedtls_ssl_conf_verify(&ssl_cfg, my_vrfy, NULL);
}
 
Mar 27, 2018 15:33
Ron Eldor

Hi Marian and Fredrik,
Thank you for your examples. I managed to reproduce your use casses according to your examples, However, as mentioned in the documentation for mbedtls_x509_crt_verify() about the custom verify callback:

All flags left after returning from the callback are also returned to the application. The function should return 0 for anything (including invalid certificates) other than fatal error, as a non-zero return code immediately aborts the verification process. For fatal errors, a specific error code should be used (different from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR can be used if no better code is available.

You custom verify callback should return 0 even for failed certificates.
Regards,
Mbed TLS Team member
Ron

 
Mar 28, 2018 06:25
Fredrik Axelsson

Yes, returning 0 from my verify callback works. Thank's for the clarification.

/fredrik

 
Mar 28, 2018 07:23
Ron Eldor

HI Fredrik,
I'm glad you managed to make it work.
I have one comment though on your code example. The flags variable is a mask of verification error flags, and it is better you add to it the error, instead of assigning it the error.:

*flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;

instead of

*flags = MBEDTLS_X509_BADCRL_NOT_TRUSTED;

as shown in your example.
Regards,
Mbed TLS Team member
Ron