
SRTP(Secure Realtime Transport Protocol)用ライブラリ
このパッケージは、Secure Real-time Transport Protocol(SRTP)、Universal Security Transform(UST)、およびそれを支える暗号カーネルの実装を提供します。SRTP APIはinclude/srtp.hに文書化されており、ライブラリは(コンパイル後に)libsrtp2.aに格納されます。
この文書は、Cisco Systems, Inc.によるオープンソースのSecure RTPライブラリであるlibSRTPについて説明します。RTP(Real-time Transport Protocol)は、RFC 3550 で定義されている、電話、音声、ビデオなどのリアルタイムデータの転送のためのIETF標準です。Secure RTP(SRTP)は、RTPデータに機密性を提供し、RTPヘッダーとペイロードに認証を提供するRTPプロファイルです。SRTPはRFC 3711で定義されたIETF標準であり、IETF Audio/Video Transport(AVT)ワーキンググループで開発されました。このライブラリはSRTPの必須機能をすべてサポートしていますが、オプション機能のすべてをサポートしているわけではありません。詳細については、対応機能のセクションを参照してください。
この文書は、/doc/フォルダ内のドキュメントファイルを生成するためにも使用され、libSRTP APIおよび関連関数のより詳細なリファレンスを作成できます(doxygenのインストールが必要です)。リファレンス資料は、いくつかのCヘッダーファイルに埋め込まれたコメントから自動的に作成されます。ドキュメントは、わかりやすさを向上させるためにモジュールに編成されています。これらのモジュールはファイルに直接対応するものではありません。基盤となる暗号カーネルはlibSRTPの基本機能の多くを提供しますが、舞台裏で動作するため、ほとんど文書化されていません。
[email protected] ニュース、アナウンス、ディスカッションのための一般メーリングリスト。これはオープンリストです。登録については、 https://lists.packetizer.com/mailman/listinfo/libsrtp を参照してください。
[email protected] libsrtpメンテナンスチームにセキュリティ問題を開示するためのリスト。クローズドリストですが、誰でも送信できます。
libSRTPは以下のライセンスの下で配布されており、このライセンスはソースコード配布に含まれています。別のソースからライブラリを入手した場合に備えて、このマニュアルにも再掲されています。
Copyright (c) 2001-2017 Cisco Systems, Inc. All rights reserved.
ソースコード形式およびバイナリ形式での再頒布および使用は、変更の有無にかかわらず、 以下の条件が満たされる場合に許可されます。 条件は次のとおりです:
- ソースコードを再頒布する場合は、上記の著作権表示、この条件リスト、 および以下の免責事項を保持しなければなりません。
- バイナリ形式で再頒布する場合は、上記の著作権表示、この条件リスト、 および以下の免責事項を、配布物とともに提供される文書および/またはその他の資料に 含めなければなりません。
- Cisco Systems, Inc.の名称およびその貢献者の名称は、 書面による事前の許可なしに、本ソフトウェアから派生した製品を 推奨または宣伝するために使用してはなりません。
本ソフトウェアは、著作権所有者および貢献者によって 「現状のまま」提供され、明示または黙示のいかなる保証も、 商品性および特定目的への適合性に関する黙示の保証を含みますが、 これに限定されず、否認されます。いかなる場合においても、 著作権所有者または貢献者は、直接的、間接的、偶発的、 特別、懲戒的、または結果的な損害(代替商品またはサービスの調達、 使用、データ、または利益の喪失、または事業の中断を含みますが、 これに限定されません)について、契約、厳格責任、 または不法行為(過失またはその他を含む)のいずれの理論に基づいても、 たとえそのような損害の可能性について助言されていたとしても、 本ソフトウェアの使用から生じるいかなる方法によっても 責任を負いません。
libSRTPは、RTPとRTCPを保護するための関数を提供します。RTPパケットは、srtp_protect()関数を使用して暗号化および認証でき、SRTPパケットに変換されます。同様に、SRTPパケットは、srtp_unprotect()関数を使用して復号化され、認証が検証され、RTPパケットに変換されます。同様の関数がRTCPパケットにセキュリティを適用します。
typedef srtp_stream_tは、SRTPストリームに関連するすべての状態を保持する構造体を指します。これには、暗号化およびメッセージ認証関数の鍵とパラメータ、およびリプレイ防止データが含まれます。特定のsrtp_stream_tは、特定のRTPストリームとRTCPストリームを保護するために必要な情報を保持します。このデータ型は、libSRTP APIをその実装からより適切に分離するために、意図的に不透明になっています。
SRTPセッション内には、それぞれ特定の送信元から発信される複数のストリームが存在できます。各送信元は、発信するRTPストリームとRTCPストリームを保護するために、個別のストリームコンテキストを使用します。typedef srtp_tは、SRTPセッションに関連するすべての状態を保持する構造体を指します。単一のsrtp_tには複数のストリームコンテキストを関連付けることができます。ストリームコンテキストはsrtp_tから独立して存在することはできませんが、もちろん単一のストリームコンテキストのみを含むsrtp_tを作成することはできます。SRTPセッションに参加するデバイスは、各送信元から受信したデータを処理できるように、そのセッション内の各送信元のストリームコンテキストを持っている必要があります。
libSRTPでは、セッションはsrtp_create()関数を使用して作成されます。セッションで実装されるポリシーは、不透明なsrtp_policy_tハンドルとしてこの関数に渡されます。単一のポリシーハンドルは、1つのストリームポリシーを記述します。複数のストリームを構成するには、セッションを作成し、srtp_stream_add()を使用して追加のポリシーを追加します。
ポリシーハンドルは、srtp_policy_set_*関数を使用して構成されます。最低限、これにはSSRCの選択、プロファイルの選択、鍵/ソルトの材料が含まれます。プロファイルはRTP/RTCP暗号ポリシー設定を構成し、SSRCセレクタはそのポリシーが適用される方法と場所を識別します。
このセクションでは、SRTPを概説し、libSRTPで使用されるいくつかの用語を紹介します。RTPセッションは、宛先トランスポートアドレスのペア、つまりネットワークアドレスとRTPおよびRTCP用のUDPポートのペアによって定義されます。RTCPは、RTP制御プロトコルであり、RTPセッションの参加者間の調整に使用されます。例えば、受信者から送信者へのフィードバックを提供します。SRTPセッションも同様に定義されます。これは、SRTPプロファイルが使用されているRTPセッションにすぎません。SRTPセッションは、SRTPまたはSRTCPの宛先トランスポートアドレスに送信されるトラフィックで構成されます。セッション内の各参加者は、同期ソース(SSRC)識別子によって識別されます。一部の参加者はSRTPトラフィックを送信しない場合があります。受信者レポートなどのSRTCPトラフィックを送信するにもかかわらず、これらの参加者は受信者と呼ばれます。
RTPでは、同じセッション中に複数の送信元がRTPトラフィックとRTCPトラフィックを送信できます。同期ソース識別子(SSRC)は、これらの送信元を区別するために使用されます。libSRTPでは、特定の送信元からのSRTPトラフィックとSRTCPトラフィックをストリームと呼びます。各ストリームには、独自のSSRC、シーケンス番号、ロールオーバーカウンタ、およびその他のデータがあります。オプション、暗号メカニズム、鍵の特定の組み合わせは、ポリシーと呼ばれます。セッション内の各ストリームには、個別のポリシーを適用できます。
単一のポリシーを特定のセッション内のすべてのストリームに使用できますが、単一の鍵を複数のストリーム間で共有する場合は注意が必要です。鍵の共有を使用する場合、ストリームを識別するSSRC値は一意でなければなりません。この要件は、各SRTP鍵およびSRTCP鍵が単一の送信者による暗号化にのみ使用されるという規則を使用して強制できます。言い換えると、鍵は特定のデバイスから発信されるストリーム間でのみ共有されます(もちろん、他のSRTP参加者は復号化のために鍵を使用する必要があります)。libSRTPは、インバウンドデータとアウトバウンドデータの両方に鍵が使用されているケースを検出することで、この強制をサポートします。
このライブラリは、SRTPの必須実装機能をすべてサポートしています(RFC 3711で定義)。これらの機能の一部は、srtp_policy_tハンドルを使用して適切なポリシーを設定することにより、実行時に選択(または選択解除)できます。プロトコルのその他の一部の動作は、例外的なイベント用の適切なイベントハンドラを定義することで適応できます。生成されたドキュメントのSRTPeventsセクションを参照してください。
SRTP仕様に記述されている一部のオプションはサポートされていません。これには以下が含まれます。
ユーザーは、このライブラリを誤用する可能性があり、その結果、提供されるセキュリティレベルが不十分になる可能性があることに注意する必要があります。このライブラリを使用して機能を実装する場合は、RFC 3711のSecurity Considerationsセクションを読むことをお勧めします。さらに、ライセンスと免責事項のセクションで概説されている条件を読み、理解することが重要です。
このライブラリは、RFC 7714で説明されているAES-GCM認証付き暗号化方式もサポートしています。
libSRTPをビルドする際に使用するサードパーティ(openssl/nssなど)の暗号バックエンドを構成できます。 サードパーティのバックエンドが設定されていない場合、libSRTPはAESとSha1の内部実装を提供します。 内部実装はAES-128とAES-256のみをサポートするため、AES-192またはAES-GCMグループの暗号を 使用するには、サードパーティの暗号バックエンドを構成する必要があります。この理由と パフォーマンス上の理由から、サードパーティの暗号バックエンドを使用することを 強くお勧めします。
srtp_protect()関数は、RTPパケットを保持するバッファに、認証タグを
そのパケットの末尾に書き込めるだけの十分なストレージが割り当てられていることを前提としています。
この前提が有効でない場合、
メモリ破損が発生します。
暗号関数の自動テストは、cipher_type_self_test()関数と
auth_type_self_test()関数を通じて提供されます。
これらの関数は、このコードを新しいプラットフォームに移植するたびに
テストするために使用する必要があります。
リプレイ保護は暗号エンジンに含まれており、 そのテストが提供されています。
この実装は、RTPパケットを初期化、保護、および保護解除するための呼び出しを提供し、 これらの関数がどのように呼び出されるかについての想定をできるだけ少なくしています。 たとえば、呼び出し側がパケットを順番に提供することは期待されていません (ただし、シーケンスから65k以上離れて呼び出された場合、 同期が 失われます)。
RTPパケット内のシーケンス番号は、送信者のローカルパケットインデックスの下位16ビットとして使用されます。
RTPはランダムな場所からシーケンス番号を開始し、
SRTPレイヤーは最初の呼び出し時にその番号までジャンプすることに注意してください。
このライブラリの以前のバージョンでは、
32768未満の初期シーケンス番号を使用していました。
rdbx_estimate_index(...)関数がバージョン1.0.1以降、
より賢く作られたため、この手法は
もはや必要ありません。
(S)RTCPのリプレイウィンドウは、長さ128ビットにハードコードされています。
libSRTPをインストールするには、https://github.com/cisco/libsrtp/releasesから配布物の最新リリースをダウンロードします。最新のリリースを入手することをお勧めします。配布物を解凍してソースファイルを抽出します。ソースファイルが配置されるディレクトリはlibsrtp-A-B-Cという名前で、Aはバージョン番号、Bはメジャーリリース番号、Cはマイナーリリース番号です。
libSRTPはGNUのautoconfおよびmakeユーティリティを使用します(BSD makeは機能しません。プラットフォームに両方のバージョンのmakeがある場合は、GNU makeをgmakeとして呼び出すことができます)。libsrtpディレクトリで、configureスクリプトを実行してからmakeを実行します:~~~.txt
./configure [ options ]
make
configure スクリプトは以下のオプションを受け付けます:
Option | Description
-------------------------------|--------------------
\-\-help \-h | ヘルプを表示
\-\-enable-debug-logging | すべてのモジュールでデバッグログを有効にする
\-\-enable-openssl | OpenSSL 暗号エンジンを有効にする
\-\-enable-nss | NSS 暗号エンジンを有効にする
\-\-enable-openssl-kdf | OpenSSL KDF アルゴリズムを有効にする
\-\-enable-log-stdout | stdout へのログ出力を有効にする
\-\-with-openssl-dir | OpenSSL インストール先の場所
\-\-with-nss-dir | NSS インストール先の場所
\-\-with-log-file | ログ出力にファイルを使用する
デフォルトではログ出力はありません。ログ出力は、configure オプションを使用して stdout
または指定されたファイルに出力できるように有効化できます。
このパッケージは以下のプラットフォームでテストされています: Mac OS X
(powerpc-apple-darwin1.4), Cygwin (i686-pc-cygwin), Solaris
(sparc-sun-solaris2.6), RedHat Linux 7.1 および 9 (i686-pc-linux)、および
OpenBSD (sparc-unknown-openbsd2.7)。
--------------------------------------------------------------------------------
<a name="changing-build-configuration"></a>
## ビルド構成の変更
上記の `./configure` スクリプトをビルドするために、libSRTP は
[automake](https://www.gnu.org/software/automake/) ツールチェーンに依存しています。
`./configure` は automake によって `configure.in` からビルドされるため、
`./configure` の動作方法に変更を加える場合(例: 新しいライブラリ依存関係を追加するなど)、
`./configure` を再ビルドし、更新されたバージョンをコミットする必要があります。
automake 自体に加えて、`pkgconfig` ツールもインストールされている必要があります。
例えば、macOS の場合:```
brew install automake pkgconfig
# Edit configure.in
autoremake -ivf
```
<a name="using-visual-studio"></a>
## Visual Studio の使用
Windows では、CMake を介して Visual Studio を使用できます。CMake はこちらからダウンロードできます:
https://cmake.org/。
Visual Studio のビルドファイルを作成するには、たとえば次のコマンドを実行します:```
# Create build subdirectory
mkdir build
cd build
# Make project files
cmake .. -G "Visual Studio 15 2017"
# Or for 64 bit project files
cmake .. -G "Visual Studio 15 2017 Win64"
```
<a name="using-meson"></a>
## Meson を使用する
Windows を含むすべてのプラットフォームで、[Meson](https://mesonbuild.com) を使用してビルドできます。
Meson のダウンロード手順はこちら: https://mesonbuild.com/Getting-meson.html
Meson でビルドするには、次のようにします:```
# Setup the build subdirectory
meson setup --prefix=/path/to/prefix builddir
# Build the project
meson compile -C builddir
# Run tests
meson test -C builddir
# Optionally, install
meson install -C builddir
```
Visual Studio でビルドするには、Visual Studio コマンド プロンプト内から上記のコマンドを実行するか、コマンド プロンプト内で適切な引数を指定して `vcvarsall.bat` を実行します。
上記のコマンドは、対応する `ninja` ターゲット (`ninja -C build`、`ninja -C build test`、`ninja -C build install`) に置き換えることもできます。
--------------------------------------------------------------------------------
<a name="applications"></a>
# アプリケーション
いくつかのテストドライバと、シンプルで移植可能な srtp アプリケーションが `test/` サブディレクトリに含まれています。
テストドライバ | テスト対象機能
--------- | -------
kernel_driver | crypto カーネル (暗号、認証関数、rng)
srtp_driver | srtp インメモリテスト (ネットワークを使用しません)
rdbx_driver | rdbx (拡張リプレイデータベース)
roc_driver | 拡張シーケンス番号関数
replay_driver | リプレイデータベース
cipher_driver | 暗号
auth_driver | ハッシュ関数
アプリケーション `rtpw` はシンプルな rtp アプリケーションで、`/usr/dict/words` から単語を読み取り、[s]rtp を使用して一度に 1 つずつ送信します。手動の srtp キー設定には -k オプションを使用します。gdoi を使用した自動鍵管理は後で追加される予定です。
使用法:~~~.txt
rtpw [[-d <debug>]* [-k|b <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port] | [-l]
-s (送信側) または -r (受信側) オプションのいずれかを選択する必要があります。
dest_ip、dest_port の値は、それぞれ辞書の
送信先となるIPアドレスとUDPポートです。
オプションは次のとおりです:
key/salt ペアとして使用するランダムな30バイトの値を取得するには、
次の bash 関数を使用して /dev/random の出力を整形できます
(そのデバイスが利用可能な場合)。~~~.txt
function randhex() {
cat /dev/random | od --read-bytes=32 --width=32 -x | awk '{ print $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 }'
}
2つのrtpwプログラムを使用したSRTPセッションの例を以下に示します:~~~.txt
set k=c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451
[sh1]$ test/rtpw -s -k $k -e 128 -a 0.0.0.0 9999
Security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
setting SSRC to 2078917053
sending word: A
sending word: a
sending word: aa
sending word: aal
...
[sh2]$ test/rtpw -r -k $k -e 128 -a 0.0.0.0 9999
security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
19 octets received from SSRC 2078917053 word: A
19 octets received from SSRC 2078917053 word: a
20 octets received from SSRC 2078917053 word: aa
21 octets received from SSRC 2078917053 word: aal
...
このセクションでは、libSRTPの簡単な使用例を示します。ここでは、
関数 get_rtp_packet() と send_srtp_packet() が利用可能であると
仮定します。前者はRTPパケットを
バッファに入れ、そのバッファに書き込まれたオクテット数を
返します。後者は、バッファ内のRTPパケットを、長さを
第2引数として送信します。~~~.c
srtp_t session;
srtp_policy_t policy;
// Set key/salt to predetermined values. uint8_t master_key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; uint8_t master_salt[14] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D};
// Initialize libSRTP. srtp_init();
// Create and configure an opaque policy handle. srtp_policy_create(&policy); srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ssrc_any_outbound, 0}); srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80); srtp_policy_add_key(policy, master_key, sizeof(master_key), master_salt, sizeof(master_salt), NULL, 0);
// Allocate and initialize the SRTP session. srtp_create(&session, policy);
srtp_policy_destroy(policy);
// Main loop: get RTP packets, send SRTP packets. while (1) { char rtp_buffer[2048]; size_t rtp_len; char srtp_buffer[2048]; size_t srtp_len = sizeof(srtp_buffer);
rtp_len = get_rtp_packet(rtp_buffer); srtp_protect(session, rtp_buffer, rtp_len, srtp_buffer, &srtp_len); send_srtp_packet(srtp_buffer, srtp_len); }
srtp_dealloc(session); srtp_shutdown();
<a name="credits"></a>
# クレジット
libSRTP の元となる実装とドキュメントは、Secure RTP の利用、理解、および相互運用性を促進するために、Cisco Systems, Inc. の David McGrew によって作成されました。Michael Jerris は MSVC でのビルドサポートに貢献しました。Andris Pavenis は多くの重要な修正に貢献しました。Brian West は動的リンクを可能にする変更に貢献しました。Yves Shumann はドキュメントのバグを報告しました。Randell Jesup は動作する SRTCP 実装とその他の修正に貢献しました。Steve Underwood は x86_64 の移植性に関する変更に貢献しました。また、Fredrik Thulin、Brian Weis、Mark Baugher、Jeff Chan、Bill Simon、Douglas Smith、Bill May、Richard Preistley、Joe Tardo およびその他の方々の貢献、コメント、訂正に感謝します。
このリファレンス資料は、該当する場合、ソースコードの自動ドキュメント化のための doxygen ユーティリティを使用して生成されました。
Copyright 2001-2005 by David A. McGrew, Cisco Systems, Inc.
--------------------------------------------------------------------------------
<a name="references"></a>
# 参考文献
SRTP および ICM の参考文献
2005年9月
Secure RTP は [RFC 3711](https://tools.ietf.org/html/rfc3711) で定義されています。
カウンターモードの定義は [セクション 4.1.1](https://tools.ietf.org/html/rfc3711#section-4.1.1) にあります。
SHA-1 は [FIPS PUB 180-4](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) で定義されています。
HMAC は [RFC 2104](https://tools.ietf.org/html/rfc2104) で定義されており、
HMAC-SHA1 のテストベクターは
[RFC 2202](https://tools.ietf.org/html/rfc2202#section-3) で利用できます。
SRTP での AES-GCM の使用法は [RFC 7714](https://tools.ietf.org/html/rfc7714) で定義されています。
| オプション | 説明 |
|---|
| -s | (S)RTP 送信 - アプリが単語を送信するようにします |
| -r | (S)RTP 受信 - アプリが単語を受信するようにします |
| -k | SRTP マスターキー を使用します。キーは16進数です (先頭の "0x" は付けません) |
| -b | -k と同じですが、キーはbase64エンコードされています |
| -e | 暗号化/復号化 (データの機密性のため) (-k オプションも併用する必要があります) (keysize には 128、192、256 のいずれかを使用します) |
| -g | AES-GCM モードを使用します (-e と併用する必要があります) |
| -a | メッセージ認証 (-k オプションも併用する必要があります) |
| -l | 利用可能なデバッグモジュールを一覧表示します |
| -d | モジュール のデバッグを有効にします |