暗号化と暗号化解除

Windows Media デバイス マネージャーでは、サービス プロバイダーとアプリケーションの間で送信されるファイルの暗号化が必要です。 これには、次の 2 とおりの方法があります。

  • サービス プロバイダーが IMDSPObject::Read および IMDSPObject::Write のみをサポートしている場合は、CSecureChannelClient メソッドと CSecureChannelServer メソッドをそれぞれ使用して、アプリケーションとサービス プロバイダーによってデータを暗号化および暗号化解除する必要があります。
  • サービス プロバイダーが IMDSPObject2::ReadOnClearChannelIMDSPObject2::WriteOnClearChannel をサポートしている場合、アプリケーションはコストのかかるセキュリティで保護されたチャネル メッセージ認証を回避できます。 (セキュリティで保護されたチャネルは保持されるため、 IMDSPObject2 を実装していないレガシ サービス プロバイダーは引き続き機能できます)。

暗号化要件は、悪意のあるアプリケーションがソフトウェア コンポーネント間で渡されるデータを取得するのを防ぎ、デバイスとの間で送信されるデータの整合性も保護します。

次の 3 つの方法では、暗号化または暗号化解除が必要です。

メソッド 説明
IWMDMOperation::TransferObjectData (アプリケーション)アプリケーションがデータを送受信しているかどうかに応じて、暗号化または暗号化解除を行います。
IMDSPObject::Read (サービス プロバイダー)暗号化。
IMDSPObject::Write (サービス プロバイダー)復 号 化。

 

暗号化と暗号化解除は、どちらも単一のメソッド呼び出しによって行われます。 暗号化は、アプリケーションの 場合は CSecureChannelClient::EncryptParam 、サービス プロバイダーの 場合は CSecureChannelServer::EncryptParam によって行われます。 復号化は、アプリケーションの 場合は CSecureChannelClient::D ecryptParam 、サービス プロバイダーの 場合は CSecureChannelServer::D ecryptParam によって行われます。 パラメーターは、クライアント メソッドとサーバー メソッドの間で同じです。

次の手順では、データの暗号化と暗号化解除を行う方法を示します。 (これらの手順は、アプリケーションが IWMDMOperation3::TransferObjectDataOnClearChannel を実装していないレガシ サービス プロバイダーと通信する場合にのみ重要です)。

暗号化

  1. 「メッセージ認証」で説明されているように、暗号化されたデータの MAC キーを作成します。
  2. 暗号化するデータを使用して EncryptParam を呼び出して、インプレース暗号化を実行します。

次のコード例は、 IMDSPObject::Read のサービス プロバイダーの実装を示しています。 このメソッドは、暗号化するデータとデータのサイズを使用して MAC キーを作成し、両方をアプリケーションに送信します。

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

暗号化の解除

  1. 暗号化するデータを使用して DecryptParam を呼び出して、インプレース復号化を実行します。
  2. 「メッセージ認証」の説明に従って、復号化されたデータの MAC キーを確認します。

次のコード例は、サービス プロバイダーによる IMDSPObject::Write の実装を示しています。 このメソッドは、暗号化するデータとデータのサイズを使用して MAC キーを作成し、両方をアプリケーションに送信します。

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

セキュリティで保護された認証済みチャネルの使用