<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Dear Trevor, All,<div class=""><br class=""></div><div class="">Nadim and I have been looking at some Noise patterns that are not in the specification and analyzing them with Noise Explorer.</div><div class="">Unless we misunderstand something, we may have found a forgery attack on one of these patterns.</div><div class="">Essentially, we can compose well-known attack vectors (invalid DH keys, repeated AEAD nonces) to attack patterns </div><div class="">that rely only on static-static DH (“ss”) for authentication.</div><div class=""><br class=""></div><div class="">====</div><div class=""><br class=""></div><div class="">Consider the pattern KXS below:</div><div class=""><br class=""></div><div class="">KXS(s,rs):</div><div class=""><span class="" style="font-family: monospace, monospace; font-size: 0.98em; white-space: pre; color: rgb(68, 68, 68); orphans: 2; widows: 2; background-color: rgb(255, 255, 255);">      -> s</span></div><div class=""><pre class="" style="font-family: monospace, monospace; font-size: 0.98em; line-height: 1.25em; background-color: rgb(255, 255, 255); white-space: pre-wrap; word-wrap: break-word; margin-top: 0px; margin-bottom: 0px; color: rgb(68, 68, 68); font-variant-ligatures: normal; orphans: 2; widows: 2;"><code class="" style="white-space: pre; font-family: monospace, monospace; font-size: 0.98em; line-height: 1.25em;">      ...
      -> e
      <- e, ee, s, ss</code></pre><div class=""><br class=""></div></div><div class="">This is a variation of KX that uses ss instead of se, and es, so it is a little more efficient, but essentially satisfies the same confidentiality and authentication goals. In particular, the responder can start sending messages immediately after the second message (with a auth=2, conf=3 guarantee).</div><div class=""><br class=""></div><div class="">However, there is an attack if the responder does not validate ephemeral public values.</div><div class="">Suppose a malicious initiator were to send an invalid ephemeral public key “e”, say e = 0 (zero)</div><div class="">Then, the responder would compute “ee” as 0 and the resulting key would depend only on the static key “ss”.</div><div class="">(Note that the responder could detect and reject the invalid public key but the noise spec explicitly discourages this behavior.)</div><div class=""><br class=""></div><div class="">Why is this bad? Since the responder will encrypt messages with a key determined only by “ss" (with nonce set to 0), </div><div class="">the malicious initiator can cause it to encrypt two messages with the same key and nonce, which allows for forgery attacks.</div><div class=""><br class=""></div><div class="">A concrete man-in-the-middle attack on this pattern is as follows:</div><div class="">(For simplicity, we use Hash to represent the more complex key derivation and mixing functions for Noise, but we hope the ideas are clear)</div><div class=""><br class=""></div><div class="">=====</div><div class="">Pre-Messages</div><div class="">=====</div><div class=""><br class=""></div><div class="">0. Before the session begins, A sends s = sA to B</div><div class=""><br class=""></div><div class="">====</div><div class="">Session 1</div><div class="">====</div><div class=""><br class=""></div><div class="">1. Malicious M initiates a session with B (pretending to be A).</div><div class="">    It sends e = Z (zero) such that Z^x would evaluate to Z for any x.</div><div class=""><br class=""></div><div class="">2. B receives e = Z and accepts a new session with:</div><div class="">  <span class="Apple-tab-span" style="white-space: pre;">      </span>hB_0 = Hash(pattern_name)</div><div class="">  <span class="Apple-tab-span" style="white-space: pre;">   </span>ckB_1 = hB0</div><div class="">  <span class="Apple-tab-span" style="white-space: pre;"> </span>hB_1 = Hash(hB0, sA, e=Z)</div><div class=""><br class=""></div><div class="">3. B generates re1, computes ee = Z, and sends back (re1,ee=Z,sB,ssAB,msg1)</div><div class="">    where sB is encrypted with </div><div class="">         key = ckB_2 = Hash(ckB_1, ee = Z)</div><div class="">         nonce = 0</div><div class="">         additional_data = hB_2 = Hash(hB_1, re1, ee=Z)</div><div class="">    and msg1 is encrypted with</div><div class="">         key = ckB_3 = Hash(ckB_2, ssAB)</div><div class="">         nonce = 0</div><div class="">         using additional_data = hB_3 = Hash(hB_2, sB)</div><div class=""><br class=""></div><div class="">4. M discards this session but remembers the encrypted message </div><div class=""><br class=""></div><div class="">====</div><div class="">Session 2</div><div class="">====</div><div class=""><br class=""></div><div class="">5. A initiates a new session with B by sending e:</div><div class="">    So at A:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>hA_0 = Hash(pattern_name)</div><div class=""> <span class="Apple-tab-span" style="white-space: pre;"> </span>ckA_1 = hA0</div><div class=""> <span class="Apple-tab-span" style="white-space: pre;">       </span>hA_1 = Hash(hA0, sA, e)</div><div class=""><br class=""></div><div class="">6. M intercepts this message and replaces it with the invalid public key Z (zero).</div><div class=""><br class=""></div><div class="">7. B receives e = Z and accepts a new session with:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>  hB_0 = Hash(pattern_name)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>  ckB_1 = hB0</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>  hB_1 = Hash(hB0, sA, e=Z)</div><div class=""><br class=""></div><div class="">8. B generates re2, computes ee = Z, and sends back (re2,ee=Z,sB,ssAB,msg2)</div><div class="">    where sB is encrypted with </div><div class="">         key = ckB_2 = Hash(ckB_1, ee = Z)</div><div class="">         nonce = 0</div><div class="">         additional_data = hB_2 = Hash(hB_1, re)</div><div class="">    and msg2 is encrypted with</div><div class="">         key = ckB_3 = Hash(ckB_2, ssAB)</div><div class="">         nonce = 0</div><div class="">         using additional_data = hB_3 = Hash(hB_2, sB)</div><div class=""><br class=""></div><div class="">9. M intercepts this response. </div><div class="">    Notably, the encryption keys (ckB_3) and the nonces (0) used for msg1 in session 1 and msg2 in session 2 are the same.</div><div class="">    Hence, if the underlying AEAD scheme is vulnerable to the repeated nonces attack, M can compute the AEAD </div><div class="">    authentication key for ckB_3 and tamper with msg1 and msg2 to produce a new message msg3 that is validly encrypted under this key.</div><div class="">    Importantly, M can also tamper with the additional data hB_3 to make it match any other hash value.</div><div class=""><br class=""></div><div class="">    M replaces the message with (re=Z, ee=Z, sB, ssAB, msg3) and sends it to A.</div><div class="">    where sB is re-encrypted by M using ckB_2 which it knows</div><div class="">    and msg3 is forged by M using the AEAD authentication key for ckB_3 </div><div class=""><br class=""></div><div class="">10. A receives this message (re=Z,ee=Z,sB,ssAB,msg3) and computes:</div><div class="">         ckA_2 = Hash(ckA_1, ee = Z)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;"> </span> hA_2 = Hash(hA_1, re = Z)</div><div class="">      and decrypts sB with ckA_2, nonce = 0, AD = hA_2</div><div class="">      It then computes</div><div class="">        ckA_3 = Hash(ckA_2, ssAB)</div><div class="">     <span class="Apple-tab-span" style="white-space: pre;">        </span>hA_3 = Hash(hA_2, sAB)</div><div class="">      and decrypts msg3 with ckA_3, nonce = 0, AD= hA_3</div><div class="">      This decryption succeeds since ckA_3 = ckB_3 and the attacker has forged the AD and the msg.</div><div class=""><br class=""></div><div class="">======</div><div class=""><br class=""></div><div class="">Result: A accepts the forged message msg3 as coming from B, even though the pattern had the maximum authenticity level 2.</div><div class=""><br class=""></div><div class="">======</div><div class=""><br class=""></div><div class=""><div class="">At a high-level, the above analysis  can be read in one of three ways:</div><div class="">1) We need to be careful about uses of “ss” in Noise patterns</div><div class="">2) We need to validate DH public values, including for Curve25519 </div><div class="">3) We need to ensure that independent sessions cannot have the same AEAD keys </div><div class=""><br class=""></div><div class="">Consequently, a simple countermeasure would be any of the following:</div></div><div class="">1) Forbid the use of “ss” unless accompanied by se or es</div><div class="">2) Require implementations to validate incoming DH public values</div><div class="">3) Mix ephemeral+static public DH values into the encryption key </div><div class=""><br class=""></div><div class="">Feedback welcome,</div><div class="">Karthik and Nadim</div></body></html>