Closed Bug 1044350 Opened 10 years ago Closed 8 years ago

enum corrupted when calling CheckKeyUsage, https: fails w/ SEC_ERROR_INADEQUATE_KEY_USAGE

Categories

(Core :: Security: PSM, defect)

31 Branch
x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: hcoin, Unassigned)

References

Details

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0 (Beta/Release)
Build ID: 20140608211457

Steps to reproduce:

v31 firefox for ubuntu, usual apt-get install firefox. amd64
gdb --args /usr/lib/firefox/firefox
Surf to internal website via https:
https://internal.site.com
CA imported, trusted:
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                C8:2B:09:5C:F3:B5:B4:D2:BB:16:98:77:05:3B:D0:31:49:10:B2:93
            X509v3 Key Usage: 
                Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 CRL Distribution Points: 

website cert: 
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Subject Alternative Name: 
                DNS:www.nottelling.com, DNS:www1.nottelling.com, DNS:dbadmin.nottelling.com, IP Address:192.168.29.253, IP Address:192.168.23.1, IP Address:127.0.0.1
            X509v3 Subject Key Identifier: 
                A8:59:22:96:79:0B:3A:55:0A:E1:55:76:D8:A6:92:90:2E:C2:AF:B2
            X509v3 Authority Key Identifier: 
                keyid:C8:2B:09:5C:F3:B5:B4:D2:BB:16:98:77:05:3B:D0:31:49:10:B2:93

            X509v3 CRL Distribution Points: 

                Full Name:
                  URI:http://www.nottelling.com/ca/myca.crl

            X509v3 Basic Constraints: critical
                CA:FALSE
---
Firefox always reports:   Certificate key usage inadequate for attempted operation. (Error code: sec_error_inadequate_key_usage)

Problem didn't happen on v30.


Actual results:

Watch 'endEntityOrCA' begin life as mozilla::pkix::MustBeEndEntity, but change to
mozilla::pkix::MustBeCA | unknown: 1390136216
as it enters CheckKeyUsage.   Could it be a compiler error, calling a function in the namespace but not in the instance confuses the variables on the stack?  

Breakpoint 2, mozilla::pkix::CheckIssuerIndependentProperties (trustDomain=..., cert=..., time=time@entry=1406341186571161, endEntityOrCA=endEntityOrCA@entry=mozilla::pkix::MustBeEndEntity, 
    requiredKeyUsageIfPresent=mozilla::pkix::digitalSignature, requiredEKUIfPresent=requiredEKUIfPresent@entry=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, 
    subCACount=subCACount@entry=0, trustLevelOut=trustLevelOut@entry=0x7fffc02fa54c) at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:603
603	                                             &trustLevel));
(gdb) s
596	{
(gdb) n
603	                                             &trustLevel));
(gdb) n
607	  if (trustLevel == TrustDomain::ActivelyDistrusted) {
(gdb) n
611	  if (trustLevel != TrustDomain::TrustAnchor &&
(gdb) n
617	  if (trustLevelOut) {
(gdb) n
618	    *trustLevelOut = trustLevel;
(gdb) n
621	  bool isTrustAnchor = endEntityOrCA == MustBeCA &&
(gdb) n
624	  PLArenaPool* arena = cert.GetArena();
(gdb) n
625	  if (!arena) {
(gdb) p endEntityOrCA
$99 = mozilla::pkix::MustBeEndEntity
(gdb) n
635	                     requiredKeyUsageIfPresent);
(gdb) p endEntityOrCA
$100 = mozilla::pkix::MustBeEndEntity
(gdb) s
mozilla::pkix::CheckKeyUsage (endEntityOrCA=(mozilla::pkix::MustBeCA | unknown: 1390136216), encodedKeyUsage=0x7fffb3004aa0, requiredKeyUsageIfPresent=requiredKeyUsageIfPresent@entry=mozilla::pkix::digitalSignature)
    at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:55
55	  if (!encodedKeyUsage) {
(gdb) p endEntityOrCA
$101 = (mozilla::pkix::MustBeCA | unknown: 1390136216)
(gdb) bt
#0  mozilla::pkix::CheckKeyUsage (endEntityOrCA=(mozilla::pkix::MustBeCA | unknown: 1390136216), encodedKeyUsage=0x7fffb3004aa0, requiredKeyUsageIfPresent=requiredKeyUsageIfPresent@entry=mozilla::pkix::digitalSignature)
    at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:55
#1  0x00007ffff1cc19ed in mozilla::pkix::CheckIssuerIndependentProperties (trustDomain=..., cert=..., time=time@entry=1406341186571161, endEntityOrCA=endEntityOrCA@entry=mozilla::pkix::MustBeEndEntity, 
    requiredKeyUsageIfPresent=<optimized out>, requiredEKUIfPresent=requiredEKUIfPresent@entry=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, subCACount=subCACount@entry=0, 
    trustLevelOut=trustLevelOut@entry=0x7fffc02fa54c) at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:635
#2  0x00007ffff1cc0bf9 in mozilla::pkix::BuildForward (trustDomain=..., subject=..., time=time@entry=1406341186571161, endEntityOrCA=endEntityOrCA@entry=mozilla::pkix::MustBeEndEntity, 
    requiredKeyUsageIfPresent=requiredKeyUsageIfPresent@entry=mozilla::pkix::digitalSignature, requiredEKUIfPresent=requiredEKUIfPresent@entry=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, 
    requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, stapledOCSPResponse=stapledOCSPResponse@entry=0x0, subCACount=subCACount@entry=0, results=...) at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixbuild.cpp:216
#3  0x00007ffff1cc1093 in mozilla::pkix::BuildCertChain (trustDomain=..., certToDup=certToDup@entry=0x7fffb2509020, time=time@entry=1406341186571161, endEntityOrCA=endEntityOrCA@entry=mozilla::pkix::MustBeEndEntity, 
    requiredKeyUsageIfPresent=requiredKeyUsageIfPresent@entry=mozilla::pkix::digitalSignature, requiredEKUIfPresent=requiredEKUIfPresent@entry=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, 
    requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, stapledOCSPResponse=stapledOCSPResponse@entry=0x0, results=...) at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixbuild.cpp:343
#4  0x00007ffff1cbe1b6 in mozilla::psm::BuildCertChainForOneKeyUsage (trustDomain=..., cert=cert@entry=0x7fffb2509020, time=time@entry=1406341186571161, requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, 
    stapledOCSPResponse=stapledOCSPResponse@entry=0x0, builtChain=..., eku=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, ku3=mozilla::pkix::keyAgreement, ku2=mozilla::pkix::keyEncipherment, ku1=mozilla::pkix::digitalSignature)
    at /build/buildd/firefox-31.0+build1/security/certverifier/CertVerifier.cpp:206
#5  0x00007ffff1cbe510 in mozilla::psm::CertVerifier::MozillaPKIXVerifyCert (this=this@entry=0x7fffc2e35800, cert=cert@entry=0x7fffb2509020, usage=usage@entry=2, time=time@entry=1406341186571161, pinArg=pinArg@entry=0x7fffb00db160, 
    flags=flags@entry=0, stapledOCSPResponse=0x0, validationChain=validationChain@entry=0x7fffc02fab58, evOidPolicy=evOidPolicy@entry=0x7fffc02fabdc) at /build/buildd/firefox-31.0+build1/security/certverifier/CertVerifier.cpp:331
#6  0x00007ffff1cbe8ad in mozilla::psm::CertVerifier::VerifyCert (this=this@entry=0x7fffc2e35800, cert=cert@entry=0x7fffb2509020, stapledOCSPResponse=<optimized out>, usage=usage@entry=2, time=time@entry=1406341186571161, 
    pinArg=0x7fffb00db160, flags=flags@entry=0, validationChain=validationChain@entry=0x7fffc02fab58, evOidPolicy=evOidPolicy@entry=0x7fffc02fabdc, verifyLog=verifyLog@entry=0x0)
    at /build/buildd/firefox-31.0+build1/security/certverifier/CertVerifier.cpp:458
#7  0x00007ffff1cbf11c in mozilla::psm::CertVerifier::VerifySSLServerCert (this=this@entry=0x7fffc2e35800, peerCert=peerCert@entry=0x7fffb2509020, stapledOCSPResponse=stapledOCSPResponse@entry=0x0, time=time@entry=1406341186571161, 
    pinarg=pinarg@entry=0x7fffb00db160, hostname=0x7fffb0f5ec80 "dbadmin.quietfountain.com", saveIntermediatesInPermanentDatabase=true, certChainOut=certChainOut@entry=0x0, evOidPolicy=evOidPolicy@entry=0x7fffc02fabdc)
    at /build/buildd/firefox-31.0+build1/security/certverifier/CertVerifier.cpp:831
#8  0x00007ffff2dc5326 in mozilla::psm::(anonymous namespace)::AuthCertificate (certVerifier=..., infoObject=0x7fffb00db160, cert=0x7fffb2509020, stapledOCSPResponse=0x0, providerFlags=<optimized out>, time=1406341186571161)
    at /build/buildd/firefox-31.0+build1/security/manager/ssl/src/SSLServerCertVerification.cpp:972
#9  0x00007ffff2dc54ec in mozilla::psm::(anonymous namespace)::SSLServerCertVerificationJob::Run (this=0x7fffb3ebd740) at /build/buildd/firefox-31.0+build1/security/manager/ssl/src/SSLServerCertVerification.cpp:1115
#10 0x00007ffff1d0efd1 in nsThreadPool::Run (this=0x7ffff6c24f00) at /build/buildd/firefox-31.0+build1/xpcom/threads/nsThreadPool.cpp:211
#11 0x00007ffff1d0ce99 in nsThread::ProcessNextEvent (this=0x7fffbaff9a00, mayWait=<optimized out>, result=0x7fffc02faddf) at /build/buildd/firefox-31.0+build1/xpcom/threads/nsThread.cpp:715
#12 0x00007ffff1ccb4fd in NS_ProcessNextEvent (thread=<optimized out>, mayWait=mayWait@entry=true) at /build/buildd/firefox-31.0+build1/xpcom/glue/nsThreadUtils.cpp:263
#13 0x00007ffff1eaf52d in mozilla::ipc::MessagePumpForNonMainThreads::Run (this=0x7fffb0f80c40, aDelegate=0x7fffbb1f86e0) at /build/buildd/firefox-31.0+build1/ipc/glue/MessagePump.cpp:336
#14 0x00007ffff1ea0f21 in RunHandler (this=0x7fffbb1f86e0) at /build/buildd/firefox-31.0+build1/ipc/chromium/src/base/message_loop.cc:222
#15 MessageLoop::Run (this=this@entry=0x7fffbb1f86e0) at /build/buildd/firefox-31.0+build1/ipc/chromium/src/base/message_loop.cc:196
#16 0x00007ffff1d0d86d in nsThread::ThreadFunc (arg=0x7fffbaff9a00) at /build/buildd/firefox-31.0+build1/xpcom/threads/nsThread.cpp:316
#17 0x00007ffff69e9488 in _pt_root (arg=0x7fffb00daf20) at /build/buildd/firefox-31.0+build1/./nsprpub/pr/src/pthreads/ptthread.c:212
#18 0x00007ffff73b6182 in start_thread (arg=0x7fffc02fb700) at pthread_create.c:312
#19 0x00007ffff70e330d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) frame 1
#1  0x00007ffff1cc19ed in mozilla::pkix::CheckIssuerIndependentProperties (trustDomain=..., cert=..., time=time@entry=1406341186571161, endEntityOrCA=endEntityOrCA@entry=mozilla::pkix::MustBeEndEntity, 
    requiredKeyUsageIfPresent=<optimized out>, requiredEKUIfPresent=requiredEKUIfPresent@entry=SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, requiredPolicy=requiredPolicy@entry=SEC_OID_X509_ANY_POLICY, subCACount=subCACount@entry=0, 
    trustLevelOut=trustLevelOut@entry=0x7fffc02fa54c) at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:635
635	                     requiredKeyUsageIfPresent);
(gdb) p endEntityOrCA
$102 = mozilla::pkix::MustBeEndEntity
(gdb) frame 0
#0  mozilla::pkix::CheckKeyUsage (endEntityOrCA=(mozilla::pkix::MustBeCA | unknown: 1390136216), encodedKeyUsage=0x7fffb3004aa0, requiredKeyUsageIfPresent=requiredKeyUsageIfPresent@entry=mozilla::pkix::digitalSignature)
    at /build/buildd/firefox-31.0+build1/security/pkix/lib/pkixcheck.cpp:55
55	  if (!encodedKeyUsage) {
(gdb) p endEntityOrCA
$103 = (mozilla::pkix::MustBeCA | unknown: 1390136216)
(gdb) quit



Expected results:

The variable endEntityOrCA passed should be the same when the CheckKeyUsage function begins. as it was in the calling function.

The result of the high value for the enum that should be 0 or 1 is the routine called with checks hoping for an end entity are instead checked as if a CA, and of course the checks fail.
QA Whiteboard: [bugday-20140728]
Component: Untriaged → Security
Version: 30 Branch → 31 Branch
This happens on default Ubuntu LTS Trusty version of Firefox.
Component: Security → Security: PSM
Product: Firefox → Core
The https:// that fails above, works with Chromium browser after importing the internal CA.  These are all the default systems on ubuntu trusty LTS. "v31 Mozillia Firefox for Ubuntu Canonical 1.0"

Possibly of interest, the internal CA has a 3072 bit dsa key.
openssl dsaparam -out foo-ca.dsaparam  -genkey 3072
openssl gendsa -out  foo-ca.key  foo-ca.dsaparam
Is the compiler just emitting bad code?   Look at this around line 141.  It appears there is a test but no following jump.


136	  if (endEntityOrCA != EndEntityOrCA::MustBeCA) {
   0x00007ffff1cbf3ef <+291>:	dec    %r13d
   0x00007ffff1cbf3f2 <+294>:	je     0x7ffff1cbf3ff <mozilla::pkix::CheckKeyUsage(SECItemStr const*, mozilla::pkix::KeyUsage, mozilla::pkix::EndEntityOrCA)+307>

137	    // RFC 5280 says "The keyCertSign bit is asserted when the subject public
138	    // key is used for verifying signatures on public key certificates. If the
139	    // keyCertSign bit is asserted, then the cA bit in the basic constraints
140	    // extension (Section 4.2.1.9) MUST also be asserted."
141	    if ((bits & KeyUsageToBitMask(KeyUsage::keyCertSign)) != 0) {
   0x00007ffff1cbf3f4 <+296>:	testb  $0x4,0xe(%rsp)

142	      return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
143	    }
144	  }
145	
146	  // The padding applies to the last byte, so skip to the last byte.
147	  while (!value.AtEnd()) {
   0x00007ffff1cbf3ff <+307>:	mov    0x28(%rsp),%rax
   0x00007ffff1cbf404 <+312>:	cmp    %rax,0x20(%rsp)
   0x00007ffff1cbf409 <+317>:	je     0x7ffff1cbf41a <mozilla::pkix::CheckKeyUsage(SECItemStr const*, mozilla::pkix::KeyUsage, mozilla::pkix::EndEntityOrCA)+334>

148	    if (value.Read(bits) != der::Success) {
Skip comment 3, that's a gdb artifact.
Moving all the local variables to the top of the function and moving the enum value to the last argument from the first cures the corruption in the last argument, but the website still fails to load with the same error.  I'm noticing during the debug process worker threads appear to end while this function is running.  My hunch is that other threads free memory being actively used by this function and it's just a matter of chance if the memory is re-used before this function ends, corrupting the results.


Result
CheckKeyUsage(const SECItem* encodedKeyUsage,
              KeyUsage requiredKeyUsageIfPresent, EndEntityOrCA endEntityOrCA)
{
  uint8_t numberOfPaddingBits;
  uint8_t bits;
  der::Input input;
  der::Input value;
  uint8_t paddingMask;
  if (!encodedKeyUsage) {
I'm not a firefox developer, so it's up to people who actually know this code to take it from here. For what it's worth:  today's install of 31.0+build1-0ubuntu0.14.04.1 loaded the same website without problems.  No changes to the CA or website cert.
See Also: → 1045491
See Also: → 1044269
See bug 1044350. It could very well be the case that this is/was due to a compiler bug. It does seem to be the case that GCC has had multiple bugs with compiling enum class. I'm not sure even if the workaround for bug 1044350 will completely fix it, or if an even newer version of GCC is required.

It could also be the case that our code is doing some undefined behavior. The most likely cause of undefined behavior is casting a value to the enum class type, where the value is outside the range of the enum. But, exactly to avoid that class of error, we (I) always cast the other way, from the enum to the integer type. So, I think it is more likely a compiler bug. But, pay attention for questionable casts, because I could well be wrong.
See Also: → 1077887
Can you still reproduce this?
Flags: needinfo?(hcoin)
Hi,

Just wanted to give a friendly ping concerning comment 7 and the ni? request in comment 8.

Thanks!
I think this bug surfaced owing to the effort to block access to previously favored, now disfavored certs, without the possibility of override.

Seems to me if it's possible to override security warnings and yet visit sites in the case of invalid certs or unsigned certs, what purpose is served by making it impossible to override in the case of otherwise valid certs with disfavored characteristics?  Seems Big-Brother-ish, not allowing users to proceed after notice.

In the affected cases, I've moved to chrome which allows the affected to proceed.  Strange world when open source is more restrictive than private source software.
Flags: needinfo?(hcoin)
Status: UNCONFIRMED → RESOLVED
Closed: 8 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.