Skip to main content
SA-021 Grade A Phase 3

SA-021 E2EE/Noise Protocol Key Negotiation Analysis Report

The Facebook iOS app implements a multi-layer encryption architecture for real-time audio/video calls: 1. **E2EE Layer**: End-to-end encryption indicated by model updates, with session-level enforcement 2. **DTLS Layer**: Transport-level encryption for WebRTC signaling 3. **Media Encryption**: Per-attachment encryption keys for audio/video content

Technical Diagrams

Found in `FBWebRTCCallModel` (`FBMessagingFramework.framework`): Line 36
| Property | Type | Purpose |
|----------|------|---------|
| `_isEndToEndEncrypted` | BOOL | Indicates if call has E2EE active |
| `_isE2EEncryptionMandated` | BOOL | Forces E2EE requirement for call |
Found in `MNSecureOutgoingAttachmentContent`: Line 100
| Property | Type | Purpose |
|----------|------|---------|
| `_audio_audioEncryptionKey` | NSData | Audio attachment encryption key |
| `_video_videoEncryptionKey` | NSData | Video attachment encryption key |
| `_images_encryptionKey` | NSData | Image attachment encryption key |
The RTC stack uses native C++ classes exposed via opaque pointers: Line 117
| Objective-C Property | C++ Type | Purpose |
|---------------------|----------|---------|
| `_nativeEngine` | `shared_ptr<WebRTCEngine>` | Native WebRTC engine |
| `_nativeCall` | `weak_ptr<RTCConferenceCall>` | Native conference call |
| `_call` | `^{__RSCall}` | RS call structure |
| `_callApi` | `^{__RSCallApi}` | RS call API |
| `_rsCallManager` | `^{__RSCallManager}` | RS call manager |
| `_huddleApi` | `^{__RSHuddleApi}` | Huddle API |
| `_audioProxy` | `^{__RSAudioProxy}` | Audio proxy |
Session Key Lifecycle Line 220
| Phase | Description |
|-------|-------------|
| **Negotiation** | Key exchange via native crypto proxy (Noise handshake in C++) |
| **Establishment** | `onCryptoE2eeModelUpdated:` callback with session parameters |
| **Active** | Per-frame key derivation via HKDF |
| **Rotation** | Implied by Noise protocol ratcheting (not visible at ObjC level) |
| **Termination** | Call end clears session keys |
Evidence Quality Line 283
| Criterion | Score | Notes |
|-----------|-------|-------|
| E2EE model identification | 9/10 | Clear Objective-C properties found |
| Key exchange mechanism | 5/10 | Inferred from structure, not visible |
| DTLS integration | 8/10 | Configuration methods found |
| SRTP implementation | 3/10 | Assumed, not visible in ObjC |
| Noise protocol | 4/10 | Indirect evidence only |
| Session key lifecycle | 6/10 | Callbacks identified |
Key Classes Line 298
| Class | Framework | Purpose |
|-------|-----------|---------|
| `FBWebRTCEngine` | FBMessagingFramework | Main WebRTC engine wrapper |
| `FBWebRTCCallModel` | FBMessagingFramework | Call state including E2EE flags |
| `FBWebRTCMultiwayCall` | FBMessagingFramework | Conference call implementation |
| `RIBRTCEngine` | FBMessagingFramework | RIB layer RTC engine |
| `RIBRTCCallClient` | FBMessagingFramework | Call client with crypto proxy |
| `RIBRSSignaling` | FBMessagingFramework | MQTT-based signaling |
| `MNSecureOutgoingAttachmentContent` | FBSharedFramework | Encrypted attachment wrapper |
Key Methods Line 310
| Method | Purpose |
|--------|---------|
| `onCryptoE2eeModelUpdated:` | Native callback for E2EE state change |
| `callUpdatedE2eeModel:` | Listener notification for E2EE |
| `rsCallClientGetCryptoProxy` | Access to native crypto proxy |
| `setNetworkingConfigShouldOfferDtls:` | DTLS configuration |
| `audioWithAudioEncryptionKey:audio:` | Create encrypted audio attachment |

Code Evidence

Objective-C
-[FBWebRTCEngine startIncomingConferenceCall:callId:ringType:peerUserIds:callerUserId:dataMessages:stateSyncInitialData:userProfiles:isE2eeMandatedCall:collisionContextData:onSuccess:onError:]

-[FBWebRTCEngine startConferenceCallWithName:localCallId:ringingUsers:initialMediaState:callTrigger:includeRingeesInPeerList:dataMessages:stateSyncInitialData:collisionKey:analyticsExtra:callConfiguration:isE2EEMandated:error:]
Plain Text
[Native C++ Layer]
    |
    v
[FBWebRTCEngine onCryptoE2eeModelUpdated:]
    |
    v
[FBWebRTCEngineListenerAnnouncer callUpdatedE2eeModel:]
    |
    v
[Multiple listeners implement callUpdatedE2eeModel:]
    - FBFacecastWithGuestFBWebRTCEngine
    - FBVideoBroadcastWebRTCSession
    - FBWebRTCCallStateLogWriter
    - FBWebRTCRingtoneManager
Objective-C
@protocol RSCallClientDelegate <NSObject>
-[RSCallClientDelegate rsCallClientGetCryptoProxy];
// ... other media proxies
@end

@interface RIBRTCCallClient : NSObject <RSCallClientDelegate>
-[RIBRTCCallClient rsCallClientGetCryptoProxy];
@end
Objective-C
-[FBWebRTCCallConfig setNetworkingConfigShouldOfferDtls:]
Objective-C
+[MNSecureOutgoingAttachmentContent audioWithAudioEncryptionKey:audio:]
+[MNSecureOutgoingAttachmentContent videoWithVideoEncryptionKey:video:]
+[MNSecureOutgoingAttachmentContent imagesWithEncryptionKey:photos:]
Objective-C
@interface RIBRSSignaling : NSObject <RIBMQTTNotificationListener>
    ^{__RSSignalingTransportProxy} _signalingTransport;
    ^{__RSSignalingTransportSink} _transportSink;
@end

@interface RIBMQTTChannel : NSObject <RIBRSSignalingDelegate>
    ^{__RTChannel} _rtChannel;
    ^{_RTMQTTBridge} _mqttBridge;
@end
Plain Text
[Session Master Key]
        |
        v
[walibra_hkdf_info (HKDF)]
        |
        v
[Frame-specific Key]
        |
        v
[AES-256-GCM Encrypt/Decrypt]
Plain Text
1. Call Initiation
   [FBWebRTCEngine startConferenceCallWithName:... isE2EEMandated:]

2. MQTT Signaling
   [RIBRSSignaling handleNotificationForTopic:andData:andSource:]

3. DTLS Handshake (Transport Layer)
   [FBWebRTCCallConfig setNetworkingConfigShouldOfferDtls:YES]

4. Crypto Proxy Setup
   [RIBRTCCallClient rsCallClientGetCryptoProxy]

5. E2EE Session Established
   [FBWebRTCEngine onCryptoE2eeModelUpdated:]

6. Frame Encryption Active
   [walibra_hkdf_info + AES-256-GCM per frame]

7. E2EE State Broadcast
   [callUpdatedE2eeModel:] -> all listeners
Plain Text
E2EE Session Key -> HKDF Expansion -> Per-Frame Key -> AES-256-GCM
Plain Text
Generated audioEncryptionKey -> AES encryption of audio blob

**Agent ID:** SA-021 **Date:** 2025-12-30 **Status:** Completed **Grade:** B


Mission

Trace E2EE/Noise protocol key negotiation for audio encryption in the Facebook iOS application.

**Target Binary:** `./analysis/facebook/345.0/Facebook.app/Frameworks/FBSharedFramework.framework/FBSharedFramework`

**Additional Target:** `FBMessagingFramework.framework` (RTC stack)


Executive Summary

The Facebook iOS app implements a multi-layer encryption architecture for real-time audio/video calls:

    undefined

The Noise protocol implementation appears to be in the native C++ layer (referenced as `__RS*` structures), not exposed in Objective-C headers.


Key Findings

1. E2EE Call Model Properties

Found in `FBWebRTCCallModel` (`FBMessagingFramework.framework`):

PropertyTypePurpose
`_isEndToEndEncrypted`BOOLIndicates if call has E2EE active
`_isE2EEncryptionMandated`BOOLForces E2EE requirement for call

**Methods that set E2EE state:**

Objective-C
-[FBWebRTCEngine startIncomingConferenceCall:callId:ringType:peerUserIds:callerUserId:dataMessages:stateSyncInitialData:userProfiles:isE2eeMandatedCall:collisionContextData:onSuccess:onError:]

-[FBWebRTCEngine startConferenceCallWithName:localCallId:ringingUsers:initialMediaState:callTrigger:includeRingeesInPeerList:dataMessages:stateSyncInitialData:collisionKey:analyticsExtra:callConfiguration:isE2EEMandated:error:]

2. E2EE Model Update Flow

The E2EE state is propagated through the call stack via callbacks:

Plain Text
[Native C++ Layer]
    |
    v
[FBWebRTCEngine onCryptoE2eeModelUpdated:]
    |
    v
[FBWebRTCEngineListenerAnnouncer callUpdatedE2eeModel:]
    |
    v
[Multiple listeners implement callUpdatedE2eeModel:]
    - FBFacecastWithGuestFBWebRTCEngine
    - FBVideoBroadcastWebRTCSession
    - FBWebRTCCallStateLogWriter
    - FBWebRTCRingtoneManager

3. Crypto Proxy Architecture

The `RSCallClientDelegate` protocol exposes a crypto proxy:

Objective-C
@protocol RSCallClientDelegate <NSObject>
-[RSCallClientDelegate rsCallClientGetCryptoProxy];
// ... other media proxies
@end

@interface RIBRTCCallClient : NSObject <RSCallClientDelegate>
-[RIBRTCCallClient rsCallClientGetCryptoProxy];
@end

This crypto proxy is the bridge to the native encryption layer but its implementation is in C++ (`^{__RS*}` pointer types).

4. DTLS Configuration

DTLS (Datagram Transport Layer Security) is configurable via `FBWebRTCCallConfig`:

Objective-C
-[FBWebRTCCallConfig setNetworkingConfigShouldOfferDtls:]

DTLS handles the transport-layer encryption and certificate exchange for WebRTC connections.

5. Media Encryption Keys

Found in `MNSecureOutgoingAttachmentContent`:

PropertyTypePurpose
`_audio_audioEncryptionKey`NSDataAudio attachment encryption key
`_video_videoEncryptionKey`NSDataVideo attachment encryption key
`_images_encryptionKey`NSDataImage attachment encryption key

**Factory Methods:**

Objective-C
+[MNSecureOutgoingAttachmentContent audioWithAudioEncryptionKey:audio:]
+[MNSecureOutgoingAttachmentContent videoWithVideoEncryptionKey:video:]
+[MNSecureOutgoingAttachmentContent imagesWithEncryptionKey:photos:]

6. Native RTC Infrastructure

The RTC stack uses native C++ classes exposed via opaque pointers:

Objective-C PropertyC++ TypePurpose
`_nativeEngine``shared_ptr`Native WebRTC engine
`_nativeCall``weak_ptr`Native conference call
`_call``^{__RSCall}`RS call structure
`_callApi``^{__RSCallApi}`RS call API
`_rsCallManager``^{__RSCallManager}`RS call manager
`_huddleApi``^{__RSHuddleApi}`Huddle API
`_audioProxy``^{__RSAudioProxy}`Audio proxy

7. Signaling Transport

Call signaling uses MQTT through:

Objective-C
@interface RIBRSSignaling : NSObject <RIBMQTTNotificationListener>
    ^{__RSSignalingTransportProxy} _signalingTransport;
    ^{__RSSignalingTransportSink} _transportSink;
@end

@interface RIBMQTTChannel : NSObject <RIBRSSignalingDelegate>
    ^{__RTChannel} _rtChannel;
    ^{_RTMQTTBridge} _mqttBridge;
@end

8. Connection to SA-006 Findings

From SA-006 Key Derivation report, the encryption uses:

    undefined

**Key Derivation Flow:**

Plain Text
[Session Master Key]
        |
        v
[walibra_hkdf_info (HKDF)]
        |
        v
[Frame-specific Key]
        |
        v
[AES-256-GCM Encrypt/Decrypt]

Noise Protocol Analysis

Expectation vs Reality

**Expected:** Explicit Noise protocol handshake classes (e.g., `NoiseHandshake`, `NoiseSession`, `NoiseCipherState`)

**Found:** The Noise protocol implementation appears to be:

    undefined

The "Noise" references found in class dump (`FBCrowdNoise*`) are unrelated - they are UI effects for live streaming audience reactions, not cryptographic protocols.

Evidence of Noise Protocol

Indirect evidence suggests Noise protocol usage:

    undefined

Key Negotiation Sequence (Inferred)

Based on class analysis:

Plain Text
1. Call Initiation
   [FBWebRTCEngine startConferenceCallWithName:... isE2EEMandated:]

2. MQTT Signaling
   [RIBRSSignaling handleNotificationForTopic:andData:andSource:]

3. DTLS Handshake (Transport Layer)
   [FBWebRTCCallConfig setNetworkingConfigShouldOfferDtls:YES]

4. Crypto Proxy Setup
   [RIBRTCCallClient rsCallClientGetCryptoProxy]

5. E2EE Session Established
   [FBWebRTCEngine onCryptoE2eeModelUpdated:]

6. Frame Encryption Active
   [walibra_hkdf_info + AES-256-GCM per frame]

7. E2EE State Broadcast
   [callUpdatedE2eeModel:] -> all listeners

Session Key Lifecycle

PhaseDescription
**Negotiation**Key exchange via native crypto proxy (Noise handshake in C++)
**Establishment**`onCryptoE2eeModelUpdated:` callback with session parameters
**Active**Per-frame key derivation via HKDF
**Rotation**Implied by Noise protocol ratcheting (not visible at ObjC level)
**Termination**Call end clears session keys

SRTP Analysis

**Finding:** No explicit SRTP classes found in Objective-C layer.

SRTP (Secure Real-time Transport Protocol) is likely:

    undefined

DTLS Analysis

DTLS integration confirmed via:

    undefined

DTLS handles:

    undefined

Connection to audioEncryptionKey

The `audioEncryptionKey` in `MNSecureOutgoingAttachmentContent` is used for:

    undefined

Real-time call audio encryption:

Plain Text
E2EE Session Key -> HKDF Expansion -> Per-Frame Key -> AES-256-GCM

Attachment audio encryption:

Plain Text
Generated audioEncryptionKey -> AES encryption of audio blob

Critical Blockers

    undefined

Evidence Quality

CriterionScoreNotes
E2EE model identification9/10Clear Objective-C properties found
Key exchange mechanism5/10Inferred from structure, not visible
DTLS integration8/10Configuration methods found
SRTP implementation3/10Assumed, not visible in ObjC
Noise protocol4/10Indirect evidence only
Session key lifecycle6/10Callbacks identified

Technical Artifacts

Key Classes

ClassFrameworkPurpose
`FBWebRTCEngine`FBMessagingFrameworkMain WebRTC engine wrapper
`FBWebRTCCallModel`FBMessagingFrameworkCall state including E2EE flags
`FBWebRTCMultiwayCall`FBMessagingFrameworkConference call implementation
`RIBRTCEngine`FBMessagingFrameworkRIB layer RTC engine
`RIBRTCCallClient`FBMessagingFrameworkCall client with crypto proxy
`RIBRSSignaling`FBMessagingFrameworkMQTT-based signaling
`MNSecureOutgoingAttachmentContent`FBSharedFrameworkEncrypted attachment wrapper

Key Methods

MethodPurpose
`onCryptoE2eeModelUpdated:`Native callback for E2EE state change
`callUpdatedE2eeModel:`Listener notification for E2EE
`rsCallClientGetCryptoProxy`Access to native crypto proxy
`setNetworkingConfigShouldOfferDtls:`DTLS configuration
`audioWithAudioEncryptionKey:audio:`Create encrypted audio attachment

Recommendations for Further Investigation

    undefined

Impact on H3 Decoding

**Contribution to H3 Investigation:** Moderate

This analysis confirms:

    undefined

**Blockers for audio decryption:**

    undefined

*SA-021 E2EE/Noise Protocol Analysis - Generated 2025-12-30*

Related Reports

Phase 3 Navigation