Leaked source code of windows server 2003
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.

964 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. blob.c
  5. Abstract:
  6. Generic blob manipulators for the IIS cryptographic package.
  7. The following routines are exported by this module:
  8. IISCryptoReadBlobFromRegistry
  9. IISCryptoWriteBlobToRegistry
  10. IISCryptoIsValidBlob
  11. IISCryptoFreeBlob
  12. IISCryptoCompareBlobs
  13. IISCryptoCloneBlobFromRawData
  14. IISCryptoCreateCleartextBlob
  15. IcpCreateBlob
  16. Author:
  17. Keith Moore (keithmo) 02-Dec-1996
  18. Revision History:
  19. --*/
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. //
  23. // Private constants.
  24. //
  25. //
  26. // Private types.
  27. //
  28. //
  29. // Private globals.
  30. //
  31. //
  32. // Private prototypes.
  33. //
  34. //
  35. // Public functions.
  36. //
  37. HRESULT
  38. WINAPI
  39. IISCryptoReadBlobFromRegistry(
  40. OUT PIIS_CRYPTO_BLOB * ppBlob,
  41. IN HKEY hRegistryKey,
  42. IN LPCTSTR pszRegistryValueName
  43. )
  44. /*++
  45. Routine Description:
  46. This routine creates a new blob, reading the blob out of the
  47. registry.
  48. Arguments:
  49. ppBlob - Receives a pointer to the newly created blob if successful.
  50. hRegistryKey - An open handle to a registry key.
  51. pszRegistryValueName - The name of the REG_BINARY registry value
  52. containing the blob.
  53. Return Value:
  54. HRESULT - Completion status, 0 if successful, !0 otherwise.
  55. --*/
  56. {
  57. HRESULT result;
  58. PIIS_CRYPTO_BLOB blob;
  59. long status;
  60. DWORD type;
  61. long length;
  62. //
  63. // Sanity check.
  64. //
  65. DBG_ASSERT( IcpGlobals.Initialized );
  66. DBG_ASSERT( ppBlob != NULL );
  67. DBG_ASSERT( hRegistryKey != NULL );
  68. DBG_ASSERT( pszRegistryValueName != NULL );
  69. //
  70. // Setup our locals so we know how to cleanup on exit.
  71. //
  72. blob = NULL;
  73. //
  74. // Determine the size of the blob.
  75. //
  76. length = 0;
  77. status = RegQueryValueEx(
  78. hRegistryKey,
  79. pszRegistryValueName,
  80. NULL,
  81. &type,
  82. NULL,
  83. ( LPDWORD )&length
  84. );
  85. if( status != NO_ERROR ) {
  86. result = RETURNCODETOHRESULT(status);
  87. goto fatal;
  88. }
  89. //
  90. // Allocate a new blob.
  91. //
  92. blob = IcpAllocMemory( length );
  93. if( blob == NULL ) {
  94. result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  95. goto fatal;
  96. }
  97. //
  98. // Read the blob.
  99. //
  100. status = RegQueryValueEx(
  101. hRegistryKey,
  102. pszRegistryValueName,
  103. NULL,
  104. &type,
  105. (LPBYTE)blob,
  106. ( LPDWORD )&length
  107. );
  108. if( status != NO_ERROR ) {
  109. result = RETURNCODETOHRESULT(status);
  110. goto fatal;
  111. }
  112. //
  113. // Validate the blob.
  114. //
  115. if( !IISCryptoIsValidBlob( blob ) ) {
  116. result = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  117. goto fatal;
  118. }
  119. //
  120. // Success!
  121. //
  122. *ppBlob = blob;
  123. UpdateBlobsCreated();
  124. return NO_ERROR;
  125. fatal:
  126. if( blob != NULL ) {
  127. IcpFreeMemory( blob );
  128. }
  129. DBG_ASSERT( FAILED(result) );
  130. return result;
  131. } // IISCryptoReadBlobFromRegistry
  132. HRESULT
  133. WINAPI
  134. IISCryptoWriteBlobToRegistry(
  135. IN PIIS_CRYPTO_BLOB pBlob,
  136. IN HKEY hRegistryKey,
  137. IN LPCTSTR pszRegistryValueName
  138. )
  139. /*++
  140. Routine Description:
  141. This routine writes the given blob to the given registry location.
  142. Arguments:
  143. pBlob - A pointer to the blob to write.
  144. hRegistryKey - An open handle to a registry key.
  145. pszRegistryValueName - The name of the REG_BINARY registry value
  146. that will receive the blob.
  147. Return Value:
  148. HRESULT - Completion status, 0 if successful, !0 otherwise.
  149. --*/
  150. {
  151. long status;
  152. //
  153. // Sanity check.
  154. //
  155. DBG_ASSERT( IcpGlobals.Initialized );
  156. DBG_ASSERT( pBlob != NULL );
  157. DBG_ASSERT( IISCryptoIsValidBlob( pBlob ) );
  158. DBG_ASSERT( hRegistryKey != NULL );
  159. DBG_ASSERT( pszRegistryValueName != NULL );
  160. //
  161. // Write the blob.
  162. //
  163. status = RegSetValueEx(
  164. hRegistryKey,
  165. pszRegistryValueName,
  166. 0,
  167. REG_BINARY,
  168. (LPBYTE)pBlob,
  169. IISCryptoGetBlobLength( pBlob )
  170. );
  171. return RETURNCODETOHRESULT(status);
  172. } // IISCryptoWriteBlobToRegistry
  173. BOOL
  174. WINAPI
  175. IISCryptoIsValidBlob(
  176. IN PIIS_CRYPTO_BLOB pBlob
  177. )
  178. /*++
  179. Routine Description:
  180. This routine determines if the specified blob is indeed a valid
  181. blob.
  182. Arguments:
  183. pBlob - The blob to validate.
  184. Return Value:
  185. BOOL - TRUE if the blob is valid, FALSE otherwise.
  186. --*/
  187. {
  188. PIC_BLOB blob;
  189. BOOL result;
  190. //
  191. // Sanity check.
  192. //
  193. DBG_ASSERT( IcpGlobals.Initialized );
  194. DBG_ASSERT( pBlob != NULL );
  195. //
  196. // Validate the signature.
  197. //
  198. blob = (PIC_BLOB)pBlob;
  199. switch( blob->Header.BlobSignature ) {
  200. case KEY_BLOB_SIGNATURE :
  201. case PUBLIC_KEY_BLOB_SIGNATURE :
  202. case DATA_BLOB_SIGNATURE :
  203. case HASH_BLOB_SIGNATURE :
  204. case CLEARTEXT_BLOB_SIGNATURE :
  205. result = TRUE;
  206. break;
  207. default :
  208. result = FALSE;
  209. break;
  210. }
  211. if( result &&
  212. blob->Header.BlobSignature != CLEARTEXT_BLOB_SIGNATURE ) {
  213. //
  214. // Validate some of the blob internal structure. Note that we
  215. // don't validate the internal structure of the cleartext blobs,
  216. // as they do not conform to the normal IC_BLOB structure.
  217. //
  218. if( blob->DataLength == 0 ||
  219. blob->Header.BlobDataLength !=
  220. CALC_BLOB_DATA_LENGTH( blob->DataLength, blob->SignatureLength ) ) {
  221. result = FALSE;
  222. }
  223. }
  224. return result;
  225. } // IISCryptoIsValidBlob
  226. BOOL
  227. WINAPI
  228. IISCryptoIsValidBlob2(
  229. IN PIIS_CRYPTO_BLOB pBlob
  230. )
  231. /*++
  232. Routine Description:
  233. This routine determines if the specified blob is indeed a valid
  234. blob.
  235. Arguments:
  236. pBlob - The blob to validate.
  237. Return Value:
  238. BOOL - TRUE if the blob is valid, FALSE otherwise.
  239. --*/
  240. {
  241. PIC_BLOB2 blob;
  242. BOOL result;
  243. //
  244. // Sanity check.
  245. //
  246. DBG_ASSERT( IcpGlobals.Initialized );
  247. DBG_ASSERT( pBlob != NULL );
  248. //
  249. // Validate the signature.
  250. //
  251. blob = (PIC_BLOB2)pBlob;
  252. switch( blob->Header.BlobSignature ) {
  253. case SALT_BLOB_SIGNATURE :
  254. result = TRUE;
  255. break;
  256. default :
  257. result = FALSE;
  258. break;
  259. }
  260. if( result ) {
  261. //
  262. // Validate some of the blob internal structure. Note that we
  263. // don't validate the internal structure of the cleartext blobs,
  264. // as they do not conform to the normal IC_BLOB structure.
  265. //
  266. if( blob->DataLength == 0 ||
  267. blob->Header.BlobDataLength !=
  268. CALC_BLOB_DATA_LENGTH2( blob->DataLength, blob->SaltLength ) ) {
  269. result = FALSE;
  270. }
  271. }
  272. return result;
  273. } // IISCryptoIsValidBlob2
  274. HRESULT
  275. WINAPI
  276. IISCryptoFreeBlob(
  277. IN PIIS_CRYPTO_BLOB pBlob
  278. )
  279. /*++
  280. Routine Description:
  281. This routine frees all resources associated with the given blob.
  282. After this routine completes, the blob is unusable.
  283. Arguments:
  284. pBlob - The blob to free.
  285. Return Value:
  286. HRESULT - Completion status, 0 if successful, !0 otherwise.
  287. --*/
  288. {
  289. //
  290. // Sanity check.
  291. //
  292. DBG_ASSERT( IcpGlobals.Initialized );
  293. DBG_ASSERT( pBlob != NULL );
  294. DBG_ASSERT( IISCryptoIsValidBlob( pBlob ) );
  295. //
  296. // Corrupt the structure signature before freeing the blob.
  297. //
  298. *(PCHAR)(&pBlob->BlobSignature) = 'X';
  299. //
  300. // Free the resources.
  301. //
  302. IcpFreeMemory( pBlob );
  303. //
  304. // Success!
  305. //
  306. UpdateBlobsFreed();
  307. return NO_ERROR;
  308. } // IISCryptoFreeBlob
  309. HRESULT
  310. WINAPI
  311. IISCryptoFreeBlob2(
  312. IN PIIS_CRYPTO_BLOB pBlob
  313. )
  314. /*++
  315. Routine Description:
  316. This routine frees all resources associated with the given blob.
  317. After this routine completes, the blob is unusable.
  318. Arguments:
  319. pBlob - The blob to free.
  320. Return Value:
  321. HRESULT - Completion status, 0 if successful, !0 otherwise.
  322. --*/
  323. {
  324. //
  325. // Sanity check.
  326. //
  327. DBG_ASSERT( IcpGlobals.Initialized );
  328. DBG_ASSERT( pBlob != NULL );
  329. DBG_ASSERT( IISCryptoIsValidBlob2( pBlob ) );
  330. //
  331. // Corrupt the structure signature before freeing the blob.
  332. //
  333. *(PCHAR)(&pBlob->BlobSignature) = 'X';
  334. //
  335. // Free the resources.
  336. //
  337. IcpFreeMemory( pBlob );
  338. //
  339. // Success!
  340. //
  341. UpdateBlobsFreed();
  342. return NO_ERROR;
  343. } // IISCryptoFreeBlob2
  344. BOOL
  345. WINAPI
  346. IISCryptoCompareBlobs(
  347. IN PIIS_CRYPTO_BLOB pBlob1,
  348. IN PIIS_CRYPTO_BLOB pBlob2
  349. )
  350. /*++
  351. Routine Description:
  352. This routine compares two blobs to determine if they are identical.
  353. Arguments:
  354. pBlob1 - Pointer to a blob.
  355. pBlob2 - Pointer to another blob.
  356. Return Value:
  357. BOOL - TRUE if the blobs match, FALSE otherwise, or if the blobs
  358. are invalid.
  359. --*/
  360. {
  361. //
  362. // Sanity check.
  363. //
  364. DBG_ASSERT( IcpGlobals.Initialized );
  365. DBG_ASSERT( pBlob1 != NULL );
  366. DBG_ASSERT( pBlob2 != NULL );
  367. DBG_ASSERT( IISCryptoIsValidBlob( pBlob1 ) );
  368. DBG_ASSERT( IISCryptoIsValidBlob( pBlob2 ) );
  369. //
  370. // Just do a straight memory compare of the two blobs.
  371. //
  372. if( memcmp( pBlob1, pBlob2, sizeof(*pBlob1) ) == 0 ) {
  373. return TRUE;
  374. }
  375. //
  376. // No match.
  377. //
  378. return FALSE;
  379. } // IISCryptoCompareBlobs
  380. HRESULT
  381. WINAPI
  382. IISCryptoCloneBlobFromRawData(
  383. OUT PIIS_CRYPTO_BLOB * ppBlob,
  384. IN PBYTE pRawBlob,
  385. IN DWORD dwRawBlobLength
  386. )
  387. /*++
  388. Routine Description:
  389. This routine makes a copy of a blob from raw data. The raw data
  390. buffer may be unaligned.
  391. Arguments:
  392. ppBlob - Receives a pointer to the newly created blob if successful.
  393. pRawBlob - Pointer to the raw blob data.
  394. dwRawBlobLength - Length of the raw blob data.
  395. Return Value:
  396. HRESULT - Completion status, 0 if successful, !0 otherwise.
  397. --*/
  398. {
  399. PIIS_CRYPTO_BLOB newBlob;
  400. IIS_CRYPTO_BLOB UNALIGNED *unalignedBlob;
  401. DWORD blobLength;
  402. //
  403. // Sanity check.
  404. //
  405. DBG_ASSERT( ppBlob != NULL );
  406. DBG_ASSERT( pRawBlob != NULL );
  407. //
  408. // Allocate space for the new blob.
  409. //
  410. unalignedBlob = (IIS_CRYPTO_BLOB UNALIGNED *)pRawBlob;
  411. blobLength = IISCryptoGetBlobLength( unalignedBlob );
  412. if( blobLength != dwRawBlobLength ) {
  413. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  414. }
  415. newBlob = IcpAllocMemory( blobLength );
  416. if( newBlob != NULL ) {
  417. //
  418. // Clone it. The (PCHAR) casts are necessary to force the compiler
  419. // to copy BYTE-wise.
  420. //
  421. RtlCopyMemory(
  422. (PCHAR)newBlob,
  423. (PCHAR)unalignedBlob,
  424. blobLength
  425. );
  426. //
  427. // Validate its contents.
  428. //
  429. if( IISCryptoIsValidBlob( newBlob ) ) {
  430. *ppBlob = newBlob;
  431. UpdateBlobsCreated();
  432. return NO_ERROR;
  433. }
  434. IcpFreeMemory( newBlob );
  435. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  436. }
  437. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  438. } // IISCryptoCloneBlobFromRawData
  439. HRESULT
  440. WINAPI
  441. IISCryptoCloneBlobFromRawData2(
  442. OUT PIIS_CRYPTO_BLOB * ppBlob,
  443. IN PBYTE pRawBlob,
  444. IN DWORD dwRawBlobLength
  445. )
  446. /*++
  447. Routine Description:
  448. This routine makes a copy of a blob from raw data. The raw data
  449. buffer may be unaligned.
  450. Arguments:
  451. ppBlob - Receives a pointer to the newly created blob if successful.
  452. pRawBlob - Pointer to the raw blob data.
  453. dwRawBlobLength - Length of the raw blob data.
  454. Return Value:
  455. HRESULT - Completion status, 0 if successful, !0 otherwise.
  456. --*/
  457. {
  458. PIIS_CRYPTO_BLOB newBlob;
  459. IIS_CRYPTO_BLOB UNALIGNED *unalignedBlob;
  460. DWORD blobLength;
  461. //
  462. // Sanity check.
  463. //
  464. DBG_ASSERT( ppBlob != NULL );
  465. DBG_ASSERT( pRawBlob != NULL );
  466. //
  467. // Allocate space for the new blob.
  468. //
  469. unalignedBlob = (IIS_CRYPTO_BLOB UNALIGNED *)pRawBlob;
  470. blobLength = IISCryptoGetBlobLength( unalignedBlob );
  471. if( blobLength != dwRawBlobLength ) {
  472. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  473. }
  474. newBlob = IcpAllocMemory( blobLength );
  475. if( newBlob != NULL ) {
  476. //
  477. // Clone it. The (PCHAR) casts are necessary to force the compiler
  478. // to copy BYTE-wise.
  479. //
  480. RtlCopyMemory(
  481. (PCHAR)newBlob,
  482. (PCHAR)unalignedBlob,
  483. blobLength
  484. );
  485. //
  486. // Validate its contents.
  487. //
  488. if( IISCryptoIsValidBlob2( newBlob ) ) {
  489. *ppBlob = newBlob;
  490. UpdateBlobsCreated();
  491. return NO_ERROR;
  492. }
  493. IcpFreeMemory( newBlob );
  494. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  495. }
  496. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  497. } // IISCryptoCloneBlobFromRawData2
  498. HRESULT
  499. WINAPI
  500. IISCryptoCreateCleartextBlob(
  501. OUT PIIS_CRYPTO_BLOB * ppBlob,
  502. IN PBYTE pBlobData,
  503. IN DWORD dwBlobDataLength
  504. )
  505. /*++
  506. Routine Description:
  507. This routine creates a cleartext blob containing the specified
  508. data.
  509. Arguments:
  510. ppBlob - Receives a pointer to the newly created blob if successful.
  511. pBlobData - Pointer to the blob data.
  512. dwBlobDataLength - Length of the blob data.
  513. Return Value:
  514. HRESULT - Completion status, 0 if successful, !0 otherwise.
  515. --*/
  516. {
  517. PIIS_CRYPTO_BLOB blob;
  518. //
  519. // Sanity check.
  520. //
  521. DBG_ASSERT( ppBlob != NULL );
  522. DBG_ASSERT( pBlobData != NULL );
  523. //
  524. // Allocate space for the new blob.
  525. //
  526. blob = IcpAllocMemory( dwBlobDataLength + sizeof(*blob) );
  527. if( blob != NULL ) {
  528. //
  529. // Initialize the blob.
  530. //
  531. blob->BlobSignature = CLEARTEXT_BLOB_SIGNATURE;
  532. blob->BlobDataLength = dwBlobDataLength;
  533. RtlCopyMemory(
  534. blob + 1,
  535. pBlobData,
  536. dwBlobDataLength
  537. );
  538. *ppBlob = blob;
  539. UpdateBlobsCreated();
  540. return NO_ERROR;
  541. }
  542. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  543. } // IISCryptoCreateCleartextBlob
  544. PIC_BLOB
  545. IcpCreateBlob(
  546. IN DWORD dwBlobSignature,
  547. IN DWORD dwDataLength,
  548. IN DWORD dwSignatureLength OPTIONAL
  549. )
  550. /*++
  551. Routine Description:
  552. This routine creates a new blob.
  553. Arguments:
  554. dwBlobSignature - The structure signature for the new blob.
  555. dwDataLength - The data length for the blob.
  556. dwSignatureLength - The length of the digital signature, 0 if
  557. there is no signature for this blob. This value cannot be
  558. CLEARTEXT_BLOB_SIGNATURE; cleartext blobs are "special".
  559. Return Value:
  560. PIC_BLOB - Pointer to the newly created blob if successful,
  561. NULL otherwise.
  562. --*/
  563. {
  564. PIC_BLOB blob;
  565. DWORD blobDataLength;
  566. //
  567. // Sanity check.
  568. //
  569. DBG_ASSERT( dwBlobSignature == KEY_BLOB_SIGNATURE ||
  570. dwBlobSignature == PUBLIC_KEY_BLOB_SIGNATURE ||
  571. dwBlobSignature == DATA_BLOB_SIGNATURE ||
  572. dwBlobSignature == HASH_BLOB_SIGNATURE );
  573. //
  574. // Allocate storage for the blob.
  575. //
  576. blobDataLength = CALC_BLOB_DATA_LENGTH( dwDataLength, dwSignatureLength );
  577. blob = IcpAllocMemory( blobDataLength + sizeof(IIS_CRYPTO_BLOB) );
  578. if( blob != NULL ) {
  579. //
  580. // Initialize the blob.
  581. //
  582. blob->Header.BlobSignature = dwBlobSignature;
  583. blob->Header.BlobDataLength = blobDataLength;
  584. blob->DataLength = dwDataLength;
  585. blob->SignatureLength = dwSignatureLength;
  586. }
  587. return blob;
  588. } // IcpCreateBlob
  589. PIC_BLOB2
  590. IcpCreateBlob2(
  591. IN DWORD dwBlobSignature,
  592. IN DWORD dwDataLength,
  593. IN DWORD dwSaltLength OPTIONAL
  594. )
  595. /*++
  596. Routine Description:
  597. This routine creates a new blob.
  598. Arguments:
  599. dwBlobSignature - The structure signature for the new blob.
  600. dwDataLength - The data length for the blob.
  601. dwSaltLength - The length of the random salt
  602. Return Value:
  603. PIC_BLOB2 - Pointer to the newly created blob if successful,
  604. NULL otherwise.
  605. --*/
  606. {
  607. PIC_BLOB2 blob;
  608. DWORD blobDataLength;
  609. //
  610. // Sanity check.
  611. //
  612. DBG_ASSERT( dwBlobSignature == SALT_BLOB_SIGNATURE );
  613. //
  614. // Allocate storage for the blob.
  615. //
  616. blobDataLength = CALC_BLOB_DATA_LENGTH( dwDataLength, dwSaltLength );
  617. blob = IcpAllocMemory( blobDataLength + sizeof(IIS_CRYPTO_BLOB) );
  618. if( blob != NULL ) {
  619. //
  620. // Initialize the blob.
  621. //
  622. blob->Header.BlobSignature = dwBlobSignature;
  623. blob->Header.BlobDataLength = blobDataLength;
  624. blob->DataLength = dwDataLength;
  625. blob->SaltLength = dwSaltLength;
  626. }
  627. return blob;
  628. } // IcpCreateBlob2
  629. //
  630. // Private functions.
  631. //