Autenticação de Mensagem
A autenticação de mensagens é um processo que permite que aplicativos e provedores de serviços verifiquem se os dados passados entre eles não foram adulterados. O Windows Media Gerenciador de Dispositivos permite que aplicativos e provedores de serviços executem a autenticação de mensagens usando MACs (códigos de autenticação de mensagem). Veja como funciona a autenticação MAC:
O remetente de dados, geralmente o provedor de serviços, passa uma ou mais partes de dados por meio de uma função criptográfica unidirecional que produz uma única assinatura, o MAC, para todos os dados. Em seguida, o remetente envia todos os dados assinados junto com o MAC para o receptor (geralmente o aplicativo). O receptor passa os dados pela mesma função criptográfica para gerar um MAC e os compara ao MAC que foi enviado. Se o MAC corresponder, os dados não foram modificados.
Para executar a autenticação MAC, o aplicativo ou provedor de serviços requer uma chave de criptografia e um certificado correspondente. Para obter informações sobre onde obtê-los, consulte Ferramentas para desenvolvimento.
As etapas a seguir descrevem como os dados são assinados pelo remetente e, posteriormente, verificados pelo receptor. No Windows Media Gerenciador de Dispositivos, o provedor de serviços usa a classe CSecureChannelServer para gerar MACs e o aplicativo usa a classe CSecureChannelClient. Ambas as classes fornecem funções idênticas com parâmetros idênticos, portanto, as etapas a seguir se aplicam a ambas as classes.
O remetente (normalmente o provedor de serviços):
- Obtenha os dados a serem assinados.
- Crie um novo identificador MAC chamando MACInit.
- Adicione um pedaço de dados a ser assinado no identificador chamando MACUpdate. Essa função aceita o identificador criado anteriormente, além de uma parte dos dados que devem ser assinados.
- Repita a etapa 3 com cada parte adicional dos dados que devem ser assinados. Não importa em que ordem os dados são adicionados ao MAC.
- Copie o MAC do identificador para um novo buffer de bytes chamando MACFinal. Essa função aceita o identificador MAC e um buffer que você aloca e copia o MAC do identificador para o buffer fornecido.
Ao executar a autenticação MAC, é importante que o remetente e o receptor estejam colocando os mesmos dados no MAC. Para os métodos de aplicativo que fornecem um MAC, normalmente todos os parâmetros são incluídos no valor MAC (exceto para o mac em si, é claro). Por exemplo, considere o método IWMDMOperation::TransferObjectData :
HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE[WMDM_MAC_LENGTH] abMac);
Nesse método, o MAC incluiria pData e pdwSize. Se você não incluir os dois parâmetros, o MAC criado não corresponderá ao MAC passado para abMac. Um provedor de serviços deve ter certeza de colocar todos os parâmetros necessários no método de aplicativo no valor MAC.
O código C++ a seguir demonstra a criação de um MAC na implementação de um provedor de serviços 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;
}
O receptor (normalmente o aplicativo):
Se o receptor não tiver implementado a interface IWMDMOperation3 , ele deverá executar as mesmas etapas que o remetente e comparar os dois valores MAC. O exemplo de código C++ a seguir mostra como um aplicativo marcar mac recebido em uma chamada para IWMDMStorageGlobals::GetSerialNumber para garantir que o número de série não foi adulterado em 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.
}
}
Tópicos relacionados