Platform SDK: Cryptography |
Bulk encryption and MAC keys are derived from a master key but can include other sources depending on the protocol and cipher suite used.
The process of deriving bulk encryption and MAC keys is the same for both client and server:
Note When performing SSL reconnects, a protocol engine can perform the above procedure several times using the same master key. This enables the client and server to have multiple, often simultaneous connections, each using different bulk encryption and MAC keys without additional RSA or Diffie-Hellman operations.
All CSPs must use good thread-safe practices. Thread counts of several dozen are not unusual.
The following is typical source code for the protocol engine:
//-------------------------------------------------------------------- // Define and initialize local variables. BOOL fClient = <TRUE if this is code for the client?>; CRYPT_DATA_BLOB Data; HCRYPTHASH hMasterHash; //-------------------------------------------------------------------- // Finish creating the master_secret. switch(<protocol being used>) { case <PCT 1.0>: //------------------------------------------------------------ // Specify clear key value. Data.pbData = pClearKey; Data.cbData = cbClearKey; CryptSetKeyParam( hMasterKey, KP_CLEAR_KEY, (PBYTE)&Data, 0); //------------------------------------------------------------ // Specify the CH_CHALLENGE_DATA. Data.pbData = pChallenge; Data.cbData = cbChallenge; CryptSetKeyParam( hMasterKey, KP_CLIENT_RANDOM, (PBYTE)&Data, 0); //------------------------------------------------------------ // Specify the SH_CONNECTION_ID_DATA. Data.pbData = pConnectionID; Data.cbData = cbConnectionID; CryptSetKeyParam( hMasterKey, KP_SERVER_RANDOM, (PBYTE)&Data, 0); //------------------------------------------------------------ // Specify the SH_CERTIFICATE_DATA. Data.pbData = pbServerCertificate; Data.cbData = cbServerCertificate; CryptSetKeyParam( hMasterKey, KP_CERTIFICATE, (PBYTE)&Data, 0); break; case <SSL 2.0>: //------------------------------------------------------------ // Specify clear key value. Data.pbData = pClearKey; Data.cbData = cbClearKey; CryptSetKeyParam( hMasterKey, KP_CLEAR_KEY, (PBYTE)&Data, 0); //------------------------------------------------------------ // Specify the CH_CHALLENGE_DATA. Data.pbData = pChallenge; Data.cbData = cbChallenge; CryptSetKeyParam( hMasterKey, KP_CLIENT_RANDOM, (BYTE*)&Data, 0); //------------------------------------------------------------ // Specify the SH_CONNECTION_ID_DATA. Data.pbData = pConnectionID; Data.cbData = cbConnectionID; CryptSetKeyParam( hMasterKey, KP_SERVER_RANDOM, (BYTE*)&Data, 0); break; case <SSL 3.0>: case <TLS 1.0>: //------------------------------------------------------------ // Specify client_random. Data.pbData = pClientRandom; Data.cbData = cbClientRandom; CryptSetKeyParam( hMasterKey, KP_CLIENT_RANDOM, (PBYTE)&Data, 0); //------------------------------------------------------------ // Specify server_random. Data.pbData = pServerRandom; Data.cbData = cbServerRandom; CryptSetKeyParam( hMasterKey, KP_SERVER_RANDOM, (PBYTE)&Data, 0); } //------------------------------------------------------------ // Create the master hash object from the master key. CryptCreateHash( hProv, CALG_SCHANNEL_MASTER_HASH, hMasterKey, 0, &hMasterHash); //------------------------------------------------------------ // Derive read key from the master hash object. CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, fClient ? CRYPT_SERVER : 0, &hReadKey); //------------------------------------------------------------ // Derive write key from the master hash object. CryptDeriveKey( hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, fClient ? 0 : CRYPT_SERVER, &hWriteKey); if(<protocol being used> != <SSL 2.0>) // for SSL 2.0, the master // key is also the MAC. { //------------------------------------------------------------ // Derive read MAC from the master hash object. CryptDeriveKey( hProv, CALG_SCHANNEL_MAC_KEY, hMasterHash, fClient ? CRYPT_SERVER : 0, &hReadMAC); //------------------------------------------------------------ // Derive write MAC from the master hash object. CryptDeriveKey( hProv, CALG_SCHANNEL_MAC_KEY, hMasterHash, fClient ? 0 : CRYPT_SERVER, &hWriteMAC); } CryptDestroyHash(hMasterHash);