The protocol engine's client-side code is typically:
HCRYPTPROV hProv = <protocol engine's key container>;
HCRYPTKEY hClientDHKey; // handle to the client's DH key
HCRYPTKEY hMasterKey;
ALG_ID Algid;
PBYTE pbServerPub = <pointer to Server Public Key>;
DWORD cbServerPub = <size of Server Public Key>;
BYTE rgbServerBlob[<max blob size>];
DWORD cbServerBlob;
PBYTE pbG = <pointer to generator G from Server>;
DWORD cbG = <size of generator G from Server>;
PBYTE pbP = <pointer to prime P from Server>;
DWORD cbP = <size of prime P from Server>;
CRYPT_DATA_BLOB Data;
BYTE rgbClientPubBlob[size of the client public key blob];
DWORD cbClientPubBlob;
// generate and set the parameters on the client DH key
CryptGenKey(hProv, CALG_DH_EPHEM, 0, &hClientDHKey);
Data.pbData = pbP;
Data.cbData = cbP;
CryptSetKeyParam(hClientDHKey, KP_P, (BYTE*)&Data, 0);
Data.pbData = pbG;
Data.cbData = cbG;
CryptSetKeyParam(hClientDHKey, KP_G, (BYTE*)&Data, 0);
// actually create the client private DH key
CryptSetKeyParam(hClientDHKey, KP_X, NULL, 0);
// Build PUBLICKEYBLOB around the server's public key
{
BLOBHEADER *pBlobHeader = (BLOBHEADER *)rgbServerBlob;
DHPUBKEY *pDHPubKey = (DHPUBKEY *)(pBlobHeader + 1);
BYTE *pData = (BYTE *)(pDHPubKey + 1);
pBlobHeader->bType = PUBLICKEYBLOB;
pBlobHeader->bVersion = CUR_BLOB_VERSION;
pBlobHeader->reserved = 0;
pBlobHeader->aiKeyAlg = CALG_DH_EPHEM;
pDHPubKey->magic = 0x31484400;
pDHPubKey->bitlen = dwServerPub * 8;
ReverseMemCopy(pData, pbServerPub, cbServerPub);
cbServerBlob = sizeof(BLOBHEADER) + sizeof(DHPUBKEY) +
cbServerPub;
}
// import the server's public key and get an agreed key
CryptImportKey(hProv, rgbServerBlob, cbServerBlob, hClientDHKey, 0,
&hMasterKey);
// Select the master key type.
switch(<protocol being used>)
{
case <SSL 3.0>:
Algid = CALG_SSL3_MASTER;
break;
case <TLS 1.0>:
Algid = CALG_TLS1_MASTER;
break;
}
// Convert the agreed key to the appropriate master key
CryptSetKeyParam(hMasterKey, KP_ALGID, (BYTE*)&Algid, 0);
// Get the client Diffie-Hellman public key.
cbClientPubBlob = sizeof(rgbClientPubBlob);
CryptExportKey(hClientDHKey, 0, PUBLICKEYBLOB,
0, rgbClientPubBlob, & cbClientPubBlob);
CryptDestroyKey(hClientDHKey);