인증서 체인 유효성 검사

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

이 항목에서는 COPP(Certified Output Protection Protocol)를 사용할 때 드라이버의 인증서 체인의 유효성을 검사하는 방법을 설명합니다.

그래픽 드라이버의 인증서 체인은 XML 문서입니다. 인증서 체인에는 세 개의 인증서가 포함되어 있습니다. 첫 번째 인증서를 리프 인증서라고 하며 드라이버의 COPP 인증서입니다. 다음 인증서는 IHV(Independent Hardware Vendor)의 서명 인증서입니다. 마지막 인증서는 Microsoft의 서명 인증서입니다. 그래픽 드라이버가 합법적인 COPP 디바이스인지 확인하려면 애플리케이션에서 이러한 세 인증서의 유효성을 모두 검사해야 합니다. 애플리케이션이 체인의 인증서 유효성을 올바르게 검사하지 않으면 악성 프로그램이 COPP 작동을 방지할 수 있습니다.

COPP 인증서 체인은 UTF-8 문자 집합을 사용합니다. RSA 공개 키와 같은 인증서의 이진 데이터는 base64로 인코딩되고 big-endian 순서로 저장됩니다. (Big-endian은 가장 중요한 바이트가 가장 낮은 주소로 메모리 위치에 저장됨을 의미합니다.)

인증서 내의 일부 요소에는 인증서의 기능이 있음을 나타내는 부울 값이 포함되어 있습니다. 기능이 있는 경우 해당 자식 요소 값은 1로 설정됩니다. 기능이 없으면 해당 자식 요소가 인증서에 없습니다.

XML 요소 정의

다음은 인증서 스키마의 요소에 대한 정의입니다.

  • CertificateCollection. XML 문서의 루트 요소입니다. 체인의 각 인증서에 대해 하나씩 인증서 요소가 포함되어 있습니다.
  • 인증서. 하나의 인증서를 포함합니다. 이 요소에는 데이터 및 서명 요소가 포함되어 있습니다.
  • 데이터. 인증서에 대한 정보를 포함합니다. 특히 인증서의 공개 키와 형식이 포함됩니다. Data 요소에는 다음과 같은 자식 요소가 포함됩니다.
    • PublicKey. 인증서의 RSA 공개 키를 포함합니다. PublicKey 요소는 RSAKeyValue 요소를 포함하는 KeyValue 요소를 포함합니다. RSAKeyValue 요소에는 Modulus 및 Exponent라는 두 개의 자식 요소가 있으며 이러한 요소는 공개 키를 정의합니다. Modulus 및 지수 요소는 base64로 인코딩되고 big-endian 순서로 저장됩니다.
    • KeyUsage. 인증서가 드라이버의 COPP 인증서인 경우 이 요소에는 EncryptKey라는 자식 요소가 포함되어야 합니다. 인증서가 IHV의 서명 인증서 또는 Microsoft의 서명 인증서인 경우 SignCertificate라는 자식 요소가 포함되어야 합니다. 이러한 자식 요소 모두 부울 값을 포함합니다.
    • SecurityLevel. 이 요소는 무시해야 합니다.
    • ManufacturerData. 그래픽 디바이스의 제조업체 및 모델을 지정합니다. 이 요소는 정보 전용입니다.
    • 기능. 인증서 사용을 지정하는 자식 요소를 포함합니다. COPP와 관련된 유일한 요소는 COPPCertificate 요소입니다. 다른 자식 요소가 있을 수 있습니다. 그렇다면 무시해야 합니다. COPPCertificate 요소가 있는 경우 인증서는 COPP 인증서입니다. 이 요소는 유효한 COPP 인증서의 리프 노드에 있어야 합니다. 이 요소에는 부울 값이 포함되어 있습니다.
  • 서명. 이 인증서의 서명을 포함합니다. 여기에는 다음과 같은 자식 요소가 포함됩니다.
    • SignedInfo. 서명에 대한 정보를 포함합니다. 이 요소의 중요한 자식 요소는 Data 요소에 대한 SHA-1 해시의 base64로 인코딩된 값을 포함하는 DigestValue 요소입니다. 다이제스트 값은 CRL(인증서 해지 목록)에 대해 인증서를 확인할 때 사용됩니다.
    • SignatureValue. 이 값은 Data 요소를 통해 계산되며 Public-Key PKCS(Cryptography Standards) #1(버전 2.1)에 정의된 RSASSA-PSS 디지털 서명 체계에 따라 계산됩니다. PKCS #1에 대한 자세한 내용은 를 참조하세요 https://www.rsa.com/.
    • KeyInfo. 체인에 있는 다음 인증서의 RSA 공개 키를 포함합니다. 이 요소는 Data 요소의 데이터가 변조되지 않았는지 확인하는 데 사용됩니다. 이 요소의 형식은 PublicKey 요소와 동일합니다.

인증서 유효성 검사

애플리케이션은 인증서 체인의 유효성을 올바르게 검사하려면 다음 단계를 수행해야 합니다. 단계가 실패하거나 이러한 절차에서 참조된 요소가 없으면 유효성 검사가 실패합니다.

인증서 수집 프로시저 유효성 검사

인증서 체인의 유효성을 검사하려면 다음 단계를 수행합니다.

  1. CertificateCollection이 올바른 형식의 XML인지 확인합니다.
  2. CertificateCollection이 UTF-8 형식으로 인코딩되었는지 확인합니다.
  3. CertificateCollection 요소의 Version 특성이 2.0 이상인지 확인합니다.
  4. 인증서 체인에 정확히 세 개의 인증서 요소가 포함되어 있는지 확인합니다.
  5. 인증서 체인의 각 인증서 요소를 반복하고 아래에 설명된 인증서 유효성 검사 절차를 각각 수행합니다.

인증서 프로시저 유효성 검사

체인에서 인증서의 유효성을 검사하려면 다음 단계를 수행합니다.

  1. Data 요소의 자식 요소가 중복되지 않는지 확인합니다. 예를 들어 PublicKey 요소는 하나만 있어야 합니다.
  2. Data/PublicKey/KeyValue/RSAKeyValue/Modulus 요소가 있는지 확인합니다. base64 디코딩된 값은 루트를 제외한 모든 인증서에 대해 256바이트 길이여야 합니다. 루트 인증서에서 이 요소는 128바이트 길이여야 합니다.
  3. Data/PublicKey/KeyValue/RSAKeyValue/Exponent 요소가 있는지 확인합니다. base64 디코딩된 값은 4바이트보다 크지 않아야 합니다.
  4. 이 인증서가 리프 인증서인 경우 다음을 확인합니다.
    • KeyUsage 요소에는 값이 1인 EncryptKey 요소가 포함되어 있습니다.
    • Features 요소에는 값이 1인 COPPCertificate 요소가 포함되어 있습니다.
  5. 이 인증서가 리프 인증서가 아닌 경우 다음을 확인합니다.
    • Data/PublicKey 요소의 모듈러스 및 지수는 이전 인증서의 Signature/KeyInfo 요소의 모듈러스 및 지수와 정확히 일치합니다.
    • KeyUsage 요소에는 값이 1인 SignCertificate 요소가 포함됩니다.
  6. SHA-1 해시 알고리즘을 사용하여 인증서의 Data 요소에 있는 모든 바이트를 해시합니다. 데이터> 태그의 첫 번째 문자<부터 닫는 </Data> 태그의 마지막 문자까지 모든 바이트를 해시해야 합니다. 해시 값은 인증서 해지 목록에 설명된 대로 CRL(인증서 해지 목록)에 대해 인증서를 검사 데 사용됩니다.
  7. 6단계의 해시 값을 Signature/SignedInfo/Reference/DigestValue 요소의 base64 디코딩 값과 비교합니다. 이러한 값이 일치해야 합니다.
  8. 아래에 설명된 서명 확인 절차를 수행합니다.
  9. 이 인증서가 체인의 최종 인증서가 아닌 경우 루프의 다음 반복을 위해 Signature/KeyInfo/KeyValue/RSAKeyValue 값을 저장합니다.
  10. 이 인증서가 체인의 최종 인증서인 경우 Signature/KeyInfo/KeyValue/RSAKeyValue 값이 Microsoft의 공개 키와 일치하는지 확인합니다. Microsoft 공개 키에는 다음과 같은 base64로 인코딩된 값이 있습니다.
    • 계수:

      pjoeWLSTLDonQG8She6QhkYbYott9fPZ8tHdB128ZETcghn5KHoyin7HkJEcPJ0Eg4UdSv a0KDIYDjA3EXd69R3CN2Wp/QyOo0ZPYWYp3NXpJ700tKPgIplzo5wVd/69g7j+j8M66W7V NmDwaNs9mDc1p2+VVMsDhOsV/Au6E+E=

    • 지: AQAB

서명 프로시저 확인

SignatureValue 요소의 값은 PKCS #1 버전 2.1(이하 PKCS라고 함)에 정의된 RSASSA-PSS 디지털 서명 체계에 따라 Data 요소를 통해 계산됩니다. 이 서명을 확인하려면 다음 단계를 수행합니다.

  1. Signature/KeyInfo/KeyValue/RSAKeyValue 요소에서 Modulus 및 지수 값을 디코딩합니다. 이러한 값은 서명 인증서의 RSA 공개 키를 정의합니다.
  2. Signature/SignatureValue 요소를 디코딩합니다.
  3. PKCS의 8.1.2 섹션에 정의된 RSASSA-PSS-Verify 작업을 계산합니다.

RSASSA-PSS-Verify 작업의 경우 다음 입력을 사용합니다.

  • (n,e)는 1단계의 공개 키입니다.
  • M은 요소를 묶는 Data 및 </Data> 태그를 <포함하여 Data> 요소의 모든 바이트입니다.
  • S 는 2단계의 디코딩된 서명 값입니다.

RSASSA-PSS-Verify 작업은 섹션 9.1.1에 정의된 EMSA-PSS-ENCODE 작업을 사용합니다. PKCS의 이 작업의 경우 COPP는 다음 옵션을 사용합니다.

  • 해시 = SHA-1
  • hLen = 20
  • MGF(마스크 생성 함수) = MGF1
  • sLen = 0

마스크 생성 함수 MGF1은 PKCS의 부록 B.2에 정의되어 있습니다. 이 함수의 경우 COPP는 다음 옵션을 사용합니다.

  • 해시 = SHA-1
  • hLen = 20

RSASSA-PSS-Verify 작업의 출력은 서명이 유효한지 잘못된지 여부를 나타냅니다.

COPP(Certified Output Protection Protocol) 사용