Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

I am working on a project that needs to securely authenticating one or more smartphone clients with a server running on a microcontroller so it has very limited resources. I have found plenty of lightweight HMAC hashing libraries. Therefore it seems to me that an HOTP authentication mechanism would be feasible on the limited resources of the microcontroller.

My concern however is with the authentication of multiple clients. I know that ideally (or so I am told) in an HOTP implementation each client would have its own shared secret key with the server. However I don't have the resources to have a database of shared secret keys on the microcontroller.

I was wondering if it would be OK to have all clients and the server share the same secret key and for the server to tell any client that requests it what the next expected counter would be. This would be an unauthenticated request that would do nothing more than provide the expected counter. The client could then issue an authenticated command with an HOTP code in it (using the provided counter) that would actually perform the desired action.

As per the RFC that defines HOTP each counter would only be accepted once even if the server gave the same counter to 2 clients, in this case the first one in wins and the second needs to get the next counter.

I know this isn't quite ideal, but it is the best implementation I can think of. Security is about balancing weakness with usability or in my case server constraints. This is for a door unlocking mechanism for what its worth. I think that my implementation would be at least as good as a typical physical key.

What are the security implications and trade offs here? Is there a better implementation (HOTP or not) given the constraints of the inability for the server to maintain multiple keys?

share|improve this question
add comment

1 Answer

up vote 1 down vote accepted

RFC 4226, section 7.5 defines two shared key generation schemes: deterministic and random. I would suggest that you use the deterministic scheme, which only requires the server to store a single "master key":

"Deterministic Generation

A possible strategy is to derive the shared secrets from a master secret. The master secret will be stored at the server only. A tamper-resistant device MUST be used to store the master key and derive the shared secrets from the master key and some public information. The main benefit would be to avoid the exposure of the shared secrets at any time and also avoid specific requirements on storage, since the shared secrets could be generated on-demand when needed at provisioning and validation time."

Addendum: To also avoid storing a separate counter value for each client, you could still use a shared counter for all clients as you suggest, at least as long as the intended purpose of the server is such that it's unlikely for more than one legitimate client to attempt to authenticate simultaneously.

However, simply sending a counter value to the client and having the client reply with the corresponding one-time password could allow an attacker masquerading as the server to send an artificially high counter value to the client and store the response for later use. (If the client enforces the monotonicity of counter values, this could also render the client temporarily unable to authenticate until the server's counter catches up with the bogus counter value sent by the attacker.)

One way to avoid this attack, and eliminate the extra round-trip to request the counter, would be to use a timestamp as the counter, something like this:

  • When the user want to authenticate, the server sends to the server the current timestamp $T$, its client ID $i$ and the one-time password $P = HOTP(K_i,T)$, where $K_i$ is the client's HOTP key.

  • On receiving an authentication request $(T,i,P)$, the server checks that:

    • $i$ is a valid and non-revoked client ID;
    • $T$ is a valid timestamp, and is not too far in the past or the future;
    • $T$ is greater than the timestamp $T'$ for the previous successful authentication; and
    • $P = HOTP(K_i,T)$, where $K_i$ is the client key derived from the client ID $i$ and the master key $MK$.

    If all these checks pass, the client is allowed access.

Thus, the server only needs to store the master key $MK$, the last successful authentication timestamp $T'$, and possibly list of revoked client IDs. (This ability to revoke access for compromised clients is one of the main advantages of not sharing keys between clients.)

The valid time window allows for some degree of clock skew between the clients and the server, and should be set to reflect a balance between that and security requirement.

An attacker intercepting the authentication request in this protocol can't really do much: if they pass the request on to the server, the password they just captured becomes useless (and if the client and server encrypt any further communications with their shared secret $K_i$, the attacker can't even eavesdrop on it); if they don't, the client will know something went wrong, and in any case the password will still expire after the limited time window passes (and possibly sooner, if the client tries to reauthenticate and succeeds).

(Obviously, the protocol also needs to protect against brute force attacks, either by implementing request rate throttling as recommended in the HOTP spec, and/or by making the password long enough. Indeed, if the password need not be human-enterable, one could just as well — and, indeed, preferably — use the full non-truncated HMAC output as the one-time password.)

share|improve this answer
    
So it sounds like I'd still have to track the current counter for each serial number in the microcontroller eeprom (which is honestly fairly tamper resistant) for each client (much more feasible than the key/counter combination). In this case would I send the HOTP code along with the serial number? Then on the server I'd derive the key from the master via the serial number and lookup the expected counter? –  Devin Sep 21 '12 at 16:50
    
@Devin: I amended my answer to suggest using a timestamp as the counter to avoid storing individual counter values for each client. –  Ilmari Karonen Sep 21 '12 at 18:34
    
Thanks for your input. The man in the middle attack you mentioned isn't one I had considered in my original proposal. Thank you for pointing it out. I really like the timestamp model here. It is almost but not quite a full TOTP implementation. My server won't have a clock (beyond elapsed time since startup) but will have network access. Pinging NIST once at startup for the correct time shouldn't be too hard to add. Thanks again for taking the time to help me with this question. –  Devin Sep 21 '12 at 19:07
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.