Binary packet protocol rethink (was: Re: ChaCha20-Poly1305 for SSH)
Simon Tatham <anakin@pobox.com> Fri, 27 November 2015 05:20 UTC
Return-Path: <bounces-ietf-ssh-owner-secsh-tyoxbijeg7-archive=lists.ietf.org@NetBSD.org>
X-Original-To: ietfarch-secsh-tyoxbijeg7-archive@ietfa.amsl.com
Delivered-To: ietfarch-secsh-tyoxbijeg7-archive@ietfa.amsl.com
Received: from localhost (ietfa.amsl.com [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 25BEE1AC3C1 for <ietfarch-secsh-tyoxbijeg7-archive@ietfa.amsl.com>; Thu, 26 Nov 2015 21:20:04 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.286
X-Spam-Level:
X-Spam-Status: No, score=-0.286 tagged_above=-999 required=5 tests=[BAYES_20=-0.001, MIME_8BIT_HEADER=0.3, RP_MATCHES_RCVD=-0.585] autolearn=ham
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vJ1KUfwZcRfO for <ietfarch-secsh-tyoxbijeg7-archive@ietfa.amsl.com>; Thu, 26 Nov 2015 21:20:02 -0800 (PST)
Received: from mail.netbsd.org (mail.NetBSD.org [IPv6:2001:4f8:3:7::25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 4E8661AC3BF for <secsh-tyoxbijeg7-archive@lists.ietf.org>; Thu, 26 Nov 2015 21:20:02 -0800 (PST)
Received: by mail.netbsd.org (Postfix, from userid 605) id E8FC814A2BC; Fri, 27 Nov 2015 05:19:59 +0000 (UTC)
Delivered-To: ietf-ssh@netbsd.org
Received: by mail.netbsd.org (Postfix, from userid 1347) id 93B0F14A2B9; Fri, 27 Nov 2015 05:19:59 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1]) by mail.netbsd.org (Postfix) with ESMTP id 69B1314A27F for <ietf-ssh@netbsd.org>; Thu, 26 Nov 2015 17:52:59 +0000 (UTC)
X-Virus-Scanned: amavisd-new at NetBSD.org
Received: from mail.netbsd.org ([127.0.0.1]) by localhost (mail.NetBSD.org [127.0.0.1]) (amavisd-new, port 10025) with ESMTP id B-HQQ_xbg8XN for <ietf-ssh@netbsd.org>; Thu, 26 Nov 2015 17:52:58 +0000 (UTC)
Received: from atreus.tartarus.org (atreus.tartarus.org [80.252.125.10]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.netbsd.org (Postfix) with ESMTPS id 5179D14A267 for <ietf-ssh@netbsd.org>; Thu, 26 Nov 2015 17:52:57 +0000 (UTC)
Received: from simon by atreus.tartarus.org with local (Exim 4.69) (envelope-from <simon@atreus.tartarus.org>) id 1a1zbq-0006VF-UT; Thu, 26 Nov 2015 16:41:27 +0000
Content-Type: text/plain; charset="UTF-8"
From: Simon Tatham <anakin@pobox.com>
To: Niels Möller <nisse@lysator.liu.se>
Cc: Simon Josefsson <simon@josefsson.org>, ietf-ssh@netbsd.org
Subject: Binary packet protocol rethink (was: Re: ChaCha20-Poly1305 for SSH)
In-reply-to: <nny4dksr3i.fsf@armitage.lysator.liu.se>
References: <87egfdxebo.fsf@latte.josefsson.org> <87egfdxebo.fsf@latte.josefsson.org> <nny4dksr3i.fsf@armitage.lysator.liu.se>
Date: Thu, 26 Nov 2015 16:41:26 +0000
Message-Id: <1448554180-sup-7145@atreus.tartarus.org>
User-Agent: Sup/git
Content-Transfer-Encoding: 8bit
Sender: ietf-ssh-owner@NetBSD.org
List-Id: ietf-ssh.NetBSD.org
Precedence: list
> Simon Josefsson <simon@josefsson.org> writes: >> Does anyone see a strong need for encrypting the length field? Niels Möller <nisse@lysator.liu.se> wrote: > Yes. I think it's valuable defence-in-depth to hide packet lengths and > message boundaries. Note that in the ssh protocol, the boundaries of the > TCP segments need not match the SSH message boundaries at all. It's not > too difficult to arrange that most or all segment boundaries are in the > middle of an ssh message, using SSH_MSG_IGNORE packets when needed. On that subject, perhaps this is a good moment to re-raise a thing I've been wondering about for ages. Not for immediate consideration as part of any of the current set of RFCs-in-progress, but as a thought for the further future. Is there any possible way - and would people be interested in pursuing it if there were - to invent a replacement binary packet protocol for SSH which decouples the unit of encryption and the unit of protocol semantics into completely separate layers? Handling of packet length fields in SSH has always been tricky, and we've got it wrong several times. The cleartext _unpadded_ lengths in SSH-1 had very obvious flaws; the switch to encrypting the length field as part of the first cipher block in SSH-2 caused an accidental decryption oracle. And even if you encrypt the length field in a way that avoids that mistake, you still don't reliably hide your _padded_ packet lengths anyway, in the face of an active attacker who can proxy the TCP stream, dribble it out a byte at a time, and wait to see which byte triggers a response. I suspect some defensive uses of SSH_MSG_IGNORE may still have this issue. I think all of these problems ultimately arise from the fact that the SSH protocol messages and the encrypted packets are the same thing, so that the lengths of the former (being at least somewhat sensitive data) are at constant risk of being exposed by design flaws in the latter. So I've always thought a good way to solve this _in principle_ would be to replace our current all-in-one message/packet structure with two independent layers. The outer layer would interpret the incoming TCP stream as a series of what I'll refer to as 'encrypted chunks', each consisting of a length, some encrypted data, and a MAC. The validated and decrypted contents of those chunks would be concatenated into a single byte stream, with no remaining trace of the chunk boundaries, and passed on to the inner layer which would break that byte stream up into 'SSH protocol messages'. The inner layer would need no cryptography at all; it could be something very close to SFTP's bare (length,type,data) tuples, except that you'd probably want to make it easy to insert N bytes of padding in between messages for a wide variety of N (perhaps even all N). Then you really could have the length fields of the encrypted chunks be in cleartext, because they wouldn't be telling an attacker anything they couldn't have inferred from the TCP segment boundaries anyway. And at the same time, that would tell you nothing about the SSH message boundaries inside those chunks; you could have one chunk containing many messages, or one message split across many chunks, or chunks ending in mid-message, however the sending implementation saw fit. For concealing the length of a critical message (see past attempts at traffic-analysis defences relating to SSH_MSG_PASSWORD in particular), this would be much better than just squashing two successive messages into the same TCP segment, because now the dribbling attack completely stops working - a receiver isn't going to be replying anyway until the whole encrypted chunk is received, and the proxying attacker already knows when _that_ will happen. There would be no possible way to find out how much of a large chunk corresponded to a particular message without actually breaking the cryptography. Furthermore, by inserting padding at random between messages, it would be trivial to make the starting points of messages within a chunk unpredictable, so that you could make it impossible for an attacker to reliably identify (say) a cipher block containing part of a password. Is this an idea that appeals to anyone else? I've never been entirely sure whether there's any remaining space to introduce it in the current protocol while keeping intercompatibility with existing implementations; but it's only worth trying to solve that problem if anyone else would be interested in pursuing the idea anyway. Cheers, Simon -- for k in [pow(x,37,0x1a1298d262b49c895d47f) for x in [0x50deb914257022de7fff, 0x213558f2215127d5a2d1, 0x90c99e86d08b91218630, 0x109f3d0cfbf640c0beee7, 0xc83e01379a5fbec5fdd1, 0x19d3d70a8d567e388600e, 0x534e2f6e8a4a33155123]]: print "".join([chr(32+3*((k>>x)&1))for x in range(79)]) # <anakin@pobox.com> -- for k in [pow(x,37,0x1a1298d262b49c895d47f) for x in [0x50deb914257022de7fff, 0x213558f2215127d5a2d1, 0x90c99e86d08b91218630, 0x109f3d0cfbf640c0beee7, 0xc83e01379a5fbec5fdd1, 0x19d3d70a8d567e388600e, 0x534e2f6e8a4a33155123]]: print "".join([chr(32+3*((k>>x)&1))for x in range(79)]) # <anakin@pobox.com>
- ChaCha20-Poly1305 for SSH Simon Josefsson
- Re: ChaCha20-Poly1305 for SSH Niels Möller
- Re: Binary packet protocol rethink Niels Möller
- Binary packet protocol rethink (was: Re: ChaCha20… Simon Tatham
- Re: Binary packet protocol rethink Simon Josefsson
- RE: Binary packet protocol rethink (was: Re: ChaC… Peter Gutmann
- RE: Binary packet protocol rethink (was: Re: ChaC… Damien Miller
- Re: ChaCha20-Poly1305 for SSH Damien Miller
- Re: Binary packet protocol rethink (was: Re: ChaC… Damien Miller
- Re: Binary packet protocol rethink (was: Re: ChaC… Mark D. Baushke
- Re: ChaCha20-Poly1305 for SSH Niels Möller
- RE: Binary packet protocol rethink (was: Re: ChaC… Peter Gutmann
- Re: Binary packet protocol rethink Niels Möller
- RE: Binary packet protocol rethink Peter Gutmann
- RE: Binary packet protocol rethink Simon Tatham
- Re: Binary packet protocol rethink (was: Re: ChaC… Simon Josefsson
- Re: Binary packet protocol rethink Niels Möller
- Re: Binary packet protocol rethink Niels Möller
- Re: Binary packet protocol rethink Niels Möller
- Re: Binary packet protocol rethink Bryan Ford
- Re: Binary packet protocol rethink Bryan Ford
- RE: Binary packet protocol rethink Peter Gutmann
- RE: Binary packet protocol rethink Peter Gutmann
- Re: Binary packet protocol rethink Niels Möller
- Re: Binary packet protocol rethink Niels Möller
- RE: Binary packet protocol rethink Peter Gutmann
- Re: Binary packet protocol rethink Bryan Ford
- Re: ChaCha20-Poly1305 for SSH Stefan Bühler
- Re: ChaCha20-Poly1305 for SSH Niels Möller
- Re: ChaCha20-Poly1305 for SSH Stefan Bühler
- Re: ChaCha20-Poly1305 for SSH Niels Möller
- Re: ChaCha20-Poly1305 for SSH Damien Miller
- Re: ChaCha20-Poly1305 for SSH Stefan Bühler
- Re: ChaCha20-Poly1305 for SSH Damien Miller