Partager via


Authentification des messages

L’authentification de message est un processus qui permet aux applications et aux fournisseurs de services de vérifier que les données passées entre eux n’ont pas été falsifiées. Windows Media Gestionnaire de périphériques permet aux applications et aux fournisseurs de services d’effectuer l’authentification des messages à l’aide de codes d’authentification des messages (MAC). Voici comment fonctionne l’authentification MAC :

L’expéditeur de données, généralement le fournisseur de services, transmet un ou plusieurs éléments de données via une fonction de chiffrement unidirectionnel qui produit une signature unique, le MAC, pour toutes les données. L’expéditeur envoie ensuite toutes les données signées avec le MAC au destinataire (généralement l’application). Le récepteur transmet les données via la même fonction de chiffrement pour générer un MAC et les comparer au MAC qui a été envoyé. Si le MAC correspond, les données n’ont pas été modifiées.

Pour effectuer l’authentification MAC, l’application ou le fournisseur de services a besoin d’une clé de chiffrement et d’un certificat correspondant. Pour plus d’informations sur l’emplacement où les obtenir, consultez Outils pour le développement.

Les étapes suivantes décrivent comment les données sont signées par l’expéditeur, puis vérifiées par le destinataire. Dans Windows Media Gestionnaire de périphériques, le fournisseur de services utilise la classe CSecureChannelServer pour générer des maC, et l’application utilise la classe CSecureChannelClient. Les deux classes fournissent des fonctions identiques avec des paramètres identiques. Les étapes suivantes s’appliquent donc aux deux classes.

L’expéditeur (généralement le fournisseur de services) :

  1. Obtenez les données à signer.
  2. Créez un nouveau handle MAC en appelant MACInit.
  3. Ajoutez un élément de données à signer au handle en appelant MACUpdate. Cette fonction accepte le handle créé précédemment, ainsi qu’un élément de données qui doit être signé.
  4. Répétez l’étape 3 avec chaque élément de données supplémentaire qui doit être signé. Peu importe l’ordre dans lequel les données sont ajoutées au MAC.
  5. Copiez le MAC du handle vers une nouvelle mémoire tampon d’octets en appelant MACFinal. Cette fonction accepte le handle MAC et une mémoire tampon que vous allouez, puis copie le MAC du handle dans la mémoire tampon fournie.

Lors de l’authentification MAC, il est important que l’expéditeur et le destinataire mettent les mêmes données dans le MAC. Pour les méthodes d’application qui fournissent un MAC, tous les paramètres sont généralement inclus dans la valeur MAC (à l’exception du MAC lui-même, bien sûr). Par exemple, considérez la méthode IWMDMOperation::TransferObjectData :

HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE[WMDM_MAC_LENGTH] abMac);

Dans cette méthode, le MAC inclut pData et pdwSize. Si vous n’incluez pas les deux paramètres, le MAC que vous créez ne correspondra pas au MAC passé à abMac. Un fournisseur de services doit veiller à placer tous les paramètres requis dans la méthode d’application dans la valeur MAC.

Le code C++ suivant illustre la création d’un MAC dans l’implémentation par un fournisseur de services d’IMDSPStorageGlobals::GetSerialNumber.

HRESULT CMyDevice::GetSerialNumber(
    PWMDMID pSerialNumber, 
    BYTE abMac[WMDM_MAC_LENGTH])
{
    HRESULT hr;

    // g_pSecureChannelServer is a global CSecureChannelServer object
    // created earlier.

    // Standard check that the CSecureChannelServer was authenticated previously.
    if ( !(g_pSecureChannelServer->fIsAuthenticated()) )
    {
        return WMDM_E_NOTCERTIFIED;
    }

    // Call a helper function to get the device serial number.
    hr = UtilGetSerialNumber(m_wcsName, pSerialNumber, TRUE);
    if(hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
    {
        hr = WMDM_E_NOTSUPPORTED;
    }

    if(hr == S_OK)
    {
        // Create the MAC handle.
        HMAC hMAC;
        hr = g_pSecureChannelServer->MACInit(&hMAC);
        if(FAILED(hr))
            return hr;

        // Add the serial number to the MAC.
        g_pSecureChannelServer->MACUpdate(hMAC, (BYTE*)(pSerialNumber), sizeof(WMDMID));
        if(FAILED(hr))
            return hr;

        // Get the created MAC value from the handle.
        g_pSecureChannelServer->MACFinal(hMAC, abMac);
        if(FAILED(hr))
            return hr;
    }

    return hr;
}

Récepteur (généralement l’application) :

Si le destinataire n’a pas implémenté l’interface IWMDMOperation3 , il doit effectuer les mêmes étapes que l’expéditeur, puis comparer les deux valeurs MAC. L’exemple de code C++ suivant montre comment une application case activée le MAC reçu lors d’un appel à IWMDMStorageGlobals::GetSerialNumber pour s’assurer que le numéro de série n’a pas été falsifié en transit.

//
// Get and verify the serial number.
//
WMDMID serialNumber;
BYTE receivedMAC[WMDM_MAC_LENGTH];
hr = pIWMDMDevice->GetSerialNumber(&serialNumber, receivedMAC);

// Check the MAC to guarantee the serial number has not been tampered with.
if (hr == S_OK)
{
    // Initialize a MAC handle, 
    // add all parameters to the MAC,
    // and retrieve the calculated MAC value.
    // m_pSAC is a global CSecureChannelClient object created earlier.
    HMAC hMAC;
    BYTE calculatedMAC[WMDM_MAC_LENGTH];
    hr = m_pSAC->MACInit(&hMAC);
    if(FAILED(hr))
        return hr;

    hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(&serialNumber), sizeof(serialNumber));
    if(FAILED(hr))
        return hr;

    hr = m_pSAC->MACFinal(hMAC, (BYTE*)calculatedMAC);
    if(FAILED(hr))
        return hr;

    // If the two MAC values match, the MAC is authentic. 
    if (memcmp(calculatedMAC, receivedMAC, sizeof(calculatedMAC)) == 0)
    {
        // The MAC is authentic; print the serial number.
        CHAR* serialNumberBuffer = 
            new CHAR[serialNumber.SerialNumberLength + 1];
        ZeroMemory(serialNumberBuffer, 
            (serialNumber.SerialNumberLength + 1) * sizeof(CHAR));
        memcpy(serialNumberBuffer, serialNumber.pID, 
            serialNumber.SerialNumberLength * sizeof(CHAR));
        // TODO: Display the serial number.
        delete serialNumberBuffer;
    }
    else
    {
        // TODO: Display a message indicating that the serial number MAC 
        // does not match.
    }
}

Utilisation de canaux authentifiés sécurisés