I just completed a review of XEP-0220, which went through a Last Call in late 2010 and is now under consideration by the XMPP Council for advancement from Experimental to Draft (whether it should have been Experimental after we copied it from RFC 3920 is another question...).
I think this spec contains serious bugs. I am writing this message to the standards@xmpp.org list before making changes to the spec so that my co-authors (really Philipp Hancke because Jer isn't on this list anymore, although I've cc'd him), Council members, and others can check my reading of the spec. I don't think I'm wrong about what follows, but if I am wrong then we've all missed some serious bugs. There are two basic problems: 1. In all of the examples of XEP-0220, the dialback key should be the same key -- but the key varies across examples. 2. The 'id' of the <db:verify/> element should always be the StreamID of the response stream header sent from the Receiving Server to the Originating Server -- but sometimes the 'id' is the StreamID of the response stream header sent from the Authoritative Server to the Receiving Server. Let's roll the video tape... ### SECTION 2.1.1 ### Example 1. Originating Server Sends Dialback Key (step 1) send: <db:result from='sender.tld' to='target.tld'> ==> 1e701f120f66824b57303384e83b51feba858024fd2221d39f7acc52dcf767a9 </db:result> The key sent is generated as described in Dialback Key Generation and Validation [6]: key = HMAC-SHA256( SHA256('s3cr3tf0rd14lb4ck'), { 'target.tld', ' ', 'sender.tld', ' ', 'D60000229F' } ) [Philipp, can you verify that the key in Example 1 is correct based on the inputs?] ### SECTION 2.1.2 ### Example 5. Receiving Server Sends Verification Request to Authoritative Server (step 2) send: <db:verify from='target.tld' ==> id='417GAF25' to='sender.tld'> ==> 38b501ec606752318f72ad53de17ac6d15f86257485b0d8f5d54e1f619e6b869 </db:verify> ### SECTION 2.2.1 ### Example 9. Receiving Server Receives Dialback Key from Originating Server (step 1) recv: <db:result from='sender.tld' to='target.tld'> ==> 1e701f120f66824b57303384e83b51feba858024fd2221d39f7acc52dcf767a9 </db:result> ### SECTION 2.2.2 ### Example 13. Authoritative Server Receives Verification Request from Receiving Server (step 2) recv: <db:verify from='target.tld' ==> id='417GAF25' to='sender.tld'> ==> fed84f34d39682fd80bd04e01894f98c4149cf9df47575b134eeb6d2c7fe9fee </db:verify> [...] Upon receiving this <db:verify/> element, the Authoritative Server determines the validity of the dialback key provided in the XML character data of the element. This can be achieved for example by comparing the character data with the output of applying the same key generation mechanism that was (presumably) used for the generation of the key, using as input the values of the 'from', 'to', and 'id' attributes contained in the verification request and the secret known only to the Sender Domain: key = HMAC-SHA256( SHA256('d14lb4ck43v3r'), { 'sender.tld', ' ', 'target.tld', ' ', '417GAF25' } ) = fed84f34d39682fd80bd04e01894f98c4149cf9df47575b134eeb6d2c7fe9fee ### What the heck is going on here?!? (And yes, I'm to blame because I am the primary author of this spec.) Look at that last text snippet. It shows the Authoritative Server checking a dialback key that is generated using the secret key of the *Target Domain* ("d14lb4ck43v3r") instead of the secret key of the *Sender Domain* ("s3cr3tf0rd14lb4ck"), and using the StreamID of the response stream header from the Authoritative Server to the Receiving Server ("417GAF25") instead of the StreamID of the response stream header from the Receiving Server to the Originating Server ("D60000229F"). This is utter nonsense! Also nonsensical are Examples 5 and 13, which show the Receiving Server sending a dialback key different from the dialback key that the Originating Server sent in Example 1. But the Receiving Server does not generate a dialback key -- it just sends to the Authoritative Server whatever it has received from the Originating Server! I also think that the <db:verify/> element in Examples 5 and 13 needs to include the StreamID of the response stream header that the Receiving Server has sent to the Originating Server. This ensures that the Authoritative Server has the right StreamID to use as input to its calculation of the key: key = HMAC-SHA256( SHA256('s3cr3tf0rd14lb4ck'), { 'target.tld', ' ', 'sender.tld', ' ', 'D60000229F' } ) If the Authoritative server doesn't know about that StreamID, then obviously it needs to return "invalid" to the Receiving Server: <db:verify from='sender.tld' id='417GAF25' to='target.tld' type='invalid'/> (Naturally the Authoritative Server would also return "invalid" if its secret is different from whatever the Originating Server used.) But wait, there's more! These errors about the dialback key and StreamID needlessly stray from RFC 3920, which has the following... ### 3. The Receiving Server SHOULD send a stream header back to the Originating Server, including a unique ID for this interaction: <stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:server' xmlns:db='jabber:server:dialback' ==> id='457F9224A0...'> [...] 4. The Originating Server sends a dialback key to the Receiving Server: <db:result to='Receiving Server' from='Originating Server'> ==> 98AF014EDC0... </db:result> [...] 8. The Receiving Server sends the Authoritative Server a request for verification of a key: <db:verify from='Receiving Server' to='Originating Server' ==> id='457F9224A0...'> ==> 98AF014EDC0... </db:verify> [Same key, same 'id'!] ### This mess is fairly easy to clean up, but the bugs are so fundamental that I'd like a sanity check from folks on this list to ensure that I'm not way off base here! Thanks for listening. Peter -- Peter Saint-Andre https://stpeter.im/
smime.p7s
Description: S/MIME Cryptographic Signature