DRM コンテンツ ID の転送
DRMK システム ドライバーは、保護されたコンテンツを含むオーディオ再生ストリームをスクランブル解除します。 DRMK は KS フィルターを実装します。KS フィルターは、スクランブルされたデータを含む入力ストリームを受け取りて、スクランブル解除し、一部のカーネル常駐モジュールで構成されるデータ パスに、非暗号化ストリームをフィードします。 これらのモジュールには、KS フィルターまたは他の種類のドライバーを指定できます。 データ パスは通常、スピーカーを介してデジタル コンテンツを再生できるアナログ信号に変換するオーディオ レンダリング デバイスで終わります。
DRMK は、スクランブル解除されたコンテンツがデータ パスに入ることを許可する前に、データ パスがセキュアであることを確認します。 これを行うために、DRMK はデータ パス内の各モジュールを認証します。これは、データ パスのアップストリーム側のモジュールから始まり、データ パスのもう一方のダウンストリーム側まで移動します。 このプロセスを次の図に示します。
上の図では、実線矢印はデータ パスを表しており、破線矢印はデータ パスがセキュアであることを確認するために必要な通信を表しています。 スクランブル解除されたデータは、DRMK がそのパス内のすべてのモジュールの認証を完了した後にのみ、パスに入ります。
DRMK が各モジュールを認証すると、そのモジュールはデータ パス内の次のモジュールに関する情報を DRMK に提供し、認証もできるようにします。 各モジュールは、認証されると、ストリームを識別する DRM コンテンツ ID を受け取ります。
DRMK は、セキュア データ パスのアップストリーム側から、コンテンツ ID をモジュール A に転送した後、コンテンツ ID をモジュール B に転送します。このプロセスは、コンテンツ ID が、セキュア データ パスの最後のモジュールであるモジュール Z に転送されるまで続きます。
次の図は、データ パス内の隣接するモジュールのペアを示しています。
アップストリーム側のモジュールは、次のいずれかの DRM 関数を呼び出して、ダウンストリーム モジュールに関する情報を DRMK に提供し、コンテンツ ID をそのモジュールに転送します。
DrmForwardContentToDeviceObject
これらの "転送" 関数はそれぞれ、保護されたストリームを識別する DRM コンテンツ ID と、DRMK がダウンストリーム モジュールを認証するために必要な情報を DRMK に提供します。 これら 3 つの関数のうちどれを呼び出すのかは、保護されたコンテンツの転送を管理する際に、隣接する 2 つのモジュールが相互に通信するために使用するインターフェイスの種類によって異なります。
アップストリーム モジュールが IoCallDriver を呼び出してダウンストリーム モジュールと通信する場合、ダウンストリーム モジュールは WDM ドライバーの一部となります。 この場合、アップストリーム モジュールは DrmForwardContentToDeviceObject を呼び出し、ダウンストリーム モジュールを表すデバイス オブジェクトを DRMK に提供します。 DRMK は、デバイス オブジェクトを使用してダウンストリーム モジュールを認証します。
ダウンストリーム モジュールにより実装された COM インターフェイスを介して 2 つのモジュールが通信する場合、アップストリーム モジュールは DrmForwardContentToInterface を呼び出します。 この呼び出しは、ダウンストリーム モジュールの COM インターフェイスへのポインターを DRMK に提供します。 DRMK は、このインターフェイスの IUnknown メソッドのみを呼び出し、他のメソッドについては仮定を行いませんが、2 つのモジュール自体がこれらのメソッドの動作に同意する必要があります。 DRMK は、インターフェイス内の各メソッドのエントリ ポイントが認証済みモジュールに属していることを確認します。 エントリ ポイントが複数のモジュールに分散している場合、DRMK はこれらすべてのモジュールを認証します。
2 つのモジュールが通信に COM インターフェイスも IoCallDriver 関数も使用しない場合、アップストリーム モジュールは DrmAddContentHandlers を呼び出して、ダウンストリーム モジュールに実装されている "コンテンツ ハンドラー" へのエントリ ポイントの一覧を DRMK に提供します。 DRMK はコンテンツ ハンドラーを呼び出さず、実行する関数に関する仮定も行いません。 ただし、DRMK は、エントリ ポイントが存在する単一のモジュール (または複数のモジュール) を認証します。
認証された後、ダウンストリーム モジュールには次の情報が必要になります。
保護されたコンテンツを含むストリームを識別する DRM コンテンツ ID。 モジュールでは、この ID を使用して、保護されたコンテンツを送信する予定の任意のモジュール (さらにダウンストリーム方向) を DRMK に通知する必要があります。
保護されたコンテンツに関連付けられている DRM コンテンツ権限。 適切なレベルのセキュリティを適用するため、モジュールにはコンテンツ権限が必要です。
3 つの各転送関数は、少し異なる方法でモジュールにこの情報を提供します。
DrmForwardContentToDeviceObject 関数は、KSPROPERTY_DRMAUDIOSTREAM_CONTENTID 設定プロパティ要求をダウンストリーム モジュールのデバイス オブジェクトに送信します。 この要求により、ストリームのコンテンツ ID とコンテンツ権限がダウンストリーム モジュールに転送されます。
DrmForwardContentToInterface 関数は、ダウンストリーム モジュールの COM インターフェイスに対して IDrmAudioStream インターフェイスのクエリを実行します。 クエリに成功した場合、関数は IDrmAudioStream::SetContentId メソッドを呼び出して、コンテンツ ID とコンテンツ権限をダウンストリーム モジュールに転送します。
DrmAddContentHandlers 関数の場合、呼び出し元 (アップストリーム モジュール) は、ストリームのコンテンツ ID とコンテンツ権限をダウンストリーム モジュールに転送する役割を担います。 ダウンストリーム モジュールが認証されたことを示す成功コードを DrmAddContentHandlers が返すと、アップストリーム モジュールはコンテンツ ハンドラーのいずれかを呼び出して、コンテンツ ID とコンテンツ権限をダウンストリーム モジュールに渡します。
アップストリーム モジュールが WaveCyclic または WavePci ミニポート ドライバーの場合、次のいずれかのメソッドを使用して、適切な DRM 関数を間接的に呼び出すことができます。
IDrmPort2::ForwardContentToDeviceObject
IDrmPort::ForwardContentToInterface
詳細については、「DRM 関数」を参照してください。
わかりやすくするため、前の説明では、データ パス内の各モジュールが 1 つのソースからのストリームを受け入れ、そのストリームを最大 1 つのダウンストリーム モジュールに転送することを前提としています。 実際、モジュールはストリームを 2 つ以上のダウンストリーム モジュールに転送できますが、最初に 3 つの転送関数のいずれかを呼び出して、各ダウンストリーム モジュールを認証する必要があります。 同様に、モジュールは複数の入力ストリームを混在させることができますが、混合出力ストリームに適切なレベルの保護を提供することにより、入力ストリームのコンテンツ権限に従う必要があります。 詳しくは、「コンテンツ ID とコンテンツ権限」の DrmCreateContentMixed 関数の説明をご覧ください。
一般的なセキュア データ パスは、KMixer システム ドライバーの後、オーディオ レンダリング デバイスを表すウェーブ フィルターで構成されます。 フィルターは、対応するポート ドライバーと組み合わせて WaveCyclic または WavePci ミニポート ドライバーとして実装されます。 データ パスがセキュアであることを確認するため、DRMK はコンテンツ ID を KMixer に転送し、コンテンツ ID をフィルターに転送します。 汎用フィルター機能を実装するポート ドライバーは、コンテンツ ID を受け取り、ミニポート ドライバーに転送します。 具体的には、ポート ドライバーは、オーディオ レンダリング デバイスのウェーブ出力ピンを表すためにミニポート ドライバーによってインスタンス化されたストリーム オブジェクトにコンテンツ ID を転送する DrmForwardContentToInterface 関数を呼び出します。 この呼び出しのパラメーター値の 1 つは、ストリーム オブジェクトの IMiniportWaveCyclicStream または IMiniportWavePciStream インターフェイスへのポインターです。 このインターフェイスを通じて、関数はストリーム オブジェクトに対してその IDrmAudioStream インターフェイスのクエリを実行し、そのインターフェイスの SetContentId メソッドを 呼び出します。
詳しくは、「サンプル オーディオ ドライバー」で説明されている Sysvad サンプル ドライバーの SetContentId メソッドの実装をご覧ください。