Initiieren einer COPP-Sitzung
[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde durch MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation ersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code nach Möglichkeit MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet. Microsoft schlägt vor, vorhandenen Code, der die Legacy-APIs verwendet, um nach Möglichkeit die neuen APIs zu verwenden.]
Um eine COPP-Sitzung (Certified Output Protection Protocol) zu initiieren, müssen Sie eine Signatur vorbereiten, bei der es sich um ein Array handelt, das die Verkettung der folgenden Zahlen enthält:
- Die vom Treiber zurückgegebene 128-Bit-Zufallszahl. (Dieser Wert wird unter Abrufen der Zertifikatkette des Treibers als guidRandom angezeigt.)
- Ein symmetrischer 128-Bit-AES-Schlüssel.
- Eine 32-Bit-Startsequenznummer für status Anforderungen.
- Eine 32-Bit-Startsequenznummer für COPP-Befehle.
Generieren Sie einen symmetrischen AES-Schlüssel wie folgt:
DWORD dwFlag = 0x80; // Bit length: 128-bit AES.
dwFlag <<= 16; // Move this value to the upper 16 bits.
dwFlag |= CRYPT_EXPORTABLE; // We want to export the key.
CryptGenKey(
hCSP, // Handle to the CSP.
CALG_AES_128, // Use 128-bit AES block encryption algorithm.
dwFlag,
&m_hAESKey // Receives a handle to the AES key.
);
Die CryptGenKey-Funktion erstellt den symmetrischen Schlüssel, aber der Schlüssel befindet sich weiterhin im CSP. Um den Schlüssel in ein Bytearray zu exportieren, verwenden Sie die Funktion CryptExportKey . Dies ist der Grund für die Verwendung des CRYPT_EXPORTABLE-Flags beim Aufrufen von CryptGenKey. Der folgende Code exportiert den Schlüssel und kopiert ihn in die
pData
Array.
DWORD cbData = 0;
BYTE *pData = NULL;
// Get the size of the blob.
CryptExportKey(hAESKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &cbData);
// Allocate the array and call again.
pData = new BYTE[cbData];
CryptExportKey(hAESKey, 0, PLAINTEXTKEYBLOB, 0, pData, &cbData);
Die in zurückgegebenen Daten
pData
hat das folgende Layout:
BLOBHEADER header
DWORD cbSize
BYTE key[]
In den CryptoAPI-Headern ist jedoch keine Struktur definiert, die diesem Layout entspricht. Sie können entweder eine oder eine Zeigerarithmetik definieren. So überprüfen Sie beispielsweise die Größe des Schlüssels:
DWORD *pcbKey = (DWORD*)(pData + sizeof(BLOBHEADER));
if (*pcbKey != 16)
{
// Wrong size! Should be 16 bytes (128 bits).
}
So rufen Sie den Zeiger auf den Schlüssel selbst ab:
BYTE *pKey = pData + sizeof(BLOBHEADER) + sizeof(DWORD);
Generieren Sie als Nächstes eine 32-Bit-Zufallszahl, die als Startsequenz für COPP-status-Anforderungen verwendet werden soll. Die empfohlene Möglichkeit zum Erstellen einer Zufallszahl besteht darin, die CryptGenRandom-Funktion aufzurufen. Verwenden Sie die rand-Funktion nicht in der C-Laufzeitbibliothek, da sie nicht wirklich zufällig ist. Generieren Sie eine zweite 32-Bit-Zufallszahl, die als Startsequenz für COPP-Befehle verwendet werden soll.
UINT uStatusSeq; // Status sequence number.
UINT uCommandSeq; // Command sequence number.
CryptGenRandom(hCSP, sizeof(UINT), &uStatusSeq);
CryptGenRandom(hCSP, sizeof(UINT), &uCommandSeq);
Jetzt können Sie die COPP-Signatur vorbereiten. Dies ist ein 256-Byte-Array, das als AMCOPPSignature-Struktur definiert ist. Initialisieren Sie den Inhalt des Arrays auf Null. Kopieren Sie dann die vier Zahlen in das Array – die Zufallszahl des Treibers, die AES-Taste, die status Sequenznummer und die Befehlssequenznummer in dieser Reihenfolge. Tauschen Sie schließlich die Bytereihenfolge des gesamten Arrays aus.
Gemäß der Dokumentation für CryptEncrypt:
- "Die Länge der Klartextdaten, die mit einem Aufruf von **CryptEncrypt** mit einem RSA-Schlüssel verschlüsselt werden können, ist die Länge des Schlüsselmoduls minus elf Bytes. Die elf Bytes sind das für PKCS \#1-Auffüllung ausgewählte Minimum."
In diesem Fall beträgt das Modul 256 Bytes, sodass die maximale Nachrichtenlänge 245 Bytes (256 – 11) beträgt. Die AMCOPPSignature-Struktur ist 256 Bytes, aber die aussagekräftigen Daten in der Signatur sind nur 40 Bytes. Der folgende Code verschlüsselt die Signatur und stellt das Ergebnis in bereit.
CoppSig
.
AMCOPPSignature CoppSig;
ZeroMemory(&CoppSig, sizeof(CoppSig));
// Copy the signature data into CoppSig. (Not shown.)
// Encrypt the signature:
const DWORD RSA_PADDING = 11; // 11-byte padding.
DWORD cbDataOut = sizeof(AMCOPPSignature);
DWORD cbDataIn = cbDataOut - RSA_PADDING;
CryptEncrypt(
hRSAKey,
NULL, // No hash object.
TRUE, // Final block to encrypt.
0, // Reserved.
&CoppSig, // COPP signature.
&cbDataOut,
cbDataIn
);
Übergeben Sie nun das verschlüsselte Array an IAMCertifiedOutputProtection::SessionSequenceStart:
hr = pCOPP->SessionSequenceStart(&CoppSig);
if (SUCCEEDED(hr))
{
// Ready to send COPP commands and status requests.
}
Wenn diese Methode erfolgreich ist, können Sie COPP-Befehle und status Anforderungen an den Treiber senden.
Zugehörige Themen