Last Comment Bug 321156 - Firefox does not honor some issuers' code signing certs for XPI signatures
: Firefox does not honor some issuers' code signing certs for XPI signatures
Status: RESOLVED WORKSFORME
:
Product: Core
Classification: Components
Component: Security: PSM (show other bugs)
: 1.9.2 Branch
: All All
: P3 normal with 5 votes (vote)
: mozilla2.0
Assigned To: Nobody; OK to take it and work on it
:
:
Mentors:
: 591870 (view as bug list)
Depends on: 158078
Blocks:
  Show dependency treegraph
 
Reported: 2005-12-21 16:32 PST by TJ
Modified: 2016-05-05 15:03 PDT (History)
16 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments

Description TJ 2005-12-21 16:32:07 PST
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5 Mnenhy/0.7.3.0
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5 Mnenhy/0.7.3.0

I'm working with Mozilla XPI extensions, using NSS for code-signing.

Firefox contains the public root CA from Unizeto Certum "Certum CA".

Unizeto issue class 3 code-signing certificates using their "Certum Level I" certificate, which is issued by their "Certum CA" certificate.

I install the "Certum CA" and "Certum Level I" certificates in the NSS db, and import the private key and newly-issued code-signing certificate from Unizeto (obtained via Firefox and exported/imported using PKCS12).

The code is signed using :

signtool.exe -d C:\Projects\CodeSigning -k "Code Signing (Certum)" -p "password" build/

Firefox will refuse to install the signed XPI, because it does not have the "Certum Level I" certificate in its key store.
If "Certum Level I" is installed in Firefox the verification is successful, as it should be.

I expected to be able to include a certificate chain when signing so Firefox could navigate to the root certificate and then validate the chain.

I cannot see any way to do this with NSS, although its available on other platforms.

Is signtool (or another tool) supposed to support signing where chains are included?

Reproducible: Always

Steps to Reproduce:
1. Sign code with a certificate that is chained, where intermediate certificates aren't available to the target verification system.


Actual Results:  
signtool doesn't put the full certificate-chain in the zigbert.rsa file. Code-signing certificate fails to verify.

Expected Results:  
signtool provides option to include certificate chain. Target system able to verify certificates from root CA.
Comment 1 Kaspar Brand 2006-02-19 03:01:52 PST
(In reply to comment #0)
> I expected to be able to include a certificate chain when signing so Firefox
> could navigate to the root certificate and then validate the chain.

While your observation is correct, your analysis is not, I'm afraid - here's the result of my (hopefully correct) research:

It's not an issue with signtool, but with the chain verification. signtool does its job pretty well, it does add intermediate CA certs when signing (you can verify this with "openssl pkcs7 -print_certs -inform der -in zigbert.rsa" e.g.).

In the case of the Certum intermediate CA certs (all from Level I to Level IV), the issue is with the chain verification. These intermediate CA certs lack both an extended key usage (EKU) and an nsCertType extension (they only include basic constraints) and will therefore fail the following check in cert_VerifyCertChain() (line 860 in security/nss/lib/certhigh/certvfy.c approx., see also http://lxr.mozilla.org/security/source/security/nss/lib/certhigh/certvfy.c#860)


      flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
      
      if (flags & CERTDB_VALID_CA) {
          if ( ( flags & requiredFlags ) == requiredFlags) {
              /* we found a trusted one, so return */
              rv = rvFinal; 
              goto done;
          }
          validCAOverride = PR_TRUE;
      }
  }

  if (!validCAOverride) {
      /*
       * Make sure that if this is an intermediate CA in the chain that
       * it was given permission by its signer to be a CA.
       */
      /*
       * if basicConstraints says it is a ca, then we check the
       * nsCertType.  If the nsCertType has any CA bits set, then
       * it must have the right one.
       */
      if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
          isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
      }

      if (  !isca  ) {
          PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
          LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
      }


For (intermediate) CA certs which are not stored in the certdb, the CERTDB_VALID_CA flag is not set and validCAOverride will therefore remain at PR_FALSE - which means that an additional check for the correct CA certificate type is executed ("issuerCert->nsCertType & caCertType").

For object signing, caCertType must include NS_CERT_TYPE_OBJECT_SIGNING_CA, which is set if the respective CA cert either includes an appropriate netscape-cert-type extension (bit 7 set) or an EKU extension with the code signing OID (1.3.6.1.5.5.7.3.3). The Certum intermediate CA certs have neither of them, so the chain verification in cert_VerifyCertChain() will fail with SEC_ERROR_CA_CERT_INVALID.

What's irritating (as noted by you) is the fact that as soon as the intermediate CA cert is added to the certdb the chain verification will succeed... but this actually comes as no surprise when looking at the code: in this case the intermediate CA cert will have CERTDB_VALID_CA, too, so validCAOverride is set to PR_TRUE and the subsequent check is skipped therefore.

Things can get pretty strange in Thunderbird e.g.: since sec_pkcs7_verify_signature() in p7decode.c will add end-entity and intermediate CA certs to the certdb when verifying a message signed with S/MIME, this will lead to cases where installing a signed XPI will depend on whether the user has previously received a signed message including the required intermediate CA certs or not - if he has, then the installation will succeed, otherwise it will fail... not really reliable behavior from the user's point of view, in my opinion.

Bottom line: I think the code for chain verification needs to be reviewed, especially for cases where object signing is concerned and user-supplied certificate chains are involved.

To be on the safe side in the meantime, you need an object signing certificate which is signed by a CA certificate including either 1) a code signing EKU or 2) an appropriate netscape-cert-type or 3) the required objectSigningFlags in the certdb file (for builtin tokens).
Comment 2 Nelson Bolyard (seldom reads bugmail) 2006-03-16 13:15:08 PST
IIRC, there are two separate definitions for validity of cert chains for signing
code.  They are known as "object signing" (originally: Netscape Object Signing)
and "code signing".  

Code signing has the simpler and less rigorous definnition.  It requires that
the EE cert have the code signing OID in the EKU, and that the "trust anchor"
(typically the root) be marked trusted for code/object signing, and that the
chain be complete between the two (all cert signatures verifiable, none expired,
etc.)  Code signing does NOT require any special EKU OID in intermediate CAs
(or, indeed in any CAs).  It only requires the special EKU in the EE cert.

Object Signing has a slightly more complicated and more rigorous definition.
It is like code signing, except that it ALSO requires that all intermediate
CAs between the trust anchor and the EE cert have a special EKU OID, or 
a special Netscape cert type extension with the object signing bit present.

NSS provides a way for an otherwise-invalid cert to be marked by the user
as being valid, overriding the normal validity checks for that cert.  
This is accomplished through a special "valid CA" trust flag in the cert DB.  

Based on your report, and others, I gather that this special "valid CA" 
override trust flag is being set routinely on all certs in the cert DB,
thus creating the perception that an intermediate CA cert must be in the 
DB to be part of a valid object signing cert chain.  The error is that this 
"valid CA" flag is being routinely set on all CA certs in the DB.  

I suspect that error is due to a misunderstanding on the part of one or more 
NSS developers/maintainers concerning the intended/defined meaning of the 
VALID_CA trust flag.  As it now appears to be implemented, merely putting a
cert in the DB suffices to override any invalidity, meaning that it is not
possible to put invalid CA certs in the cert DB and have them remain invalid!
That's horrific!

I would propose to fix it by finding whatever code routinely sets the 
valid CA flag on all certs in the DB and changing it to no longer routinely
does so.  

If and while mozilla requires "object signing" (rather than code signing)
validity for XPIs, the solution is for the XPI signer to get a cert chain
wherein the intermediate CA certs have (at least) one of the necessary 
extensions to qualify them as object signing intermediate CAs.
Comment 3 Shawn Wilsher :sdwilsh 2006-05-13 19:38:16 PDT
(In reply to comment #2)
> If and while mozilla requires "object signing" (rather than code signing)
> validity for XPIs, the solution is for the XPI signer to get a cert chain
> wherein the intermediate CA certs have (at least) one of the necessary 
> extensions to qualify them as object signing intermediate CAs.
> 

I think the problem is that all of those places want to charge large sums of money, but Certum gives free certificates to Open Source developers.  This would be great if it would work in Firefox 2.0, but I don't expect it too.  I would much rather release an extension that is signed.
Comment 4 Nelson Bolyard (seldom reads bugmail) 2006-08-29 02:19:34 PDT
Kaspar Brand's analysis in comment 1 above is correct.  
mozilla's XPI signature verifier is looking for an "Object signing" cert chain,
which has an EKU extension in the EE cert *and* in all intermediate CA certs.

The Certum code signing cert chains that I've seen are "Code signing" certs, 
not "object signing" chains.  The Certum CA certs do not have EKU extensions 
in them.  

CA certificates are not required to have EKU extensions by any standard, and indeed some think that CA certificates with EKU extensions are non-standard. 

The older object-signing chain convention was stronger than the code signing 
convention because it required that every CA cert in the chain have been 
explicitly authorized by its issuer to issue object signing certs.  The 
object-signing convention predates the code signing convention by several 
years.  It was originlly used in Netscape browsers, which are part of the 
heritage of mozilla browsers.  

Perhaps the time has come for mozilla to adopt the weaker code signing 
convention, and no longer require the stronger object signing convention.

Comment 5 Nelson Bolyard (seldom reads bugmail) 2008-02-13 16:45:23 PST
I believe that this bug will be solved with the (eventual) adoption by PSM 
of NSS's new libPKIX as a replacement for its old cert library code.  
libPKIX knows nothing about the old object signing criteria and is only 
capable of enforcing the new code signing criteria, IINM.
Comment 6 Nelson Bolyard (seldom reads bugmail) 2010-07-16 10:35:00 PDT
I'm converting this into a PSM bug.  

As I noted in comment 5, from NSS's point of view, the fix is for users 
of NSS, such as Firefox, to stop using the old cert validation library 
and start using the newer one, named libPKIX, which claims conformance 
to RFC 3280.  (Yes, 3280 is no longer the latest, but it's newer than 
what the previous library conformed to.)  

So, since this bug complains about a behavior of Firefox with respect to 
Firefox XPI files, (XPI files are unique to Firefox, or gecko-based products),
I am converting this bug into a request that PSM change its XPI signature 
validation check code from calling the old library to calling the new one.

Now, it may be that the code that does that check in not in PSM, but 
rather is elsewhere.  In that case, this bug will need to be reassigned to 
yet another product and/or component.
Comment 7 ryanfox 2010-07-19 10:14:50 PDT
Seems like this may now be a duplicate of https://bugzilla.mozilla.org/show_bug.cgi?id=479393
Comment 8 Kai Engert (:kaie) 2010-09-24 07:43:02 PDT
*** Bug 591870 has been marked as a duplicate of this bug. ***
Comment 9 Joe Siegrist 2011-10-11 13:14:13 PDT
Firefox's current state of support for properly handling code signing of XPIs is pretty abysmal. 

Comodo is recommended by https://developer.mozilla.org/en/Signing_a_XPI 

Unfortunately Comodo no longer works for orders filled after the 24th of August 2011 when Comodo switched to a new intermediary that is no longer trusted by Firefox by default.

Thawte appears to be in the same boat according to the bug: 479393, it's likely other cert providers are not supported either..

What is the recommendation for code signing XPIs from now until PKIX lands and is enabled by default?
Comment 10 Kaspar Brand 2011-10-11 22:25:38 PDT
(In reply to Joe Siegrist from comment #9)
> Unfortunately Comodo no longer works for orders filled after the 24th of
> August 2011 when Comodo switched to a new intermediary that is no longer
> trusted by Firefox by default.

Not entirely correct, I believe. Maybe you're confusing it with the "COMODO Code Signing CA" which was issued in April 2011. The "COMODO Code Signing CA 2", issued in August 2011, on the other hand, addresses the issue with one of the options mentioned in comment 1:

> For object signing, caCertType must include NS_CERT_TYPE_OBJECT_SIGNING_CA,
> which is set if the respective CA cert either includes an appropriate
> netscape-cert-type extension (bit 7 set) or an EKU extension with the code
> signing OID (1.3.6.1.5.5.7.3.3).

The difference between the "COMODO Code Signing CA" and the "COMODO Code Signing CA 2" is exactly this: the latter has an EKU extension with the code signing OID (and the public key in the certs is different, in case somebody is wondering).(In reply to Joe Siegrist from comment #9)

> Thawte appears to be in the same boat according to the bug: 479393, it's
> likely other cert providers are not supported either..

Thawte (aka Symantec) has implemented a similar solution - see bug 601083 and bug 601950 comment 11 ff.
Comment 11 David Keeler [:keeler] (use needinfo?) 2016-05-05 15:03:08 PDT
Add-ons must be signed by the addons.mozilla.org key now, so I don't think this is relevant any longer (furthermore, code signing isn't really a thing in Firefox anymore).

Note You need to log in before you can comment on or make changes to this bug.