jiebi/CodeConvo huggingface dataset:
Proposal to clarify "stream fragmentation". Suggested by Issue .
I don’t understand what section 21.6 is about… the title seems to suggests it is about IP Fragmentation and Reassembly Attacks, but elsewhere the spec already prohibits IP Fragmentation in section 14? And I have seen no encouragement to do any form of network-layer fragmentation - so I don’t understand a security consideration in this topic. Is this therefiore some other thing? It may about something different where a sender originates data with “holes” of missing packet to try and exercise the server? or soemthing? What is this?
Hi NAME 21.6 is titled "Stream Fragmentation and Reassembly Attacks". It refers to streams, not IP packets. The attack involves sending stream frames with holes such as and some receivers might allocate the entire stream receive buffer between 0 and 10000001. I found the section pretty clear, but we should make it clear to everyone - could you perhaps suggest text that would make it clearer?
OK. I see. I can try a PR, if I can find words that avoid "fragment": Is this close enough to start: /An adversarial sender might intentionally omit to send portions of the stream data causing the receiver to commit resources for the omitted data, this could cause a disproportionate receive buffer memory commitment and/or creation of a large and inefficient data structure.
Do we really need to avoid the term "fragment"? It's not the only overloaded networking term in the spec. Perhaps adding a "Note that stream fragmentation is unrelated to IP fragmentation" could suffice?
I don't think this clarification is necessary. The context makes it clear what fragmentation this is, and talking about IP fragmentation only leads to confuse the reader. (I like the first part of your PR though, as I've noted on my review of it.)
` 1) Is this a normative statement? 2) I think the next paragraph says that maybe it’s not an asymmetric key, and anyways, keys are out of scope for RATS Arch
In a layered device architecture the previous layer "provisions" the next layer. Hence, it isn't possible for the 'manufacturer' entity to do that. I don't know why a section on "Verifier" is going into so much detail about the Attester.
The idea of a session is important, both because it is used in the API document, and because it helps to tie everything together. Define it in the terminology.
This is a first stab at defining the session. I suspect we may need to iterate on it once or twice. Let me know if you think it deserves its own section on top of the terminology.
Thanks for doing this! Here’s a suggested alternate way to explain this. Feel free to modify as desired. Captive Portal Session: Also referred to simply as the “session”, a Captive Portal Session is the association for a particular User Equipment that starts when it interacts with the Captive Portal and gains open access to the network, and ends when the User Equipment moves back into the original captive state. The Captive Network maintains the state of each active Session, and can limit Sessions based on a length of time or a number of bytes used. The Session is associated with a particular User Equipment using the User Equipment's identifier (see ).
Your phrasing is better. It manages to work in the session limits while keeping it about the same lenght. I've taken it almost verbatim. NAME Do you have any input on this topic?
From Ben's review of the API document, we should define "session" formally in the architecture. The architecture doc mentions it in passing once already. The API doc uses the term session much more.
I noticed this in the Transport Draft (ID-30): Is this intentional? Should an invalid transport parameter result in a frame encoding error?
I believe this aligns with our principles that a framing error which can be detected with no connection context is a FRAMEENCODINGERROR. Is there another error you'd suggest?
My concern is that transport parameter values have nothing to do with framing and using FRAMEENCODINGERROR is therefore misleading.
We only ever applied this principle to frames though, so I'm not sure we can use it as a precedent here. The name is indeed confusing, as it's FRAMEENCODINGERROR and not FRAMINGERROR or ENCODINGERROR.
I always rationalized this as "the encoded content of the CRYPTO frame is erroneous".
Well, if we've been through this before, I won't insist -- it's just something that jumped out at me.
That's even more confusing. The CRYPTO frame itself is totally fine. I'd be in favor of changing it to a TRANSPORTPARAMETERERROR.
Interim 2022-12-08: Distinguish "time-invalid" from "invalid" There is a slightly more general issue: When catching up, there might be messages sent by members whose credentials were valid when the message was sent, but have since expired Recommend accepting messages from members with time-invalid credentials when catching up
I think a note on consistency would work a little better in the architecture document, especially because it applies in the general case as well as the time-varying case. I filed URL
Latest change uses "expired" to refer generically to all time based reasons for a transition. (So, excluding , as NAME suggests.)
We ran into this case, which does not seem to have a defined solution within the RFC and I'm wondering if this ambiguity should be resolved at the RFC level, or be left up to the application. Existing group with Alice, and Bob. Bob had a valid certificate upon being added to the group by Alice. Bob's certificate expires . Alice does a commit to add Charlie to the group. Bob accepts the valid commit to add Charlie. Charlie follows 8.3 and validates the tree. In this process if certificate expiration is enforced, then Charlie would drop the Welcome, which would not be optimal. Solution 1: Leave this behavior up to the application, consider it part of the AS. Solution 2: Add an explicit mention that credentials that expire should be considered valid after expiration once they are a member of the group. Solution 3: A committer MUST validate that all existing credentials in the tree are still considered valid at the time a commit is made. If an existing credential is no longer considered valid, then the resulting commit MUST contain a Remove proposal for the leaf containing that credential.
Of course it would be better to have the same credential validation algorithm, but at the protocol level, there is no reason to constrain all clients to that, applications can enforce a consistent policy across clients. So, in my mind this is not symmetric between senders and receivers and solutions 1 and 3 are not incompatible, however 2 is not acceptable IMO.
I would suggest the following: Alice MUST verify that she considers all credentials valid before adding Charlie and act if it is not the case (Solution 3) Charlie MUST check all the credentials upon joining and act according to its authentication policy* Charlie MUST NOT send any application message before she considers all credentials valid
Are you suggesting that it should not be a requirement that each member of the group has the same validation algorithm? That would create forks in any case that individuals disagree on a particular credential's validity. We can of course punt to the application, but I feel like that should at least be cautioned against?
I don't quite see how the validation algorithms are different. They are the same, just executed at different points in time. Or am I missing something here? In any case it would be unfortunate if Charlie couldn't send any messages until someone committed to their proposal. So I would propose to change point 2 of the algorithm suggested by NAME to the following: Charlie MUST check all the credentials upon joining. If any group members have expired credentials, Charlie MUST issue a commit to remove the affected members.
I am saying that it is not a requirement. Most applications will want to use the same algorithm, but the protocol doesn't need to make that mandatory, it is just a convenience for applications. The protocol is designed so that each client can make its own choice. It would not create forks, as for example the case Alice decides to remove Bob, Bob is removed for everyone. I would be - ok - with the change proposed by Konrad but we need to be aware that this is a restriction on what clients can decide with respect to authentication (especially in a context where there is no AS).
I think it's also important to remember that there may be a delay between when a user is sent a Welcome and when they process it. So when a user processes a Welcome, the first epoch they see after joining may be quite old and have expired credentials for that reason, and this epoch may not even be the most recent epoch anymore. So I would lean towards solution 2 actually, of "members that are joining a group just need to ignore expired credentials." And if the application wants to have a policy of not sending new messages to a group if there are expired credentials present, then that's fine but not something we need to require in the spec.
Edit: Or maybe we do want to specify that, but I'd be clear that it's a check done before sending new messages, not part of processing the Welcome.
Although I started the dialog here around certificates and expiration, I think maybe it is useful to ignore the idea of "expired" credentials for now, because I agree with the comment by NAME that we should try to avoid being opinionated in that regard. I think what I am trying to get across is that regardless of what credential system you use that the protocol can only operate without forks if the validation of that credential is consistent across all members while also taking into account the asynchronous nature of the protocol. If each member of the group has the same state for epoch N, they should all independently determine that new credentials presented as part of a commit are valid or invalid regardless of when they process that commit. I'm viewing a credential being invalid as a trigger for rejecting a commit, which maybe in itself is a bias. Not sure if the above belongs in the protocol, the AS definition, or no where at all :-). If everyone thinks this is too restrictive of a statement I'm fine with that. Maybe a better solution to this issue is that there could be a separately defined standard way of dealing with certificates within MLS that can be more opinionated than the base protocol and introduce concepts discussed above like MUST remove of expired certs on commit, use an external packet timestamp for consistent expiration checking on the receive side, etc. I think a lot of applications would benefit from that and NAME NAME and I have been doing a lot of experimentation in that area.
After a couple long chats with NAME and NAME here's where I stand on this. A guiding thought I have is this: IMO creds aren't just for getting in to a group. They should also be necessary for continued participation. After all MLS is designed for sessions that can last years. That means, I'm uneasy with an MLS design that allows me to join a group (epoch even) where someone has an invalid (e.g. expired) cred. Worse yet, I don't want MLS to let me send application messages to users with invalid creds at the time of my sending.
With that in mind, how about this approach which tries to leave as much freedom to an app/AS while still giving guidance to an app/AS that wants to ensure valid creds are needed for ongoing participation in a group and, optionally, that forks are being avoided as much as possible. MLS clients MUST validate the creds at all leaves in a ratchet tree (via the AS) in the following cases: a. Sending a commit (validation done on new epoch's tree after applying commit). b. Receiving a commit (validation done on new epoch's tree after applying commit). c. When joining a group. d. When client wants to send an application message. Based on this MLS now gives 3 guarantees. Call an application/AS "consistent" if it ensures that for any given epoch and cred in its ratchet tree, the result of any client validating the cred is the same (i.e. regardless of the time the validation is performed and which rule of a. b. or c. triggered it). (Edit: Just to further clarify "consistency" doesnt mean validating the same cred but when taken from different ratchet trees should have the same result. It only concerns validations pertaining to the same epoch but performed by different clients at different times.) 1) Regardless of the app/AS's consistency and any insider attacks, clients only ever join epochs in which all members have valid creds. 2) Regardless of the app/AS's consistency and any insider attacks, clients will never send application messages to receiver with invalid creds (at the time of sending). 3) If the app/AS is consistent, all parties follow the protocol and all packets are delivered by the DS then no forks will occur. My justification for this approach is that it strikes the following balance: On the one hand, we now give guidance to app/AS devs for how they can enforce (1-3) if thats what they want. On the other hand, we don't actually tie an app/AS's hands at all (e.g. compared to mandating almost no checks ever). That's because MLS says nothing about how cred validation should be implemented. Hard-coding always returning true is an MLS spec compliant AS. So if an app/AS doesn't want the constraints imposed by the above rules it is still free to hard-code those validations as returning true; i.e.
it can skip the checks if it really needs to. In summary: the idea is basically to tell app/AS devs when/which are the right checks to perform to get good security & availability but also to leave it up to them to make those checks meaningful. Finally, regarding "consistency": in my mind creds are validated relative to a context (e.g. a time-stamp for checking expiration, a root CA cert, a blockchain or even particular block for checking wallets and/or balances, etc.) One way to get consistency is for the app/AS to ensure that all clients use the same context when checking the creds in a ratchet tree regardless of when they perform their checks.
In my mind, applications are only ever in one of two states: A.) I'm reading backlogged messages, or B.) I've read all the messages and I'm waiting for new ones. When you're in state B, you can send messages and also check time-related things. When you're in state A, you have no idea when the messages you're reading were truly sent. We don't currently provide any way to communicate a "context" against which time-related things should be validated in state B. So I don't see how we can implement b or c from this list?
Implementing b. and c. in some spec compliant way is actually trivial because the spec doesnt require "consistency" (in the sense that I defined that term in my previous post.) The only thing the spec says about consistency is that if you want guarantee (3.) then you need consistent cred validation. So e.g. always returning true when validating in cases b. and c. while doing something more interesting for cases (a.) would be fine; i.e. spec compliant. You just wouldn't necessarily get guarantee (3.) is all. But I figure what you meant is how to implement (a.) b. and c. to be consistent, right? And that'd be a good question that any app trying to avoid forks would have to think about. (Notice, the RFC already creates this concern for such apps with out my proposed changes because to avoid forks now you already need commit sender and receivers to agree on their validation.)
In our opinion, we landed on leaving it up to the app/AS how it guarantees consistent validations because we think there are a bunch of different but reasonable ways this could be done. Yet, which of those is best (even among just the couple we could come with on the fly) depends on things like the app's security assumptions, communication models and access to third-party services, not to mention the details of how the AS works. To start off with, it wasn't even totally clear to us that the "context"-based syntax really applies to all reasonable AS designs. (Thats how we ended up on the notion of "consistency" as that is the more abstract and minimal guarantee we really needed to avoid forks. Context is just one way we thought of to get consistency.) But say the AS does conform to "context"-based syntax. Maybe the app/AS ensure consistency by only ensuring that the (possibly different!) contexts being used by clients still produce the same result. Further, even if we are more opinionated and assume an app/AS will ensure an identical context is used in all validation cases this still leaves room for many variations. Who chooses the context used for a given epoch? Maybe the commitor? Maybe the AS? Maybe the DS (which we already have to trust it to avoid forks)? Maybe a group-context extension? Also, how is the context distributed? Out-of band? By the AS? By the DS along with commit/welcome packets? Along with group contexts? Each made sense to us in the right setting... One thing we toyed with for a while was the requirement that the commitor authenticates the particular context C they used when creating a commit packet (e.g. by using C as associated data or a PSK or something). But, not only is that already pretty opinionated about how consistency should be enforced, it also wasn't clear to us what the actual point is. TBH at first I was for it at first out of instinct (and ignoring the being opinionated part for the moment), but NAME did a good job of convincing me that I couldn't actually justify it beyond "it feels right". What kind of, otherwise not possible, attack is this trying to defend against?
In the end, the point is there were enough plausible but diverging options for how to get consistency that we didnt feel comfortable enforcing anything that constrained an app/AS's options. But it's not due to lack of ways to solve for consistency. We just didn't want to be opinionated in a way we couldn't STRONGLY justify.
Thanks NAME I'm not sure I agree with checking every time I send an application message as TLS sets a precedent for not checking in that case. I do agree though that I view each epoch as a session renegotiation of sorts, which means that you reevaluate if credentials you previously thought were valid are still valid according to whatever rules that are in place. I believe this conversation winds up in a place where its a very small statement in the main doc that explains how to avoid forks, and then an entirely separate document for each credential type (starting with certificates) that aims to set guidelines on how one could achieve various goals like not allowing expired certs etc. Im all for helping write that document as Wickr will be using the x509 system in production quite a bit.
Solution 4: Bob has to do an UpdatePath before his Credential expires with a LeafNode with a valid Credential (certificate). If he doesn't, the other members should Remove him from the group. Same goes if Bob's Credential is revoked.
NAME I think the core of the discussion at this point is more around the fact that the base protocol does not have any concept of "expiration" of credentials, so their behavior is undefined. Either we put an opinionated statement around it in the core protocol, or just punt to applications / another RFC. Thoughts on that?
Hi NAME , My opinion is that whatever credentials you have in an MLS group should be valid (including not expired, not revoked, not too early, etc.). Therefore it would logically follow: It is the responsibility of each member to make sure their LeafNode credentials are valid and consistent with the group policy at all times. Any member of the group that detects another member is out of policy or invalid can remove the offending member. To the extent possible a DS that detects that a member is out of compliance with group policy or no longer has valid credentials, can try to remove the member (ex: via an external proposal). The definition of "valid" could be done per-credential type or per profile.
Side note: under the general rubric of "validity changes over time", revocation is also an issue! Overall, my thinking aligns with what NAME says here. Saying that the credentials presented by group members should be valid at all times is a concise, clear standard. It is arguably implied by the current requirement to validate credentials on joining (if you also assume that the group should be joinable at any time). The more difficult question is how it is implemented in practical reality. I don't think we can really write hard requirements around this. The only remediation is Remove, and we don't have other situations where we say a client MUST send a specific proposal. In part because this might conflict with application-level policies about who is allowed to send Proposals/Commits. And it seems like there are valid situations where availability might trump authenticity (cf. browsers' click-through on expired certs). Overall, this seems like more of an operational question than a core protocol question here. In terms of how to reflect all this in documents: The details of how to manage credential freshness seem better suited for an implementation guidance document. (I believe NAME is gathering ideas for one?) In the MLS protocol spec, we could add some high-level guidance, something like the following: I think that would fit well either in the Credentials section (between "Credential Validation" and "Uniquely Idenitfying Clients") or in the security considerations.
We could use the sender_generation field of the MLS message to signal what was the global app generation of the sender. Functionally, this allows receivers to know if they received all previous application messages from the sender. In the current design, if S sent M0, M1, M2 you can know if you missed M1 when receiving M2, but you cannot know if you missed M2. There are many ways of doing this: global sender counter, counter between two operations of the sender...
We seemed in agreement at the interim because it prevents the application message suppression attacks
Looks great thanks NAME I like the separate treatment of expired vs. revoked. Looks good to me now!