인증서 해지 목록

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngineMedia Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

이 항목에서는 COPP(Certified Output Protection Protocol)를 사용할 때 해지된 드라이버에 대해 CRL(인증서 해지 목록)을 검사하는 방법을 설명합니다.

CRL에는 해지된 인증서의 다이제스트가 포함되어 있으며 Microsoft에서만 제공하고 서명할 수 있습니다. CRL은 DRM(디지털 권한 관리) 라이선스를 통해 배포됩니다. CRL은 드라이버의 인증서 체인에 있는 모든 인증서를 해지할 수 있습니다. 체인의 인증서가 해지되면 해당 인증서와 체인의 인증서 아래에 있는 모든 인증서도 해지됩니다.

CRL을 얻으려면 애플리케이션에서 Windows Media Format SDK 버전 9 이상을 사용하고 다음 단계를 수행해야 합니다.

  1. WMCreateReader를 호출하여 Windows Media Format SDK 판독기 개체를 만듭니다.
  2. IWMDRMReader 인터페이스에 대한 판독기 개체를 쿼리합니다.
  3. G_WSZWMDRMNET_REVOCATION 값으로 IWMDRMReader::GetDRMProperty 를 호출하여 CRL을 가져옵니다. 이 메서드를 두 번 호출해야 합니다. 할당할 버퍼의 크기를 얻으려면 한 번, 버퍼를 채우려면 한 번 호출해야 합니다. 두 번째 호출은 CRL을 포함하는 문자열을 반환합니다. 전체 문자열은 base-64로 인코딩됩니다.
  4. base-64로 인코딩된 문자열을 디코딩합니다. CryptStringToBinary 함수를 사용하여 이 작업을 수행할 수 있습니다. 이 함수는 CryptoAPI의 일부입니다.

참고

IWMDRMReader 인터페이스를 사용하려면 Microsoft에서 정적 DRM 라이브러리를 가져와서 애플리케이션을 이 라이브러리 파일에 연결해야 합니다. 자세한 내용은 Windows Media Format SDK 설명서의 "필수 DRM 라이브러리 가져오기" 항목을 참조하세요.

 

CRL이 사용자의 컴퓨터에 없는 경우 GetDRMProperty 메서드는 NS_E_DRM_UNSUPPORTED_PROPERTY 반환합니다. 현재 CRL을 얻는 유일한 방법은 DRM 라이선스를 획득하는 것입니다.

다음 코드는 CRL을 반환하는 함수를 보여줍니다.

////////////////////////////////////////////////////////////////////////
//  Name: GetCRL
//  Description: Gets the certificate revocation list (CRL).
//
//  ppBuffer: Receives a pointer to the buffer that contains the CRL.
//  pcbBuffer: Receives the size of the buffer returned in ppBuffer.
//
//  The caller must free the returned buffer by calling CoTaskMemFree.
////////////////////////////////////////////////////////////////////////
HRESULT GetCRL(BYTE **ppBuffer, DWORD *pcbBuffer)
{
    IWMReader *pReader = NULL;
    IWMDRMReader *pDrmReader = NULL;
    HRESULT hr = S_OK;

    // DRM attribute data.
    WORD cbAttributeLength = 0;
    BYTE *pDataBase64 = NULL;
    WMT_ATTR_DATATYPE type;

    // Buffer for base-64 decoded CRL.
    BYTE *pCRL = NULL;
    DWORD cbCRL = 0;

    // Create the WMReader object.
    hr = WMCreateReader(NULL, 0, &pReader);

    // Query for the IWMDRMReader interface.
    if (SUCCEEDED(hr))
    {
        hr = pReader->QueryInterface(
            IID_IWMDRMReader, (void**)&pDrmReader);
    }

    // Call GetDRMProperty once to find the size of the buffer.
    if (SUCCEEDED(hr))
    {
        hr = pDrmReader->GetDRMProperty(
            g_wszWMDRMNET_Revocation,
            &type,
            NULL,
            &cbAttributeLength
            );
    }

    // Allocate a buffer.
    if (SUCCEEDED(hr))
    {
        pDataBase64 = (BYTE*)CoTaskMemAlloc(cbAttributeLength);
        if (pDataBase64 == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    // Call GetDRMProperty again to get the property.
    if (SUCCEEDED(hr))
    {
        hr = pDrmReader->GetDRMProperty(
            g_wszWMDRMNET_Revocation,
            &type,
            pDataBase64,
            &cbAttributeLength
            );
    }

    // Find the size of the buffer for the base-64 decoding.
    if (SUCCEEDED(hr))
    {
        BOOL bResult = CryptStringToBinary(
            (WCHAR*)pDataBase64,    // Base-64 encoded string.
            0,                      // Null-terminated.
            CRYPT_STRING_BASE64,    
            NULL,                   // Buffer (NULL).
            &cbCRL,                 // Receives the size of the buffer. 
            NULL, NULL              // Optional.
            );
        if (!bResult)
        {
            hr = __HRESULT_FROM_WIN32(GetLastError());
        }
    }

    // Allocate a buffer for the CRL.
    if (SUCCEEDED(hr))
    {
        pCRL = (BYTE*)CoTaskMemAlloc(cbCRL);
        if (pCRL == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    // Base-64 decode to get the CRL.
    if (SUCCEEDED(hr))
    {
        BOOL bResult = CryptStringToBinary(
            (WCHAR*)pDataBase64,    // Base-64 encoded string.
            0,                      // Null-terminated.
            CRYPT_STRING_BASE64,    
            pCRL,                   // Buffer.
            &cbCRL,                 // Receives the size of the buffer. 
            NULL, NULL              // Optional.
            );
        if (!bResult)
        {
            hr = __HRESULT_FROM_WIN32(GetLastError());
        }
    }

    // Return the buffer to the caller. Caller must free the buffer.
    if (SUCCEEDED(hr))
    {
        *ppBuffer = pCRL;
        *pcbBuffer = cbCRL;
    }
    else
    {
        CoTaskMemFree(pCRL);
    }

    CoTaskMemFree(pDataBase64);
    SAFE_RELEASE(pReader);
    SAFE_RELEASE(pDrmReader);
    return hr;
}

다음으로, 애플리케이션은 CRL이 유효한지 확인해야 합니다. 이렇게 하려면 CRL의 일부인 CRL 인증서가 Microsoft 루트 인증서에 의해 직접 서명되고 SignCRL 요소 값이 1로 설정되어 있는지 확인합니다. 또한 CRL의 서명을 확인합니다.

CRL을 확인한 후 애플리케이션은 CRL을 저장할 수 있습니다. 또한 CRL 버전 번호는 애플리케이션이 항상 최신 버전을 저장할 수 있도록 저장하기 전에 확인해야 합니다.

CRL의 형식은 다음과 같습니다.

섹션 콘텐츠
헤더 32비트 CRL 버전32비트 항목 수
해지 항목 여러 160비트 해지 항목
인증서 32비트 인증서 길이변성 길이 인증서
서명 8비트 서명 형식16비트 서명 길이변성 길이 서명

 

참고

모든 정수 값은 부호가 없으며 big-endian(네트워크 바이트 순서) 표기법으로 표시됩니다.

 

CRL 섹션 설명

헤더

헤더에는 CRL의 버전 번호와 CRL의 해지 항목 수가 포함됩니다. CRL에는 0개 이상의 항목이 포함될 수 있습니다.

해지 항목

각 해지 항목은 해지된 인증서의 160비트 다이제스트입니다. 이 다이제스트를 인증서 내의 DigestValue 요소와 비교합니다.

인증서

인증서 섹션에는 XML 인증서 및 해당 인증서 체인의 길이(바이트)를 나타내는 32비트 값과 CA(인증 기관)의 XML 인증서와 Microsoft가 Root인 인증서 체인이 모두 포함된 바이트 배열이 포함되어 있습니다. 인증서는 CRL을 발급할 권한이 있는 CA에서 서명해야 합니다.

참고

인증서는 null로 종료되어서는 안 됩니다.

 

Signature

서명 섹션에는 서명 유형과 길이, 디지털 서명 자체가 포함됩니다. 8비트 형식은 1024비트 RSA 암호화와 함께 SHA-1을 사용함을 나타내기 위해 2로 설정됩니다. 길이는 디지털 서명의 길이를 바이트 단위로 포함하는 16비트 값입니다. 디지털 서명은 CRL의 모든 이전 섹션에 대해 계산됩니다.

서명은 PKCS #1(버전 2.1)에 정의된 RSASSA-PSS 디지털 서명 체계를 사용하여 계산됩니다. 해시 함수는 FIPS(Federal Information Processing Standard) 180-2에 정의된 SHA-1이고 마스크 생성 함수는 PKCS #1(버전 2.1)의 B.2.1 섹션에 정의된 MGF1입니다. RSASP1 및 RSAVP1 작업은 검증 지수가 65537인 1024비트 모듈러스가 있는 RSA를 사용합니다.

COPP(Certified Output Protection Protocol) 사용