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.

728 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. icrypt.hxx
  5. Abstract:
  6. C++ wrappers around the IISCrypto APIs.
  7. This module contains the declarations for one base class and three
  8. derived classes:
  9. IIS_CRYPTO_BASE
  10. |
  11. +--- IIS_CRYPTO_STORAGE
  12. |
  13. +--- IIS_CRYPTO_EXCHANGE_BASE
  14. |
  15. +--- IIS_CRYPTO_EXCHANGE_CLIENT
  16. |
  17. +--- IIS_CRYPTO_EXCHANGE_SERVER
  18. IIS_CRYPTO_BASE is a general base class, containing the crypto
  19. provider handle, as well as the key exchange and signature handles.
  20. This class also provides a couple of member functions used by the
  21. derived classes.
  22. IIS_CRYPTO_STORAGE is used by applications that need to store or
  23. transfer data in a secure manner. This class provides services
  24. for data encryption and descryption.
  25. IIS_CRYPTO_EXCHANGE_BASE is a general base class for the key
  26. exchange classes.
  27. IIS_CRYPTO_EXCHANGE_CLIENT is used by the client (i.e. sending)
  28. side of the multi-phase key exchange protocol.
  29. IIS_CRYPTO_EXCHANGE_SERVER is used by the server (i.e. receiving)
  30. side of the multi-phase key exchange protocol.
  31. The multi-phase key exchange protocol consists of the following
  32. steps:
  33. Phase 1 (client.1):
  34. 1. Export public key exchange and signature blobs.
  35. 2. Send blobs to server.
  36. Phase 2 (server.1):
  37. 1. Import client's public key exchange and signature blobs.
  38. 2. Export public key exchange and signature blobs.
  39. 3. Send blobs to client.
  40. 4. Generate random session key (call it Ka).
  41. 5. Encrypt session key with client's key exchange key.
  42. 6. Send encrypted session key to client.
  43. Phase 3 (client.2):
  44. 1. Import server's public key exchange and signature blobs.
  45. 2. Import encrypted session key.
  46. 3. Generate random session key (call it Kb).
  47. 4. Encrypt session key with server's key exchange key.
  48. 5. Send encrypted session key to server.
  49. 6. Generate hash containing Ka, Kb, and string "Phase 3".
  50. 7. Send hash to the server.
  51. Phase 4 (server.2):
  52. 1. Import encrypted session key.
  53. 2. Validate client's hash.
  54. 3. Generate hash containing Kb and string "Phase 4".
  55. 4. Send hash to the client.
  56. Phase 5 (client.3):
  57. 1. Validate server's hash.
  58. The end result is that each side has two session keys: one for
  59. sending encrypted data, one for receiving encrypted data. Each of
  60. these keys is represented by a IIS_CRYPTO_STORAGE class.
  61. A few notes about the Win32 crypto APIs, IE4, and impersonating
  62. threads...
  63. IE4 has changed the relationship between crypto key containers and
  64. security context. In the pre-IE4 days, whenever an application
  65. acquired a crypto context, the crypto APIs opened the necessary
  66. registry keys and kept them open until the context was released.
  67. With IE4 installed (actually this is an issue with the Protected
  68. Storage service that's installed with IE4) the crypto container
  69. registry keys are NOT opened when the context is aquired, they are
  70. are opened on demand when they're first needed. This causes much
  71. grief for us, as we may acquire the crypto context in one security
  72. context then try to import/whatever in another security context.
  73. The hack (er, solution) implemented in these classes is to try the
  74. import/whatever operation in the current security context. If that
  75. operation fails and the current thread has an impersonation token,
  76. then we "revert to self" and retry the operation.
  77. This solution has the blessing of the NT crypto team (specifically,
  78. Jeff Spelman).
  79. Author:
  80. Keith Moore (keithmo) 02-Dec-1996
  81. Revision History:
  82. --*/
  83. #ifndef _ICRYPT_HXX_
  84. #define _ICRYPT_HXX_
  85. //
  86. // Get the IIS Crypto stuff.
  87. //
  88. #include <iiscrypt.h>
  89. //
  90. // The base crypto class. This class contains the provider handle
  91. // and the public (key exchange & signature) handles. This is intended
  92. // as a base class for IIS_CRYPTO_STORAGE and IIS_CRYPTO_EXCHANGE_BASE.
  93. //
  94. class IIS_CRYPTO_BASE {
  95. public:
  96. //
  97. // Constructor/destructor.
  98. //
  99. IIS_CRYPTO_BASE();
  100. ~IIS_CRYPTO_BASE();
  101. //
  102. // Static method to open a crypto container by name. This method
  103. // performs all of the games necessary to open a container, even
  104. // if we're running in an impersonated security context.
  105. //
  106. static
  107. HRESULT
  108. GetCryptoContainerByName(
  109. OUT HCRYPTPROV * phProv,
  110. IN LPTSTR pszContainerName,
  111. IN DWORD dwAdditionalFlags,
  112. IN BOOL fApplyAcl
  113. );
  114. //
  115. // Initialize the crypto context.
  116. //
  117. HRESULT
  118. Initialize(
  119. IN HCRYPTPROV hProv = CRYPT_NULL,
  120. IN HCRYPTKEY hKeyExchangeKey = CRYPT_NULL,
  121. IN HCRYPTKEY hSignatureKey = CRYPT_NULL,
  122. IN BOOL fUseMachineKeyset = FALSE
  123. );
  124. HRESULT
  125. Initialize2(
  126. IN HCRYPTPROV hProv = CRYPT_NULL
  127. );
  128. //
  129. // Query the key exchange key as a public key blob.
  130. //
  131. HRESULT
  132. GetKeyExchangeKeyBlob(
  133. OUT PIIS_CRYPTO_BLOB * ppKeyExchangeKeyBlob
  134. );
  135. //
  136. // Query the signature key as a public key blob.
  137. //
  138. HRESULT
  139. GetSignatureKeyBlob(
  140. OUT PIIS_CRYPTO_BLOB * ppSignatureKeyBlob
  141. );
  142. //
  143. // Accessors.
  144. //
  145. HCRYPTPROV
  146. QueryProviderHandle()
  147. {
  148. return m_hProv;
  149. }
  150. protected:
  151. //
  152. // A handle to a crypto service provider.
  153. //
  154. HCRYPTPROV m_hProv;
  155. BOOL m_fCloseProv;
  156. //
  157. // A handle to our key exchange key.
  158. //
  159. HCRYPTKEY m_hKeyExchangeKey;
  160. //
  161. // A handle to our signature key.
  162. //
  163. HCRYPTKEY m_hSignatureKey;
  164. #if DBG
  165. //
  166. // Validate object state.
  167. //
  168. BOOL
  169. ValidateState();
  170. BOOL
  171. ValidateState2();
  172. #endif
  173. //
  174. // Wrappers around the corresponding IISCryptoXxx() routines that
  175. // Do The Right Thing when the current thread has an impersonation
  176. // token.
  177. //
  178. static
  179. HRESULT
  180. SafeImportSessionKeyBlob(
  181. OUT HCRYPTKEY * phSessionKey,
  182. IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
  183. IN HCRYPTPROV hProv,
  184. IN HCRYPTKEY hSignatureKey
  185. );
  186. static
  187. HRESULT
  188. SafeImportSessionKeyBlob2(
  189. OUT HCRYPTKEY * phSessionKey,
  190. IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
  191. IN HCRYPTPROV hProv,
  192. IN LPSTR pszPasswd
  193. );
  194. static
  195. HRESULT
  196. SafeExportSessionKeyBlob(
  197. OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob,
  198. IN HCRYPTPROV hProv,
  199. IN HCRYPTKEY hSessionKey,
  200. IN HCRYPTKEY hKeyExchangeKey
  201. );
  202. static
  203. HRESULT
  204. SafeExportSessionKeyBlob2(
  205. OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob,
  206. IN HCRYPTPROV hProv,
  207. IN HCRYPTKEY hSessionKey,
  208. IN LPSTR pszPasswd
  209. );
  210. static
  211. HRESULT
  212. SafeEncryptDataBlob(
  213. OUT PIIS_CRYPTO_BLOB * ppDataBlob,
  214. IN PVOID pBuffer,
  215. IN DWORD dwBufferLength,
  216. IN DWORD dwRegType,
  217. IN HCRYPTPROV hProv,
  218. IN HCRYPTKEY hSessionKey
  219. );
  220. static
  221. HRESULT
  222. SafeEncryptDataBlob2(
  223. OUT PIIS_CRYPTO_BLOB * ppDataBlob,
  224. IN PVOID pBuffer,
  225. IN DWORD dwBufferLength,
  226. IN DWORD dwRegType,
  227. IN HCRYPTPROV hProv,
  228. IN HCRYPTKEY hSessionKey
  229. );
  230. //
  231. // Thread token manipulators.
  232. //
  233. static
  234. HRESULT
  235. GetThreadImpersonationToken(
  236. OUT HANDLE * Token
  237. );
  238. static
  239. HRESULT
  240. SetThreadImpersonationToken(
  241. IN HANDLE Token
  242. );
  243. static
  244. BOOL
  245. AmIRunningInTheLocalSystemContext(
  246. VOID
  247. );
  248. }; // IIS_CRYPTO_BASE
  249. class IIS_CRYPTO_STORAGE : public IIS_CRYPTO_BASE {
  250. public:
  251. //
  252. // Constructor/destructor.
  253. //
  254. IIS_CRYPTO_STORAGE();
  255. ~IIS_CRYPTO_STORAGE();
  256. //
  257. // Initialize the crypto context, generating a new (random) session
  258. // key.
  259. //
  260. HRESULT
  261. Initialize(
  262. IN BOOL fUseMachineKeyset = FALSE,
  263. IN HCRYPTPROV hProv = CRYPT_NULL
  264. );
  265. //
  266. // Initialize the crypto context, importing the session key from the
  267. // given session key blob.
  268. //
  269. HRESULT
  270. Initialize(
  271. IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
  272. IN BOOL fUseMachineKeyset = FALSE,
  273. IN HCRYPTPROV hProv = CRYPT_NULL
  274. );
  275. //
  276. // Initialize the crypto context, using pre-created provider,
  277. // session, key exchange, and signature keys.
  278. //
  279. HRESULT
  280. Initialize(
  281. IN HCRYPTPROV hProv,
  282. IN HCRYPTKEY hSessionKey,
  283. IN HCRYPTKEY hKeyExchangeKey,
  284. IN HCRYPTKEY hSignatureKey,
  285. IN BOOL fUseMachineKeyset = FALSE
  286. );
  287. //
  288. // Query the session key as a session key blob.
  289. //
  290. HRESULT
  291. GetSessionKeyBlob(
  292. OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob
  293. );
  294. //
  295. // Encrypt data into a data blob.
  296. //
  297. virtual
  298. HRESULT
  299. EncryptData(
  300. OUT PIIS_CRYPTO_BLOB * ppDataBlob,
  301. IN PVOID pBuffer,
  302. IN DWORD dwBufferLength,
  303. IN DWORD dwRegType
  304. );
  305. //
  306. // Decrypt data from a data blob.
  307. //
  308. virtual
  309. HRESULT
  310. DecryptData(
  311. OUT PVOID * ppBuffer,
  312. OUT LPDWORD pdwBufferLength,
  313. OUT LPDWORD pdwRegType,
  314. IN PIIS_CRYPTO_BLOB pDataBlob
  315. );
  316. protected:
  317. //
  318. // A handle to the session key.
  319. //
  320. HCRYPTKEY m_hSessionKey;
  321. #if DBG
  322. //
  323. // Validate object state.
  324. //
  325. virtual
  326. BOOL
  327. ValidateState();
  328. #endif
  329. }; // IIS_CRYPTO_STORAGE
  330. class IIS_CRYPTO_STORAGE2 : public IIS_CRYPTO_STORAGE {
  331. public:
  332. //
  333. // Constructor/destructor.
  334. //
  335. IIS_CRYPTO_STORAGE2(){}
  336. ~IIS_CRYPTO_STORAGE2(){}
  337. //
  338. // Initialize the crypto context, generating a new (random) session
  339. // key.
  340. //
  341. HRESULT
  342. Initialize(
  343. IN HCRYPTPROV hProv = CRYPT_NULL
  344. );
  345. //
  346. // Initialize the crypto context, importing the session key from the
  347. // given session key blob.
  348. //
  349. HRESULT
  350. Initialize(
  351. IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
  352. IN LPSTR pszPasswd,
  353. IN HCRYPTPROV hProv = CRYPT_NULL
  354. );
  355. HRESULT
  356. GetSessionKeyBlob(
  357. IN LPSTR pszPasswd,
  358. OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob
  359. );
  360. //
  361. // Encrypt data into a data blob.
  362. //
  363. HRESULT
  364. EncryptData(
  365. OUT PIIS_CRYPTO_BLOB * ppDataBlob,
  366. IN PVOID pBuffer,
  367. IN DWORD dwBufferLength,
  368. IN DWORD dwRegType
  369. );
  370. //
  371. // Decrypt data from a data blob.
  372. //
  373. HRESULT
  374. DecryptData(
  375. OUT PVOID * ppBuffer,
  376. OUT LPDWORD pdwBufferLength,
  377. OUT LPDWORD pdwRegType,
  378. IN PIIS_CRYPTO_BLOB pDataBlob
  379. );
  380. #if DBG
  381. //
  382. // Validate object state.
  383. //
  384. BOOL
  385. ValidateState();
  386. #endif
  387. }; // IIS_CRYPTO_STORAGE
  388. class IIS_CRYPTO_EXCHANGE_BASE : public IIS_CRYPTO_BASE {
  389. public:
  390. //
  391. // Constructor/destructor.
  392. //
  393. IIS_CRYPTO_EXCHANGE_BASE();
  394. ~IIS_CRYPTO_EXCHANGE_BASE();
  395. //
  396. // Accessors for the keys we create. Note that once the calling
  397. // application assumes ownership for one of these keys, it is the
  398. // application's responsibility to close it.
  399. //
  400. HCRYPTKEY
  401. AssumeClientSessionKey()
  402. {
  403. HCRYPTKEY hTmp;
  404. hTmp = m_hClientSessionKey;
  405. m_hClientSessionKey = CRYPT_NULL;
  406. return hTmp;
  407. }
  408. HCRYPTKEY
  409. AssumeServerSessionKey()
  410. {
  411. HCRYPTKEY hTmp;
  412. hTmp = m_hServerSessionKey;
  413. m_hServerSessionKey = CRYPT_NULL;
  414. return hTmp;
  415. }
  416. protected:
  417. //
  418. // Create the phase 3 and 4 hash values.
  419. //
  420. HRESULT
  421. CreatePhase3Hash(
  422. OUT PIIS_CRYPTO_BLOB * ppHashBlob
  423. );
  424. HRESULT
  425. CreatePhase4Hash(
  426. OUT PIIS_CRYPTO_BLOB * ppHashBlob
  427. );
  428. //
  429. // Various keys we create/import.
  430. //
  431. HCRYPTKEY m_hServerSessionKey;
  432. HCRYPTKEY m_hClientSessionKey;
  433. private:
  434. //
  435. // Helper function for creating hash values.
  436. //
  437. HRESULT
  438. CreateHashWorker(
  439. OUT PIIS_CRYPTO_BLOB * ppHashBlob,
  440. IN BOOL fPhase3
  441. );
  442. }; // IIS_CRYPTO_EXCHANGE_BASE
  443. class IIS_CRYPTO_EXCHANGE_CLIENT : public IIS_CRYPTO_EXCHANGE_BASE {
  444. public:
  445. //
  446. // Constructor/destructor.
  447. //
  448. IIS_CRYPTO_EXCHANGE_CLIENT();
  449. ~IIS_CRYPTO_EXCHANGE_CLIENT();
  450. //
  451. // The guts of the client-side multi-phase key exchange protocol.
  452. //
  453. HRESULT
  454. ClientPhase1(
  455. OUT PIIS_CRYPTO_BLOB * ppClientKeyExhangeKeyBlob,
  456. OUT PIIS_CRYPTO_BLOB * ppClientSignatureKeyBlob
  457. );
  458. HRESULT
  459. ClientPhase2(
  460. IN PIIS_CRYPTO_BLOB pServerKeyExchangeKeyBlob,
  461. IN PIIS_CRYPTO_BLOB pServerSignatureKeyBlob,
  462. IN PIIS_CRYPTO_BLOB pServerSessionKeyBlob,
  463. OUT PIIS_CRYPTO_BLOB * ppClientSessionKeyBlob,
  464. OUT PIIS_CRYPTO_BLOB * ppClientHashBlob
  465. );
  466. HRESULT
  467. ClientPhase3(
  468. IN PIIS_CRYPTO_BLOB pServerHashBlob
  469. );
  470. //
  471. // Accessors for the server keys we import. Note that once the calling
  472. // application assumes ownership for one of these keys, it is the
  473. // application's responsibility to close it.
  474. //
  475. HCRYPTKEY
  476. AssumeServerKeyExchangeKey()
  477. {
  478. HCRYPTKEY hTmp;
  479. hTmp = m_hServerKeyExchangeKey;
  480. m_hServerKeyExchangeKey = CRYPT_NULL;
  481. return hTmp;
  482. }
  483. HCRYPTKEY
  484. AssumeServerSignatureKey()
  485. {
  486. HCRYPTKEY hTmp;
  487. hTmp = m_hServerSignatureKey;
  488. m_hServerSignatureKey = CRYPT_NULL;
  489. return hTmp;
  490. }
  491. protected:
  492. //
  493. // Server-side keys we'll import.
  494. //
  495. HCRYPTKEY m_hServerKeyExchangeKey;
  496. HCRYPTKEY m_hServerSignatureKey;
  497. }; // IIS_CRYPTO_EXCHANGE_CLIENT
  498. class IIS_CRYPTO_EXCHANGE_SERVER : public IIS_CRYPTO_EXCHANGE_BASE {
  499. public:
  500. //
  501. // Constructor/destructor.
  502. //
  503. IIS_CRYPTO_EXCHANGE_SERVER();
  504. ~IIS_CRYPTO_EXCHANGE_SERVER();
  505. //
  506. // The guts of the server-side multi-phase key exchange protocol.
  507. //
  508. HRESULT
  509. ServerPhase1(
  510. IN PIIS_CRYPTO_BLOB pClientKeyExchangeKeyBlob,
  511. IN PIIS_CRYPTO_BLOB pClientSignatureKeyBlob,
  512. OUT PIIS_CRYPTO_BLOB * ppServerKeyExchangeKeyBlob,
  513. OUT PIIS_CRYPTO_BLOB * ppServerSignatureKeyBlob,
  514. OUT PIIS_CRYPTO_BLOB * ppServerSessionKeyBlob
  515. );
  516. HRESULT
  517. ServerPhase2(
  518. IN PIIS_CRYPTO_BLOB pClientSessionKeyBlob,
  519. IN PIIS_CRYPTO_BLOB pClientHashBlob,
  520. OUT PIIS_CRYPTO_BLOB * ppServerHashBlob
  521. );
  522. //
  523. // Accessors for the client keys we import. Note that once the calling
  524. // application assumes ownership for one of these keys, it is the
  525. // application's responsibility to close it.
  526. //
  527. HCRYPTKEY
  528. AssumeClientKeyExchangeKey()
  529. {
  530. HCRYPTKEY hTmp;
  531. hTmp = m_hClientKeyExchangeKey;
  532. m_hClientKeyExchangeKey = CRYPT_NULL;
  533. return hTmp;
  534. }
  535. HCRYPTKEY
  536. AssumeClientSignatureKey()
  537. {
  538. HCRYPTKEY hTmp;
  539. hTmp = m_hClientSignatureKey;
  540. m_hClientSignatureKey = CRYPT_NULL;
  541. return hTmp;
  542. }
  543. protected:
  544. //
  545. // Client-side keys we'll import.
  546. //
  547. HCRYPTKEY m_hClientKeyExchangeKey;
  548. HCRYPTKEY m_hClientSignatureKey;
  549. }; // IIS_CRYPTO_EXCHANGE_SERVER
  550. #endif // _ICRYPT_HXX_