Talk:Extension Manager:Addon Update Security:Signature

From MozillaWiki
Jump to: navigation, search

Introduction

After learning about this effort to "disable insecure extension updates" in b.m.o bug 378216, I inquired (in comment 95) about a specification for the cryptographic signature formats used. The reply (in comment 96) pointed me to User:Mossop:Fx-Docs:AddonUpdateSecurity which contains a link to User:Mossop:Fx-Docs:AddonUpdateSignature (the article being discussed in this page).

So I went to User:Mossop:Fx-Docs:AddonUpdateSignature looking for an open specification. I was looking for a specification clear enough that one could implement something that worked based on that specification alone, and not on other existing implementations. It needn't be too formal, but it needs to be complete. What I found instead are examples that don't work.

The discussion of that page (on this page) should not be understood as a criticism of the actual implemented crypto features as much as a discussion about the lack of a specification for them.

Below, Dave explains that there is a developer page with more examples, which may work, but it's still not a specification.

Nelson's original comments of 2007-09-15 19:15:21 PST

Here are some comments on the page User:Mossop:Fx-Docs:AddonUpdateSignature

There are certain essential details that are missing.

Q1. What is the required/expected ASN.1 syntax of the key that is DER encoded and base64 encoded?

A1. It is a SubjectPublicKeyInfo sequence (as defined in RFC 3280 and elsewhere) and NOT a simple RSAPublicKey sequence (as defined in PKCS#1) nor as a simple DSAPublicKey . (That's a good definition. It's just missing from the document.)

Q2. What is the required/expected syntax of an RSA signature?

A2. According to the example, it is the raw binary RSA signature, base64 encoded. It is not encoded as an ASN.1 bit string, and so is not the same signature format as that used in certificates in RFC 3280. Neither is it encoded as an ASN.1 "encryptedDigest" (an octet string) as defined in RFC 2315 (PKCS#7), nor as a "SignatureValue" (also an octet string) as defined in RFC 3852. Whether leading zero octets are to be suppressed or not is not specified.

Update: See definition of ManifestSignature below.

Q3. What is the required/expected syntax of a DSA signature?

A2. Unknown. The answer is not given in the page. The example does not illustrate. A DSA signature has two parts, named 'r' and 's', each of which is exactly 20 bytes. Perhaps they are to be concatenated into a single 40-byte binary block, as done by SSL 3.0, or perhaps they are to be ASN.1 encoded as a sequence of two integers, as in the Dss-Sig-Value in RFC 2246 (TLS 1.0).

Update: See definition of ManifestSignature below.

Other issues of cryptographic significance:

1. The page gives an example of an RDF/XML construct that contains a key. I am not sure, but I think that construct is called an "install-manifest". This install-manifest appears to have many of the properties of a public key certificate. It appears to be a binding of a contributor name, and one or more product identifiers, to a public key. However, the manifest itself is not cryptographically protected. It is not signed. I imagine this is because it is intended to be downloaded via https, and the copy downloaded is presumed to be valid at the source server. That's not unreasonable. However, if it was signed, it would also offer detection of alteration after downloading. Also, IINM, there is another proposed standard that defines a certificate entirely encoded in XML. One wonders if that standard should be used rather than inventing yet another.

2. The page shows an example of an RDF/XML construct that contains a signature and also other information (GUIDs and http URLs). This does not appear to be the same RDF/XML construct as the first one (which contained the key), but I could not find a separate name for it (both XML constructs appear to be called manifests). As I understand it, the signature applies to the content of the same XML construct in which it appears, the content that precedes it in that construct. So, the signature ensures the authenticity of those GUIDs and http URLs, but not the content of the download(s) obtained from the http URL(s).

It was not apparent to me how those GUIDs or http URLs ensure the authenticity of the content downloaded from the http URLs. What stops a download from one of those http URLs from being modified in transit? What ensures that the user who downloads the content of those http URLs is actually getting content from the expected server? I expected that the signed data would include at least a digest (a hash) of the download, but that is not apparent. It occurred to me that the thing that looks like a GUID could actually be an MD5 hash. But it is called an "id", so I doubt that.

Dave's Reply of 2007-09-16 02:28:05 PST

Some answers for you:

1. Yes the key is contained in the install manifest which is the original extension installed by the user. This manifest format is that already in use by add-ons for previous versions of Firefox and other Mozilla applications and it was important to make the manifest continue to work on those previous versions, thus just the addition of the updateKey property to it.

2. The signed manifest is the update manifest. This is the update information that is automatically retrieved periodically to find updates for the add-on. It is necessary to sign the update manifest because it can be retrieved over insecure channels. The final downloaded updated add-on (the xpi file) is protected by virtue of the fact that it must either be available on a https url, or there must be a hash provided for the xpi.

Nelson's Followup of 2007-09-16 13:13:42 PST

Dave, I agree that it is reasonable to require that "it must either be available on a https url, or there must be a hash provided for the xpi." but (unlesss I'm misunderstanding it) the example given on User:Mossop:Fx-Docs:AddonUpdateSignature has neither. It has http URLs, not https, and I see no hashes in it. Where's the protection? Where are the signed hashes in the example?

Please specify the expected/required syntax of a DSA signature. /Nelson

Dave's Reply of 2007-09-16 13:20:00 PST

The example includes neither and so you are correct it would not show any secure updates for the given add-on. The example is basically there to describe method of generating the signature which doesn't depend on the presence of a https link to the xpi or a hash at all.

You can probably explain better than me the syntax of a DSA signature, the signature is just generated with SEC_SignData regardless of the key type. Though at the moment there is no plan to use a DSA signature.

Nelson's Followup of 2007-09-16 15:39 PDT

Dave, if the addons feature requires that an update either come from an https URL or that the manifest provide a hash for the XPI, then shouldn't the example illustrate how do to those forms successfully? Shouldn't it show an example with a hash of the XPI? In the absence of a specification or example of how to represent such a hash in the manifest, is it going to be obvious to everyone but me how to do it?

There are several common ways of encoding DSA signatures. I've described them above. The question is: what syntax does your code require? If you're not sure, but you can give me an lxr or mxr URL for the code that checks the signatures, I'll be happy to look at that code and answer the question here.

Dave's Reply of 2007-09-16 15:44 PDT

Maybe, but the spec we are looking at here is about validating the update manifest when delivered over an insecure channel, not about how the application then interprets that information. The requirements on url and hashing for the xpi file are a separate issue, though they are both part of the wider issue of securing the entire process of updating add-ons. If I get a spare moment though I will update the example to include some hashes.

If you want a fuller example then please talk a look at the example in the developer documentation.

I was under the impression you had already seen the code that does the verifying, but here it is: http://mxr.mozilla.org/seamonkey/source/security/manager/ssl/src/nsDataSignatureVerifier.cpp#59

Nelson's Followup of 2007-09-17 22:22 PDT

In my original question and answer 2 above, I commented that the RSA signature in the example shown on the page User:Mossop:Fx-Docs:AddonUpdateSignature was a "bare" RSA signature, not encoded the way RSA signatures are encoded in certificates. In Dave's Reply of 2007-09-16 15:44 PDT, he cited the code that parses the signature, so I looked at it and found that it expects the signature format to be very similar (but not identical) to the format of a certificate. In ASN.1 syntax, the required signature is:

   ManifestSignature  ::=  SEQUENCE  {
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

where signatureAlgorithm and signatureValue are as defined in RFC 3280.

Dave also cited a page with a "fuller example", and upon examination, I see that that page has an example signature that same ASN.1 encoding, which is what the cited code expects. So I conclude that the example in User:Mossop:Fx-Docs:AddonUpdateSignature is wrong and doesn't work.

So I think we now know the expected and required signature format for these manifests, including DSA signature format. Unfortunately, this particular ASN.1 sequence doesn't match any standard signature syntax known to me. So, I think a custom signature generating tool will be necessary, to produce signatures in this unusual encoding.

Update: That tool is named "McCoy" (the Real McCoy ?). The source may be found here and discussion is found at McCoy this wiki page.