Listes de révocation de certificat

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement au nouveau code d’utiliser MediaPlayer, IMFMediaEngine et La capture audio/vidéo dans Media Foundation au lieu de DirectShow, lorsque cela est possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Cette rubrique explique comment examiner la liste de révocation de certificats (CRL) pour les pilotes révoqués lors de l’utilisation du protocole COPP (Certified Output Protection Protocol).

La liste de révocation de certificats contient des synthèses de certificats révoqués et peut être fournie et signée uniquement par Microsoft. La liste de révocation de certificats est distribuée via des licences de gestion des droits numériques (DRM). La liste de révocation de certificats peut révoquer n’importe quel certificat dans la chaîne de certificats du pilote. Si un certificat de la chaîne est révoqué, ce certificat et tous les certificats en dessous de celui-ci dans la chaîne sont également révoqués.

Pour obtenir la liste de révocation de certificats, l’application doit utiliser le Kit de développement logiciel (SDK) au format Windows Media, version 9 ou ultérieure, et effectuer les étapes suivantes :

  1. Appelez WMCreateReader pour créer l’objet lecteur du Kit de développement logiciel (SDK) au format Windows Media.
  2. Interrogez l’objet lecteur pour l’interface IWMDRMReader .
  3. Appelez IWMDRMReader::GetDRMProperty avec la valeur g_wszWMDRMNet_Revocation pour obtenir la liste de révocation de certificats. Vous devez appeler cette méthode deux fois : une fois pour obtenir la taille de la mémoire tampon à allouer, et une fois pour remplir la mémoire tampon. Le deuxième appel retourne une chaîne qui contient la liste de révocation de certificats. La chaîne entière est encodée en base 64.
  4. Décodez la chaîne encodée en base 64. Pour ce faire, vous pouvez utiliser la fonction CryptStringToBinary . Cette fonction fait partie de CryptoAPI.

Notes

Pour utiliser l’interface IWMDRMReader , vous devez obtenir une bibliothèque DRM statique auprès de Microsoft et lier votre application à ce fichier de bibliothèque. Pour plus d’informations, consultez la rubrique « Obtention de la bibliothèque DRM requise » dans la documentation du Kit de développement logiciel (SDK) au format Windows Media.

 

Si la liste de révocation de certificats n’est pas présente sur l’ordinateur de l’utilisateur, la méthode GetDRMProperty retourne NS_E_DRM_UNSUPPORTED_PROPERTY. Actuellement, la seule façon d’obtenir la liste de révocation de certificats consiste à acquérir une licence DRM.

Le code suivant montre une fonction qui retourne la liste de révocation de certificats :

////////////////////////////////////////////////////////////////////////
//  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;
}

Ensuite, l’application doit vérifier que la liste de révocation de certificats est valide. Pour ce faire, vérifiez que le certificat CRL, qui fait partie de la liste de révocation de certificats, est signé directement par le certificat racine Microsoft et que la valeur de l’élément SignCRL est définie sur 1. Vérifiez également la signature de la liste de révocation de certificats.

Une fois la liste de révocation de certificats vérifiée, l’application peut la stocker. Le numéro de version de la liste de révocation de certificats doit également être vérifié avant le stockage afin que l’application stocke toujours la version la plus récente.

La liste de révocation de certificats a le format suivant.

Section Contents
En-tête Nombre d’entrées de la liste de révocation de certificats 32 bits
Entrées de révocation Plusieurs entrées de révocation 160 bits
Certificat Longueur du certificat 32 bits Certificate de longueur variable
Signature Type de signature 8 bits 16 bits Signature de longueur variable

 

Notes

Toutes les valeurs entières ne sont pas signées et sont représentées en notation big-endian (ordre d’octet réseau).

 

Descriptions des sections de la liste de révocation de révocation de certificats

Header

L’en-tête contient le numéro de version de la liste de révocation de certificats et le nombre d’entrées de révocation dans la liste de révocation de certificats. Une liste de révocation de certificats peut contenir zéro ou plusieurs entrées.

Entrées de révocation

Chaque entrée de révocation est la synthèse 160 bits d’un certificat révoqué. Comparez cette synthèse avec l’élément DigestValue dans le certificat.

Certificat

La section certificat contient une valeur 32 bits indiquant la longueur (en octets) du certificat XML et de sa chaîne de certificats, ainsi qu’un tableau d’octets qui contient à la fois le certificat XML de l’autorité de certification et la chaîne de certificats avec Microsoft comme racine. Le certificat doit être signé par une autorité de certification qui a le pouvoir d’émettre des listes de contrôle d’accès.

Notes

Le certificat ne doit pas être terminé par null.

 

Signature

La section signature contient le type et la longueur de la signature, ainsi que la signature numérique elle-même. Le type 8 bits est défini sur 2 pour indiquer qu’il utilise SHA-1 avec le chiffrement RSA 1024 bits. La longueur est une valeur 16 bits contenant la longueur de la signature numérique en octets. La signature numérique est calculée sur toutes les sections précédentes de la liste de révocation de certificats.

La signature est calculée à l’aide du schéma de signature numérique RSASSA-PSS défini dans PKCS #1 (version 2.1). La fonction de hachage est SHA-1, qui est définie dans la norme FIPS (Federal Information Processing Standard) 180-2, et la fonction de génération de masque est MGF1, qui est définie dans la section B.2.1 de PKCS #1 (version 2.1). Les opérations RSASP1 et RSAVP1 utilisent RSA avec un module 1024 bits avec un exposant de vérification de 65537.

Utilisation du protocole COPP (Certified Output Protection Protocol)