When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities. To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important. -...
OpenMLS 0.6 released
Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release. +...
OpenMLS 0.6 released
Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release. New Storage Provider To make it easier to persist group state, the KeyStoreProvider was replaced with the more powerful StorageProvider trait for tracking the state of a group or a party. This includes keys, but also other group state like the ratchet tree and the group context. OpenMLS writes to the storage at the end of any successful operation. This means that if the provider is backed by some persistent memory, the entire long-lived state of OpenMLS is automatically persisted. ...
Post-Quantum OpenMLS
OpenMLS now offers security against harvest-now-decrypt-later (HNDL) quantum adversaries.
In #1546 we merged support for the X-Wing KEM draft, which is an early draft for securely combining elliptic-curve-based Diffie-Hellman with ML-KEM. In particular, OpenMLS now supports the ciphersuite MLS_256_XWING_CHACHA20POLY1305_SHA256_Ed25519 with ciphersuite 0x004D. There is no IANA code-point for this ciphersuite yet, such that interoperability may not be guaranteed. We work with other implementers towards interoperability of this ciphersuite.
diff --git a/index.xml b/index.xml
index 23b5313..c1a9ec3 100644
--- a/index.xml
+++ b/index.xml
@@ -1,4 +1,4 @@
- When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities. To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the In the context of MLS, consider what would happen if we didn’t do the check that validates the signature over This is a drastic example of course, and it’s unlikely one would forget to implement this particular check. However, MLS is a large complex protocol and there are a lot of these checks in the MLS RFC that need to be done by OpenMLS (we counted 50 so far). The good news is that the RFC lays them all out. The bad news is that they are somewhat scattered across the document and there is no good overview. In addition, the way the RFC abstracts away delivery and authentication also means that it is not always obvious whether a check would need to happen inside the client implementation (e.g. OpenMLS), the Delivery Service or the Authentication Service. This means that understanding whether a check has to be done inside or outside of OpenMLS is not always straightforward. And while in theory it is enough that all the checks are in the code, in practice it’s also important to test that all the checks are being performed, so they don’t accidentally get removed or circumvented in a refactor years later. We knew we needed some sort of list or database of checks. This raised two questions: What sort of data do we want to keep, and how do we structure it? What is the format of the list? Let’s look at the data first. The main information we want to capture are checks, and each check consists of an ID, a text quoted from and linking to the RFC text, and some way of referring to the code where the check is implemented and tested. We are still experimenting with that last part, but for now we have settled on keeping the modpath of the function we refer to, as well as a permalink to the specific part of the code. We also mention the check ID in the code, so that can also be searched for. Most validation checks belong to a group of checks that are performed together, and we would like to maintain that grouping, so each “check” is part of a “check set”. The check set also provides some context for the check. So a check set consists of another RFC quote (with link) and a list of checks. As for the formats, we wanted a uniform structure, and we want it to be relatively simple to update. And, maybe most importantly, we want to be able to look at and understand what we are missing. Let’s first look at what we thought didn’t work very well: The obvious third choice would be a JSON file that contains an array of check sets. We could then write a tool that generates an HTML file providing an overview over the checks from the JSON. However, this would mean everything is in a single large file, and modifying that by hand seems pretty error-prone. YAML might be a bit nicer to write, but is also error-prone. It would be nice if we had a language that was a bit like JSON, but nicer to write and with strong types, to catch errors early. I had heard of the Dhall language before and while it always sounded interesting, I never had use for it. It’s a small programming language that mostly seems to be intended for generating config files. The idea is that it enforces termination and handling of all possible inputs. This means it can’t hang or error out because the program doesn’t handle an edge case. This seemed like an interesting option, and the fact that one of the main features of Dhall is that it can easily produce a JSON representation of the contained data, it would be easy to pivot to a different format if Dhall would turn out to not work well for us. We followed a pretty boring structure: In one file we define the domain types (e.g. Let’s go back to the check we looked at earlier. The check is part of a section that describes what need to be checked when validating a commit. In our dashboard, we made that whole section a check set, and at the time of writing it looks like this: The check set starts with quotes from the RFC and links to the places in the RFC that the quotes come from. It is followed by a table of checks. Each check has an identifier for the check, if we want to reference it in text. We then have the text from the RFC and a link to the specific paragraph of the RFC that contains the text. In the rightmost column we have a link to a search for the check ID in the OpenMLS repository on Github, some notes as well as references to the implementation of the check and tests for the check (if available). Links into the code show modpath of the linked function but link to the permalink to the specific lines of code where a check is implemented or tested. The pilcrows (¶) link to the check set or check itself, to make it easier to link it elsewere. For example, the check set for commits contains check valn1203, which has a link to the RFC at exactly the right place, as well as links to the places where the check is implemented. We don’t have links to where we test that the check is done correctly, that’s why there are no test refs, and that’s also why the status of that check is Partial instead of Complete. The nice thing about having the data in a machine-readable format is that we can also do other things with it. For example, we generate a bookmarklet (a little snippet of JS that is stored in a bookmark) that when it is clicked while browsing the RFC, it highlights all the parts of the RFC that have already been captured in the database. This helps with searching the RFC for checks we missed. In the future, we could also generate a dashboard that has its focus on the checks that are not completely implemented or tested yet. Try it, it’s here. Overall, Dhall works pretty well for us. There are some warts, such as not-very-helpful syntax error messages, the linter sometimes removing comments as well as documentation sometimes being a bit confusing and spread across several places, but it was reasonably easy to set up something that works and does the job reliably. Another thing we haven’t completely figured out yet is how to best link into the code. Linking to source code lines at specific commits means we can link to specific lines, but also that links will quickly go out-of-date. Using Rust modpaths is more stable, in the sense that the path correctly identifies a piece of code across commits (unless you refactor). On the other hand, they are more granular (you can only reference functions) and there is no tooling for using them as hyperlinks. Also, it’s unclear how to deal with aliases and visibility. Because we were not sure what the right thing to do is here, we do both for now. On top of that, we added a link to search the source code for the ID of the check, to quickly find mentions in comments and function names. However, this requires being logged into Github and only works on the current main branch. But now, the real work starts: Double-checking that we captured all the checks that we need to do, and making sure that we actually do all the checks, and properly test them. And while all that is going on, we are getting a better understanding of what we really need and how we can improve the dashboard. We started adding missing checks and will continue doing so until all checks are implemented and tested. In future we will also prove that all required checks have been performed. Stay tuned for more on this soon. When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities. To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the In the context of MLS, consider what would happen if we didn’t do the check that validates the signature over This is a drastic example of course, and it’s unlikely one would forget to implement this particular check. However, MLS is a large complex protocol and there are a lot of these checks in the MLS RFC that need to be done by OpenMLS (we counted 50 so far). The good news is that the RFC lays them all out. The bad news is that they are somewhat scattered across the document and there is no good overview. In addition, the way the RFC abstracts away delivery and authentication also means that it is not always obvious whether a check would need to happen inside the client implementation (e.g. OpenMLS), the Delivery Service or the Authentication Service. This means that understanding whether a check has to be done inside or outside of OpenMLS is not always straightforward. And while in theory it is enough that all the checks are in the code, in practice it’s also important to test that all the checks are being performed, so they don’t accidentally get removed or circumvented in a refactor years later. We knew we needed some sort of list or database of checks. This raised two questions: What sort of data do we want to keep, and how do we structure it? What is the format of the list? Let’s look at the data first. The main information we want to capture are checks, and each check consists of an ID, a text quoted from and linking to the RFC text, and some way of referring to the code where the check is implemented and tested. We are still experimenting with that last part, but for now we have settled on keeping the modpath of the function we refer to, as well as a permalink to the specific part of the code. We also mention the check ID in the code, so that can also be searched for. Most validation checks belong to a group of checks that are performed together, and we would like to maintain that grouping, so each “check” is part of a “check set”. The check set also provides some context for the check. So a check set consists of another RFC quote (with link) and a list of checks. As for the formats, we wanted a uniform structure, and we want it to be relatively simple to update. And, maybe most importantly, we want to be able to look at and understand what we are missing. Let’s first look at what we thought didn’t work very well: The obvious third choice would be a JSON file that contains an array of check sets. We could then write a tool that generates an HTML file providing an overview over the checks from the JSON. However, this would mean everything is in a single large file, and modifying that by hand seems pretty error-prone. YAML might be a bit nicer to write, but is also error-prone. It would be nice if we had a language that was a bit like JSON, but nicer to write and with strong types, to catch errors early. I had heard of the Dhall language before and while it always sounded interesting, I never had use for it. It’s a small programming language that mostly seems to be intended for generating config files. The idea is that it enforces termination and handling of all possible inputs. This means it can’t hang or error out because the program doesn’t handle an edge case. This seemed like an interesting option, and the fact that one of the main features of Dhall is that it can easily produce a JSON representation of the contained data, it would be easy to pivot to a different format if Dhall would turn out to not work well for us. We followed a pretty boring structure: In one file we define the domain types (e.g. Let’s go back to the check we looked at earlier. The check is part of a section that describes what need to be checked when validating a commit. In our dashboard, we made that whole section a check set, and at the time of writing it looks like this: The check set starts with quotes from the RFC and links to the places in the RFC that the quotes come from. It is followed by a table of checks. Each check has an identifier for the check, if we want to reference it in text. We then have the text from the RFC and a link to the specific paragraph of the RFC that contains the text. In the rightmost column we have a link to a search for the check ID in the OpenMLS repository on Github, some notes as well as references to the implementation of the check and tests for the check (if available). Links into the code show modpath of the linked function but link to the permalink to the specific lines of code where a check is implemented or tested. The pilcrows (¶) link to the check set or check itself, to make it easier to link it elsewere. For example, the check set for commits contains check valn1203, which has a link to the RFC at exactly the right place, as well as links to the places where the check is implemented. We don’t have links to where we test that the check is done correctly, that’s why there are no test refs, and that’s also why the status of that check is Partial instead of Complete. The nice thing about having the data in a machine-readable format is that we can also do other things with it. For example, we generate a bookmarklet (a little snippet of JS that is stored in a bookmark) that when it is clicked while browsing the RFC, it highlights all the parts of the RFC that have already been captured in the database. This helps with searching the RFC for checks we missed. In the future, we could also generate a dashboard that has its focus on the checks that are not completely implemented or tested yet. Try it, it’s here. Overall, Dhall works pretty well for us. There are some warts, such as not-very-helpful syntax error messages, the linter sometimes removing comments as well as documentation sometimes being a bit confusing and spread across several places, but it was reasonably easy to set up something that works and does the job reliably. Another thing we haven’t completely figured out yet is how to best link into the code. Linking to source code lines at specific commits means we can link to specific lines, but also that links will quickly go out-of-date. Using Rust modpaths is more stable, in the sense that the path correctly identifies a piece of code across commits (unless you refactor). On the other hand, they are more granular (you can only reference functions) and there is no tooling for using them as hyperlinks. Also, it’s unclear how to deal with aliases and visibility. Because we were not sure what the right thing to do is here, we do both for now. On top of that, we added a link to search the source code for the ID of the check, to quickly find mentions in comments and function names. However, this requires being logged into Github and only works on the current main branch. But now, the real work starts: Double-checking that we captured all the checks that we need to do, and making sure that we actually do all the checks, and properly test them. And while all that is going on, we are getting a better understanding of what we really need and how we can improve the dashboard. We started adding missing checks and will continue doing so until all checks are implemented and tested. In future we will also prove that all required checks have been performed. Stay tuned for more on this soon. When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities.
To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.
-... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
+... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
New Storage Provider To make it easier to persist group state, the KeyStoreProvider was replaced with the more powerful StorageProvider trait for tracking the state of a group or a party. This includes keys, but also other group state like the ratchet tree and the group context. OpenMLS writes to the storage at the end of any successful operation. This means that if the provider is backed by some persistent memory, the entire long-lived state of OpenMLS is automatically persisted.
... OpenMLS now offers security against harvest-now-decrypt-later (HNDL) quantum adversaries.
In #1546 we merged support for the X-Wing KEM draft, which is an early draft for securely combining elliptic-curve-based Diffie-Hellman with ML-KEM. In particular, OpenMLS now supports the ciphersuite MLS_256_XWING_CHACHA20POLY1305_SHA256_Ed25519 with ciphersuite 0x004D. There is no IANA code-point for this ciphersuite yet, such that interoperability may not be guaranteed. We work with other implementers towards interoperability of this ciphersuite.
diff --git a/posts/index.xml b/posts/index.xml
index 56b42a1..3bcb4ec 100644
--- a/posts/index.xml
+++ b/posts/index.xml
@@ -1,4 +1,4 @@
- When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities.
To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.
-... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
+... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
New Storage Provider To make it easier to persist group state, the KeyStoreProvider was replaced with the more powerful StorageProvider trait for tracking the state of a group or a party. This includes keys, but also other group state like the ratchet tree and the group context. OpenMLS writes to the storage at the end of any successful operation. This means that if the provider is backed by some persistent memory, the entire long-lived state of OpenMLS is automatically persisted.
... OpenMLS now offers security against harvest-now-decrypt-later (HNDL) quantum adversaries.
In #1546 we merged support for the X-Wing KEM draft, which is an early draft for securely combining elliptic-curve-based Diffie-Hellman with ML-KEM. In particular, OpenMLS now supports the ciphersuite MLS_256_XWING_CHACHA20POLY1305_SHA256_Ed25519 with ciphersuite 0x004D. There is no IANA code-point for this ciphersuite yet, such that interoperability may not be guaranteed. We work with other implementers towards interoperability of this ciphersuite.
diff --git a/tags/mls/index.xml b/tags/mls/index.xml
index 03068bb..fc6fec2 100644
--- a/tags/mls/index.xml
+++ b/tags/mls/index.xml
@@ -1,4 +1,4 @@
- When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities.
To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.
-... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
+... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
New Storage Provider To make it easier to persist group state, the KeyStoreProvider was replaced with the more powerful StorageProvider trait for tracking the state of a group or a party. This includes keys, but also other group state like the ratchet tree and the group context. OpenMLS writes to the storage at the end of any successful operation. This means that if the provider is backed by some persistent memory, the entire long-lived state of OpenMLS is automatically persisted.
... OpenMLS now offers security against harvest-now-decrypt-later (HNDL) quantum adversaries.
In #1546 we merged support for the X-Wing KEM draft, which is an early draft for securely combining elliptic-curve-based Diffie-Hellman with ML-KEM. In particular, OpenMLS now supports the ciphersuite MLS_256_XWING_CHACHA20POLY1305_SHA256_Ed25519 with ciphersuite 0x004D. There is no IANA code-point for this ciphersuite yet, such that interoperability may not be guaranteed. We work with other implementers towards interoperability of this ciphersuite.
diff --git a/tags/openmls/index.xml b/tags/openmls/index.xml
index 9f42e26..d9f7de2 100644
--- a/tags/openmls/index.xml
+++ b/tags/openmls/index.xml
@@ -1,4 +1,4 @@
- When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities.
To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.
-... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
+... Today, we are releasing version 0.6 of OpenMLS. In this post we’ll go over the most significant changes since our last release.
New Storage Provider To make it easier to persist group state, the KeyStoreProvider was replaced with the more powerful StorageProvider trait for tracking the state of a group or a party. This includes keys, but also other group state like the ratchet tree and the group context. OpenMLS writes to the storage at the end of any successful operation. This means that if the provider is backed by some persistent memory, the entire long-lived state of OpenMLS is automatically persisted.
... Today, we are releasing OpenMLS v0.5. This release has been a while in the making and covers substantial changes since the last release. We are grateful for the support of the Sovereign Tech Fund towards this goal. These are some of the changes:
The implementation caught up with the latest changes in the protocol specification. The last version was roughly based on draft 12. Since then, the protocol has iteratively evolved all the way through draft 20. The library now implements the wire format of messages and mechanisms specified in RFC 9420. Extensive interoperability testing has been done between OpenMLS, Cisco’s MLS++, and another closed-source MLS protocol implementation. The goal of this exercise was to validate the last set of changes in the specification and ascertain that all implementations implemented the specification correctly. The next phase Until recently, the specification was a moving target and so was the implementation. Now that the specification is no longer subject to changes, the implementation can finally mature in terms of correctness, ease-of-use, and efficiency. We would like OpenMLS to be as useful as possible to those who consider end-to-end encryption with MLS. We are ready to evolve the library in the following areas:
diff --git a/tags/rfc9420/index.xml b/tags/rfc9420/index.xml
index 010cffc..ffd2b03 100644
--- a/tags/rfc9420/index.xml
+++ b/tags/rfc9420/index.xml
@@ -1,4 +1,4 @@
- When implementing cryptographic protocols, probably the most important thing is to not forget validating all inputs. Failing to do so can lead to inadvertant leakage of private information, state corruption, impersonation attacks… all kinds of vulnerabilities.
To give an example, you might remember the “goto fail” vulnerability, a bug in the TLS implementation used in iOS. Here, the verification function of signatures sent along with the ServerKeyExchange message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.
-...Taking Stock of Validation Checks
ServerKeyExchange
message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.FramedContent
objects, which wrap the relevant parts of MLS messages to provide authentication. An attacker could change the sender field of FramedContent
to a different member and we wouldn’t notice, because we don’t get an error when trying to validate the signature with that other member’s public key.The Data We Need
The Format We Keep It In
Check
, CheckSet
, ), in another file we generate HTML for the domain types. We also have a folder that contains one check set per file and a file that bundles all the check sets into a single place that can be processed. These all behave a bit like libraries. We then have a file that imports the check sets and the code generating the HTML and returns a string containing the dashboard, which looks like this.An example
Learnings
Next Steps
Taking Stock of Validation Checks
ServerKeyExchange
message, which ties the server identity to the transcript and ephemeral key material. Due to a hard-to-spot slipup, it returned success early and never really checked the signature, which would allow an attacker to man-in-the-middle the connection. While in this case they didn’t just forget to do the check, it does demonstrate why these checks are important.FramedContent
objects, which wrap the relevant parts of MLS messages to provide authentication. An attacker could change the sender field of FramedContent
to a different member and we wouldn’t notice, because we don’t get an error when trying to validate the signature with that other member’s public key.The Data We Need
The Format We Keep It In
Check
, CheckSet
, ), in another file we generate HTML for the domain types. We also have a folder that contains one check set per file and a file that bundles all the check sets into a single place that can be processed. These all behave a bit like libraries. We then have a file that imports the check sets and the code generating the HTML and returns a string containing the dashboard, which looks like this.An example
Learnings
Next Steps
Posts
Taking Stock of Validation Checks
OpenMLS 0.6 released
OpenMLS 0.6 released
Post-Quantum OpenMLS
Mls
Taking Stock of Validation Checks
OpenMLS 0.6 released
OpenMLS 0.6 released
Post-Quantum OpenMLS
Openmls
Taking Stock of Validation Checks
OpenMLS 0.6 released
OpenMLS 0.6 released
Post-Quantum OpenMLS
Rfc9420
Taking Stock of Validation Checks
OpenMLS 0.6 released
OpenMLS 0.6 released
OpenMLS 0.5 released
Validation
Taking Stock of Validation Checks