Autenticación de mensajes

La autenticación de mensajes es un proceso que permite a las aplicaciones y a los proveedores de servicios comprobar que los datos pasados entre ellos no se han alterado. Windows Media Administrador de dispositivos permite que las aplicaciones y los proveedores de servicios realicen la autenticación de mensajes mediante códigos de autenticación de mensajes (MAC). Aquí se muestra cómo funciona la autenticación MAC:

El remitente de datos, normalmente el proveedor de servicios, pasa uno o varios fragmentos de datos a través de una función criptográfica unidireccional que genera una sola firma, el MAC, para todos los datos. A continuación, el remitente envía todos los datos firmados junto con el MAC al receptor (normalmente la aplicación). El receptor pasa los datos a través de la misma función criptográfica para generar un MAC y lo compara con el MAC que se envió. Si el MAC coincide, los datos no se han modificado.

Para realizar la autenticación MAC, la aplicación o el proveedor de servicios requiere una clave de cifrado y un certificado coincidente. Para obtener información sobre dónde obtenerlas, consulte Herramientas para el desarrollo.

En los pasos siguientes se describe cómo el remitente firma los datos y, posteriormente, los comprueba el receptor. En Windows Media Administrador de dispositivos, el proveedor de servicios usa la clase CSecureChannelServer para generar MAC y la aplicación usa la clase CSecureChannelClient. Ambas clases proporcionan funciones idénticas con parámetros idénticos, por lo que los pasos siguientes se aplican a ambas clases.

El remitente (normalmente el proveedor de servicios):

  1. Obtenga los datos que se van a firmar.
  2. Cree un nuevo identificador MAC llamando a MACInit.
  3. Agregue un fragmento de datos para que se firme en el identificador mediante una llamada a MACUpdate. Esta función acepta el identificador creado anteriormente, además de un fragmento de datos que se debe firmar.
  4. Repita el paso 3 con cada parte adicional de datos que se deben firmar. No importa en qué orden se agregan los datos al MAC.
  5. Copie el MAC del identificador en un nuevo búfer de bytes llamando a MACFinal. Esta función acepta el identificador MAC y un búfer que se asigna y copia el MAC del identificador en el búfer proporcionado.

Al realizar la autenticación MAC, es importante que tanto el remitente como el receptor coloquen los mismos datos en el MAC. Para los métodos de aplicación que proporcionan un MAC, normalmente todos los parámetros se incluyen en el valor MAC (excepto el propio MAC, por supuesto). Por ejemplo, considere el método IWMDMOperation::TransferObjectData :

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

En este método, el MAC incluiría pData y pdwSize. Si no incluye ambos parámetros, el MAC que cree no coincidirá con el MAC pasado a abMac. Un proveedor de servicios debe asegurarse de colocar todos los parámetros necesarios en el método de aplicación en el valor MAC.

El siguiente código de C++ muestra cómo crear un MAC en la implementación de un proveedor de servicios de 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;
}

Receptor (normalmente la aplicación):

Si el receptor no ha implementado la interfaz IWMDMOperation3 , debe realizar los mismos pasos que el remitente y, a continuación, comparar los dos valores MAC. En el siguiente ejemplo de código de C++ se muestra cómo una aplicación comprobaría el MAC recibido en una llamada a IWMDMStorageGlobals::GetSerialNumber para asegurarse de que el número de serie no se manipuló en tránsito.

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

Uso de canales autenticados seguros