콘텐츠 보호 GPU-Based
이 항목에서는 그래픽 드라이버가 제공할 수 있는 비디오 콘텐츠 보호 기능에 대해 설명합니다.
- 소개
- 디코딩 프로세스 대한 개요
- 디코더 대한 압축 비디오 버퍼 암호화
- 1. 드라이버 콘텐츠 보호 기능 쿼리
- 2. 인증된 채널 구성
- 3. 암호화 세션 구성
- 4. DXVA 디코더 디바이스 핸들 가져오기
- 5. DXVA 디코더를 암호화 세션 연결
- 인증된 채널 명령 보내는
- 인증된 채널 쿼리 보내는
- 관련 항목
소개
다음 다이어그램에서는 보호된 비디오 콘텐츠가 파이프라인을 통해 렌더링되는 방식을 간략하게 보여 줍니다.
보호된 비디오 콘텐츠를 보여 주는 다이어그램을
메모
PMP(보호된 미디어 경로)는 이 다이어그램에 표시되지 않습니다. 여기에 표시된 데이터 흐름은 PMP 프로세스 내에서 또는 애플리케이션 프로세스 내에서 발생할 수 있습니다.
디코더는 외부 원본에서 암호화된 압축된 비디오 데이터를 받습니다. 디코더도 이 데이터의 암호를 해독하는 암호화 키를 수신하는 것으로 가정합니다. 이 항목에서는 비디오 원본과 디코더 간의 키 교환에 대해 설명하지 않지만 PMP는 가능한 메커니즘을 정의합니다. GPU는 이 단계에 포함되지 않습니다.
하드웨어 가속 디코딩의 경우 소프트웨어 디코더는 압축된 비디오 콘텐츠를 GPU에 전달합니다. 이 콘텐츠를 보호하기 위해 디코더는 데이터를 하드웨어 가속기로 전달하기 전에 일반적으로 AES-CTR을 사용하여 데이터를 다시 암호화합니다. 키 교환 메커니즘은 디코더와 그래픽 드라이버 간에 정의됩니다.
디코딩된 비디오 프레임은 일반적으로 명확한 비디오 메모리에 저장됩니다. 이 시점에서 프레임이 처리된 다음 표시됩니다. 프레젠테이션에는 두 가지 주요 옵션이 있습니다.
- 프레임은 하드웨어 오버레이를 사용하여 표시할 수 있습니다. 자세한 내용은 하드웨어 오버레이 지원 참조하세요.
- 공유 화면을 사용하여 DWM(데스크톱 창 관리)에서 프레임을 표시할 수 있습니다.
마지막 단계는 그래픽 카드와 디스플레이 장치 간에 링크 보호가 필요할 수 있는 모니터에 프레임을 표시하는 것입니다. 링크 보호의 예로 High-Bandwidth HDCP(Digital Content Protection)가 있습니다. 링크 보호는 OPM(Output Protection Manager)을 사용하여 구성됩니다. 이 항목에서는 OPM에 대해 설명하지 않습니다. 자세한 내용은 출력 보호 관리자 사용하여참조하세요.
디코딩 프로세스 개요
하드웨어 가속 디코딩 중에 소프트웨어 디코더는 압축된 비디오 데이터를 그래픽 카드에 전달해야 합니다. 프리미엄 콘텐츠의 경우 일반적으로 GPU로 전송되기 전에 대칭 키 암호화를 사용하여 이 데이터를 암호화해야 합니다.
디코딩을 위해 비디오를 암호화하기 위해 소프트웨어 디코더는 다음 인터페이스를 사용합니다.
- IDirectXVideoDecoder. 가속기라고도 하는 DXVA 디코더 디바이스를 나타냅니다.
- IDirect3DCryptoSession9. 암호화 키를 제공하는 암호화 세션을 나타냅니다.
- IDirect3DAuthenticatedChannel9. 소프트웨어 디코더가 암호화 세션을 DXVA 디코더와 연결할 수 있도록 하는 인증된 채널을 나타냅니다.
direct3d9 디코딩 인터페이스를 보여 주는 다이어그램을
이러한 모든 인터페이스는 다음과 같이 Direct3D 디바이스에서 가져옵니다.
인터페이스 | 창작 |
---|---|
IDirectXVideoDecoder | IDirectXVideoDecoderService::CreateVideoDecoder호출합니다. DXVA 디코더 디바이스는 DXVA 프로필 GUID로 식별됩니다. |
IDirect3DCryptoSession9 | IDirect3DDevice9Video::CreateCryptoSession호출합니다. |
IDirect3DAuthenticatedChannel9 | IDirect3DDevice9Video::CreateAuthenticatedChannel호출합니다. |
메모
IDirect3DDevice9Video 인터페이스에 대한 포인터를 얻으려면 D3D9Ex 디바이스에서 QueryInterface 호출합니다.
인증된 채널은 소프트웨어 디코더와 드라이버 간에 신뢰할 수 있는 통신 채널을 제공합니다. 통신 채널은 다음과 같이 작동합니다.
- 드라이버는 루트 인증서가 Microsoft에서 서명된 X.509 인증서 체인을 제공합니다.
- 인증서에는 드라이버에 대한 RSA 공개 키가 포함되어 있습니다.
- 소프트웨어 디코더는 공개 키를 사용하여 드라이버에 128비트 AES 세션 키를 보냅니다.
- 소프트웨어 디코더는 인증된 채널에 쿼리 및 명령을 보냅니다.
- 세션 키는 쿼리 및 명령에 대한 MAC(메시지 인증 코드)를 계산하는 데 사용됩니다. 드라이버는 MAC를 사용하여 쿼리/명령 데이터의 무결성을 확인하고 소프트웨어 디코더는 이를 사용하여 드라이버에서 응답 데이터의 무결성을 확인합니다.
디코더에 대한 압축된 비디오 버퍼 암호화
다음은 암호화 및 디코딩 프로세스에 대한 개략적인 개요입니다.
소프트웨어 디코더는 비디오 원본에서 암호화된 데이터 스트림을 받습니다. 디코더는 이 스트림의 암호를 해독합니다.
소프트웨어 디코더는 암호화 세션과 세션 키를 협상합니다.
소프트웨어 디코더는 인증된 채널을 사용하여 암호화 세션을 DXVA 디코더 디바이스와 연결합니다.
소프트웨어 디코더는 DXVA 디코더 디바이스(가속기)에서 가져오는 DXVA 버퍼에 압축된 데이터를 넣습니다. 보호된 콘텐츠의 경우 소프트웨어 인코더는 암호화에 대한 세션 키를 사용하여 DXVA 버퍼에 배치되는 데이터를 암호화합니다.
메모
일부 드라이버는 암호화를 위해 세션 키 대신 콘텐츠 키를 사용합니다. 콘텐츠 키는 한 프레임에서 다음 프레임으로 변경됩니다.
디코더는 암호화된 압축 버퍼를 가속기로 제출합니다. AES-CTR의 경우 디코더는 초기화 벡터도 전달합니다. 콘텐츠 키를 사용하는 경우 디코더는 세션 키를 사용하여 암호화된 콘텐츠 키를 전달합니다.
Direct3D는 128비트 AES-CTR에 대한 표준 지원을 제공하지만 추가 암호화 유형으로 확장되도록 설계되었습니다.
다음 5개 섹션에서는 더 자세한 단계를 제공합니다.
- 1. 드라이버 콘텐츠 보호 기능 쿼리
- 2. 인증된 채널 구성
- 3. 암호화 세션 구성
- 4. DXVA 디코더 디바이스 핸들 가져오기
- 5. DXVA 디코더를 암호화 세션 연결
1. 드라이버의 콘텐츠 보호 기능 쿼리
암호화를 적용하기 전에 드라이버의 콘텐츠 보호 기능을 가져옵니다.
- Direct3D 9 디바이스에 대한 포인터를 가져옵니다.
- IDirect3DDevice9Video 인터페이스에 대한 QueryInterface 호출합니다.
- IDirect3DDevice9Video::GetContentProtectionCaps호출합니다. 이 메서드는 드라이버의 콘텐츠 보호 기능으로 D3DCONTENTPROTECTIONCAPS 구조를 채웁니다.
특히 다음 기능을 찾습니다.
- Caps 멤버에 D3DCPCAPS_SOFTWARE 또는 D3DCPCAPS_HARDWARE 플래그가 포함된 경우 드라이버는 암호화를 수행할 수 있습니다.
- KeyExchangeType 멤버는 세션 키에 대한 키 교환을 수행하는 방법을 지정합니다.
- Caps 멤버에 D3DCPCAPS_CONTENTKEY 플래그가 포함된 경우 드라이버는 암호화에 별도의 콘텐츠 키를 사용합니다. 이는 세션 키를 생성할 때 중요합니다.
추가 기능은 Caps 멤버에 표시됩니다.
2. 인증된 채널 구성
다음 단계는 인증된 채널을 구성하는 것입니다.
IDirect3DDevice9Video::CreateAuthenticatedChannel 호출하여 인증된 채널을 만듭니다. ChannelType 매개 변수의 경우 드라이버의 기능과 일치하는 채널 형식을 지정합니다.
- D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE 채널 형식은 D3DCPCAPS_SOFTWARE해당합니다.
- D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE 채널 형식은 D3DCPCAPS_HARDWARE해당합니다.
CreateAuthenticatedChannel 메서드는 채널에 대한 핸들과 함께 IDirect3DAuthenticatedChannel9 인터페이스에 대한 포인터를 반환합니다. 이 핸들은 나중에 암호화 세션을 인증된 채널과 연결하는 데 사용됩니다.
IDirect3DAuthenticatedChannel9::GetCertificateSize 호출하여 드라이버의 X.509 인증서 크기를 가져옵니다. 필요한 크기의 버퍼를 할당합니다.
IDirect3DAuthenticatedChannel9::GetCertificate 호출하여 인증서를 가져옵니다. 이 메서드는 이전 단계에서 할당된 버퍼에 인증서를 복사합니다.
드라이버의 인증서가 Microsoft에서 서명되었으며 해지되지 않은지 확인합니다.
인증서에서 공개 키를 가져옵니다.
임의의 RSA 세션 키를 생성합니다. 이 세션 키는 인증된 채널로 전송되는 데이터에 서명하는 데 사용됩니다. 드라이버의 공개 키를 사용하여 세션 키를 암호화합니다.
IDirect3DAuthenticatedChannel9::NegotiateKeyExchange 호출하여 암호화된 세션 키를 드라이버에 보냅니다.
다음과 같이 보안 채널을 초기화합니다.
- 설명서에 설명된 대로 D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE 구조를 입력합니다.
- IDirect3DAuthenticatedChannel9::Configure 호출하여 D3DAUTHENTICATEDCONFIGURE_INITIALIZE 명령을 보냅니다. 인증된 채널 명령 보내기섹션에 설명된 대로 구성합니다. 이 명령은 인증된 채널로 전송되는 명령 및 쿼리에 대한 시작 시퀀스 번호를 포함합니다.
인증된 채널 쿼리 보내기 섹션에 설명된 대로 인증된 채널에D3DAUTHENTICATEDQUERY_CHANNELTYPE 쿼리를 전송하여 채널 유형을 확인합니다. 채널 형식이 CreateAuthenticatedChannel 메서드에서 지정한 것과 일치하는지 확인합니다.
3. 암호화 세션 구성
다음으로, 암호화 세션을 구성하고 세션 키를 설정합니다.
- IDirect3DDevice9Video::CreateCryptoSession 호출하여 암호화 세션을 만듭니다. 이 메서드는 IDirect3DCryptoSession9 인터페이스에 대한 포인터와 암호화 세션에 대한 핸들을 반환합니다.
- IDirect3DCryptoSession9::GetCertificateSize 호출하여 드라이버의 X.509 인증서 크기를 가져옵니다. 필요한 크기의 버퍼를 할당합니다.
- IDirect3DCryptoSession9::GetCertificate 호출하여 인증서를 가져옵니다. 이 메서드는 이전 단계에서 할당된 버퍼에 인증서를 복사합니다.
- 드라이버의 인증서가 Microsoft에서 서명되었으며 해지되지 않은지 확인합니다.
- 인증서에서 공개 키를 가져옵니다.
- 임의의 RSA 세션 키를 생성합니다. 인증된 채널 세션 키와는 별도의 세션 키입니다. 드라이버의 공개 키를 사용하여 세션 키를 암호화합니다.
- IDirect3DCryptoSession9::NegotiateKeyExchange 호출하여 암호화된 세션 키를 드라이버에 보냅니다.
- 콘텐츠 보호 기능에 D3DCPCAPS_CONTENTKEY포함된 경우 임의의 RSA 콘텐츠 키를 만듭니다. 디코딩 프로세스의 뒷부분에서 사용됩니다.
4. DXVA 디코더 디바이스에 대한 핸들 가져오기
다음 단계에서는 DXVA 디코더 디바이스에 대한 핸들이 필요합니다. 이 핸들을 가져오려면 다음과 같이 DXVA2_DecodeExecuteParams 구조를 입력합니다.
HANDLE hDecodeDeviceHandle;
DXVA2_DecodeExecuteParams execParams = {0};
DXVA2_DecodeExtensionData ExtensionExecute = {0};
execParams.NumCompBuffers = 0;
execParams.pCompressedBuffers = NULL;
execParams.pExtensionData = &ExtensionExecute;
ExtensionExecute.Function = DXVA2_DECODE_GET_DRIVER_HANDLE;
ExtensionExecute.pPrivateInputData = NULL;
ExtensionExecute.PrivateInputDataSize = 0;
ExtensionExecute.pPrivateOutputData = &hDecodeDeviceHandle;
ExtensionExecute.PrivateOutputDataSize = sizeof(HANDLE);
DXVA2_DecodeExecuteParams 구조체의 pExtensionData 멤버를 DXVA2_DecodeExtensionData 구조체의 주소로 설정합니다.
DXVA2_DecodeExtensionData 구조에서 함수 멤버를 DXVA2_DECODE_GET_DRIVER_HANDLE설정합니다. pPrivateOutputDataHANDLE 값을 저장할 수 있을 만큼 큰 버퍼의 주소로 설정합니다. (이전 예제에서 이 버퍼는 hDecodeDeviceHandle 변수입니다.)
그런 다음 IDirectXVideoDecoder::Execute 호출하고 DXVA2_DecodeExecuteParams 구조체의 주소를 전달합니다. DXVA 디코더에 대한 핸들은 pPrivateOutputData반환됩니다.
5. DXVA 디코더를 암호화 세션과 연결
다음으로, 다음과 같이 DXVA 디코더 디바이스를 Direct3D 디바이스 및 암호화 세션과 연결합니다.
- 이전 섹션에서 설명한 대로 DXVA 디코더 디바이스에 대한 핸들을 가져옵니다.
- 인증된 채널에 D3DAUTHENTICATEDQUERY_DEVICEHANDLE 쿼리를 전송하여 Direct3D 디바이스에 대한 핸들을 가져옵니다.
- 다음 정보를 사용하여 D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION 구조를 채웁니다.
- DXVA2DecodeHandle 멤버를 DXVA 디코더 디바이스에 대한 핸들로 설정합니다.
- CryptoSessionHandle 멤버를 암호화 세션의 핸들로 설정합니다. 이 핸들은 IDirect3DDevice9Video::CreateCryptoSession 메서드에 의해 반환됩니다.
- DeviceHandle 멤버를 Direct3D 디바이스 핸들로 설정합니다.
- IDirect3DAuthenticatedChannel9:: 호출하여 인증된 채널에 D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION 명령을 보냅니다.
다음 다이어그램에서는 핸들 교환을 보여 줍니다.
dxva 디코더가 암호화 세션과 연결되는 방법을 보여 주는 다이어그램을
이제 소프트웨어 디코더가 암호화 세션 키를 사용하여 압축된 비디오 버퍼를 암호화할 수 있습니다. 압축된 각 버퍼에는 DXVA2_DecodeBufferDesc 구조의 pvPVPState 멤버에 지정된 고유한 IV(초기화 벡터)가 있습니다.
인증된 채널 명령 보내기
명령 집합은 인증된 채널을 구성하고 다양한 콘텐츠 보호를 설정하기 위해 정의됩니다. 명령 목록은 Content Protection 명령참조하세요.
인증된 채널에 명령을 보내려면 다음 단계를 수행합니다.
- 입력 데이터 구조를 입력합니다. 이 데이터 구조는 항상 D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT 구조와 추가 필드입니다. 다음 표와 같이 D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT 구조를 채웁니다.
구성원 | 묘사 |
---|---|
omac | 지금은 이 필드를 건너뜁니다. |
ConfigureType | 명령을 식별하는 GUID입니다. 명령 목록은 Content Protection 명령참조하세요. |
hChannel | 인증된 채널에 대한 핸들입니다. |
SequenceNumber | 시퀀스 번호입니다. 첫 번째 시퀀스 번호는 D3DAUTHENTICATEDCONFIGURE_INITIALIZE 명령을 전송하여 지정됩니다. 다른 명령을 보낼 때마다 이 숫자를 1씩 증분합니다. 시퀀스 번호는 재생 공격을 방지합니다.
참고: 두 개의 개별 시퀀스 번호가 사용됩니다. 하나는 명령에, 다른 하나는 쿼리용입니다. |
- 입력 구조의 omac 멤버 뒤 나타나는 데이터 블록에 대한 OMAC 태그를 계산합니다. 그런 다음 이 태그 값을 omac 멤버에 복사합니다.
- IDirect3DAuthenticatedChannel9::configure호출합니다.
- 드라이버는 명령의 출력을 D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT 구조에 배치합니다.
- 출력 구조의 omac 멤버 뒤 나타나는 데이터 블록에 대한 OMAC 태그를 계산합니다. 이를 omac 멤버의 값과 비교합니다. 일치하지 않으면 실패합니다.
- 출력 구조의 ConfigureType, hChannel및 SequenceNumber 멤버의 값을 해당 멤버의 값과 비교합니다. 일치하지 않으면 실패합니다.
- 다음 명령에 대한 시퀀스 번호를 증분합니다.
인증된 채널 쿼리 보내기
인증된 채널에 대한 정보를 검색하기 위한 쿼리 집합이 정의됩니다. 쿼리 목록은 Content Protection 쿼리참조하세요.
인증된 채널에 명령을 보내려면 다음 단계를 수행합니다.
- 입력 데이터 구조를 입력합니다. 이 데이터 구조는 항상 D3DAUTHENTICATEDCHANNEL_QUERY_INPUT 구조이며 추가 필드가 뒤따를 수 있습니다. 다음 표와 같이 D3DAUTHENTICATEDCHANNEL_QUERY_INPUT 구조를 채웁니다.
구성원 | 묘사 |
---|---|
QueryType | 쿼리를 식별하는 GUID입니다. 쿼리 목록은 Content Protection 쿼리참조하세요. |
hChannel | 인증된 채널에 대한 핸들입니다. |
SequenceNumber | 시퀀스 번호입니다. 첫 번째 시퀀스 번호는 D3DAUTHENTICATEDCONFIGURE_INITIALIZE 명령을 전송하여 지정됩니다. 다른 쿼리를 보낼 때마다 이 숫자를 1씩 증분합니다. 시퀀스 번호는 재생 공격을 방지합니다.
참고: 두 개의 개별 시퀀스 번호가 사용됩니다. 하나는 명령에, 다른 하나는 쿼리용입니다. |
- IDirect3DAuthenticatedChannel9::Query호출합니다.
- 드라이버는 쿼리의 출력을 D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT 구조에 배치합니다. 이 구조 다음에는 쿼리 형식에 따라 추가 필드가 추가됩니다.
- 출력 구조의 omac 멤버 뒤 나타나는 데이터 블록에 대한 OMAC 태그를 계산합니다. 이를 omac 멤버의 값과 비교합니다. 일치하지 않으면 실패합니다.
- 출력 구조의 ConfigureType, hChannel및 SequenceNumber 멤버의 값을 해당 멤버의 값과 비교합니다. 일치하지 않으면 실패합니다.
- 다음 쿼리의 시퀀스 번호를 증분합니다.