No idea how that compares to TFA, because they have no documentation.
Do they? Doesn't the server just need to share the salt and algorithm parameters it stores anyway?
Stored on server: x = SHA256("mypassword")
Server challenge to client: send a secure random nonce
Client sends: c = HMACSHA256(nonce, SHA256("mypassword"))
Server verifies: c == HMACSHA256(nonce, x)
In some implementations, the server challenge and 'c' are encrypted using 'x' or some derivation that both sides can create. In addition, salts can remove the sensitivity of the stored 'x' values (https://en.wikipedia.org/wiki/Salted_Challenge_Response_Auth...)
This only mitigates knowing the password itself, not anything to do with authentication.
But now you have to grab the hash first from one of the endpoints, MITMing the connection no longer suffices to impersonate the user.
I suppose public key schemes would be preferable, but deploying those isn't feasible for a lot of use cases.