Unfortunately, this is the top result on google for HMAC double submit. So I will leave this here.

[OWASP cheat sheet][1] includes a section on HMAC double submit including some pseudocode. I would suggest that anyone looking for information starts there.

I think a lot of confusion in your question and some of the comments stem from a misunderstanding of what double submit is for. We are **not** trying to prove that the user's browser **has** the cookie that we sent it. Session cookies already do this. We are trying to prove something different: that the origin of the call **can read** the token. We are basically piggybacking on the browsers same-origin policy.

> Is the server supposed to send 2 cookies? 1 encrypted/HMAC and 1 plain-text?

That would be pointless, just send both as a single cookie as proposed in the owasp cheat sheet.

    hmac + "." + message

>Is the encrypted/HMAC cookie Http-Only=true?

You can set to true and template the token into the html or set it to false and read it with javascript, false is a lot more flexible. 

This goes back to my point about what we are trying to prove. This is not a session cookie, it's not a protection from XSS or any other attack vector. This only protects you from CSRF, nothing else. This is not a vulnerability, proving that you can read the token is the whole point of double submit.

>Does HSTS render encrypted/HMAC cookies useless?

Not totally. HMAC stops an attacker who can set cookies. HSTS only prevents the most common way for an attacker to set cookies (through a subdomain) but there are other ways. see: https://owasp.org/www-chapter-london/assets/slides/David_Johansson-Double_Defeat_of_Double-Submit_Cookie.pdf

As to why this matters: The problem with the naive approach is that we accept any token as long as the one in the cookie and the one in the request match. This means that an attacker who can set cookies can just put any random value in there and send a matching request. We prevent this by signing the token and tying it to some session-specific value(most likely the sessionID). So only a token generated by the server for this specific session will be considered valid.

  [1]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html