Skip to content

Commit

Permalink
Setup SRTP decryption (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
LVala authored Nov 7, 2023
1 parent e3f734e commit d9aafde
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- run: sudo apt install -y libsrtp2-dev
- run: mix deps.get
- run: mix credo
- run: mix dialyzer
Expand All @@ -37,6 +38,7 @@ jobs:
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- run: sudo apt install -y libsrtp2-dev
- run: mix deps.get
- run: mix coveralls.json
- uses: codecov/codecov-action@v3
56 changes: 47 additions & 9 deletions lib/ex_webrtc/dtls_transport.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule ExWebRTC.DTLSTransport do
:pkey,
:fingerprint,
:mode,
:srtp,
finished: false
]

Expand All @@ -25,11 +26,14 @@ defmodule ExWebRTC.DTLSTransport do
{:ok, fingerprint} = ExDTLS.get_cert_fingerprint(cert_client)
:ok = ExDTLS.stop(cert_client)

srtp = ExLibSRTP.new()

%__MODULE__{
ice_agent: ice_agent,
cert: cert,
pkey: pkey,
fingerprint: fingerprint
fingerprint: fingerprint,
srtp: srtp
}
end

Expand Down Expand Up @@ -93,31 +97,65 @@ defmodule ExWebRTC.DTLSTransport do
dtls
end

def process_data(dtls, data) do
def process_data(dtls, <<f, _::binary>> = data) when f in 20..63 and not dtls.finished do
case ExDTLS.process(dtls.client, data) do
{:handshake_packets, packets} when dtls.ice_state in [:connected, :completed] ->
:ok = ICEAgent.send_data(dtls.ice_agent, packets)
dtls
{:ok, dtls}

{:handshake_packets, packets} ->
Logger.debug("""
Generated local DTLS packets but ICE is not in the connected or completed state yet.
We will send those packets once ICE is ready.
""")

%__MODULE__{dtls | buffered_packets: packets}
{:ok, %__MODULE__{dtls | buffered_packets: packets}}

{:handshake_finished, _keying_material, packets} ->
{:handshake_finished, keying_material, packets} ->
Logger.debug("DTLS handshake finished")
ICEAgent.send_data(dtls.ice_agent, packets)
%__MODULE__{dtls | finished: true}
# TODO: validate fingerprint
dtls = setup_srtp(dtls, keying_material)
{:ok, %__MODULE__{dtls | finished: true}}

{:handshake_finished, _keying_material} ->
{:handshake_finished, keying_material} ->
Logger.debug("DTLS handshake finished")
%__MODULE__{dtls | finished: true}
dtls = setup_srtp(dtls, keying_material)
{:ok, %__MODULE__{dtls | finished: true}}

:handshake_want_read ->
dtls
{:ok, dtls}
end
end

def process_data(dtls, <<f, _::binary>> = data) when f in 128..191 and dtls.finished do
case ExLibSRTP.unprotect(dtls.srtp, data) do
{:ok, payload} ->
{:ok, dtls, payload}

{:error, _reason} = err ->
err
end
end

def process_data(_dtls, _data) do
{:error, :invalid_data}
end

defp setup_srtp(dtls, keying_material) do
{_local_material, remote_material, profile} = keying_material

{:ok, crypto_profile} =
ExLibSRTP.Policy.crypto_profile_from_dtls_srtp_protection_profile(profile)

policy = %ExLibSRTP.Policy{
ssrc: :any_inbound,
key: remote_material,
rtp: crypto_profile,
rtcp: crypto_profile
}

:ok = ExLibSRTP.add_stream(dtls.srtp, policy)
dtls
end
end
17 changes: 13 additions & 4 deletions lib/ex_webrtc/peer_connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,19 @@ defmodule ExWebRTC.PeerConnection do
end

@impl true
def handle_info({:ex_ice, _from, {:data, data}}, state)
when not state.dtls_transport.finished do
dtls = DTLSTransport.process_data(state.dtls_transport, data)
{:noreply, %__MODULE__{state | dtls_transport: dtls}}
def handle_info({:ex_ice, _from, {:data, data}}, state) do
case DTLSTransport.process_data(state.dtls_transport, data) do
{:ok, dtls} ->
{:noreply, %__MODULE__{state | dtls_transport: dtls}}

{:ok, dtls, payload} ->
notify(state.owner, {:data, payload})
{:noreply, %__MODULE__{state | dtls_transport: dtls}}

{:error, reason} ->
Logger.error("Unable to process data, reason: #{inspect(reason)}")
{:noreply, state}
end
end

@impl true
Expand Down
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ defmodule ExWebRTC.MixProject do
{:ex_sdp, "~> 0.13"},
{:ex_ice, "~> 0.1"},
{:ex_dtls, "~> 0.13"},
{:ex_libsrtp, "~> 0.6"},

# dev/test
{:excoveralls, "~> 0.14", only: [:dev, :test], runtime: false},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"},
"ex_dtls": {:hex, :ex_dtls, "0.13.0", "4d7631eefc19a8820d4f79883f379ff2ad642976bda55493d4ec4e5d10d6c078", [:mix], [{:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "3ece30967006ec12a4088e60514cb08847814fba8b8a21aca3862e5d1fd4a6bc"},
"ex_ice": {:hex, :ex_ice, "0.1.0", "2653c884872d8769cf9fc655c74002a63ed6c21be1b3c2badfa42bdc74de2355", [:mix], [{:ex_stun, "~> 0.1.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "e2539a321f87f31997ba974d532d00511e5828f2f113b550b1ef6aa799dd2ffe"},
"ex_libsrtp": {:hex, :ex_libsrtp, "0.6.0", "d96cd7fc1780157614f0bf47d31587e5eab953b43067f4885849f8177ec452a9", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "e9ce8a507a658f7e2df72fae82a4b3ba0a056c175f0bc490e79ab03058e094d5"},
"ex_sdp": {:hex, :ex_sdp, "0.13.0", "b464cf5f6b70433159be243115857599f82b07234ee022997868c85ae1f225f7", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:uuid, "~> 1.1", [hex: :uuid, repo: "hexpm", optional: false]}], "hexpm", "975ca4d274240c51ee85909bc0618bd4dd940e69f7d8c8f0d701f1524eaffaad"},
"ex_stun": {:hex, :ex_stun, "0.1.0", "252474bf4c8519fbf4bc0fbfc6a1b846a634b1478c65dbbfb4b6ab4e33c2a95a", [:mix], [], "hexpm", "629fc8be45b624a92522f81d85ba001877b1f0745889a2419bdb678790d7480c"},
"excoveralls": {:hex, :excoveralls, "0.17.1", "83fa7906ef23aa7fc8ad7ee469c357a63b1b3d55dd701ff5b9ce1f72442b2874", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "95bc6fda953e84c60f14da4a198880336205464e75383ec0f570180567985ae0"},
Expand Down

0 comments on commit d9aafde

Please sign in to comment.