From owner-freebsd-security@FreeBSD.ORG Thu Apr 10 12:40:01 2014 Return-Path: Delivered-To: freebsd-security@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DABB33CB for ; Thu, 10 Apr 2014 12:40:01 +0000 (UTC) Received: from outgoing.tristatelogic.com (segfault.tristatelogic.com [69.62.255.118]) by mx1.freebsd.org (Postfix) with ESMTP id B4CCB1CDA for ; Thu, 10 Apr 2014 12:40:01 +0000 (UTC) Received: from segfault-nmh-helo.tristatelogic.com (localhost [127.0.0.1]) by segfault.tristatelogic.com (Postfix) with ESMTP id 87A783AE82 for ; Thu, 10 Apr 2014 05:39:55 -0700 (PDT) From: "Ronald F. Guilmette" To: freebsd-security@freebsd.org Subject: Re: Heartbleed, a few naive questions In-Reply-To: <867g6x5u2r.fsf@nine.des.no> Date: Thu, 10 Apr 2014 05:39:55 -0700 Message-ID: <43981.1397133595@server1.tristatelogic.com> X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "Security issues \[members-only posting\]" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Apr 2014 12:40:02 -0000 In message <867g6x5u2r.fsf@nine.des.no>, =?utf-8?Q?Dag-Erling_Sm=C3=B8rgrav?= wrote: >"Ronald F. Guilmette" writes: >> Xin Li writes: >> > For this bug, doing calloc() makes no difference. >> I would very much like to know how you reached that conclusion. > >It's very simple. The explpoit relies on reading past the end of the >allocated buffer. You're right, of course, and I missed that. My apologies. My other points still stand however, the most important of which is that the protocol definition itself seems to be asking for trouble, and that this bug was/is the almost inevitable outgrowth of an entirely poorly considered bit of the SSL protocol specification. Hummm... In fact, now that I look at the code some more I'm not even sure if my suggestion for using calloc() in place of malloc() throughout OpenSSL was even entirely off the mark... although the exact _place_ where that suggestion might have been most profitably applied is *not* within the dtls1_process_heartbeat() function itself, but rather is wherever the original receive buffer was allocated, i.e. the buffer that is pointed to by s->s3->rrec.data upon entry to the dtls1_process_heartbeat() function. I have not searched the code to find the place where this original packet receive buffer is allocated, however regardless of whereever this allocation takes place I think that it is safe to say that if such buffers were always allocated to the maximum possible size needed (1+2+65536+16) _and_ if they were always obtained via calls to calloc() or its functional equivalent, then there would never have been such a thing as the Heartbleed bug and this conversation would not now be taking place. Does anyone happen to have a copy of the complete original (unpatched) source code lying around? I have a sudden urge to look and see where exactly the buffer corresponding to s->s3->rrec.data is allocated, with an eye to trying to understand why on earth it was ever made shorter than 1+2+65536+16 bytes long. (Well, actually, it appears that these buffers could all have reasonably be allocated to the rather smaller fixed size of 2^14+16 if the OpenSSL authors had actually followed the RFC. See below.) Regards, rfg P.S. Public reports regarding this bug assert that an attacker can gulp down up to 64KB long chunks of one's private data at a time. I have no reason at present to disbelieve those assertions, however if those assertions are true, then that would seem to suggest that in addition to creating a rather awful bug, the implementors of OpenSSL may have also failed to perform range checking on the payload_length values provided within received HeartbeatRequest packets... range checking that is apparently *MANDITORY* in order to simply meet the requirements of the relevant RFC (6520): "The total length of a HeartbeatMessage MUST NOT exceed 2^14 or max_fragment_length when negotiated as defined in [RFC6066]." ... "If the payload_length of a received HeartbeatMessage is too large, the received HeartbeatMessage MUST be discarded silently. ^^^^ If the OpenSSL authors had simply bothered to implement the requirements of RFC6520, then it would appear that the worst case data leakage would have been on the order of 16KB(-3) per gulp... still quite an awful bug, but not quite as bad as the one currently making headlines.