Draft: draft-ietf-mls-protocol

Commentary: Depends on Conflicts with The diff here is messy because it includes . The biggest change is the extended example , for which you can just scroll to the bottom . 
 Regarding the Tree Hash the parentnode in the tree hash which is supposed to be computed from the leaves , makes the definition appear circular to a new reader . Since the situation when you have blank nodes in the middle of a tree but not at the root is a rather complicated , the situation when you could calculate a tree hash using the parentnode is non - obvious . the description of Tree Hash the document says that the ParentNode object is optional " depending on whether the node is blank or not . " This is n't clear specification language . Saying the parentnode object is present if the node is blank or present if the node is not blank would be clear . if the parent node is also blank ? What if the root is blank ? think an example with and without blank nodes would be appropriate . the reason why the parentnode is included will help the reader establish a better mental model . Regarding the Parent Hash I still find this section super confusing . A few points a tree hash ( siblingtreehash ) inside the parent hash is non - obvious . There should be some explanation about what property this is providing and that it is a tree hash and not a parent hash . ( Honestly it was the third time I read the section that I realized that it was really the tree hash and not the parent hash of the sibling . ) P , V , and S for Parent , target node , and sibling node is introduced here and never used anywhere else in the document . P for parent and S for sibling make sense . I ca n't tell what  is supposed to stand for , and it unfortunately could cause people to confuse the < Vvector notation used throughout , but shortly after introducing V for the target node . I propose using " N " for node or " X " instead . is one reference to the filtered direct path of U. Perhaps this is V , or a child of V ? calculations are sufficiently complicated that I think this warrants a complete , non - trivial , worked example ( possibly in an appendix ) . At some point we should consider providing test vectors in a future document , and this would be an ideal candidate . 
 Regarding the Tree Hash To be clear , the that is included in the tree hash is the node whose subtree is being hashed . The tree hash does n't include only the leaves , it includes all the nodes in the tree . If you mean , then yes , I agree the connection is a little subtle . I 've tried to explain this a little better . Updated this to be clear that the ParentNode is omitted if and only if the node is blank . Not clear what situation you mean here . I think the specific computations are pretty clearly specified for these cases . Something like this was in : I extended the example and put it in an appendix . Assuming you mean here , hopefully this is addressed by the above notes . Added a note to clarify that this is the tree hash and why . Changed to " D " for " direct path " , and explained the semantics . Actually it 's the leaf , which is now called " L " . I think the example linked above does a pretty good job . Feedback obviously welcome . Agreed that a test vectors document will be a useful follow - on . 
 This is a huge improvement . While I still prefer " path hash " to " parent hash " , the new language in this PR is clear and I think will be straightforward for new implementers to read .
Paragraph (version A):
A hash of certain information about the node's parent, as of the
last time the node was changed (see parent-hash).
Paragraph (version B):
A hash of certain information about the node's parent, as of the
last time the node was changed (see parent-hashes).
Paragraph (version A):
The "encryption_key" field contains an HPKE public key whose private
key is held only by the members at the leaves among its descendants.
The "parent_hash" field contains a hash of this node's parent node,
as described in parent-hash.  The "unmerged_leaves" field lists the
leaves under this parent node that are unmerged, according to their
indices among all the leaves in the tree.  The entries in the
"unmerged_leaves" vector MUST be sorted in increasing order.
Paragraph (version B):
The "encryption_key" field contains an HPKE public key whose private
key is held only by the members at the leaves among its descendants.
The "parent_hash" field contains a hash of this node's parent node,
as described in parent-hashes.  The "unmerged_leaves" field lists the
leaves under this parent node that are unmerged, according to their
indices among all the leaves in the tree.  The entries in the
"unmerged_leaves" vector MUST be sorted in increasing order.
Paragraph (version A):
In the case where the leaf node was inserted into the tree via a
Commit message, the "parent_hash" field contains the parent hash for
this leaf node (see parent-hash).
Paragraph (version B):
In the case where the leaf node was inserted into the tree via a
Commit message, the "parent_hash" field contains the parent hash for
this leaf node (see parent-hashes).
Paragraph (version A):
To allow group members to verify that they agree on the public
cryptographic state of the group, this section defines a scheme for
generating a hash value (called the "tree hash") that represents the
contents of the group's ratchet tree and the members' leaf nodes.
Paragraph (version B):
MLS hashes the contents of the tree in two ways to authenticate
different properties of the tree.  This section defines _tree
hashes_, and _parent hashes_ are defined in parent-hashes.
Paragraph (version B):
Each node in a ratchet tree has a tree hash that summarizes the
subtree below that node.  The tree hash of the root is used in the
GroupContext to confirm that the group agrees on the whole tree.
Tree hashes are computed recursively from the leaves up to the root.
Paragraph (version A):
The tree hash of an individual node is the hash of the node's
"TreeHashInput" object, which may contain either a
"LeafNodeHashInput" or a "ParentNodeHashInput" depending on the type
of node.  "LeafNodeHashInput" objects contain the "leaf_index" and
the "LeafNode" (if any).  "ParentNodeHashInput" objects contain the
"ParentNode" (if any) and the tree hash of the node's left and right
children.
Paragraph (version B):
The tree hash of an individual node is the hash of the node's
"TreeHashInput" object, which may contain either a
"LeafNodeHashInput" or a "ParentNodeHashInput" depending on the type
of node.  "LeafNodeHashInput" objects contain the "leaf_index" and
the "LeafNode" (if any).  "ParentNodeHashInput" objects contain the
"ParentNode" (if any) and the tree hash of the node's left and right
children.  For both parent and leaf nodes, the optional node value
MUST be absent if the node is blank and present if the node contains
a value.
Paragraph (version A):
The "parent_hash" field in ratchet tree nodes carries information to
authenticate the information in the ratchet tree.  Parent hashes
chain together so that the signature on a leaf node, by covering the
leaf node's parent hash, indirectly includes information about the
structure of the tree at the time the leaf node was last updated.
Paragraph (version A):
Consider a ratchet tree with a non-blank parent node P and children V
and S.
Paragraph (version A):
The parent hash of P changes whenever an "UpdatePath" object is
applied to the ratchet tree along a path from a leaf U traversing
node V (and hence also P).  The new "Parent hash of P (with copath
child S)" is obtained by hashing P's "ParentHashInput" struct.
Paragraph (version A):
The field "encryption_key" contains the HPKE public key of P.  If P
is the root, then the "parent_hash" field is set to a zero-length
octet string.  Otherwise, "parent_hash" is the Parent Hash of the
next node after P on the filtered direct path of U.  This way, P's
Parent Hash fixes the new HPKE public key of each node V on the path
from P to the root.  Note that the path from P to the root may
contain some blank nodes that are not fixed by P's Parent Hash.
However, for each node that has an HPKE key, this key is fixed by P's
Parent Hash.
Paragraph (version B):
While tree hashes summarize the state of a tree at point in time,
parent hashes capture information about how keys in the tree were
populated.
Paragraph (version B):
When a client sends a commit to change a group, it can include an
UpdatePath to assign new keys to the nodes along its filtered direct
path.  When a client computes an UpdatePath (as defined in
synchronizing-views-of-the-tree), it computes and signs a parent hash
that summarizes the state of the tree after the UpdatePath has been
applied.  These summaries are constructed in a chain from the root to
the member's leaf so that the part of the chain closer to the root
can be overwritten as nodes set in one UpdatePath are reset by a
later UpdatePath.
Paragraph (version B):
As a result, the signature over the parent hash in each member's leaf
effectively signs the subtree of the tree that hasn't been changed
since that leaf was last changed in an UpdatePath.  A new member
joining the group uses these parent hashes to verify that the parent
nodes in the tree were set by members of the group, not chosen by an
external attacker.  For an example of how this works, see ph-
evolution.
Paragraph (version B):
The parent hash of P changes whenever an "UpdatePath" object is
applied to the ratchet tree along a path from a leaf L traversing
node D (and hence also P).  The new "Parent hash of P (with copath
child S)" is obtained by hashing P's "ParentHashInput" struct.
Paragraph (version B):
The field "encryption_key" contains the HPKE public key of P.  If P
is the root, then the "parent_hash" field is set to a zero-length
octet string.  Otherwise, "parent_hash" is the Parent Hash of the
next node after P on the filtered direct path of the leaf L.  This
way, P's Parent Hash fixes the new HPKE public key of each non-blank
node on the path from P to the root.  Note that the path from P to
the root may contain some blank nodes that are not fixed by P's
Parent Hash.  However, for each node that has an HPKE key, this key
is fixed by P's Parent Hash.
Paragraph (version B):
Note that "original_sibling_tree_hash" is the tree hash of S, not the
parent hash.  The "parent_hash" field in ParentHashInput captures
information about the nodes above P. the "original_sibling_tree_hash"
captures information about the subtree under S that is not being
updated (and thus the subtree to which a path secret for P would be
encrypted according to synchronizing-views-of-the-tree).
Paragraph (version A):
If, on the other hand, V is the leaf U and its LeafNode has
"leaf_node_source" set to "commit", then the Parent Hash of P (with
V's sibling as copath child) is stored in the "parent_hash" field.
This is true in particular of the LeafNode object sent in the
"leaf_node" field of an UpdatePath.  The signature of such a LeafNode
thus also attests to which keys the group member introduced into the
ratchet tree and to whom the corresponding secret keys were sent.
This helps prevent malicious insiders from constructing artificial
ratchet trees with a node V whose HPKE secret key is known to the
insider yet where the insider isn't assigned a leaf in the subtree
rooted at V.  Indeed, such a ratchet tree would violate the tree
invariant.
Paragraph (version A):
The "parent_hash" field of U is equal to the parent hash of P with
copath child S, where S is the child of P that is not on the path
from U to P.
Paragraph (version B):
In ParentNode objects and LeafNode objects with "leaf_node_source"
set to "commit", the value of the "parent_hash" field is the parent
hash of the next non-blank parent node above the node in question
(the next node in the filtered direct path).  Using the node labels
in parent-hash-inputs, the "parent_hash" field of D is equal to the
parent hash of P with copath child S.  This is the case even when the
node D is a leaf node.
Paragraph (version B):
The "parent_hash" field of a LeafNode is signed by the member.  The
signature of such a LeafNode thus also attests to which keys the
group member introduced into the ratchet tree and to whom the
corresponding secret keys were sent.  This prevents malicious
insiders from constructing artificial ratchet trees with a node D
whose HPKE secret key is known to the insider yet where the insider
isn't assigned a leaf in the subtree rooted at D.  Indeed, such a
ratchet tree would violate the tree invariant.
Paragraph (version B):
The "parent_hash" field of D is equal to the parent hash of P with
copath child S, where S is the child of P that is not on the path
from D to P.
Paragraph (version A):
Since these chains collectively cover all non-blank parent nodes in
the tree, the tree is parent-hash valid.
Paragraph (version A):
Note that this tree, though valid, contains invalid parent-hash
links.  If a client were checking parent hashes top-down from X, for
example, they would find that Z has an invalid parent hash relative
to X, but that U has valid parent hash.  Likewise, if the client were
checking bottom-up, they would find that the chain from F ends in an
invalid link from Y to Z.  These invalid links are the natural result
of multiple clients having committed.