Re: Proposal for ISSUE-25 (Globally unique pre-shared keys)

On Oct 29, 2012, at 4:10 PM, Ryan Sleevi wrote:

> On Mon, Oct 29, 2012 at 7:48 AM, Mark Watson <watsonm@netflix.com> wrote:
>> 
>> On Oct 29, 2012, at 2:41 PM, Ryan Sleevi wrote:
>> 
>>> On Mon, Oct 29, 2012 at 6:23 AM, Mark Watson <watsonm@netflix.com> wrote:
>>>> All,
>>>> 
>>>> To address ISSUE-25 [1] I'd like to propose the following changes. I hope we
>>>> can discuss this later in the week.
>>>> 
>>>> 1) To Section 6, Privacy Considerations, replace the last sentence of the
>>>> "Super-cookies" section ('This is especially true for keys that were
>>>> pre-provisioned for particular origins and for which no user interaction was
>>>> provided') with a more detailed separate section:
>>>> 
>>>> "Pre-shared keys
>>>> 
>>>> Pre-shared keys may be long-lived and may be securely associated with
>>>> specific hardware elements. Without sufficient safeguards it may be possible
>>>> for an origin to identify a user or device without the knowledge or consent
>>>> of the user. Access to pre-shared keys SHOULD require explicit user
>>>> authorization on a per origin basis. User Agents supporting pre-shared keys
>>>> SHOULD ensure that each origin receives a unique origin-specific pre-shared
>>>> key. This could be accomplished, for example, by transforming an
>>>> origin-independent secret using a suitable origin-specific one-way
>>>> function."
>>> 
>>> My initial reaction regarding the transformation is that while it's
>>> good, I'm not sure how reasonable it may be to recommend at a SHOULD
>>> level.
>> 
>> The "transformation" was just an example of how an implementor could follow the SHOULD recommendation. The recommendation is to make sure pre-shared keys are different across origins. Another way would be to only support pre-shared keys that were explicitly provisioned separately for each origin. Another way would be for an implementor to have a back-end service which they use to obtain new keys when they need them etc.
> 
> Yes, but you seem to have been designing this API with the assumption
> there is some master key which is then used to derive origin-specific
> keys.

That's always been just an example, not an assumption.

> Based on your past descriptions of the Netflix architecture,
> this seems a reasonable extrapolation, and is equally reflected in the
> concerns regarding user access.

Actually, in practice people often provision a key explicitly for Netflix. But whether they do that or derive from some master key (as above) should be transparent to us.

> 
> But that's not something that I think is general to pre-shared or
> pre-provisioned keys. Both pre-shared and pre-provisioned keys may
> already be origin-provisioned, thus there is no need for some form of
> derivation function.

Right. In fact that's what we often do.

> That is, the language "pre-shared keys"
> implicitly presumes (global? user-specific? multi-origin?) pre-shared
> keys, and then describes a function on how to get "unique
> origin-specific pre-shared keys".
> 
> It seems to me that your requirements for both user-access and
> derivation are thus *not* related to pre-shared/pre-provisioned keys,
> but more generally concerns regarding keys shared between origins.
> That's why I think it's a weird fit for where you put it.

Ok, well, I could move it, or even remove it (the transformation) because it was just an example.

> 
> As well, there are potentially cases where access to the "master" key
> material (that is, the key material **as provisioned**) is desired,
> but the current recommendation seems to aggressively discourage that.
> If the key material is not shared between origins, is that still a
> concern?

No. The only reason for even mentioning the "master key" thing was as an example of how you could support pre-provisioned origin-specific keys for all origins. But there is no requirement to do that. An implementor could equally support pre-provisioned keys for their favorite three origins only.

> 
>> 
>>> In the case of smart card keys (for example), such
>>> transformation may not be acceptable or possible - since access to the
>>> key material is generally not available.
>> 
>> Sure. As per ISSUE-19, keys with this origin-specific property have different privacy properties than those which might be shared across origins, even with user consent. I'm not claiming to have answers to the privacy issues associated with the later, but I'm keen that we support the former.
> 
> Right - so this really is a distinction between origin-specific and
> origin-shared keys, and not pre-shared vs generated keys.

IIUC, you're suggesting that any key shared across origins could be made origin-specific with a technique like this. That's fine. I wouldn't even call that an origin-shared key because there's no difference (as far as applications are concerned) between this case and keys which are totally independent.

There may be a difference as far as the user is concerned, as the user may know that both keys are ultimately generated from the same passphrase, for example.

> 
>> 
>>> It's also only really
>>> applicable to symmetric keys (which generally lack any particular
>>> structure), rather than asymmetric keys (which must follow some form
>>> of mathematical construct)
>> 
>> Yes. That paragraph should be restricted to symmetric keys. For asymmetric keys I think you need to one of the other two approaches I mentioned above.
> 
> Or neither.

Well, yes, of course ;-) This is all optional.

> 
>>> 
>>> It *sounds* like you think of pre-shared keys as being symmetric only,
>>> but I'm not sure I'd agree with that.
>> 
>> That's the use-case we're most interested in but I didn't intent to make the text restrictive.
>> 
>>> 
>>>> 
>>>> 2) To Section 10 (Key interface) [or wherever is most appropriate], add new
>>>> sub-section, as follows:
>>>> 
>>>> "10.2 Pre-shared keys
>>>> 
>>>> User Agents MAY expose origin-specific pre-shared keys as Key objects
>>>> visible within the keys attribute of the Crypto interface. Examples of
>>>> pre-shared keys include keys stored in secure hardware elements.
>>> 
>>> I'm working on a proposal to fully remove the window.keys interface,
>>> which I believe is the right approach. So we'll need to re-consider
>>> the pre-provisioned key case.
>> 
>> I'll read your mail and respond to that.
>> 
>>> 
>>> Note - I think of the general issue being pre-provisioned (eg:
>>> including symmetric and asymmetric), and not pre-shared (which implies
>>> symmetric only, as a general term of art)
>> 
>> Ah, ok, I wasn't aware of the terminology restriction. Most of my text should be changed to pre-provisoned, then.
>> 
>>> 
>>>> 
>>>> 10.2.1 Pre-shared key pairs and certificates
>>>> 
>>>> Where a pre-shared public/private key pair has an associated X.509
>>>> certificate, this certificate SHOULD be made available in a property named
>>>> "x509certificate" within the extra attribute of the Key object. The
>>>> "x509certificate" property contains the base64 encoding of the … <specify
>>>> encoding of X.509 certificate here>.
>>> 
>>> I really think this as problematic - for the various reasons we've
>>> discussed during certificate. Minimally, we'd need to consider this as
>>> an array, but I think practical/implementation concerns mean this is
>>> not generally possible. For example, a key may be stored in one device
>>> but a certificate stored in another device.
>> 
>> Can you elaborate ? I am thinking of a very simple, dumb, capability that just exposes the bytes of the encoded X.509 certificate, if it's available in the same place as the key.
> 
> I'm saying that the certificates associated with a key may not be
> stored with the key itself, nor is it a static list. For example, new
> certificates may be deployed via application/x-x509-user-cert (for
> user agents supporting it) at any point. What is the value of the
> attribute as keys are added? As they're removed?
> 
> Does accessing the object force the user agent to query all (external)
> certificate storage mechanisms to discover if any certificates have
> been added or removed? I fear under the current language, it does, and
> that's not an acceptable solution.
> 
> Alternatively, it requires the user agent to store within its own
> persistence store a static list of all associated certificates with a
> key, and that's not a solution I can see as workable either.

I didn't intend either of the above. The intent was that, for these pre-provisioned keys the UA would not even process the certificate - it's just a blob of bytes associated with the key and obtained from the same place the key was obtained from.

I think having the UA maintain certificate chains, handle revocation, renewal and do the things above is a whole other topic.

I'm assuming that this certificate is pre-provisioned, renewed etc. in the same way as the pre-provisioned key itself, not by the UA.

> 
>> 
>>> 
>>> I'm also very loathe to expose attributes that are stored/managed on
>>> security devices. The current (albiet synchronous) API is primarily
>>> designed for attributes read/set by authors, and perhaps is a poor fit
>>> for exposing pre-provisioned key attributes of meaningful semantic
>>> form.
>> 
>> The two issues of "whether to expose attributes stored/managed on security devices" and "how to expose them on the API" are separate issues. The second should not dictate the first. If we want to expose them, then we can design an API that works for that (presumably with some asynchronous component).
> 
> I'm not sure if I agree or disagree with your point here.
> 
> Certificates, to me, are attributes that are stored/managed on
> security devices. Therefore, IF we want to expose them (and I think we
> do have general consensus that we do), THEN we need to define the API,
> which I view your proposal as the 'certificate[s]' attribute as doing.
> And I don't think that API is a good API, for the reasons expressed
> previously and above.

I'm more than happy to talk about alternative APIs for exposing the certificate. I would say that I think the problem of exposing a certificate associate with a pre-provisioned key and maintained in the same way as the key itself is an easier task than more general handling for certificates. Particularly because that maintenance is than out of scope for us.

> 
>> 
>>> 
>>> Case in point: A key stored on a smart card may have multiple
>>> certificates issued, with various lifetimes and purposes, even though
>>> they use the same key, such as cross-certified by different
>>> organizations.
>> 
>> Ok, so the attribute should be "certificates" and be an array of certificates.
>> 
>>> 
>>>> 
>>>> 10.2.2 Pre-shared symmetric keys and identities
>>>> 
>>>> Where a pre-shared symmetric key has an associated globally unique identity,
>>>> this identity SHOULD be made available in a property named "uid" within the
>>>> extra attribute of the Key object. The "uid" property contains the base64
>>>> encoding of the bytes of the globally unique identity."
>>> 
>>> As I mentioned on IRC during the proposed wording, and as mentioned
>>> during previous conversations, my big concern here is that there's
>>> absolutely no definition of what a "globally unique identity" is, nor
>>> how an implementor can determine, for the various forms of key storage
>>> supported (whether hardware or software), if a given identifier is a
>>> "globally unique ID"
>> 
>> There are many cases where there will only be one choice, or where the choice is obvious.
>> 
>> But even if the choices made by implementors are arbitrary, then this is still useful. In some cases an implementor will tell me the keys they have put into devices and the identities they associated with them. In another case, all I want to learn from the implementor is what properties the identities have, since I am more interested in knowing when the same X visits again than which X it was (where X is the thing the identifier identifies).
> 
> Respectfully, I think the point "If the choices made by implementors
> are arbitrary, then this is still useful" is wrong. I think arbitrary
> choices make this useless and dangerous to the spec, because it
> provides effectively no portability for implementations in terms of
> something spec'd in the standard. This is exactly why we're trying to
> define, as absolutely and concretely as possible, how RSA, AES, ECC,
> etc are performed - so that they're compatible across implementations.

There's an important difference. In the case of all the algorithms, if different implementors made different choices it would be very hard, if not impossible, for me as an application running on those implementations to accommodate those differences.

This is not the case with choice of unique identities. I'm just going to provision those things into my back-end database. It doesn't matter what they are (within reason - if the identity was 2MB in size, that might be a problem), so long as I know their general properties (which I use to inform my offline decision on the authorization and other policies to apply to those devices).

On the other hand, if we don't specify anything, then the choices of attribute will also be arbitrary and that is a problem for me to cope with on the application side.

> 
> While I realize there's an implementation dependence in terms of what
> algorithms are implemented, I think we want to absolutely avoid
> situations where "The same thing behaves differently on different
> APIs". If you want to get into implementation-dependent free-for-all,
> then it should not be normatively (or, arguably, informatively) spec'd
> via the API, because it provides zero guidance for implementors and
> misleads users.

I can see the concern if the problem was that the same SmartCard exposed a different id on different browsers. There's a different problem there which is that the SmartCard doesn't *have* an obvious unique identifier. 

> 
> 
>> 
>> I can see two kinds of problem arising from functional decompositions:
>> 
>> 1) A SmartCard API just provides you with a bag of attributes, potentially different ones for each SmartCard inserted. Which one do you expose as "uid". I'd suggest in this case none of them. The fact that different SmartCards might have completely different attributes is a bigger problem.
> 
> Agreed ;)
> 
>> 
>> 2) The API for some some secure element on Platform A exposes xid and yid. The API for the same kind of secure element on Platform B exposes pid and qid. Again, there's a deeper problem here which I'm not purporting to solve.
> 
> And that's why I feel, without solving it, it shouldn't be in the spec
> as some form of standard (normative or informative) behavior.

I don't follow the logic. We have two scenarios A and B. In A the identifier for a pre-shared key is well-defined (say on a TV, where this is commonly done). In B it's not (say the SmartCard example above).

Because we haven't solved the problem for scenario B does not mean we shouldn't enable scenario A. We just need the right words to characterize scenario A and make it clear that the capability is restricted to that scenario.

> 
>> 
>> 
>>> 
>>> For example, in PKCS#11, there is no such global *or* unique ID
>>> requirement. Typically, such attributes are embedded in vendor ID
>>> attributes that are specific to the hardware vendor, the middleware
>>> being used, the version of the card being used, the provisioning
>>> profile, etc. So it's reasonably impossible for a generic
>>> implementation to reliably determine what construction constitutes a
>>> "globally unique identity"
>> 
>> Agreed. That's fine. Don't expose a "uid" attribute in that case.
>> 
>>> 
>>> Further, it doesn't help that some "globally unique identities" are
>>> the combinations of several attributes that, together, provide the
>>> unique identifier. The fact that a key has a globally unique
>>> identifier formed through the combination of n-number of attributes
>>> creates ambiguity for implementations in determining if and how this
>>> should be exposed to applications.
>>> 
>>> As such, unless we're defining exact storage semantics (which we're
>>> not, at least so far), or defining exactly how pre-shared keys are
>>> implemented (which, I would hope, we're not), then I'm not sure we can
>>> reasonably or reliably provide this sort of statement.
>> 
>> The statement has a pre-condition ("where and identity exists") and is a SHOULD not a MUST. There is plenty of get-out for the ambiguous cases, but a simple recommendation for the simple case.
>> 
>>> 
>>> Minimally though, I think the above wording MUST specify how an
>>> implementation can determine if a "globally unique identifier" is
>>> present for a pre-shared key, and I personally believe that's an
>>> intractable task.
>> 
>> I think we could give guidance, but since the whole requirement is a recommendation I don't see any need for requirement-level text.
>> 
>> Guidance would be along the lines of saying that if a key has an associated identifier which is defined to be unique amongst all similar keys, this should be chosen as the "uid" identifier. In your examples above, there is no such identifier.
>> 
>> …Mark
>> 
>>> 
>> 
> 
> As an implementor, I think the only time the "uid" can be reasonably
> exposed then is by Netflix and those working with Netflix.

Well, this set includes all the major TV manufacturers, so we're talking 100s of millions of browser instances by the time this is implemented.

Even accepting your position, you can extend to all other websites that also work with those manufactures, which now includes all the major streaming video providers.

> The
> proposed wording provides no guidance whatsoever for Mozilla,
> Microsoft, Chromium, Apple, Opera, Intel, or any other potential
> implementor.

I disagree - see below.

> It's fully compliant with the spec to not implement it.

Right. That's what optional means ;-)

> It's fully compliant with the spec to implement different things.

Yes and no. All implementations are different in some respects. Probably all distinct implementations of anything in the web platform have different behaviors in some aspect - performance for example - but that doesn't matter from an interoperability perspective except at the extremes.

Similarly the differences in implementation that would be allowed under this proposal don't affect the usefulness of the feature, as I described above.

> It
> does not resolve the issues with UA sniffing that you raised in the
> past, it does not resolve the issues with UA portability. In short,
> it's a specific solution for a specific UA, and I don't think that's a
> good thing to add.
> 
> IF we could come up with language that could be followed by all
> implementors and lead to the same result, I think that's a good thing
> and it's worth considering. But I think that's only possible by
> defining exactly how to determine if a key has a uid, and that
> requires enumerating all types of keys (past, present, and future), OR
> defining that only certain keys have a uid, and neither of those are
> really desirable to put in the spec IMO.

These points are addressed above.

…Mark

> 

Received on Monday, 29 October 2012 16:08:17 UTC