Symmetric mutual authentication with client using a derived secret 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 -&gt; Server
CID, CNonce

Server -&gt; Client (Server derives expected CT with secret and CID)
SNonce, HMAC(CT, CNonce)

Client -&gt; 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.
The general answer is "no, you can't authenticate someone over a wire unless they know some secret information." The only way to authenticate someone is to have them do something that no one else can do. If you're trying to do it by just sending messages between the parties, the only way I can do something that someone else can't is if I know something they don't (whatever I would send is based only on things I know; if they know what I know they could figure out what I would send themselves).

Your scheme isn't quite that, though. You do have a secret on each side; in fact, it's the same secret on each side (i.e. CT). With a shared secret, authentication absolutely becomes possible; when the shared secret is high-entropy (i.e. not derived from a password), it's even better. MACs should be a decent way to achieve this, although I'd be wary of possible pitfalls (one notable one being that an attacker could get whatever he wants MACed by the server, but with a strong MAC this only allows straight replay, and the scheme stops that).

The other part of your scheme is deriving the shared secrets from a server master secret. If the idea of using HMAC with a secret key to derive client tokens is that you don't need to have a master list of client tokens, then that seems like a sensible approach; HMAC should stop an attacker from creating any secret tokens that they don't already know from other sources. TLS uses HMAC as a PRF to produce cryptographic keys from a secret, so it's a perfectly reasonable choice (the way TLS uses it is having a seed and computing HMAC(secret, label+seed), but in your case you don't need a label).

Much depends on what you plan to do after authentication -- if they'll keep communicating, nothing you did prevents an attacker from tampering with the rest of the communication. For instance, an attacker can hold up message 3 and then send it days later. Is this a problem for your protocol? If so, you have to deal with it somehow.