Partager via


Chiffrement et déchiffrement

Windows Media Gestionnaire de périphériques nécessite le chiffrement des fichiers envoyés entre le fournisseur de services et l’application. Cette opération peut être effectuée de deux manières :

L’exigence de chiffrement empêche les applications malveillantes d’obtenir des données transmises entre les composants logiciels, et protège également l’intégrité des données envoyées vers ou depuis l’appareil.

Les trois méthodes suivantes nécessitent un chiffrement ou un déchiffrement.

Méthode Description
IWMDMOperation::TransferObjectData (Application) Chiffrement ou déchiffrement, selon que l’application envoie ou reçoit des données.
IMDSPObject::Read (Fournisseur de services) Cryptage.
IMDSPObject::Write (Fournisseur de services) Décryptage.

 

Le chiffrement et le déchiffrement sont tous deux effectués par des appels de méthode unique. Le chiffrement est effectué par CSecureChannelClient::EncryptParam pour les applications ou par CSecureChannelServer::EncryptParam pour les fournisseurs de services. Le déchiffrement est effectué par CSecureChannelClient::D ecryptParam pour les applications ou par CSecureChannelServer::D ecryptParam pour les fournisseurs de services. Les paramètres sont identiques entre les méthodes client et serveur.

Les étapes suivantes montrent comment chiffrer et déchiffrer des données. (Ces étapes sont importantes uniquement si votre application communique avec un fournisseur de services hérité qui n’implémente pas IWMDMOperation3::TransferObjectDataOnClearChannel.)

Chiffrement

  1. Créez la clé MAC pour les données chiffrées, comme décrit dans Authentification de message.
  2. Appelez EncryptParam avec les données à chiffrer pour effectuer un chiffrement sur place.

L’exemple de code suivant illustre l’implémentation d’IMDSPObject::Read par un fournisseur de services. Cette méthode crée la clé MAC à l’aide des données à chiffrer et de la taille des données, puis les envoie à l’application.

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

Déchiffrement

  1. Appelez DecryptParam avec les données à chiffrer, pour effectuer un déchiffrement sur place.
  2. Vérifiez la clé MAC pour les données déchiffrées, comme décrit dans Authentification des messages.

L’exemple de code suivant illustre l’implémentation d’IMDSPObject::Write par un fournisseur de services. Cette méthode crée la clé MAC à l’aide des données à chiffrer et de la taille des données, puis les envoie à l’application.

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

Utilisation de canaux authentifiés sécurisés