Re: ISSUE-3: Algorithm discovery

On Mon, Jul 16, 2012 at 10:41 AM, Anthony Nadalin <tonynad@microsoft.com> wrote:
> Not saying keyless algorithms, what I'm saying is that the key material is in the 4758 and you are not going to know what type of key it is and thus the 4758 may support the algorithm but the key may not. I still see very little value in the discovery effort.

Hi Anthony,

I'm sorry, I'm still not clear at all what you're talking about. While
I'm admittedly not familiar with the 4758 specifically, and it sounds
like you may be, I've tried to provide concrete examples from major
cryptographic APIs, both standard and vendor-specific, that
demonstrate how .supports can be implemented.

If I understand you correctly, you're saying it's impossible for this
device, although it's not clear to me why this is. It's also not clear
to me how this can be, since this specific device claims to be
compatible with the aforementioned APIs, which means it can/should
support the abilities.

Perhaps we're at a disconnect, because it also seems like you're
mentioning that an individual key may or may not support given
algorithms - and the API, as currently spec'd in the draft, fully
accomodates this. So if there's something else missing, could you
perhaps provide a strawman example?

Cheers,
Ryan

>
> -----Original Message-----
> From: Ryan Sleevi [mailto:sleevi@google.com]
> Sent: Tuesday, July 10, 2012 4:50 PM
> To: Anthony Nadalin
> Cc: Mike Jones; public-webcrypto@w3.org; David Dahl
> Subject: Re: ISSUE-3: Algorithm discovery
>
> On Tue, Jul 10, 2012 at 4:39 PM, Anthony Nadalin <tonynad@microsoft.com> wrote:
>> This does not help as the 4758 may not have a specific key to support
>> the specific algorithm but the 4758 may in general support the
>> algorithm
>
> Can you provide an example of a keyless algorithm, beyond hashing, where you would lack a specific key but would support a specific algorithm? Or are you specifically thinking of hashing?
>
> Or are you saying that if you have a raw key, and then import it into the device, THEN you could use AES-128-CBC? If so, I feel like that really goes into "key provisioning" APIs (when and how to get a key on the device), and that such problems may be out of scope.
>
> For what it's worth, for the "keyless algorithm" support, the equivalent calls would be BCryptOpenAlgorithmProvider or PKCS#11's CK_MECHANISM_INFO fields combined with enumerating a token's slots.
>
> If you're using IBM's raw APIs, and they lack algorithm-discovery equivalents, well, then you already know you're talking to a 4758 and then there is no special casing needed - your entire app is special-cased and you know all the supported algorithms.
>
>>
>> -----Original Message-----
>> From: Ryan Sleevi [mailto:sleevi@google.com]
>> Sent: Tuesday, July 10, 2012 3:14 PM
>> To: Anthony Nadalin
>> Cc: Mike Jones; public-webcrypto@w3.org; David Dahl
>> Subject: Re: ISSUE-3: Algorithm discovery
>>
>> On Tue, Jul 10, 2012 at 2:23 PM, Anthony Nadalin <tonynad@microsoft.com> wrote:
>>>> My primary goal for discovery is not to provide an absolute, immutable commitment that algorithm X is implemented and will always be implemented, since errors happen and implementations will vary, thus such requirements may not always be guaranteed. However, I am trying to separate out the states of "Is this [user agent, key, operation] compatible with my application" and "Perform a specific operation on a key".
>>>
>>> Not sure how you actually do this with a HSM like a IBM4758 (or
>>> follow-on), as I have no way to determine if the keys held in the
>>> IBM4758 are compatible with the application, only way to know this is
>>> to develop the application with specific knowledge of what I'm
>>> putting in the IBM4758
>>
>> CNG (Windows)
>> NCryptEnumAlgorithms + NCryptGetProperty
>>
>> PKCS#11 (OS independent)
>> C_GetMechanismInfo
>>
>> Keychain Services (OSX)
>> kSecClassKey + kSecAttrCanWrap/kSecAttrCanSign + kSecAttrKeyType
>>
>>
>>
>>
>>>
>>> -----Original Message-----
>>> From: Ryan Sleevi [mailto:sleevi@google.com]
>>> Sent: Tuesday, July 10, 2012 12:35 PM
>>> To: Mike Jones
>>> Cc: Anthony Nadalin; public-webcrypto@w3.org; David Dahl
>>> Subject: Re: ISSUE-3: Algorithm discovery
>>>
>>> Thanks, it's good to have actual examples to consider.
>>>
>>> With the example of a smart card - which can be extended to any number of smart-card independent key storage examples, such as network-based file key stores - a smart card being ejected can happen at any point during an operation. For example, during .processData(), before calling .complete(), or between creation of the CryptoStream and the first call to .processData().
>>>
>>> Logically, I would think of .supports() as thus being another state in that state machine - whether implicitly via a call to .supports() and then a call to .encrypt(), or explicitly, by making a .init() method on the CryptoStream prior to .processData().
>>>
>>> As such, I'm not sure how it's actually different from the error handling applications would already expect, and thus doesn't seem an argument against discovery.
>>>
>>> My primary goal for discovery is not to provide an absolute, immutable commitment that algorithm X is implemented and will always be implemented, since errors happen and implementations will vary, thus such requirements may not always be guaranteed. However, I am trying to separate out the states of "Is this [user agent, key, operation] compatible with my application" and "Perform a specific operation on a key".
>>>
>>> Since my arguments for discovery are hinged upon use cases that I believe are only enabled by algorithm discovery, perhaps it's better to rephrase the discussion and see what alternative proposals for addressing this are:
>>>
>>> 1) Should the low-level API protect users from mixing incompatible cryptographic primitives, such as sign+verify and encrypt+decrypt?
>>>   - If not, but the underlying key store does not allow them to be mixed, should applications be able to discover this?
>>> 2) Do implementers/U-A's expect a need to prompt for operations (perhaps prompting for every .sign operation), or does the fact that the application have a key handle mean that they are authorized for as many operations as possible (related to ISSUE-2)
>
>>>   - If prompting is expected, when is it anticipated that this prompting will occur? Creation of the CryptoStream? The first call to .processData()? The final call to .complete()?
>>>   - If prompting happens, is it expected to happen for every operation (every .sign())? Once per browsing context? Once ever?
>>> 3) What is the expected experience if an algorithm is not implemented/not supported.
>>>   - For the script (eg: what error handling facilities will exist)
>>>   - For the user (eg: might they be prompted to insert a smart card
>>> that does support the algorithm?)
>>>
>>> On Tue, Jul 10, 2012 at 11:41 AM, Mike Jones <Michael.Jones@microsoft.com> wrote:
>>>>
>>>> For example, an algorithm could be supported when a smart card is inserted and not supported when it's removed, because the implementation is on the card.  Between the "discovery" step and the code trying to use the algorithm, a smart could have been removed by the user.
>>>>
>>>>
>>>>
>>>> Tony may have other examples in mind.
>>>>
>>>>
>>>>
>>>>                                                                 --
>>>> Mike
>>>>
>>>>
>>>>
>>>> From: Ryan Sleevi [mailto:sleevi@google.com]
>>>> Sent: Tuesday, July 10, 2012 8:34 AM
>>>> To: Anthony Nadalin
>>>> Cc: public-webcrypto@w3.org; David Dahl; Mike Jones
>>>> Subject: Re: ISSUE-3: Algorithm discovery
>>>>
>>>>
>>>>
>>>> On Tue, Jul 10, 2012 at 7:38 AM, Anthony Nadalin <tonynad@microsoft.com> wrote:
>>>>
>>>> Even with this approach you still don't know if the algorithm is
>>>> supported given the various input parameters
>>>>
>>>>
>>>>
>>>> I thought this concern had already been addressed, so can you provide an example of an input parameter that would not be able to be passed via .supports?
>>>>
>>>>
>>>>
>>>> I've identified the operation (encrypt/decrypt/sign/verify) as a known deficiency, but your reply and the past discussion suggest that there may be some other parameter/set of parameters not being considered, so it would be good to have a concrete example for the WG to consider.
>>>>
>>>>
>>>>
>>>> As demonstrated in the pseudo-algorithm-registry for the original strawman and in the current draft, parameters such as IV were to be passed via the Algorithm/AlgorithmParams dictionary.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> From: Ryan Sleevi [mailto:sleevi@google.com]
>>>> Sent: Monday, July 09, 2012 6:27 PM
>>>> To: public-webcrypto@w3.org
>>>> Cc: David Dahl; Mike Jones
>>>> Subject: ISSUE-3: Algorithm discovery
>>>>
>>>>
>>>>
>>>> In the original straw-man and current draft, I proposed an API
>>>>
>>>>
>>>>
>>>> bool supports(Algorithm algorithm, optional Key key);
>>>>
>>>>
>>>>
>>>> This was to allow determining whether or not a given algorithm was supported, without having to actually create a CryptoStream object. The intent was to provide a way to discover whether the necessary complete set of ciphers was available for an application, before beginning potentially expensive operations (key generation, data download, key discovery that may result in user interaction, etc).
>>>>
>>>>
>>>>
>>>> However, as some have pointed out, there are implicit facilities for algorithm discovery, by virtue of the fact that .encrypt/.decrypt/.sign/.verify need to have some well-defined behaviour for handling invalid or unsupported Algorithms. It has also been raised that whether or not a given algorithm is supported is dependent upon the key being used, although I believe I addressed that point via the optional "Key" parameter, since it allows a user optionally to determine if a particular key supports the algorithm, rather than just whether or not an implementation exists.
>>>>
>>>>
>>>>
>>>> However, I'm now thinking that the currently defined synchronous interface is neither desirable nor sufficient. It seems to me that, for at least some key storage types, determining whether or not a particular algorithm is supported may involve some form of user interaction or, in the case where key storage is backed by hardware, some form of hardware communication. For example, if using PKCS#11, this may involve calls to C_GetMechanismInfo, which may involve talking to a token/slot.
>>>>
>>>>
>>>>
>>>> These calls may be slow - especially if other programs are using the token or key storage mechanism (including software storage systems that need to have locks) - so it would seem like this should be an asynchronous call. It would also seem that my straw man proposal fails to distinguish the uses of a particular algorithm - for example, a key may only support verification, but not signatures. These sorts of scenario arises even if raw keying material is exposed and implementations are fully software, I believe, since there are still limitations on how a key may be used.
>>>>
>>>>
>>>>
>>>> Ultimately, this means that the current proposed synchronous API is likely insufficient.
>>>>
>>>>
>>>>
>>>> Based on what was proposed in the strawman-now-draft, this would seem to imply that the error/exception for an invalid Algorithm would not be able to be raised until the first call to .processData on the CryptoStream.
>>>>
>>>>
>>>>
>>>> eg:
>>>>
>>>> try {
>>>>
>>>>   var stream = window.crypto.encrypt("RS256", key);
>>>>
>>>> } catch (err) {
>>>>
>>>>   if (err instanceof InvalidAlgorithmException) {
>>>>
>>>>     // "RS256" does not parse as a valid Algorithm
>>>>
>>>>   }
>>>>
>>>> }
>>>>
>>>> stream.onerror = function(err) {
>>>>
>>>>   if (err instanceof UnsupportedAlgorithmException) {
>>>>
>>>>     // "RS256" is parsed, but either the key or the underlying implementation doesn't support it.
>>>>
>>>>   }
>>>>
>>>> }
>>>>
>>>> // Until this is called, it's unknown whether or not "stream" will actually work. If it ends up failing, stream.onerror will be called.
>>>>
>>>> stream.processData(...);
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Note that none of the above semantics would necessarily be altered by a MUST-IMPLEMENT registry (ISSUE-1), since there would still need to be some form of error handling for invalid constants/strings and for unsupported key+algorithm+operation tuples.
>
>>>>
>>>>
>>>>
>>>> Further, attempting to discover an algorithm by sending 'junk' data (constants or random) may result in user agents having to interact with the user, since there may be security concerns about even calling .processData() on an object (regardless of .complete()), which is some of what ISSUE-2 may be related to.
>>>>
>>>>
>>>>
>>>> As an implementer, the above semantics look both undesirable and limiting to potential consumers. How do others in the WG feel? Should there be an explicitly asynchronous call to determine whether or not an algorithm/algorithm+key pair/algorithm+key+operation tuple is supported, without requiring .processBytes()? Are there alternate proposals that would simplify or could replace the above API?
>>>>
>>>>
>>>>
>>>> Cheers,
>>>>
>>>> Ryan
>>>>
>>>>
>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>>
>>
>
>
>
>
>

Received on Monday, 16 July 2012 17:48:26 UTC