I'm attempting to find a client/server authentication protocol that allows the client and server to authenticate each other when the client doesn't know the server secret but does have a sensitive key derived from the secret.
I would like to use asymmetric certs, but the server in this case is extremely limited in CPU and memory resources, on the order of 16MHz and 32K Ram; but it does have hardware AES support. Speed of the process is critical to the user-experience, but security is paramount.
I was thinking through it and I'd like something like this (The most secure form of each function is implicit):
ClientID (CID): Unique client identifier that ties the token to the client.
Client Token (CT): HMAC(Secret, CID)
Secret (S): A secret that the server knows. The server (or a third party that also knows the key) creates tokens through an offline commissioning process.
Client -> Server
CID, CNonce
Server -> Client (Server derives expected CT with secret and CID)
SNonce, HMAC(CT, CNonce)
Client -> Server
HMAC(CT, SNonce)
This seems to give me a few properties that I need:
- The client can verify that the server knows the secret because it is able to HMAC CNonce with a derived CT.
- The server can verify that the client has the token because it can HMAC the SNonce with the CT.
- Replay attacks are mitigated by the nonces.
- MITM attacks mitigated because the token is never transmitted.
CT = SHA(CID+Secret)
is an ad-hoc (but so far unbroken) key derivation function;CT = HMAC(Secret, CID)
would be more academic. $\endgroup$