Skip to main content

RFC 9420 Compliance Checklist - MLS Implementation

Overview

Comprehensive RFC 9420 compliance verification checklist for the MLS protocol implementation.

Overall Compliance: 65% (Core protocol compliant, security requirements need work)


Protocol Compliance

Section 4: Ciphersuites

RequirementStatusNotes
Support at least one ciphersuite✅ COMPLIANTMLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
Negotiate ciphersuite during init✅ COMPLIANTLine 91-95: getCiphersuiteFromName
Use ciphersuite ID 1 (mandatory)✅ COMPLIANTStandard X25519 suite
X25519 for KEM✅ COMPLIANTvia ts-mls
AES-128-GCM for AEAD✅ COMPLIANTvia ts-mls
SHA-256 for Hash✅ COMPLIANTvia ts-mls
HKDF-SHA256 for KDF✅ COMPLIANTvia ts-mls
Ed25519 for signatures✅ COMPLIANTvia ts-mls

Ciphersuite Compliance:100%


Section 5: Key Packages

RequirementStatusNotes
Generate key packages✅ COMPLIANTLine 115-140
Include protocol version✅ COMPLIANTts-mls handles
Include ciphersuite✅ COMPLIANTPassed to generateKeyPackage
Include init_key✅ COMPLIANTX25519 public key
Include leaf_node✅ COMPLIANTWith credential
Include extensions✅ COMPLIANTEmpty array allowed
Sign key package✅ COMPLIANTEd25519 signature
Validate lifetime❌ NON-COMPLIANTNo lifetime validation
Verify signature on receipt⚠️ PARTIALts-mls verifies, app doesn't

Key Package Compliance: 🟡 78% (7/9)


Section 6: Message Framing

RequirementStatusNotes
PrivateMessage format✅ COMPLIANTLines 376-380
PublicMessage format✅ COMPLIANTLines 599-603
Proper wireformat field✅ COMPLIANTLine 379, 602
Version field✅ COMPLIANT'mls10'
Encode/decode correctly✅ COMPLIANTencodeMlsMessage/decode
Handle both message types✅ COMPLIANTLines 529-553

Message Framing Compliance:100%


Section 7: Group Creation

RequirementStatusNotes
Initialize group at epoch 0✅ COMPLIANTLine 165-171
Create ratchet tree✅ COMPLIANTts-mls createGroup
Include creator's leaf✅ COMPLIANTUses keyPackage
Generate group context✅ COMPLIANTts-mls handles
Compute tree hash✅ COMPLIANTts-mls computes

Group Creation Compliance:100%


Section 8: Group Evolution

8.1 Add Members

RequirementStatusNotes
Create Add proposals✅ COMPLIANTLines 207-212
Include key packages✅ COMPLIANTFrom addMembers param
Create commit✅ COMPLIANTLine 215-218
Generate Welcome✅ COMPLIANTLine 223-225
Update epoch✅ COMPLIANTAutomatic in ts-mls
Send Welcome to new members⚠️ DOCUMENTEDApp responsibility
Send commit to existing members⚠️ DOCUMENTEDLines 238-249 doc
Validate member limit❌ NON-COMPLIANTNo limit check

Add Members Compliance: 🟡 75% (6/8)

8.2 Remove Members

RequirementStatusNotes
Create Remove proposals✅ COMPLIANTLines 582-587
Specify removed index✅ COMPLIANTBigInt(index)
Create commit✅ COMPLIANTLine 590-593
Update epoch✅ COMPLIANTAutomatic
Send to remaining members⚠️ APP RESPONSIBILITYNot enforced
Validate index bounds❌ NON-COMPLIANTNo validation

Remove Members Compliance: 🟡 67% (4/6)

8.3 Update (Key Rotation)

RequirementStatusNotes
Generate new path✅ COMPLIANTforcePathUpdate: true
Create Update commit✅ COMPLIANTLine 462-465
Update all path secrets✅ COMPLIANTts-mls handles
Increment epoch✅ COMPLIANTLine 471
Distribute commit⚠️ APP RESPONSIBILITYNot enforced
Return PrivateMessage✅ COMPLIANTLine 475 returns commit

Update Compliance:83% (5/6)


Section 9: TreeKEM

RequirementStatusNotes
Maintain binary tree structure✅ COMPLIANTts-mls handles
Use parent hashes✅ COMPLIANTts-mls computes
Update path on member changes✅ COMPLIANTAutomatic
Blank parent nodes (nulls)✅ COMPLIANTLines 33-38
Strip trailing nulls✅ COMPLIANTstripTrailingNulls function
Preserve interior nulls✅ COMPLIANTLine 34-37
Compute tree hash✅ COMPLIANTts-mls computes
Validate tree structure❌ NON-COMPLIANTNo app-level validation
Tree size limits❌ NON-COMPLIANTNo size limits

TreeKEM Compliance: 🟡 78% (7/9)


Section 10: Key Schedule

RequirementStatusNotes
Epoch-based key derivation✅ COMPLIANTts-mls handles
HKDF for derivation✅ COMPLIANTHKDF-SHA256
Proper key separation✅ COMPLIANTContext strings
Handshake secret derivation✅ COMPLIANTts-mls implements
Application secret derivation✅ COMPLIANTFor message keys
Exporter secret✅ COMPLIANTAvailable if needed
Ratchet message keys✅ COMPLIANTPer-message

Key Schedule Compliance:100%


Section 11: Message Protection

11.1 Content Encryption

RequirementStatusNotes
Use group secrets✅ COMPLIANTFrom key schedule
AES-128-GCM encryption✅ COMPLIANTVia ts-mls
Unique nonce per message✅ COMPLIANTts-mls generates
Authenticate message✅ COMPLIANTAEAD tag
Include authenticated data✅ COMPLIANTGroup context

Content Encryption Compliance:100%

11.2 Commit Distribution

RequirementStatusNotes
Send Welcome to new members⚠️ DOCUMENTEDLines 238-249
Send commit to existing members⚠️ DOCUMENTEDClear instructions
All members process commit⚠️ APP RESPONSIBILITYNot enforced
Synchronize epoch⚠️ PARTIALNo desync detection

Commit Distribution Compliance: 🟡 50% (2/4)


Section 12: Message Types

12.1 Application Messages

RequirementStatusNotes
Use PrivateMessage✅ COMPLIANTLine 376-380
Encrypt with group secret✅ COMPLIANTts-mls handles
Include epoch✅ COMPLIANTIn envelope
Include group ID✅ COMPLIANTLine 383
Proper AEAD tag✅ COMPLIANTGCM tag

Application Messages:100%

12.2 Proposal Messages

RequirementStatusNotes
Support Add proposals✅ COMPLIANTLine 207-212
Support Remove proposals✅ COMPLIANTLine 582-587
Support Update proposals✅ COMPLIANTforcePathUpdate
Support PSK proposals⚠️ UNKNOWNts-mls may support
Support ReInit proposals⚠️ UNKNOWNts-mls may support
Support ExternalInit⚠️ UNKNOWNts-mls may support

Proposal Messages: 🟡 50% (3/6 confirmed)

12.3 Commit Messages

RequirementStatusNotes
Bundle multiple proposals✅ COMPLIANTextraProposals param
Update epoch✅ COMPLIANTAutomatic
Update tree hash✅ COMPLIANTAutomatic
Include path✅ COMPLIANTWhen needed
PublicMessage for Add/Remove✅ COMPLIANTLine 529
PrivateMessage for Update✅ COMPLIANTLine 540
Correct wireformat routing✅ COMPLIANTLines 529-553
Validate epoch progression❌ NON-COMPLIANTNo validation

Commit Messages: 🟡 88% (7/8)


Section 16: Security Considerations

16.1 Message Confidentiality

RequirementStatusNotes
Encrypt all application data✅ COMPLIANTAES-128-GCM
Use group secrets✅ COMPLIANTFrom key schedule
Protect against eavesdropping✅ COMPLIANTStrong encryption
Metadata minimization⚠️ PARTIALSome metadata exposed

Confidentiality: 🟡 75% (3/4)

16.2 Message Authentication

RequirementStatusNotes
Verify sender identity✅ COMPLIANTEd25519 signatures
Authenticate message content✅ COMPLIANTAEAD tags
Prevent forgery✅ COMPLIANTSignature verification
Validate signatures⚠️ PARTIALts-mls verifies, app trusts

Authentication: 🟡 75% (3/4)

16.3 Forward Secrecy

RequirementStatusNotes
Past messages safe✅ COMPLIANTEpoch ratcheting
Delete old keys✅ COMPLIANTts-mls manages
Key derivation forward-only✅ COMPLIANTHKDF properties
Cannot recover past keys✅ COMPLIANTCryptographically secure

Forward Secrecy:100%

16.4 Post-Compromise Security

RequirementStatusNotes
Future messages recover✅ COMPLIANTKey rotation
Path update propagates✅ COMPLIANTTreeKEM mechanism
Requires participation⚠️ ACKNOWLEDGEDInactive user issue
Recovery after compromise✅ COMPLIANTAfter key rotation

Post-Compromise Security: 🟡 75% (3/4)

16.5 Denial of Service

RequirementStatusNotes
Prevent resource exhaustion❌ NON-COMPLIANTNo size limits
Limit message size❌ NON-COMPLIANTUnlimited
Limit tree size❌ NON-COMPLIANTCould accept 2^30
Rate limiting❌ NON-COMPLIANTNo limits
Validate inputs❌ NON-COMPLIANTMissing validation

DoS Protection: 🔴 0% (0/5)

16.6 Replay Protection

RequirementStatusNotes
Detect duplicate messages❌ NON-COMPLIANTNo tracking
Prevent replay attacks❌ NON-COMPLIANTNo protection
Timestamp validation❌ NON-COMPLIANTNot implemented
Nonce tracking❌ NON-COMPLIANTNot implemented

Replay Protection: 🔴 0% (0/4)


Compliance Summary by Section

RFC 9420 SectionCompliance %StatusCritical Issues
§4 Ciphersuites100%None
§5 Key Packages78%🟡No lifetime validation
§6 Message Framing100%None
§7 Group Creation100%None
§8 Group Evolution75%🟡No input validation
§9 TreeKEM78%🟡No tree validation
§10 Key Schedule100%None
§11 Message Protection75%🟡Distribution not enforced
§12 Message Types79%🟡No epoch validation
§16 Security46%🔴No DoS or replay protection

Overall Compliance: 65%


Critical Non-Compliances

1. No Input Validation (§16.5)

RFC Requirement: Implementations MUST validate all inputs to prevent DoS

Current Status: ❌ NO VALIDATION

  • Welcome messages: no size limits
  • Ratchet trees: could accept millions of nodes
  • Key packages: no validation before processing
  • Message envelopes: unlimited ciphertext size

Impact: CRITICAL - DoS attacks possible

Fix Required: Implement comprehensive input validation


2. No Replay Protection (§16.6)

RFC Requirement: Implementations SHOULD protect against replay attacks

Current Status: ❌ NO PROTECTION

  • Messages can be replayed indefinitely
  • No timestamp validation
  • No nonce tracking
  • No sequence numbers

Impact: HIGH - Replay attacks possible

Fix Required: Implement timestamp validation (24-hour window)


3. No Epoch Validation (§8)

RFC Requirement: Epoch must progress sequentially

Current Status: ❌ NO VALIDATION

  • Epoch rollback possible
  • No verification of epoch = current + 1
  • Could accept arbitrary epochs

Impact: CRITICAL - Epoch rollback attacks

Fix Required: Validate epoch progression


4. No Tree Size Limits (§9)

RFC Requirement: While §9 allows large vectors, implementations must prevent resource exhaustion

Current Status: ❌ NO LIMITS

  • Could accept 2^30 byte vectors (per RFC)
  • No practical size limits
  • Memory exhaustion possible

Impact: CRITICAL - DoS via massive trees

Fix Required: Implement tree size limit (20K nodes recommended)


MUST vs SHOULD Requirements

MUST Requirements (Critical)

RequirementStatusPriority
Validate ciphersuite✅ COMPLIANT-
Sign key packages✅ COMPLIANT-
Increment epoch on changes✅ COMPLIANT-
Distribute commits⚠️ DOCUMENTEDNot enforced
Validate inputs❌ NON-COMPLIANTP0
Prevent resource exhaustion❌ NON-COMPLIANTP0

MUST Compliance: 67% (4/6)

SHOULD Requirements (Important)

RequirementStatusPriority
Protect against replay❌ NON-COMPLIANTP1
Limit message lifetime❌ NON-COMPLIANTP1
Verify key package signatures⚠️ PARTIALP1
Detect desynchronization❌ NON-COMPLIANTP1

SHOULD Compliance: 25% (1/4)


Compliance Roadmap

Phase 1: MUST Requirements (P0)

Goal: 100% MUST compliance

  1. Implement input validation (all external inputs)
  2. Add size limits (messages, trees, JSON)
  3. Add epoch validation
  4. Enforce commit distribution (or document limitations)

Estimated Time: 40-60 hours


Phase 2: SHOULD Requirements (P1)

Goal: 80%+ SHOULD compliance

  1. Implement replay protection (timestamp validation)
  2. Add key package signature verification at app level
  3. Implement desynchronization detection
  4. Add message lifetime limits

Estimated Time: 20-30 hours


Phase 3: Best Practices (P2)

Goal: Industry-leading compliance

  1. Implement rate limiting
  2. Add monitoring/alerting
  3. Implement audit logging
  4. Add inactive user detection

Estimated Time: 30-40 hours


Deployment Checklist

Before Production Deployment

MUST (Critical):

  • All inputs validated (Welcome, key packages, commits, etc.)
  • Size limits implemented (10MB messages, 20K tree nodes)
  • Epoch validation (must be current + 1)
  • Tree structure validation
  • No resource exhaustion vulnerabilities

SHOULD (High Priority):

  • Replay protection (24-hour message lifetime)
  • Key package lifetime validation
  • Signature verification at app level
  • Desynchronization detection

Best Practices:

  • Rate limiting on key operations
  • Security monitoring enabled
  • Audit logging implemented
  • Error sanitization complete
  • Debug logging removed

Compliance Verification

Automated Tests

describe('RFC 9420 Compliance', () => {
test('§16.5: Reject messages larger than limit', async () => {
const huge = 'x'.repeat(11 * 1024 * 1024); // 11MB
await expect(
manager.encryptMessage(groupId, huge)
).rejects.toThrow('Message too large');
});

test('§16.6: Reject replayed messages', async () => {
const msg = await alice.encryptMessage(groupId, 'test');
await bob.decryptMessage(msg);

await expect(
bob.decryptMessage(msg)
).rejects.toThrow('Replay');
});

test('§8: Reject epoch rollback', async () => {
const malicious = {
wireformat: 'mls_public_message',
publicMessage: { content: { epoch: 0n } }
};

await expect(
manager.processCommit(groupId, malicious)
).rejects.toThrow('Invalid epoch');
});
});

Conclusion

RFC 9420 Compliance Status: 🟡 65% COMPLIANT

Assessment:

  • Core protocol: Fully compliant (100%)
  • Cryptography: Fully compliant (100%)
  • 🟡 Implementation: Partially compliant (75%)
  • 🔴 Security requirements: Non-compliant (46%)

Critical Gaps:

  • No input validation (§16.5)
  • No replay protection (§16.6)
  • No epoch validation (§8)
  • No size limits (§9)

Recommendation: Implement Phase 1 (MUST requirements) before production deployment to achieve 90%+ compliance.

Target Compliance: 95%+ for production deployment