The master hash is created from the master key just prior to deriving the bulk encryption keys, via a call to CPCreateHash:
CPCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH,
hMasterKey, 0, &hMasterHash);
The master hash should not maintain a reference to the master key. All relevant data associated with the master key should be copied to the master hash object.
Depending on the protocol, the CSP should perform the following operations within CPCreateHash.
The key generated via CPGenKey (or CPImportKey) is not the master key, but a "pre-master key". The "pre-master key" is used to generate the master key, via the following formula (See the SSL 3.0 specification);
Note that the master key, not the "pre-master key" is hashed via CPHashSessionKey.
master_secret =
MD5(pre_master_secret + SHA('A' + pre_master_secret +
ClientHello.random + ServerHello.random)) +
MD5(pre_master_secret + SHA('BB' + pre_master_secret +
ClientHello.random + ServerHello.random)) +
MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
ClientHello.random + ServerHello.random));
The "key block" from which the session keys are created should probably be created within this function. This key block is later used to create the respective session keys by CPDeriveKey fcalls. This is done via the following formula;
key_block =
MD5(master_secret + SHA('A' + master_secret +
ServerHello.random +
ClientHello.random)) +
MD5(master_secret + SHA('BB' + master_secret +
ServerHello.random +
ClientHello.random)) +
MD5(master_secret + SHA('CCC' + master_secret +
ServerHello.random +
ClientHello.random)) + [...];
The key generated via CPGenKey (or CPImportKey) is not the master key, but a "pre-master key". The "pre-master key" is used to generate the master key, via the following formula (See the TLS 1.0 specification);
master_secret = PRF(pre_master_secret, "master secret",
ClientHello.random + ServerHello.random) [0..47];
The "key block" from which the session keys are created should probably be created within this function. This key block is later used to create the respective session keys by the CPDeriveKey function. This is done via the following formula;
key_block = PRF(SecurityParameters.master_secret,
"key expansion",
SecurityParameters.server_random +
SecurityParameters.client_random);