Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

665 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name:
  4. sesskey.c
  5. Abstract:
  6. Contains common client/server code that generate session key.
  7. Author:
  8. Madan Appiah (madana) 24-Jan-1998
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include <seccom.h>
  14. VOID
  15. Salt8ByteKey(
  16. LPBYTE pbKey,
  17. DWORD dwSaltBytes
  18. )
  19. /*++
  20. Routine Description:
  21. This macro function salts the first 1 or 3 bytes of the 8 bytes key to a
  22. known value in order to make it a 40-bit key.
  23. Arguments:
  24. pbKey - pointer to a 8 bytes key buffer.
  25. dwSaltBytes - this value should be either 1 or 3
  26. Return Value:
  27. None.
  28. --*/
  29. {
  30. ASSERT( (dwSaltBytes == 1) || (dwSaltBytes == 3) );
  31. if( dwSaltBytes == 1 ) {
  32. //
  33. // for 56-bit encryption, salt first byte only.
  34. //
  35. *pbKey++ = 0xD1 ;
  36. }
  37. else if (dwSaltBytes == 3) {
  38. //
  39. // for 40-bit encryption, salt first 3 bytes.
  40. //
  41. *pbKey++ = 0xD1 ;
  42. *pbKey++ = 0x26 ;
  43. *pbKey = 0x9E ;
  44. }
  45. return;
  46. }
  47. VOID
  48. FinalHash(
  49. LPRANDOM_KEYS_PAIR pKeyPair,
  50. LPBYTE pbKey
  51. )
  52. /*++
  53. Routine Description:
  54. This macro function hashes the final key with the client and server randoms.
  55. Arguments:
  56. pKeyPair - pointer a random key pair structure.
  57. pbKey - pointer to a key buffer, the final key is returned back in the same
  58. buffer.
  59. Return Value:
  60. None.
  61. --*/
  62. {
  63. MD5_CTX Md5Hash;
  64. //
  65. // final_key = MD5(key + clientRandom + serverRandom)
  66. //
  67. MD5Init (&Md5Hash);
  68. MD5Update(&Md5Hash, pbKey, MAX_SESSION_KEY_SIZE);
  69. MD5Update(&Md5Hash, pKeyPair->clientRandom, RANDOM_KEY_LENGTH);
  70. MD5Update(&Md5Hash, pKeyPair->serverRandom, RANDOM_KEY_LENGTH);
  71. MD5Final (&Md5Hash);
  72. //
  73. // copy the final key back to the input buffer.
  74. //
  75. ASSERT( MD5DIGESTLEN >= MAX_SESSION_KEY_SIZE );
  76. memcpy(pbKey, Md5Hash.digest, MAX_SESSION_KEY_SIZE);
  77. return;
  78. }
  79. VOID
  80. MakeMasterKey(
  81. LPRANDOM_KEYS_PAIR pKeyPair,
  82. LPSTR FAR *ppszSalts,
  83. LPBYTE pbPreMaster,
  84. LPBYTE pbMaster
  85. )
  86. /*++
  87. Routine Description:
  88. This macro function makes a master secret using a pre-master secret.
  89. Arguments:
  90. pKeyPair - pointer a key pair structure.
  91. ppszSalts - pointer to a salt key strings array.
  92. pbPreMaster - pointer to a pre-master secret key buffer.
  93. pbMaster - pointer to a master secret key buffer.
  94. Return Value:
  95. None.
  96. --*/
  97. {
  98. DWORD i;
  99. MD5_CTX Md5Hash;
  100. A_SHA_CTX ShaHash;
  101. BYTE bShaHashValue[A_SHA_DIGEST_LEN];
  102. //
  103. //initialize all buffers with zero
  104. //
  105. memset( pbMaster, 0, PRE_MASTER_SECRET_LEN);
  106. memset( bShaHashValue, 0, A_SHA_DIGEST_LEN);
  107. for ( i = 0 ; i < 3 ; i++) {
  108. //
  109. // SHA(ppszSalts[i] + pre-master + clientRandom + serverRandom)
  110. //
  111. A_SHAInit(&ShaHash);
  112. A_SHAUpdate(&ShaHash, ppszSalts[i], strlen(ppszSalts[i]));
  113. A_SHAUpdate(&ShaHash, pbPreMaster, PRE_MASTER_SECRET_LEN );
  114. A_SHAUpdate(
  115. &ShaHash,
  116. pKeyPair->clientRandom,
  117. sizeof(pKeyPair->clientRandom) );
  118. A_SHAUpdate(
  119. &ShaHash,
  120. pKeyPair->serverRandom,
  121. sizeof(pKeyPair->serverRandom) );
  122. A_SHAFinal(&ShaHash, bShaHashValue);
  123. //
  124. // MD5(pre_master + SHA-hash)
  125. //
  126. MD5Init(&Md5Hash);
  127. MD5Update(&Md5Hash, pbPreMaster, PRE_MASTER_SECRET_LEN );
  128. MD5Update(&Md5Hash, bShaHashValue, A_SHA_DIGEST_LEN);
  129. MD5Final(&Md5Hash);
  130. //
  131. // copy part of the master secret.
  132. //
  133. memcpy(
  134. pbMaster + (i * MD5DIGESTLEN),
  135. Md5Hash.digest,
  136. MD5DIGESTLEN);
  137. }
  138. return;
  139. }
  140. VOID
  141. MakePreMasterSecret(
  142. LPRANDOM_KEYS_PAIR pKeyPair,
  143. LPBYTE pbPreMasterSecret
  144. )
  145. /*++
  146. Routine Description:
  147. This function makes a pre-master secret for the initial session key.
  148. Arguments:
  149. pKeyPair - pointer a key pair structure.
  150. pbPreMasterSecret - pointer to a pre-master secret key buffer, it is
  151. PRE_MASTER_SECRET_LEN bytes long.
  152. Return Value:
  153. None.
  154. --*/
  155. {
  156. //
  157. // copy PRE_MASTER_SECRET_LEN/2 bytes from clientRandom first.
  158. //
  159. memcpy(
  160. pbPreMasterSecret,
  161. pKeyPair->clientRandom,
  162. PRE_MASTER_SECRET_LEN/2 );
  163. //
  164. // copy PRE_MASTER_SECRET_LEN/2 bytes from serverRandom next.
  165. //
  166. memcpy(
  167. pbPreMasterSecret + PRE_MASTER_SECRET_LEN/2,
  168. pKeyPair->serverRandom,
  169. PRE_MASTER_SECRET_LEN/2 );
  170. return;
  171. }
  172. VOID
  173. GenerateMasterSecret(
  174. LPRANDOM_KEYS_PAIR pKeyPair,
  175. LPBYTE pbPreMasterSecret
  176. )
  177. /*++
  178. Routine Description:
  179. This function creates a master secret key using the pre-master key and
  180. random key pair.
  181. Arguments:
  182. pKeyPair - pointer a key pair structure.
  183. pbPreMasterSecret - pointer to a pre-master secret key buffer, it is
  184. PRE_MASTER_SECRET_LEN bytes long.
  185. Return Value:
  186. None.
  187. --*/
  188. {
  189. BYTE abMasterSecret[PRE_MASTER_SECRET_LEN];
  190. LPSTR apszSalts[3] = { "A","BB","CCC" } ;
  191. ASSERT( PRE_MASTER_SECRET_LEN == 3 * MD5DIGESTLEN );
  192. //
  193. // make master secret.
  194. //
  195. MakeMasterKey(
  196. pKeyPair,
  197. (LPSTR FAR *)apszSalts,
  198. pbPreMasterSecret,
  199. (LPBYTE)abMasterSecret );
  200. //
  201. // copy master secret in the return buffer.
  202. //
  203. memcpy( pbPreMasterSecret, abMasterSecret, PRE_MASTER_SECRET_LEN);
  204. return;
  205. }
  206. VOID
  207. UpdateKey(
  208. LPBYTE pbStartKey,
  209. LPBYTE pbCurrentKey,
  210. DWORD dwKeyLength
  211. )
  212. /*++
  213. Routine Description:
  214. This function updates a key.
  215. Arguments:
  216. pbStartKey - pointer to the start session key buffer.
  217. pbCurrentKey - pointer to the current session key buffer, new session key is
  218. copied to this buffer on return.
  219. dwKeyLength - length of the key.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. A_SHA_CTX SHAHash;
  225. MD5_CTX MD5Hash;
  226. BYTE abSHADigest[A_SHA_DIGEST_LEN];
  227. //
  228. // make a SHA(pbStartKey + g_abPad1 + pbCurrentKey) hash.
  229. //
  230. A_SHAInit(&SHAHash);
  231. A_SHAUpdate(&SHAHash, pbStartKey, dwKeyLength);
  232. A_SHAUpdate(&SHAHash, (unsigned char *)g_abPad1, 40);
  233. A_SHAUpdate(&SHAHash, pbCurrentKey, dwKeyLength);
  234. A_SHAFinal(&SHAHash, abSHADigest);
  235. //
  236. // make a MD5(pbStartKey + g_abPad2 + SHAHash) hash.
  237. //
  238. MD5Init(&MD5Hash);
  239. MD5Update(&MD5Hash, pbStartKey, dwKeyLength);
  240. MD5Update(&MD5Hash, g_abPad2, 48);
  241. MD5Update(&MD5Hash, abSHADigest, A_SHA_DIGEST_LEN);
  242. MD5Final(&MD5Hash);
  243. ASSERT( dwKeyLength <= MD5DIGESTLEN );
  244. memcpy(pbCurrentKey, MD5Hash.digest, (UINT)dwKeyLength);
  245. return;
  246. }
  247. BOOL
  248. MakeSessionKeys(
  249. LPRANDOM_KEYS_PAIR pKeyPair,
  250. LPBYTE pbEncryptKey,
  251. struct RC4_KEYSTRUCT FAR *prc4EncryptKey,
  252. LPBYTE pbDecryptKey,
  253. struct RC4_KEYSTRUCT FAR *prc4DecryptKey,
  254. LPBYTE pbMACSaltKey,
  255. DWORD dwKeyStrength,
  256. LPDWORD pdwKeyLength,
  257. DWORD dwEncryptionLevel
  258. )
  259. /*++
  260. Routine Description:
  261. Make the server session key using the client and server random keys.
  262. Assume : the encrypt and decrypt buffer presented are
  263. atleast MAX_SESSION_KEY_SIZE (16) bytes long.
  264. Arguments:
  265. pKeyPair - pointer a key pair structure.
  266. pbEncryptKey - pointer to a buffer where the encryption key is stored.
  267. prc4EncryptKey - pointer to a RC4 encrypt key structure.
  268. pbDecryptKey - pointer to a buffer where the decryption key is stored.
  269. prc4DecryptKey - pointer to a RC4 decrypt key structure.
  270. pbMACSaltKey - pointer to a buffer where the message authentication key is
  271. stored.
  272. dwKeyStrength - specify key strength to use.
  273. pdwKeyLength - pointer to a location where the length of the above
  274. encryption/decryption key is returned.
  275. dwEncryptionLevel - encryption level, used to select the encryption
  276. algorithm.
  277. Return Value:
  278. TRUE - if successfully created the session key.
  279. FALSE - otherwise.
  280. --*/
  281. {
  282. BYTE abPreMasterSecret[PRE_MASTER_SECRET_LEN];
  283. BYTE abMasterSessionKey[PRE_MASTER_SECRET_LEN];
  284. LPSTR apszSalts[3] = { "X","YY","ZZZ" } ;
  285. DWORD dwSaltLen;
  286. //
  287. // make a pre-master secret.
  288. //
  289. MakePreMasterSecret( pKeyPair, (LPBYTE)abPreMasterSecret );
  290. //
  291. // generate master secret.
  292. //
  293. GenerateMasterSecret( pKeyPair, (LPBYTE)abPreMasterSecret );
  294. //
  295. // make a master session key for all three session keys (encrypt, decrypt
  296. // and MACSalt).
  297. //
  298. MakeMasterKey(
  299. pKeyPair,
  300. (LPSTR FAR *)apszSalts,
  301. (LPBYTE)abPreMasterSecret,
  302. (LPBYTE)abMasterSessionKey );
  303. ASSERT( PRE_MASTER_SECRET_LEN == 3 * MAX_SESSION_KEY_SIZE );
  304. //
  305. // copy first part of the master key as MAC salt key.
  306. //
  307. memcpy(
  308. pbMACSaltKey,
  309. (LPBYTE)abMasterSessionKey,
  310. MAX_SESSION_KEY_SIZE );
  311. //
  312. // copy second part of the master key as encrypt key and final hash it.
  313. //
  314. memcpy(
  315. pbEncryptKey,
  316. (LPBYTE)abMasterSessionKey + MAX_SESSION_KEY_SIZE,
  317. MAX_SESSION_KEY_SIZE );
  318. FinalHash( pKeyPair, pbEncryptKey );
  319. //
  320. // copy second part of the master key as decrypt key and final hash it.
  321. //
  322. memcpy(
  323. pbDecryptKey,
  324. (LPBYTE)abMasterSessionKey + MAX_SESSION_KEY_SIZE * 2,
  325. MAX_SESSION_KEY_SIZE );
  326. FinalHash( pKeyPair, pbDecryptKey );
  327. //
  328. // finally select the key length.
  329. //
  330. ASSERT( MAX_SESSION_KEY_SIZE == 16 );
  331. dwSaltLen = 0;
  332. switch ( dwKeyStrength ) {
  333. case SM_40BIT_ENCRYPTION_FLAG:
  334. *pdwKeyLength = MAX_SESSION_KEY_SIZE/2;
  335. dwSaltLen = 3;
  336. break;
  337. case SM_56BIT_ENCRYPTION_FLAG:
  338. *pdwKeyLength = MAX_SESSION_KEY_SIZE/2;
  339. dwSaltLen = 1;
  340. break;
  341. case SM_128BIT_ENCRYPTION_FLAG:
  342. ASSERT( g_128bitEncryptionEnabled );
  343. *pdwKeyLength = MAX_SESSION_KEY_SIZE;
  344. break;
  345. default:
  346. //
  347. // we shouldn't reach here.
  348. //
  349. ASSERT( FALSE );
  350. *pdwKeyLength = MAX_SESSION_KEY_SIZE/2;
  351. dwSaltLen = 1;
  352. break;
  353. }
  354. if( dwSaltLen ) {
  355. Salt8ByteKey( pbMACSaltKey, dwSaltLen );
  356. Salt8ByteKey( pbEncryptKey, dwSaltLen );
  357. Salt8ByteKey( pbDecryptKey, dwSaltLen );
  358. }
  359. //
  360. // finally make rc4 keys.
  361. //
  362. // use microsoft version of rc4 algorithm (super fast!) for level 1 and
  363. // level 2 encryption, for level 3 use RSA rc4 algorithm.
  364. //
  365. if( dwEncryptionLevel <= 2 ) {
  366. msrc4_key( prc4EncryptKey, (UINT)*pdwKeyLength, pbEncryptKey );
  367. msrc4_key( prc4DecryptKey, (UINT)*pdwKeyLength, pbDecryptKey );
  368. }
  369. else {
  370. rc4_key( prc4EncryptKey, (UINT)*pdwKeyLength, pbEncryptKey );
  371. rc4_key( prc4DecryptKey, (UINT)*pdwKeyLength, pbDecryptKey );
  372. }
  373. return( TRUE );
  374. }
  375. BOOL
  376. UpdateSessionKey(
  377. LPBYTE pbStartKey,
  378. LPBYTE pbCurrentKey,
  379. DWORD dwKeyStrength,
  380. DWORD dwKeyLength,
  381. struct RC4_KEYSTRUCT FAR *prc4Key,
  382. DWORD dwEncryptionLevel
  383. )
  384. /*++
  385. Routine Description:
  386. Update the session key using the current and start session keys.
  387. Arguments:
  388. pbStartKey - pointer to the start session key buffer.
  389. pbCurrentKey - pointer to the current session key buffer, new session key is
  390. copied to this buffer on return.
  391. dwKeyStrength - specify key strength to use.
  392. dwKeyLength - length of the key.
  393. prc4Key - pointer to a RC4 key structure.
  394. dwEncryptionLevel - encryption level, used to select the encryption
  395. algorithm.
  396. Return Value:
  397. TRUE - if the successfully update the key.
  398. FALSE - otherwise.
  399. --*/
  400. {
  401. DWORD dwSaltLen;
  402. //
  403. // update current key first.
  404. //
  405. UpdateKey( pbStartKey, pbCurrentKey, dwKeyLength );
  406. //
  407. // use microsoft version of rc4 algorithm (super fast!) for level 1 and
  408. // level 2 encryption, for level 3 use RSA rc4 algorithm.
  409. //
  410. if( dwEncryptionLevel <= 2 ) {
  411. //
  412. // re-initialized RC4 table.
  413. //
  414. msrc4_key( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  415. //
  416. // scramble the current key.
  417. //
  418. msrc4( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  419. }
  420. else {
  421. //
  422. // re-initialized RC4 table.
  423. //
  424. rc4_key( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  425. //
  426. // scramble the current key.
  427. //
  428. rc4( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  429. }
  430. //
  431. // salt the key appropriately.
  432. //
  433. dwSaltLen = 0;
  434. switch ( dwKeyStrength ) {
  435. case SM_40BIT_ENCRYPTION_FLAG:
  436. ASSERT( dwKeyLength = MAX_SESSION_KEY_SIZE/2 );
  437. dwSaltLen = 3;
  438. break;
  439. case SM_56BIT_ENCRYPTION_FLAG:
  440. ASSERT( dwKeyLength = MAX_SESSION_KEY_SIZE/2 );
  441. dwSaltLen = 1;
  442. break;
  443. case SM_128BIT_ENCRYPTION_FLAG:
  444. ASSERT( g_128bitEncryptionEnabled );
  445. ASSERT( dwKeyLength = MAX_SESSION_KEY_SIZE );
  446. break;
  447. default:
  448. //
  449. // we shouldn't reach here.
  450. //
  451. ASSERT( FALSE );
  452. ASSERT( dwKeyLength = MAX_SESSION_KEY_SIZE/2 );
  453. dwSaltLen = 1;
  454. break;
  455. }
  456. if( dwSaltLen ) {
  457. Salt8ByteKey( pbCurrentKey, dwSaltLen );
  458. }
  459. //
  460. // re-initialized RC4 table again.
  461. //
  462. if( dwEncryptionLevel <= 2 ) {
  463. msrc4_key( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  464. }
  465. else {
  466. rc4_key( prc4Key, (UINT)dwKeyLength, pbCurrentKey );
  467. }
  468. return( TRUE );
  469. }