Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bundlepolicy.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

// nolint:dupl,staticcheck
package webrtc

import (
Expand Down
4 changes: 4 additions & 0 deletions configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ type Configuration struct {
// AlwaysNegotiateDataChannels specifies whether the application prefers
// to always negotiate data channels in the initial SDP offer.
AlwaysNegotiateDataChannels bool `json:"alwaysNegotiateDataChannels,omitempty"`

// RTPHeaderEncryptionPolicy affects whether RTP header extension encryption
// (RFC 9335 Cryptex) is negotiated.
RTPHeaderEncryptionPolicy RTPHeaderEncryptionPolicy `json:"rtpHeaderEncryptionPolicy,omitempty"`
}
4 changes: 4 additions & 0 deletions configuration_js.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ type Configuration struct {
// to always negotiate data channels in the initial SDP offer.
AlwaysNegotiateDataChannels bool

// RTPHeaderEncryptionPolicy affects whether RTP header extension encryption
// (RFC 9335 Cryptex) is negotiated.
RTPHeaderEncryptionPolicy RTPHeaderEncryptionPolicy

Certificates []Certificate `json:"certificates,omitempty"`
}
34 changes: 33 additions & 1 deletion dtlstransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type DTLSTransport struct {
remoteCertificate []byte
state DTLSTransportState
srtpProtectionProfile srtp.ProtectionProfile
cryptexMode srtp.CryptexMode

onStateChangeHandler func(DTLSTransportState)
internalOnCloseHandler func()
Expand Down Expand Up @@ -192,12 +193,20 @@ func (t *DTLSTransport) GetRemoteCertificate() []byte {
return t.remoteCertificate
}

func (t *DTLSTransport) startSRTP() error {
// startSRTP requires the caller holds the lock.
func (t *DTLSTransport) startSRTP() error { //nolint:cyclop
srtpConfig := &srtp.Config{
Profile: t.srtpProtectionProfile,
BufferFactory: t.api.settingEngine.BufferFactory,
LoggerFactory: t.api.settingEngine.LoggerFactory,
}

if t.cryptexMode == srtp.CryptexModeEnabled || t.cryptexMode == srtp.CryptexModeRequired {
opt := srtp.Cryptex(t.cryptexMode)
srtpConfig.LocalOptions = append(srtpConfig.LocalOptions, opt)
srtpConfig.RemoteOptions = append(srtpConfig.RemoteOptions, opt)
}

if t.api.settingEngine.replayProtection.SRTP != nil {
srtpConfig.RemoteOptions = append(
srtpConfig.RemoteOptions,
Expand Down Expand Up @@ -709,3 +718,26 @@ func (t *DTLSTransport) streamsForSSRC(
rtcpInterceptor: rtcpInterceptor,
}, nil
}

func (t *DTLSTransport) getCryptexMode() srtp.CryptexMode {
t.lock.RLock()
defer t.lock.RUnlock()

return t.cryptexMode
}

func (t *DTLSTransport) setCryptexMode(mode srtp.CryptexMode) {
t.lock.Lock()
defer t.lock.Unlock()

t.cryptexMode = mode
}

// rtpHeaderEncryptionNegotiated reports if RFC 9335 RTP Header Extension Encryption ("Cryptex")
// has been negotiated and is enabled for this transceiver.
func (t *DTLSTransport) rtpHeaderEncryptionNegotiated() bool {
t.lock.RLock()
defer t.lock.RUnlock()

return t.cryptexMode == srtp.CryptexModeEnabled || t.cryptexMode == srtp.CryptexModeRequired
}
19 changes: 19 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ var (
// RTCPMuxPolicy was made after PeerConnection has been initialized.
ErrModifyingRTCPMuxPolicy = errors.New("rtcp mux policy cannot be modified")

// errModifyingRTPHeaderEncryptionPolicy indicates that an attempt to modify
// RTPHeaderEncryptionPolicy was made after PeerConnection has been initialized.
errModifyingRTPHeaderEncryptionPolicy = errors.New("rtp header encryption policy cannot be modified")

// ErrModifyingICECandidatePoolSize indicates that an attempt to modify
// ICECandidatePoolSize was made after PeerConnection has been initialized.
ErrModifyingICECandidatePoolSize = errors.New("ice candidate pool size cannot be modified")
Expand Down Expand Up @@ -135,6 +139,21 @@ var (
// ErrNoSRTPProtectionProfile indicates that the DTLS handshake completed and no SRTP Protection Profile was chosen.
ErrNoSRTPProtectionProfile = errors.New("DTLS Handshake completed and no SRTP Protection Profile was chosen")

// ErrRTPHeaderEncryptionRequired indicates that the local endpoint requires
// RFC 9335 Cryptex negotiation, but the remote SDP did not negotiate it.
ErrRTPHeaderEncryptionRequired = errors.New("rtp header extension encryption required")

// ErrRTPHeaderEncryptionModeChangeNotSupported indicates that the remote SDP attempted
// to change the negotiated RTP header extension encryption mode after SRTP has started.
// Pion's SRTP sessions cannot currently switch Cryptex mode without a full restart.
ErrRTPHeaderEncryptionModeChangeNotSupported = errors.New(
"rtp header extension encryption mode change not supported")

// ErrRTPHeaderEncryptionMixedModeNotSupported indicates that the remote SDP negotiated
// RTP header extension encryption for only some RTP media sections. Pion currently
// configures Cryptex as a connection-wide SRTP behavior and cannot support mixed mode.
ErrRTPHeaderEncryptionMixedModeNotSupported = errors.New("rtp header extension encryption mixed mode not supported")

// ErrFailedToGenerateCertificateFingerprint indicates that we failed to generate the fingerprint
// used for comparing certificates.
ErrFailedToGenerateCertificateFingerprint = errors.New("failed to generate certificate fingerprint")
Expand Down
Loading
Loading