The Server Side (Diffie-Hellman)

The protocol engine's server-side code is typically:

HCRYPTPROV hProv      = <protocol engine's key container>;
HCRYPTKEY  hServerDHKey;  // handle to the client's DH key
HCRYPTKEY  hMasterKey;
ALG_ID     Algid;
PBYTE      pbClientPub = <pointer to Client Public Key>;
DWORD      cbServerPub = <size of Client Public Key>;
BYTE       rgbClientBlob[<max blob size>];
DWORD      cbClientBlob = <size of the Client Key blob>;
CRYPT_DATA_BLOB Data;

// Build PUBLICKEYBLOB around the client's public key
{
     BLOBHEADER *pBlobHeader = (BLOBHEADER *)rgbClientBlob;
     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 = dwClientPub * 8;

     ReverseMemCopy(pData, pbClientPub, cbClientPub);
     cbClientBlob = sizeof(BLOBHEADER) + sizeof(DHPUBKEY) + 
        cbClientPub;
}

// import the client's public key and get an agreed key
CryptImportKey(hProv, rgbClientBlob, cbClientBlob, hServerDHKey, 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);