Hi,
George Kadianakis wrote: [SNIP]
Some further questions here:
i) Should we fake the client-auth-desc-key blob in case client authorization is not enabled? Otherwise, we leak to the HSDir whether client auth is enabled. The drawback here is the desc size increase (by about 330 bytes).
Alternatively, we can try to put it in the encrypted part of the descriptor. So that we require subcredential knowledge to access the encrypted part, and then client_auth_cookie knowledge to get the encryption key to decrypt the intro points etc. I feel that this double-encryption design might be too annoying to implement, but perhaps it's worth it?
I suggest faking the client-auth-desc-key blob. 330 bytes should be worth it for making both auth non-auth hidden services look very alike (in size). The double-encryption, aside that it might be too annoying to implement, will grow the size of the descriptor too, right? Except it will be a guess if it uses authentication or has more introduction points (since we raised the max limit for this and one HS can have 3, one 20 for example). I think just increasing both auth and non-auth HS descriptors with 330 bytes is cleaner and simpler.
ii) Should we use the descriptor ASCII format to encode all the client-auth-desc-key data? Or is that weird binary format OK?
If there are no indications that this can cause problems, yes of course. It's not weird if it's not "possible problematic".
iii) Should we use a fresh IV for each ENCRYPTED_DESC_COOKIE? rend-spec.txt does not do that, and IIUC that's OK because it uses a fresh key for every encryption (even though the plaintext and IV is the same).
There's little cost for using a fresh IV for each ENCRYPTED_DESC_COOKIE so we should do it.
b) Do we want a NACK from the HS for when client authorization fails? Currently the only way for a client to learn that they are not authorized (or that their keys changed or got revoked) is that they never complete the rendezvous.
To achieve that we would need a whole new cell (INTRODUCE_SERVICE_NACK) from the hidden service all the way to the client. Worth it?
No. I think it complicates stuff, adds extra code, adds a whole new cell and could be a potential DoS surface for a hidden service with auth enabled (you can trivially make a HS to send thousands of INTRODUCE_SERVICE_NACK cells and add extra load / bandwidth usage). I think failing with 'invalid authorization data or too many unsuccessful retries to connect to [scrubbed].onion.' if we can't complete rendezvous is ok. This way we also don't learn that a HS uses auth or doesn't exist any more or never existed, if we don't know anything about that HS and just found its address somewhere.
c) Another suggestion here by special, is to introduce an additional layer of access control at the HSDir request level, such that HSDirs don't even serve descriptors to clients that do not prove knowledge of a pre-shared fetch key.
This way unauthorized clients cannot even learn presense information of hidden services. This might be quite useful for applications like Ricochet, who want to hide their presense from revoked clients.
Of course this assumes that the HSDir is honest and will honor the fetch key protocol. However, even if the HSDir is dishonest we are just back to the current security level.
Interesting, this doesn't sound bad. But then the protocol to fetch the descriptor from the HSDir will have additional steps, so padding at this level will be needed to ensure a HSDir cannot distinguish if it just served a descriptor for which a pre-shared fetch key was provided or not. If presence hiding is very important and we have important use cases for it, we should think about this because it sounds like a good solution. My 2 cents are that presence hiding is considerably less important than the ability to allow only who I want to reach (connect) to me, and 100% presence hiding is very hard to achieve for, in my view, little gains.
We started sketching out a solution in the bottom of these notes: https://people.torproject.org/~asn/hs_notes/client_auth.jpg but the solution is not trivial to implement and we are not sure whether it's worth complicating the protocol further (e.g. we need to design a way for apps like Ricochet to get access to the fetch key).
d) It might be worthwhile padding the encrypted part of INTRODUCE1 to obscure whether client authorization is in place.
Don't understand how this exactly helps. This will hide the existence of a client authorization at introduction point side, correct? The introduction point doesn't know the hidden service, and it's rotated after a random number of introductions so the worst it can do is collect (highly inaccurate stats) about how many auth enabled HSes and non-auth HSes are out there? This should be fine and not enough of a threat to add padding (thinking about mobile clients trying to connect often here).
As you can see I have mainly worked on point (a) which I consider the most urgent. I welcome feedback on all points, so that we move forward with the design here.
Thanks :)
Thanks for your great work on this and everything else!