Bug 1300655

Summary: OpenSSL: X509_verify_cert() fails to report error when check_trust() returns X509_TRUST_REJECTED
Product: [Other] Security Response Reporter: Adam Mariš <amaris>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: bbaranow, bmaxwell, cdewolf, cheimes, csutherl, dandread, darran.lofthouse, dknox, jason.greene, jawilson, jclere, jdoyle, lgao, mbabacek, mjc, myarboro, pgier, psakar, pslavice, rsvoboda, security-response-team, tmraz, twalsh, vtunka, weli
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard: impact=moderate,public=20160301,reported=20160121,source=redhat,cvss2=6.4/AV:N/AC:L/Au:N/C:P/I:P/A:N,rhel-5/openssl=notaffected,rhel-5/openssl097a=notaffected,rhel-6/openssl=notaffected,rhel-6/openssl098e=notaffected,rhel-7/openssl=notaffected,rhel-7/openssl098e=notaffected,jbews-1/openssl=notaffected,jbews-2/openssl=notaffected,jbews-3/openssl=notaffected,eap-6/openssl=notaffected,fedora-all/openssl=notaffected,fedora-all/mingw-openssl=notaffected
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-08-11 06:21:37 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---
Bug Depends On:    
Bug Blocks: 1300659, 1301692    
Description Flags
Proposed patch
OpenSSL patch with test cases
Proposed patch from upstream none

Description Adam Mariš 2016-01-21 11:20:02 UTC
It was reported that x509_cerify_cert() fails to report an error when check_trust() helper function returns X509_TRUST_REJECTED.
Internally trust settings are stored in ASN1_SEQUENCE(X509_CERT_AUX) on disk and in X509->aux member of X.509 certificates. By default certificates have no auxiliary data. Self-signed certificates without auxiliary trust data are considered as trustworthy. When a certificate has auxiliary data and is loaded with a proper function (e.g. PEM_read_bio_X509_AUX() or SSL_CTX_load_verify_locations()), trust settings are verified with X509_check_trust(). The actual trust depends on the purpose of a connection, e.g. NID_server_auth for a client that wants to verify a connection to a TLS web server. For TLS server and client connections, ssl_verify_cert_chain() calls X509_verify_cert() to verify the chain including trust settings. If X509_TRUST_REJECTED is returned by check_trust(), variable 'ok' is still set to 1 from previous call.

Comment 1 Adam Mariš 2016-01-21 11:23 UTC
Created attachment 1116900 [details]
Proposed patch

Comment 3 Adam Mariš 2016-01-21 11:29:10 UTC

This issue was discovered by Christian Heimes of Red Hat.

Comment 4 Christian Heimes 2016-01-21 16:58:23 UTC
I have some updates. It looks like OpenSSL 1.0.2 is broken since https://git.openssl.org/?p=openssl.git;a=commit;h=d65b8b2162f33ac0d53dace588a0847ed827626c

OpenSSL 1.0.0 is not affected. check_trust() returns ok flag.


OpenSSL 1.0.1 is not affected. check_trust() also returns ok flag.


OpenSSL 1.0.2 is buggy. check_trust() has been altered and now returns trust flags (X509_TRUST_TRUSTED, X509_TRUST_REJECTED or X509_TRUST_UNTRUSTED). X509_verify_cert() fails to set ok=0 for X509_TRUST_REJECTED. It might also handle X509_TRUST_UNTRUSTED wrong. My patch might be incomplete, I have to look into that case more closely. The X509_TRUST_UNTRUSTED case can occure for certs with e.g. '-addtrust clientAuth'. In that case a certificate is not explicitly distrusted for serverAuth but lacks the trust bit for serverAuth.


OpenSSL master (1.1.0 development) has a different trust and chain building code. It needs further investigation.

Comment 5 Christian Heimes 2016-01-25 11:17 UTC
Created attachment 1117928 [details]
OpenSSL patch with test cases

Comment 7 Tomas Mraz 2016-01-25 14:54:37 UTC
Our code does not diverge from upstream 1.0.1 branch in this regard so it is not vulnerable.

Comment 8 Adam Mariš 2016-01-27 09:45:46 UTC
According to maintainer, the issue is addressed in master (1.1.0-dev) where the chain construction code has been completely rewritten. The 1.1.0-dev code not only avoids this problem, but also exercises explicit reject auxiliary data in the verify tests.

Comment 9 Adam Mariš 2016-02-15 16:06 UTC
Created attachment 1127323 [details]
Proposed patch from upstream

Comment 12 Christian Heimes 2016-02-18 11:23:49 UTC
Mark, this ticket is about a bug in the trust check code, not about BC / EKU. It's a bug in the trust verification code that was introduced in 2012, https://github.com/openssl/openssl/commit/d65b8b2162f33ac0d53dace588a0847ed827626c#diff-06463ef55f4d9d5411a243b09e66c06fL668

An attack scenario may look like this.

'Evil Country' has a CA called 'Evil CA' that is controlled by an autocratic government. 'Evil CA' has EKU for S/MIME and TLS web server auth. I don't fully trust 'Evil CA' because I know that it signs certs for TLS interception so the government can spy on users. But I still want to trust the CA for S/MIME signing because state officials sign emails.

With OpenSSL's trust feature I can modify the root anchor and make sure that 'Evil CA' is rejected for TLS server auth. After all the feature is documented in the man page of openssl x509. Due to a bug in OpenSSL my policy is silently ignored. 'Evil CA' is able to sign a cert for *.redhat.com and intercept all traffic with Red Hat.

About three years ago we wanted to use the feature in Python and PyOpenSSL. But we weren't able to make trust reject work. We thought it was a problem on our side and gave up. About a month ago I picked up my experiments again. This time I was able to find the bug -- not in my code but in OpenSSL. I don't know if anybody actually uses the feature. But we were almost using it in Python, PyOpenSSL, python-requests and python-cryptography. Just our rigorous unit testing policy prevented us from introducing a serious bug into the Python ecosystem.

Comment 14 Christian Heimes 2016-02-18 11:34:39 UTC
I agree that the issue a low severity. As far as I know Red Hat based distros (RHEL, Fedora,...) are the only distros that ship a PEM bundle with TRUSTED CERTIFICATEs, too.

Are you sure that nobody uses /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt or /etc/pki/tls/certs/ca-bundle.trust.crt ?

Comment 16 Christian Heimes 2016-03-01 14:22:00 UTC
You can release the embargo. The fix https://github.com/openssl/openssl/commit/a3baa171053547488475709c7197592c66e427cf is in today's OpenSSL 1.0.2g release. The bug wasn't mentioned in the changelog for 1.0.2g and hasn't got a CVE assigned to.