Empty subtrees are invalid
Match draft-davidben-tls-merkle-tree-certs in saying empty subtrees are
invalid. I looked briefly at whether maybe the spec was wrong, but I
think we actually want these to be invalid?
Narrowly, there's a bug in EvaluateMerkleSubtreeConsistencyProof(). If
called with n = 0, subtree = {0, 0}, the current definition will pass
the precondition checks and go on to underflow `sn = subtree.end - 1`
and `tn = n - 1`. The spec's formulation does not have this problem.
Fortunately, this bug has no practical impact because, although we
implemented the more complex routine, we really only care about
EvaluateMerkleSubtreeInclusionProof. That function's subtree.Contains
check implicitly rejects empty subtrees. Though it is less obvious than
if we had implemented EvaluateMerkleSubtreeInclusionProof directly.
More broadly, empty subtrees seem to be weird. An empty subtree can
never be used in a subtree inclusion proof. In principle, one could make
a consistency proof between an empty subtree and a big tree, but the
current recursive definition won't actually work. If the subtree is, say
[5, 5), we'll actually unzip the tree around 5, if not cause further
mishaps. That unzipping won't work for verifying the proof anyway,
because at no point will you construct the HASH("") edge case.
In reality, a subtree consistency proof for the empty subtree should
always be the empty string, and the verification procedure is "check
that the subtree was the empty hash". But then that's also strange
because now the subtree consistency proof cannot actually construct the
bigger tree. So perhaps the consistency proof is a copy of the bigger
tree hash, just for the sake of it? But all that is still just an edge
case everywhere.
For comparison, RFC 9162 and RFC 6962's consistency proof definition
requires 0 < m < n, which similarly forbids the empty tree. As far as I
can tell, the MTH({}) = HASH() base case just never comes up.
Given that, and that the tests pass just fine, it seems subtrees should
just always be non-empty.
Change-Id: Ic0d39002a41a4d98b8df5d76cdfa7376a29be4d7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/85947
Commit-Queue: Nick Harper <nharper@chromium.org>
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Nick Harper <nharper@chromium.org>
BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.
Programs ship their own copies of BoringSSL when they use it and we update everything as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you.
BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily.
Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the NDK) and a number of other apps/programs.
Project links:
To file a security issue, use the Chromium process and mention in the report this is for BoringSSL. You can ignore the parts of the process that are specific to Chromium/Chrome.
There are other files in this directory which might be helpful: