Cifrado y descifrado

Windows Media Administrador de dispositivos requiere el cifrado de archivos enviados entre el proveedor de servicios y la aplicación. Esto se puede hacer de dos maneras:

El requisito de cifrado impide que las aplicaciones malintencionadas obtengan datos que se pasan entre componentes de software y también protege la integridad de los datos que se envían al dispositivo o desde él.

Los tres métodos siguientes requieren cifrado o descifrado.

Método Descripción
IWMDMOperation::TransferObjectData (Aplicación) Cifrado o descifrado, dependiendo de si la aplicación envía o recibe datos.
IMDSPObject::Read (Proveedor de servicios) Cifrado.
IMDSPObject::Write (Proveedor de servicios) Descifrado.

 

Tanto el cifrado como el descifrado se realizan mediante llamadas de método único. El cifrado se realiza mediante CSecureChannelClient::EncryptParam para aplicaciones o por CSecureChannelServer::EncryptParam para proveedores de servicios. El descifrado se realiza mediante CSecureChannelClient::D ecryptParam para aplicaciones o CSecureChannelServer::D ecryptParam para proveedores de servicios. Los parámetros son idénticos entre los métodos de cliente y servidor.

En los pasos siguientes se muestra cómo cifrar y descifrar datos. (Estos pasos solo son importantes si la aplicación se comunica con un proveedor de servicios heredado que no implementa IWMDMOperation3::TransferObjectDataOnClearChannel).

Cifrado

  1. Cree la clave MAC para los datos cifrados, tal y como se describe en Autenticación de mensajes.
  2. Llame a EncryptParam con los datos que se van a cifrar para realizar el cifrado en contexto.

En el ejemplo de código siguiente se muestra la implementación de IMDSPObject::Read de un proveedor de servicios. Este método crea la clave MAC mediante los datos para cifrar y el tamaño de los datos, y los envía a la aplicación.

HRESULT CMyStorage::Read(
    BYTE  *pData,
    DWORD *pdwSize,
    BYTE   abMac[WMDM_MAC_LENGTH])
{
    HRESULT  hr;
    DWORD    dwToRead;         // Bytes to read.
    DWORD    dwRead   = NULL;  // Bytes read.
    BYTE    *pTmpData = NULL;  // Temporary buffer to hold data before 
                               // it is copied to pData.

    // Use a global CSecureChannelServer member to verify that 
    // the client is authenticated.
    if (!(g_pAppSCServer->fIsAuthenticated()))
    {
        return WMDM_E_NOTCERTIFIED;
    }
    

    // Verify that the handle to the file to read is valid.
    if(m_hFile == INVALID_HANDLE_VALUE)
    {
        return E_FAIL;
    }

    // Create a buffer to hold the data read.    
    dwToRead = *pdwSize;
    pTmpData = new BYTE [dwToRead] ;
    if(!pTmpData)
        return E_OUTOFMEMORY;

    // Read data into the temporary buffer.
    if(ReadFile(m_hFile,(LPVOID)pTmpData,dwToRead,&dwRead,NULL)) 
    { 
        *pdwSize = dwRead; 

        if( dwRead )
        {
            // Create a MAC from all the parameters.
            // CORg is a macro that goes to Error label on failure.
            // MAC consists of data and size of data.
            HMAC hMAC;
            
            CORg(g_pAppSCServer->MACInit(&hMAC));
            CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), dwRead));
            CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(DWORD)));
            CORg(g_pAppSCServer->MACFinal(hMAC, abMac));
            
            // Encrypt the data.
            CORg(g_pAppSCServer->EncryptParam(pTmpData, dwRead));
            
            // Copy data from the temporary buffer into the out parameter.
            memcpy(pData, pTmpData, dwRead);
        }
    
        hr = S_OK; 
    }
    else
    { 
        *pdwSize = 0; 

        hr = E_FAIL; 
    }

Error:

    if(pTmpData) 
    {
        delete [] pTmpData;
    }

    return hr;
} 

Descifrado

  1. Llame a DecryptParam con los datos que se van a cifrar para realizar el descifrado en contexto.
  2. Compruebe la clave MAC de los datos descifrados, como se describe en Autenticación de mensajes.

En el ejemplo de código siguiente se muestra la implementación de IMDSPObject::Write de un proveedor de servicios. Este método crea la clave MAC mediante los datos para cifrar y el tamaño de los datos, y los envía a la aplicación.

HRESULT CMyStorage::Write(BYTE *pData, DWORD *pdwSize,
                                 BYTE abMac[WMDM_MAC_LENGTH])
{
    HRESULT  hr;
    DWORD    dwWritten = 0;
    BYTE    *pTmpData  = NULL;          // Temporary buffer to hold the 
                                        // data during decryption.
    BYTE     pTempMac[WMDM_MAC_LENGTH]; // Temporary MAC that will be 
                                        // copied into the abMac
                                        // out parameter.

    if( m_hFile == INVALID_HANDLE_VALUE )
    {
        return E_FAIL;
    }

    // Allocate the temporary buffer and copy the encrypted data into it.
    pTmpData = new BYTE [*pdwSize];
    if(!pTmpData)
        return E_OUTOFMEMORY;
    memcpy(pTmpData, pData, *pdwSize);

    // Decrypt the data.
    CHRg(g_pAppSCServer->DecryptParam(pTmpData, *pdwSize));

    // Check the MAC passed to the method. The MAC is built from
    // the data and data size parameters.
    // CORg is a macro that goes to the Error label on failure.
    HMAC hMAC;
    CORg(g_pAppSCServer->MACInit(&hMAC));
    CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), *pdwSize));
    CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(*pdwSize)));
    CORg(g_pAppSCServer->MACFinal(hMAC, pTempMac));

    // If the MAC values don't match, return an error.
    if (memcmp(abMac, pTempMac, WMDM_MAC_LENGTH) != 0)
    {
        hr = WMDM_E_MAC_CHECK_FAILED;
        goto Error;
    }

    // The MAC values matched, so write the decrypted data to a local file.
    if( WriteFile(m_hFile,pTmpData,*pdwSize,&dwWritten,NULL) ) 
    {
        hr = S_OK;
    }
    else 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
    }

    *pdwSize = dwWritten;

Error:

    if( pTmpData )
    {
        delete [] pTmpData;
    }

    return hr;
}

Uso de canales autenticados seguros