使用 Output Protection Manager
本主題描述如何使用 Output Protection Manager (OPM) 保護視訊內容,因為它透過實體連接器傳輸至顯示裝置。 本主題包含下列幾節:
進階版 影片內容通常會加密,以防止未經授權的重複。 當然,影片必須先解密,才能顯示影片。 解密、未壓縮的畫面格接著必須跨越實體連接器前往顯示裝置。 內容提供者此時可能需要保護視訊畫面,因為它們會跨越實體連接器。
基於此目的,存在各種保護機制,包括數位輸出的高頻寬數位內容保護 (HDCP) 和 DisplayPort 內容保護 (DPCP) :和複製產生管理系統 - 類比 (CGMS-A) 用於模擬輸出。 一般而言,這些機制牽涉到加密或爭先恐後地將訊號傳送到顯示器上。
OPM 可讓應用程式在影片輸出上強制執行內容保護機制。 使用 OPM,應用程式會透過受信任的安全通道,將命令和狀態要求傳送至圖形驅動程式。 OPM 可讓應用程式:
- 確認圖形驅動程式已由 Microsoft 簽署。
- 使用驅動程式設定受信任的通道。
- 在實體輸出上強制執行內容保護機制。
OPM 會取代認證輸出保護通訊協定 (COPP),並使用類似的 API。 為了獲得回溯相容性,OPM 介面可以模擬 COPP 介面。 OPM 和 COPP 之間的差異如下:
- OPM 使用 X.509 憑證,而 COPP 則使用專屬憑證格式。
- OPM 支援 HDCP 重複程式。
- 使用 OPM 的應用程式不需要剖析 HDCP 系統更新性訊息 (SRM)。
- 當圖形顯示使用複製模式時,可以使用 OPM。 COPP 不支援複製模式。
如果您的應用程式使用受保護的媒體路徑 (PMP) 播放視訊內容,則不需要使用 OPM API,因為 PMP 會進行所有必要的 OPM 呼叫。 OPM API 適用於不使用 PMP 的應用程式。
OPM 可在 Windows Vista 和更新版本中取得,但 API 直到 Windows 7 才公開。 若要在應用程式中使用 OPM,您必須擁有來自 Windows 7 SDK 的標頭和連結庫檔案。 您不需要轉散發任何 DLL,即可在 Windows Vista 或 Windows Server 2008 中使用 OPM。
視訊輸出
圖形配接器可以有多個實體輸出,每個輸出都有自己的功能。 在應用程式播放受保護的內容之前,它必須在與顯示視訊之圖形卡相關聯的每個視訊輸出上設定適當的保護機制。 要套用的保護機制將取決於內容的使用規則。
每個視訊輸出都會以 IOPMVideoOutput 介面的 實例來表示。 您可以使用 Direct3D 裝置或監視控制碼來取得視訊輸出。
使用 Direct3D 裝置:
- 取得您應用程式將用來建立介面來保存視訊畫面之 Direct3D 裝置的 IDirect3DDevice9 指標。
- 呼叫 OPMGetVideoOutputsFromIDirect3DDevice9Object 函式。 此函式會配置 IOPMVideoOutput 指標陣列 ,每個輸出各一個。
使用監視控制碼:
- 呼叫 EnumDisplayMonitors 以取得 對應至視訊視窗的 HMONITOR 控制碼。 數個監視器可以與相同的視窗相關聯,因此您可能會取得數個 HMONITOR 控制碼。
- 針對每個監視器控制碼,呼叫 OPMGetVideoOutputsFromHMONITOR 。 此函式會配置 IOPMVideoOutput 指標陣列 ,每個輸出各一個。
初始化 OPM 會話
在應用程式傳送 OPM 命令或狀態要求之前,它必須確認視訊輸出是否受信任,並建立工作階段金鑰。 工作階段金鑰可用來簽署應用程式與圖形驅動程式之間交換的資料。
OPM API 會定義交握,以建立信任並設定工作階段金鑰。 您必須針對 IOPMVideoOutput 介面的每個實例 執行此交握,如下所示:
呼叫 IOPMVideoOutput::StartInitialization 。 此方法會擷取兩個數據片段:
- 驅動程式所產生的亂數。 您將使用此數位來完成交握。
- 驅動程式的 X.509 憑證鏈結。
確認憑證鏈結已由 Microsoft 簽署。
注意
憑證撤銷超出 OPM 的範圍。
從憑證鏈結取得驅動程式的公開金鑰。
產生 128 位 AES 工作階段金鑰。
產生兩個隨機 32 位數位:
- OPM 狀態要求的起始序號。
- OPM 命令的起始序號。
這些數位必須使用密碼編譯保護的虛擬亂數產生器來產生,例如 CryptGenRandom 。
將驅動程式的亂數(在步驟 1 中取得)、會話索引鍵和兩個 序號複製到OPM_ENCRYPTED_INITIALIZATION_PARAMETERS 結構,如 IOPMVideoOutput::FinishInitialization 中所述 。
使用驅動程式的公開金鑰,使用驅動程式的公開金鑰,使用 RSAES-OAEP 加密OPM_ENCRYPTED_INITIALIZATION_PARAMETERS 結構。
傳送 OPM 狀態要求
OPM 狀態要求會傳回視訊輸出的相關資訊,例如實體連接器的類型和目前的保護等級。 如需要求類型清單,請參閱 OPM 狀態要求 。
若要傳送狀態要求,請執行下列步驟。
初始化OPM_GET_INFO_PARAMETERS 結構,如下表所示。
member 描述 omac 暫時略過此欄位。 rnRandomNumber 以密碼編譯方式保護 128 位亂數。 每當您提出狀態要求時,請一律產生新的亂數,即使您提出相同的要求也一樣。 將數位儲存在變數中,因為您稍後必須參考它。 guidInformation 識別狀態要求的 GUID。 如需狀態要求的清單,請參閱 OPM 狀態要求 。 ulSequenceNumber 序號。 針對第一個狀態要求,請使用您在 IOPMVideoOutput::FinishInitialization 方法中指定的 起始序號(初始化 OPM 會話 的步驟 5 )。 每次提出另一個狀態要求時,請將這個數位遞增 1。 abParameters 位元組陣列,其中包含要求的其他輸入資料。 輸入資料的格式會列在每個狀態要求的參考主題中。 cbParametersSize abParameters 陣列中 有效資料的大小。 陣列其餘部分的內容未定義。 計算單鍵 CBC MAC (OMAC-1) 以計算出現在 omac 成員之後 之資料區塊的雜湊,然後將 omac 成員設定 為此值。 請參閱 OPM 範例程式碼 。
呼叫 IOPMVideoOutput::GetInformation 方法。 傳入OPM_GET_INFO_PARAMETERS 結構的指標 ,以及OPM_REQUESTED_INFORMATION 結構的指標 。 驅動程式的回應會 寫入至OPM_REQUESTED_INFORMATION 結構。
- 這個結構的 omac 成員包含針對此成員之後資料所計算的 OMAC。
- abRequestedInformation 成員是位元組陣列,其中包含回應的輸出資料。 輸出資料的格式會列在每個狀態要求的參考主題中。
計算OPM_REQUESTED_INFORMATION 結構的 OMAC ,不包括 omac 成員。 確認 OMAC 符合 omac 成員中的 值。
請確定 OPM_REQUESTED_INFORMATION 結構的 cbRequestedInformationSize 成員 為輸出資料提供正確的大小。 例如,OPM_GET_CONNECTOR_TYPE 查詢的 輸出資料是 OPM_STANDARD_INFORMATION 結構,因此 cbRequestedInformationSize 的值 應該是
sizeof(OPM_STANDARD_INFORMATION)
。將 OPM_REQUESTED_INFORMATION 結構的 abRequestedInformation 成員 轉換成正確的輸出資料結構。 例如,如果狀態要求是 OPM_GET_CONNECTOR_TYPE ,請將 abRequestedInformation 轉換為 OPM_STANDARD_INFORMATION 結構。
請確定 輸出資料結構的 rnRandomNumber 成員符合步驟 1 中的 rnRandomNumber 值 。
檢查輸出資料結構的 ulStatusFlags 成員,如處理已停用的視訊輸出 中所述 。
如果步驟 5-8 中的任何檢查失敗,應用程式必須停止顯示受保護的內容。
傳送 OPM 命令
OPM 命令可用來設定影片輸出的保護層級和其他設定。 傳送 OPM 命令類似于傳送狀態要求,但驅動程式沒有回應資料。 如需命令清單,請參閱 OPM 命令 。
若要傳送 OPM 命令,請執行下列步驟。
填入 OPM_CONFIGURE_PARAMETERS 結構,如下表所示。
member 描述 omac 暫時略過此欄位。 guidSetting 識別命令的 GUID。 如需命令清單,請參閱 OPM 命令 。 ulSequenceNumber 序號。 針對第一個命令,請使用您在 IOPMVideoOutput::FinishInitialization 方法中指定的 起始序號(初始化 OPM 會話 的步驟 5 )。 每次傳送另一個命令時,請將這個數位遞增 1。 abParameters 位元組陣列,其中包含命令的其他輸入資料。 輸入資料的格式會列在每個命令的參考主題中。 cbSettingDataSize abParameters 陣列中 有效資料的大小。 陣列其餘部分的內容未定義。 針對出現在 omac 成員之後 的資料區塊計算 OMAC,然後將 omac 成員設定 為此值。
對於大部分的命令,有一個對應的狀態要求會傳回命令的狀態。 例如, OPM_SET_PROTECTION_LEVEL 命令會設定保護層級,而 OPM_GET_VIRTUAL_PROTECTION_LEVEL 命令會取得目前的保護層級。
處理已停用的視訊輸出
視訊輸出可以隨時停用本身,以防止未經授權的視訊內容使用。 這可能是因為保護機制停止運作,因為驅動程式偵測到竄改,或因為顯示器與實體連接器中斷連線。 停用視訊輸出時,不會顯示任何視訊畫面。
啟用內容保護時,應用程式應該定期執行下列步驟(至少每 2 秒一次)。
- 呼叫 IOPMVideoOutput::GetInformation 以傳送 OPM_GET_ACTUAL_PROTECTION_LEVEL 或 OPM_GET_VIRTUAL_PROTECTION_LEVEL 狀態要求。 這兩個 命令的傳回資料是OPM_STANDARD_INFORMATION 結構。
- 檢查 OPM_STANDARD_INFORMATION 結構的 ulInformation 成員 。 此成員包含旗標,指出是否仍啟用內容保護。 如果內容保護已關閉,請立即停止播放影片。
- 如果內容保護已開啟,請檢查 OPM_STANDARD_INFORMATION 結構的 ulStatusFlags 成員 。 如果未設定旗標,影片輸出就會正常運作。 否則,會停用視訊輸出。
下列旗標是針對 ulStatusFlags 所 定義的。
旗標 | 描述 |
---|---|
OPM_STATUS_LINK_LOST | 輸出保護因故停止運作;例如,顯示裝置可能會從連接器中解開。 停止播放並關閉所有輸出保護機制。 |
OPM_STATUS_RENEGOTIATION_REQUIRED | 應用程式必須重新建立 OPM 會話。 回應如下:
|
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED | 只有在使用 HDCP 時,才會套用此旗標,並指出已撤銷的 HDCP 裝置是否存在。 停止播放並關閉此影片輸出上的所有保護機制。 設定此旗標時, 也會設定OPM_STATUS_LINK_LOST 旗標。 |
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED | 驅動程式偵測到竄改。 停止播放,而且不要再使用此視訊輸出播放任何視訊。 也建議您停止使用任何其他視訊輸出,因為系統可能會遭到入侵。 |
使用 HDCP 保護內容
本節說明如何使用 OPM 啟用 HDCP 輸出保護。 以下是應用程式必須採取之步驟的一般大綱。 本節稍後會提供詳細資料。
- 應用程式可能必須提供 SRM 給影片輸出。 接收 SRM 的機制不在 OPM 介面的範圍內。 例如,SRM 可能會作為廣播資料流程的一部分傳遞。
- 應用程式會啟用 HDCP 輸出保護。
- 應用程式會播放影片內容。 應用程式會定期輪詢驅動程式,以確定 HDCP 已開啟。
- 播放完成時,應用程式會關閉 HDCP。
設定 SRM
若要設定 SRM,請執行下列步驟。
- 使用 SRM 版本號碼初始化OPM_SET_HDCP_SRM_PARAMETERS 結構。
- 將 SRM 儲存在變數中。
- 將OPM_SET_HDCP_SRM 命令傳送至影片輸出。 使用傳送 OPM 命令 中所述 的程式。
- OPM_CONFIGURE_PARAMETERS 結構的 abParameters 成員 包含 OPM_SET_HDCP_SRM_PARAMETERS 結構。
- IOPMVideoOutput::Configure 方法的 pbAdditionalParameters 參數會指向包含 SRM 的變數。
- 將OPM_GET_CURRENT_HDCP_SRM_VERSION 狀態要求傳送至影片輸出。 使用傳送 OPM 狀態要求 中所述 的程式。 此狀態要求沒有輸入資料,因此未定義 OPM_GET_INFO_PARAMETERS 結構的 abParameters 成員 內容 。
- 當 IOPMVideoOutput::GetInformation 方法傳回時, OPM_REQUESTED_INFORMATION 結構中的 abRequestedInformation 陣列包含 OPM_STANDARD_INFORMATION 結構。 這個結構的 ulInformation 成員包含目前 SRM 的版本號碼。 此值必須等於步驟 2 中的值。
啟用 HDCP
若要啟用 HDCP,請執行下列步驟。
- 使用下列值初始化OPM_SET_PROTECTION_LEVEL_PARAMETERS 結構:
- ulProtectionType = OPM_PROTECTION_TYPE_HDCP
- ulProtectionLevel = OPM_HDCP_ON
- 保留 = 0
- Reserved2 = 0
- 傳送OPM_SET_PROTECTION_LEVEL 命令。 abParameters 陣列中的 輸入資料是 OPM_SET_PROTECTION_LEVEL_PARAMETERS 結構。
- 傳送OPM_GET_VIRTUAL_PROTECTION_LEVEL 狀態要求,以檢查是否已啟用 HDCP。 OPM_GET_INFO_PARAMETERS 結構之 abParameters 成員 的前 4 個位元組 包含值 OPM_PROTECTION_TYPE_HDCP 。
當 GetInformation 方法傳回時, OPM_REQUESTED_INFORMATION 結構中的 abRequestedInformation 陣列包含 OPM_STANDARD_INFORMATION 結構。 這個結構的 ulInformation 成員包含來自 OPM_HDCP_PROTECTION_LEVEL 列舉的值。 如果值等於 OPM_HDCP_ON ,表示已啟用 HDCP。 否則,請重複步驟 1-2,直到啟用 HDCP 或發生錯誤為止。 (請記得遞增序號,並每次產生新的亂數。
啟用 HDCP 通常需要 100 到 200 毫秒,但可能需要較長的時間。 在驗證 HDCP 之前,請勿假設已啟用 HDCP。
當應用程式完成播放受保護的內容時,請關閉 HDCP。 這些步驟與啟用 HDCP 的步驟相同,但在步驟 1 中,將 ulProtectionLevel 設定 為 OPM_HDCP_OFF 。
注意
如果連接器類型OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED ,請勿啟用 HDCP。 (請參閱 OPM 連線or 類型旗標 。)
相關主題