Check whether our key agreement procotols assume contributory behaviour
We're migrating to Curve25519 for key agreement, and RFC 7748 warns that protocols based on Curve25519 should not assume contributory behaviour:
Protocol designers using Diffie-Hellman over the curves defined in this document must not assume "contributory behaviour". Specially, contributory behaviour means that both parties' private keys contribute to the resulting shared key. Since curve25519 and curve448 have cofactors of 8 and 4 (respectively), an input point of small order will eliminate any contribution from the other party's private key. This situation can be detected by checking for the all-zero output, which implementations MAY do, as specified in Section 6. However, a large number of existing implementations do not do this.
The Curve25519 website also has a warning:
There are some unusual non-Diffie-Hellman elliptic-curve protocols that need to ensure ``contributory'' behavior. In those protocols, you should reject the 32-byte strings that, in little-endian form, represent 0, 1, 325606250916557431795983626356110631294008115727848805560023387167927233504 (which has order 8), 39382357235489614581723060781553021112529911719440698176882885853963445705823 (which also has order 8), 2^255 - 19 - 1, 2^255 - 19, 2^255 - 19 + 1, 2^255 - 19 + 325606250916557431795983626356110631294008115727848805560023387167927233504, 2^255 - 19 + 39382357235489614581723060781553021112529911719440698176882885853963445705823, 2(2^255 - 19) - 1, 2(2^255 - 19), and 2(2^255 - 19) + 1. But these exclusions are unnecessary for Diffie-Hellman.
It's not clear to me whether the special public keys listed in the second quote will produce the all-zero output as described in the first quote. This is something we can confirm, and we can check for the all-zero output in our usage of Curve25519. But for defence in depth we should also check whether our key agreement protocols (BQP, the contact exchange protocol and the introduction protocol) assume contributory behaviour.
One thing we need to clarify is whether hashing both public keys into the shared secret (which we already do) is enough to ensure contributory behaviour.