The use of a salt serves two purposes: domain separation and randomness extraction.
If you are sure that your IKM (input keying material) is only being used in one "domain", you do not need a salt for the purposes of domain separation. Within the same domain, you instead use the info parameter to generate multiple keys from the same IKM for different contexts within the domain.
If your IKM is already uniformly random (such as when it is a uniformly random private key being used to derive sub-keys via HKDF), then you do not need a salt for the purposes of randomness extraction if the IKM is of sufficient bit length for your purposes.
Domain separation
Page 26 of the "Cryptographic Extraction and Key Derivation:
The HKDF Scheme" paper (referred to as [HKDF-paper] in rfc5869) gives the following example of the necessity of domain separation:
The importance of such independence can be illustrated by the
following “real-life” example... A
Diffie-Hellman exchange is authenticated by signing the key $g^{xy}$. In
actuality, what is signed is $H(g^{xy})$ for some hash function $H$, say
SHA-1. If the signature allows for message recovery (e.g. RSA) then
the attacker does not learn $g^{xy}$ but rather $H(g^{xy})$; thus if one
thinks of $H$ as a random oracle then nothing is learned about $g^{xy}$.
Now, suppose that the above protocol derives keys via a traditional
KDF, namely, keys are computed as $H(g^{xy} \mathbin\| v)$ for some
public values $v$. In this case, if we follow the $H$ = SHA-1 example and
assume $g^{xy}$ is of length 1024, we get that computing $H(g^{xy}\mathbin\|v)$ is
the same as computing $H$ on $v$ with the IV of $H$ set to $H(g^{xy})$ (for
simplicity assume that the computation of $H$ on $g^{xy}$ does not use
length appending). However, this means that the attacker learns all
the keys since he knows $H(g^{xy})$! The failure of the protocol is not
due to a specific weakness of $H$ but rather to the use of the same
(deterministic) function for two different functionalities: the hash
function applied to $g^{xy}$ and the KDF. In contrast, if one keyed $H$ via
a salt value in its use by the KDF one would enforce independence
between the two functionalities.
HDKF consists of two stages:
- HKDF-Extract: PRK = HMAC-Hash(salt, IKM)
- HKDF-Expand(PRK, info, L) -> OKM
(Where IKM is 'input keying material', PRK is 'a pseudorandom key', OKM is 'output keying material', L is the length of the desired output).
Therefore, if no salt were used, and the value of HMAC-Hash(NULL, IKM) were somehow leaked (e.g. in the "message recovery" scenario above), then all uses of HKDF later on using the same IKM and without salt would also be compromised.
If you do not need a salt for domain separation, then you should consider whether you need a salt for the purposes of randomness extraction. That question is posted here.