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.

1572 lines
46 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: queryobj.cpp
  8. //
  9. // Contents: OID format functions
  10. //
  11. // Functions:
  12. // CryptQueryObject
  13. //
  14. // History: 15-05-97 xiaohs created
  15. //--------------------------------------------------------------------------
  16. #include "global.hxx"
  17. #include <dbgdef.h>
  18. #include "frmtfunc.h"
  19. #include "align.h"
  20. #define ASN_ASCII_HEX_PREFIX "{ASN}"
  21. #define ASN_ASCII_HEX_PREFIX_LEN ((DWORD) strlen(ASN_ASCII_HEX_PREFIX))
  22. #define NOTEPAD_UNICODE_SPECIAL_WCHAR L'\xfeff'
  23. //**************************************************************************
  24. //
  25. // The following section is for CryptQueryObject
  26. //**************************************************************************
  27. //+-------------------------------------------------------------------------
  28. // CryptStringToBinaryA: Decode the BLOB
  29. //
  30. //--------------------------------------------------------------------------
  31. BOOL DecodeBlobA(CHAR *pbByte,
  32. DWORD cbByte,
  33. BYTE **ppbData,
  34. DWORD *pcbData)
  35. {
  36. DWORD err=0;
  37. BOOL fResult=FALSE;
  38. DWORD dwFlag=0;
  39. *ppbData=NULL;
  40. *pcbData=0;
  41. __try {
  42. if(!CryptStringToBinaryA(pbByte,
  43. cbByte,
  44. CRYPT_STRING_BASE64_ANY,
  45. NULL,
  46. pcbData,
  47. NULL,
  48. &dwFlag))
  49. {
  50. err = GetLastError();
  51. goto DecodeErr;
  52. }
  53. }
  54. __except (EXCEPTION_EXECUTE_HANDLER) {
  55. err = GetExceptionCode();
  56. goto DecodeErr;
  57. }
  58. *ppbData=(BYTE *)malloc(*pcbData);
  59. if(NULL==*ppbData)
  60. goto OutOfMemoryErr;
  61. __try {
  62. if(!CryptStringToBinaryA(pbByte,
  63. cbByte,
  64. dwFlag,
  65. *ppbData,
  66. pcbData,
  67. NULL,
  68. NULL))
  69. {
  70. err = GetLastError();
  71. goto DecodeErr;
  72. }
  73. }
  74. __except (EXCEPTION_EXECUTE_HANDLER) {
  75. err = GetExceptionCode();
  76. goto DecodeErr;
  77. }
  78. fResult=TRUE;
  79. CommonReturn:
  80. return fResult;
  81. ErrorReturn:
  82. if(*ppbData)
  83. {
  84. free(*ppbData);
  85. *ppbData=NULL;
  86. }
  87. fResult=FALSE;
  88. goto CommonReturn;
  89. SET_ERROR_VAR(DecodeErr, err);
  90. SET_ERROR(OutOfMemoryErr, E_OUTOFMEMORY);
  91. }
  92. //+-------------------------------------------------------------------------
  93. // CryptStringToBinaryW: Decode the BLOB
  94. //
  95. //--------------------------------------------------------------------------
  96. BOOL DecodeBlobW(WCHAR *pbByte,
  97. DWORD cbByte,
  98. BYTE **ppbData,
  99. DWORD *pcbData)
  100. {
  101. DWORD err=0;
  102. BOOL fResult=FALSE;
  103. DWORD dwFlag=0;
  104. *ppbData=NULL;
  105. *pcbData=0;
  106. __try {
  107. if(!CryptStringToBinaryW(pbByte,
  108. cbByte,
  109. CRYPT_STRING_BASE64_ANY,
  110. NULL,
  111. pcbData,
  112. NULL,
  113. &dwFlag))
  114. {
  115. err = GetLastError();
  116. goto DecodeErr;
  117. }
  118. }
  119. __except (EXCEPTION_EXECUTE_HANDLER) {
  120. err = GetExceptionCode();
  121. goto DecodeErr;
  122. }
  123. *ppbData=(BYTE *)malloc(*pcbData);
  124. if(NULL==*ppbData)
  125. goto OutOfMemoryErr;
  126. __try {
  127. if(!CryptStringToBinaryW(pbByte,
  128. cbByte,
  129. dwFlag,
  130. *ppbData,
  131. pcbData,
  132. NULL,
  133. NULL))
  134. {
  135. err = GetLastError();
  136. goto DecodeErr;
  137. }
  138. }
  139. __except (EXCEPTION_EXECUTE_HANDLER) {
  140. err = GetExceptionCode();
  141. goto DecodeErr;
  142. }
  143. fResult=TRUE;
  144. CommonReturn:
  145. return fResult;
  146. ErrorReturn:
  147. if(*ppbData)
  148. {
  149. free(*ppbData);
  150. *ppbData=NULL;
  151. }
  152. fResult=FALSE;
  153. goto CommonReturn;
  154. SET_ERROR_VAR(DecodeErr, err);
  155. SET_ERROR(OutOfMemoryErr, E_OUTOFMEMORY);
  156. }
  157. //+-------------------------------------------------------------------------
  158. // Decode the BLOB encoded as ASCII HEX.
  159. //
  160. // Note, pbByte has already been advanced past any leading prefix such as,
  161. // "{ASN}"
  162. //--------------------------------------------------------------------------
  163. BOOL
  164. DecodeAsciiHex(
  165. const char *pch,
  166. DWORD cch,
  167. BYTE **ppbData,
  168. DWORD *pcbData
  169. )
  170. {
  171. DWORD err;
  172. BOOL fResult;
  173. DWORD cbData;
  174. BYTE *pbData = NULL;
  175. pbData = (BYTE *) malloc(cch/2 + 1);
  176. if (NULL == pbData)
  177. goto OutOfMemory;
  178. __try {
  179. BYTE bData;
  180. BYTE *pb;
  181. BOOL fUpperNibble;
  182. fUpperNibble = TRUE;
  183. for (pb = pbData; 0 < cch; cch--, pch++) {
  184. BYTE b;
  185. char ch;
  186. // Convert ascii hex characters 0..9, a..f, A..F
  187. // silently ignore all others
  188. ch = *pch;
  189. if (ch >= '0' && ch <= '9')
  190. b = (BYTE)( ch - '0' );
  191. else if (ch >= 'a' && ch <= 'f')
  192. b = (BYTE)( 10 + ch - 'a' );
  193. else if (ch >= 'A' && ch <= 'F')
  194. b = (BYTE)( 10 + ch - 'A' );
  195. else
  196. goto InvalidData;
  197. if (fUpperNibble) {
  198. bData = (BYTE)( b << 4 );
  199. fUpperNibble = FALSE;
  200. } else {
  201. bData = (BYTE)( bData | b );
  202. *pb++ = bData;
  203. fUpperNibble = TRUE;
  204. }
  205. }
  206. cbData = (DWORD) (pb - pbData);
  207. if (0 == cbData || !fUpperNibble)
  208. goto InvalidData;
  209. } __except (EXCEPTION_EXECUTE_HANDLER) {
  210. err = GetExceptionCode();
  211. goto ExceptionErr;
  212. }
  213. fResult = TRUE;
  214. CommonReturn:
  215. *ppbData = pbData;
  216. *pcbData = cbData;
  217. return fResult;
  218. ErrorReturn:
  219. if (pbData) {
  220. free(pbData);
  221. pbData = NULL;
  222. }
  223. cbData = 0;
  224. fResult = FALSE;
  225. goto CommonReturn;
  226. SET_ERROR_VAR(ExceptionErr, err);
  227. SET_ERROR(OutOfMemory, E_OUTOFMEMORY);
  228. SET_ERROR(InvalidData, ERROR_INVALID_DATA);
  229. }
  230. //+-------------------------------------------------------------------------
  231. // Skip over the identifier and length octets in an ASN encoded blob.
  232. // Returns the number of bytes skipped.
  233. //
  234. // For an invalid identifier or length octet returns 0.
  235. //--------------------------------------------------------------------------
  236. DWORD SkipOverIdentifierAndLengthOctets(
  237. IN const BYTE *pbDER,
  238. IN DWORD cbDER
  239. )
  240. {
  241. #define TAG_MASK 0x1f
  242. DWORD cb;
  243. DWORD cbLength;
  244. const BYTE *pb = pbDER;
  245. // Need minimum of 2 bytes
  246. if (cbDER < 2)
  247. return 0;
  248. // Skip over the identifier octet(s)
  249. if (TAG_MASK == (*pb++ & TAG_MASK)) {
  250. // high-tag-number form
  251. for (cb=2; *pb++ & 0x80; cb++) {
  252. if (cb >= cbDER)
  253. return 0;
  254. }
  255. } else
  256. // low-tag-number form
  257. cb = 1;
  258. // need at least one more byte for length
  259. if (cb >= cbDER)
  260. return 0;
  261. if (0x80 == *pb)
  262. // Indefinite
  263. cb++;
  264. else if ((cbLength = *pb) & 0x80) {
  265. cbLength &= ~0x80; // low 7 bits have number of bytes
  266. cb += cbLength + 1;
  267. if (cb > cbDER)
  268. return 0;
  269. } else
  270. cb++;
  271. return cb;
  272. }
  273. //--------------------------------------------------------------------------
  274. //
  275. // Skip over the tag and length
  276. //----------------------------------------------------------------------------
  277. BOOL SignNoContentWrap(IN const BYTE *pbDER, IN DWORD cbDER)
  278. {
  279. DWORD cb;
  280. __try {
  281. cb = SkipOverIdentifierAndLengthOctets(pbDER, cbDER);
  282. if (cb > 0 && cb < cbDER && pbDER[cb] == 0x02)
  283. return TRUE;
  284. else
  285. return FALSE;
  286. }
  287. __except(EXCEPTION_EXECUTE_HANDLER) {
  288. SetLastError(GetExceptionCode());
  289. }
  290. return FALSE;
  291. }
  292. //--------------------------------------------------------------------------------
  293. //
  294. //get the bytes from the file name
  295. //
  296. //---------------------------------------------------------------------------------
  297. HRESULT RetrieveBLOBFromFile(LPWSTR pwszFileName,DWORD *pcb,BYTE **ppb)
  298. {
  299. HRESULT hr=E_FAIL;
  300. HANDLE hFile=NULL;
  301. HANDLE hFileMapping=NULL;
  302. DWORD cbData=0;
  303. BYTE *pbData=0;
  304. WIN32_FILE_ATTRIBUTE_DATA FileAttr;
  305. if(!pcb || !ppb || !pwszFileName)
  306. return E_INVALIDARG;
  307. *ppb=NULL;
  308. *pcb=0;
  309. if (!GetFileAttributesExW(
  310. pwszFileName,
  311. GetFileExInfoStandard,
  312. &FileAttr
  313. ))
  314. {
  315. hr=HRESULT_FROM_WIN32(GetLastError());
  316. goto CLEANUP;
  317. }
  318. cbData = FileAttr.nFileSizeLow;
  319. if ((FileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
  320. (0 != FileAttr.nFileSizeHigh) ||
  321. (0 == cbData))
  322. {
  323. hr=E_FAIL;
  324. goto CLEANUP;
  325. }
  326. if ((hFile = CreateFileU(pwszFileName,
  327. GENERIC_READ,
  328. FILE_SHARE_READ,
  329. NULL, // lpsa
  330. OPEN_EXISTING,
  331. FILE_ATTRIBUTE_NORMAL,
  332. NULL)) == INVALID_HANDLE_VALUE)
  333. {
  334. hFile = NULL;
  335. hr=HRESULT_FROM_WIN32(GetLastError());
  336. goto CLEANUP;
  337. }
  338. //create a file mapping object
  339. if(NULL == (hFileMapping=CreateFileMapping(
  340. hFile,
  341. NULL,
  342. PAGE_READONLY,
  343. 0,
  344. 0,
  345. NULL)))
  346. {
  347. hr=HRESULT_FROM_WIN32(GetLastError());
  348. goto CLEANUP;
  349. }
  350. //create a view of the file
  351. if(NULL == (pbData=(BYTE *)MapViewOfFile(
  352. hFileMapping,
  353. FILE_MAP_READ,
  354. 0,
  355. 0,
  356. cbData)))
  357. {
  358. hr=HRESULT_FROM_WIN32(GetLastError());
  359. goto CLEANUP;
  360. }
  361. hr=S_OK;
  362. *pcb=cbData;
  363. *ppb=pbData;
  364. CLEANUP:
  365. if(hFile)
  366. CloseHandle(hFile);
  367. if(hFileMapping)
  368. CloseHandle(hFileMapping);
  369. return hr;
  370. }
  371. //-------------------------------------------------------------------------
  372. //
  373. // Check to see if the BLOB has an embeded PKCS7 using SIP functions
  374. //
  375. //-------------------------------------------------------------------------
  376. BOOL GetEmbeddedPKCS7(CERT_BLOB *pCertBlob,
  377. LPWSTR pwszFileName,
  378. BYTE **ppbData,
  379. DWORD *pcbData,
  380. DWORD *pdwEncodingType)
  381. {
  382. BOOL fResult=FALSE;
  383. CHAR szTempPath[MAX_PATH];
  384. CHAR szTempFileName[MAX_PATH];
  385. LPSTR szPreFix="Tmp"; //we should not localize this string
  386. //since it has to be in ANSCII characeter set
  387. DWORD dwBytesWritten=0;
  388. GUID gSubject;
  389. SIP_DISPATCH_INFO SipDispatch;
  390. SIP_SUBJECTINFO SubjectInfo;
  391. HANDLE hFile=NULL;
  392. LPWSTR pwszFileToUse=NULL;
  393. //init the output
  394. *ppbData=NULL;
  395. *pcbData=0;
  396. *pdwEncodingType=0;
  397. //create a temporary file since SIP functions only takes a file name
  398. if(NULL==pwszFileName)
  399. {
  400. if(0==GetTempPath(sizeof(szTempPath), szTempPath))
  401. goto GetTempPathErr;
  402. if(0==GetTempFileName(szTempPath, szPreFix, 0, szTempFileName))
  403. goto GetTempFileNameErr;
  404. if(INVALID_HANDLE_VALUE==(hFile=CreateFile(szTempFileName,
  405. GENERIC_WRITE |GENERIC_READ,
  406. FILE_SHARE_READ,
  407. NULL,
  408. CREATE_NEW,
  409. FILE_ATTRIBUTE_NORMAL,
  410. NULL)))
  411. goto CreateFileErr;
  412. //write the BLOB to the file
  413. if(!WriteFile(hFile,
  414. pCertBlob->pbData,
  415. pCertBlob->cbData,
  416. &dwBytesWritten,
  417. NULL))
  418. goto WriteFileErr;
  419. if(dwBytesWritten != pCertBlob->cbData)
  420. goto WriteBytesErr;
  421. //close the file handle
  422. if(!CloseHandle(hFile))
  423. {
  424. hFile=NULL;
  425. goto CloseHandleErr;
  426. }
  427. hFile=NULL;
  428. //get the unicode version of the file name
  429. pwszFileToUse=MkWStr(szTempFileName);
  430. if(NULL==pwszFileToUse)
  431. goto MkWStrErr;
  432. }
  433. else
  434. pwszFileToUse=pwszFileName;
  435. //call the sip functions
  436. //get the GUID
  437. if (!CryptSIPRetrieveSubjectGuid(
  438. pwszFileToUse,
  439. NULL,
  440. &gSubject))
  441. goto CryptNoMatchErr;
  442. //load the dispatch
  443. memset(&SipDispatch, 0, sizeof(SipDispatch));
  444. SipDispatch.cbSize = sizeof(SipDispatch);
  445. if (!CryptSIPLoad(
  446. &gSubject,
  447. 0,
  448. &SipDispatch))
  449. goto CryptNoMatchErr;
  450. //fill out the subjectInfo
  451. memset(&SubjectInfo, 0, sizeof(SubjectInfo));
  452. SubjectInfo.cbSize = sizeof(SubjectInfo);
  453. SubjectInfo.pgSubjectType = (GUID*) &gSubject;
  454. SubjectInfo.hFile = INVALID_HANDLE_VALUE;
  455. SubjectInfo.pwsFileName = pwszFileToUse;
  456. SubjectInfo.dwEncodingType = *pdwEncodingType;
  457. //get the embedded PKCS7
  458. SipDispatch.pfGet(
  459. &SubjectInfo,
  460. pdwEncodingType,
  461. 0, // dwIndex
  462. pcbData,
  463. NULL // pbSignedData
  464. );
  465. if (0 == (*pcbData))
  466. goto CryptNoMatchErr;
  467. if (NULL == (*ppbData=(BYTE *)malloc(*pcbData)))
  468. goto OutOfMemoryErr;
  469. if (!SipDispatch.pfGet(
  470. &SubjectInfo,
  471. pdwEncodingType,
  472. 0, // dwIndex
  473. pcbData,
  474. *ppbData
  475. ))
  476. goto CryptNoMatchErr;
  477. fResult=TRUE;
  478. CommonReturn:
  479. //close the file handle
  480. if(INVALID_HANDLE_VALUE!=hFile && NULL !=hFile)
  481. CloseHandle(hFile);
  482. //delete the file if it was created
  483. if(NULL==pwszFileName)
  484. {
  485. DeleteFileU(pwszFileToUse);
  486. FreeWStr(pwszFileToUse);
  487. }
  488. return fResult;
  489. ErrorReturn:
  490. fResult=FALSE;
  491. if(*ppbData)
  492. {
  493. free(*ppbData);
  494. *ppbData=NULL;
  495. }
  496. goto CommonReturn;
  497. TRACE_ERROR(GetTempPathErr);
  498. TRACE_ERROR(GetTempFileNameErr);
  499. TRACE_ERROR(CreateFileErr);
  500. TRACE_ERROR(WriteFileErr);
  501. SET_ERROR(WriteBytesErr, E_FAIL);
  502. TRACE_ERROR(CloseHandleErr);
  503. TRACE_ERROR(MkWStrErr);
  504. SET_ERROR(CryptNoMatchErr, CRYPT_E_NO_MATCH);
  505. SET_ERROR(OutOfMemoryErr, E_OUTOFMEMORY);
  506. }
  507. BOOL
  508. AddCertPairToStore(
  509. IN HCERTSTORE hCertStore,
  510. IN const BYTE *pbEncoded,
  511. IN DWORD cbEncoded
  512. )
  513. {
  514. BOOL fResult;
  515. PCERT_PAIR pInfo = NULL;
  516. DWORD cbInfo;
  517. PCCERT_CONTEXT pCertForward = NULL;
  518. // CryptDecodeObjectEX should be usable here, but since this object
  519. // is included with XEnroll and XEnroll must run with Auth2UPD Crypt32
  520. // we must stick with the old CryptDecodeObject 2 pass calls.
  521. if (!CryptDecodeObject(
  522. X509_ASN_ENCODING,
  523. X509_CERT_PAIR,
  524. pbEncoded,
  525. cbEncoded,
  526. CRYPT_DECODE_NOCOPY_FLAG,
  527. NULL, // pInfo
  528. &cbInfo
  529. ))
  530. goto DecodeError;
  531. if (NULL == (pInfo = (PCERT_PAIR) malloc(cbInfo)))
  532. goto OutOfMemory;
  533. if (!CryptDecodeObject(
  534. X509_ASN_ENCODING,
  535. X509_CERT_PAIR,
  536. pbEncoded,
  537. cbEncoded,
  538. CRYPT_DECODE_NOCOPY_FLAG,
  539. pInfo,
  540. &cbInfo
  541. ))
  542. goto DecodeError;
  543. if (pInfo->Forward.cbData) {
  544. if (!CertAddEncodedCertificateToStore(
  545. hCertStore,
  546. X509_ASN_ENCODING,
  547. pInfo->Forward.pbData,
  548. pInfo->Forward.cbData,
  549. CERT_STORE_ADD_ALWAYS,
  550. &pCertForward
  551. ))
  552. goto AddCertError;
  553. }
  554. if (pInfo->Reverse.cbData) {
  555. if (!CertAddEncodedCertificateToStore(
  556. hCertStore,
  557. X509_ASN_ENCODING,
  558. pInfo->Reverse.pbData,
  559. pInfo->Reverse.cbData,
  560. CERT_STORE_ADD_ALWAYS,
  561. NULL // ppCertContext
  562. ))
  563. goto AddCertError;
  564. }
  565. if (pCertForward)
  566. CertFreeCertificateContext(pCertForward);
  567. fResult = TRUE;
  568. CommonReturn:
  569. if (pInfo)
  570. free(pInfo);
  571. return fResult;
  572. DecodeError:
  573. ErrorReturn:
  574. fResult = FALSE;
  575. if (pCertForward)
  576. CertDeleteCertificateFromStore(pCertForward);
  577. goto CommonReturn;
  578. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  579. TRACE_ERROR(AddCertError)
  580. }
  581. //-------------------------------------------------------------------------
  582. //
  583. // The real implementation of CryptQueryObject
  584. //
  585. //-------------------------------------------------------------------------
  586. BOOL I_CryptQueryObject(CERT_BLOB *pCertBlob,
  587. LPWSTR pwszFileName,
  588. DWORD dwContentTypeFlag,
  589. DWORD dwFormatTypeFlag,
  590. DWORD dwFlag,
  591. DWORD *pdwMsgAndCertEncodingType,
  592. DWORD *pdwContentType,
  593. DWORD *pdwFormatType,
  594. HCERTSTORE *phCertStore,
  595. HCRYPTMSG *phMsg,
  596. const void **ppvContext)
  597. {
  598. BOOL fResult=FALSE;
  599. DWORD dwMsgEncodingType=PKCS_7_ASN_ENCODING;
  600. DWORD dwEncodingType=X509_ASN_ENCODING;
  601. DWORD dwPKCS7EncodingType=X509_ASN_ENCODING|PKCS_7_ASN_ENCODING;
  602. DWORD dwContentType=0;
  603. DWORD dwMsgType=0;
  604. DWORD cbData=0;
  605. BOOL fEmbedded=FALSE;
  606. CERT_BLOB PKCS7Blob;
  607. BYTE *pbPKCS7=NULL;
  608. DWORD cbPKCS7=0;
  609. HCERTSTORE hCertStore=NULL;
  610. HCRYPTMSG hMsg=NULL;
  611. PCCERT_CONTEXT pCertContext=NULL;
  612. PCCRL_CONTEXT pCRLContext=NULL;
  613. PCCTL_CONTEXT pCTLContext=NULL;
  614. PCERT_REQUEST_INFO pReqInfo=NULL;
  615. //NULL the output
  616. if(pdwMsgAndCertEncodingType)
  617. *pdwMsgAndCertEncodingType=0;
  618. if(pdwContentType)
  619. *pdwContentType=0;
  620. if(pdwFormatType)
  621. *pdwFormatType=0;
  622. if(phCertStore)
  623. *phCertStore=NULL;
  624. if(phMsg)
  625. *phMsg=NULL;
  626. if(ppvContext)
  627. *ppvContext=NULL;
  628. //open a generic memory store
  629. hCertStore=CertOpenStore(CERT_STORE_PROV_MEMORY,
  630. 0,
  631. NULL,
  632. 0,
  633. NULL);
  634. if(NULL == hCertStore)
  635. goto CertOpenStoreErr;
  636. //single encoded cert
  637. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_CERT)
  638. {
  639. if(CertAddEncodedCertificateToStore(hCertStore,
  640. dwEncodingType,
  641. pCertBlob->pbData,
  642. pCertBlob->cbData,
  643. CERT_STORE_ADD_ALWAYS,
  644. &pCertContext))
  645. {
  646. dwContentType=CERT_QUERY_CONTENT_CERT;
  647. goto Found;
  648. }
  649. }
  650. //an encoded CertificatePair (contains forward and/or reverse cross certs)
  651. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_CERT_PAIR)
  652. {
  653. if(AddCertPairToStore(hCertStore,
  654. pCertBlob->pbData,
  655. pCertBlob->cbData
  656. ))
  657. {
  658. dwContentType=CERT_QUERY_CONTENT_CERT_PAIR;
  659. goto Found;
  660. }
  661. }
  662. //single encoded CTL
  663. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_CTL)
  664. {
  665. if(CertAddEncodedCTLToStore(hCertStore,
  666. dwEncodingType | dwMsgEncodingType,
  667. pCertBlob->pbData,
  668. pCertBlob->cbData,
  669. CERT_STORE_ADD_ALWAYS,
  670. &pCTLContext))
  671. {
  672. dwContentType=CERT_QUERY_CONTENT_CTL;
  673. dwEncodingType |= dwMsgEncodingType;
  674. goto Found;
  675. }
  676. }
  677. //single encoded CRL
  678. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_CRL)
  679. {
  680. if(CertAddEncodedCRLToStore(hCertStore,
  681. dwEncodingType,
  682. pCertBlob->pbData,
  683. pCertBlob->cbData,
  684. CERT_STORE_ADD_ALWAYS,
  685. &pCRLContext))
  686. {
  687. dwContentType=CERT_QUERY_CONTENT_CRL;
  688. goto Found;
  689. }
  690. }
  691. //PFX
  692. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PFX)
  693. {
  694. if(PFXIsPFXBlob((CRYPT_DATA_BLOB*)pCertBlob))
  695. {
  696. dwContentType=CERT_QUERY_CONTENT_PFX;
  697. //we need to close the temporary store
  698. CertCloseStore(hCertStore, 0);
  699. hCertStore=NULL;
  700. goto Found;
  701. }
  702. }
  703. //serialized CERT
  704. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT)
  705. {
  706. if(CertAddSerializedElementToStore(hCertStore,
  707. pCertBlob->pbData,
  708. pCertBlob->cbData,
  709. CERT_STORE_ADD_ALWAYS,
  710. 0,
  711. CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
  712. NULL,
  713. (const void **)&pCertContext))
  714. {
  715. dwContentType=CERT_QUERY_CONTENT_SERIALIZED_CERT;
  716. dwEncodingType=pCertContext->dwCertEncodingType;
  717. goto Found;
  718. }
  719. }
  720. //serialized CTL
  721. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)
  722. {
  723. if(CertAddSerializedElementToStore(hCertStore,
  724. pCertBlob->pbData,
  725. pCertBlob->cbData,
  726. CERT_STORE_ADD_ALWAYS,
  727. 0,
  728. CERT_STORE_CTL_CONTEXT_FLAG,
  729. NULL,
  730. (const void **)&pCTLContext))
  731. {
  732. dwContentType=CERT_QUERY_CONTENT_SERIALIZED_CTL;
  733. dwEncodingType=pCTLContext->dwMsgAndCertEncodingType;
  734. goto Found;
  735. }
  736. }
  737. //serialized CRL
  738. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL)
  739. {
  740. if(CertAddSerializedElementToStore(hCertStore,
  741. pCertBlob->pbData,
  742. pCertBlob->cbData,
  743. CERT_STORE_ADD_ALWAYS,
  744. 0,
  745. CERT_STORE_CRL_CONTEXT_FLAG,
  746. NULL,
  747. (const void **)&pCRLContext))
  748. {
  749. dwContentType=CERT_QUERY_CONTENT_SERIALIZED_CRL;
  750. dwEncodingType=pCRLContext->dwCertEncodingType;
  751. goto Found;
  752. }
  753. }
  754. //we need to close the temporary store
  755. CertCloseStore(hCertStore, 0);
  756. hCertStore=NULL;
  757. //serialized store
  758. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE)
  759. {
  760. if(hCertStore=CertOpenStore(
  761. CERT_STORE_PROV_SERIALIZED,
  762. dwEncodingType | dwMsgEncodingType,
  763. NULL,
  764. 0,
  765. pCertBlob))
  766. {
  767. dwContentType=CERT_QUERY_CONTENT_SERIALIZED_STORE;
  768. dwEncodingType |= dwMsgEncodingType;
  769. goto Found;
  770. }
  771. }
  772. //PKCS7 signed message
  773. if((dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
  774. (dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED) )
  775. {
  776. //get the embedded signed pkcs7
  777. if((CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED & dwContentTypeFlag))
  778. {
  779. if(GetEmbeddedPKCS7(pCertBlob, pwszFileName, &pbPKCS7, &cbPKCS7, &dwPKCS7EncodingType))
  780. fEmbedded=TRUE;
  781. else
  782. {
  783. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
  784. {
  785. //there is no embedded PKCS7
  786. dwPKCS7EncodingType=dwEncodingType | dwMsgEncodingType;
  787. pbPKCS7=pCertBlob->pbData;
  788. cbPKCS7=pCertBlob->cbData;
  789. }
  790. else
  791. pbPKCS7=NULL;
  792. }
  793. }
  794. else
  795. {
  796. //there is no embedded PKCS7
  797. dwPKCS7EncodingType=dwEncodingType | dwMsgEncodingType;
  798. pbPKCS7=pCertBlob->pbData;
  799. cbPKCS7=pCertBlob->cbData;
  800. }
  801. //proceed if there is a pkcs7 to decode
  802. if(NULL != pbPKCS7)
  803. {
  804. //check if the header is missing
  805. if(SignNoContentWrap(pbPKCS7, cbPKCS7))
  806. dwMsgType=CMSG_SIGNED;
  807. if(NULL==(hMsg=CryptMsgOpenToDecode(dwPKCS7EncodingType,
  808. 0,
  809. dwMsgType,
  810. NULL,
  811. NULL,
  812. NULL)))
  813. goto CryptMsgOpenErr;
  814. //update the message
  815. if(CryptMsgUpdate(hMsg,
  816. pbPKCS7,
  817. cbPKCS7,
  818. TRUE))
  819. {
  820. //get the message type
  821. cbData=sizeof(dwMsgType);
  822. if(!CryptMsgGetParam(hMsg,
  823. CMSG_TYPE_PARAM,
  824. 0,
  825. &dwMsgType,
  826. &cbData))
  827. goto CryptMsgGetParamErr;
  828. if(CMSG_SIGNED == dwMsgType)
  829. {
  830. PKCS7Blob.cbData=cbPKCS7;
  831. PKCS7Blob.pbData=pbPKCS7;
  832. //open a certificate store
  833. hCertStore=CertOpenStore(CERT_STORE_PROV_PKCS7,
  834. dwPKCS7EncodingType,
  835. NULL,
  836. 0,
  837. &PKCS7Blob);
  838. if(NULL==hCertStore)
  839. goto CertOpenStoreErr;
  840. //we succeeded in opening a signed PKCS7
  841. dwEncodingType = dwPKCS7EncodingType;
  842. if(TRUE==fEmbedded)
  843. dwContentType=CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED;
  844. else
  845. dwContentType=CERT_QUERY_CONTENT_PKCS7_SIGNED;
  846. goto Found;
  847. }
  848. }
  849. //close the message
  850. CryptMsgClose(hMsg);
  851. hMsg=NULL;
  852. }
  853. }
  854. //PKCS7 unsigned message, not embedded
  855. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)
  856. {
  857. //no need to check if the header is missing
  858. if(NULL==(hMsg=CryptMsgOpenToDecode(dwEncodingType | dwMsgEncodingType,
  859. 0,
  860. 0,
  861. NULL,
  862. NULL,
  863. NULL)))
  864. goto CryptMsgOpenErr;
  865. //update the message
  866. if(CryptMsgUpdate(hMsg,
  867. pCertBlob->pbData,
  868. pCertBlob->cbData,
  869. TRUE))
  870. {
  871. //get the message type
  872. cbData=sizeof(dwMsgType);
  873. if(!CryptMsgGetParam(hMsg,
  874. CMSG_TYPE_PARAM,
  875. 0,
  876. &dwMsgType,
  877. &cbData))
  878. goto CryptMsgGetParamErr;
  879. if(CMSG_SIGNED != dwMsgType)
  880. {
  881. //we succeeded in opening a unsigned PKCS7
  882. dwContentType=CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
  883. dwEncodingType =dwEncodingType | dwMsgEncodingType;
  884. goto Found;
  885. }
  886. }
  887. //close the message
  888. CryptMsgClose(hMsg);
  889. hMsg=NULL;
  890. }
  891. //PKCS10
  892. if(dwContentTypeFlag & CERT_QUERY_CONTENT_FLAG_PKCS10)
  893. {
  894. //try to decode the BLOB
  895. cbData = 0;
  896. if(CryptDecodeObject(dwEncodingType,
  897. X509_CERT_REQUEST_TO_BE_SIGNED,
  898. pCertBlob->pbData,
  899. pCertBlob->cbData,
  900. 0,
  901. NULL,
  902. &cbData))
  903. {
  904. dwContentType=CERT_QUERY_CONTENT_PKCS10;
  905. // CryptDecodeObjectEX should be usable here, but since this object
  906. // is included with XEnroll and XEnroll must run with Auth2UPD Crypt32
  907. // we must stick with the old CryptDecodeObject 2 pass calls.
  908. if( (dwFlag & CRYPT_DECODE_ALLOC_FLAG) == CRYPT_DECODE_ALLOC_FLAG ) {
  909. // allocate the space, must use local alloc
  910. if( NULL == (pReqInfo = (PCERT_REQUEST_INFO) LocalAlloc(LPTR, cbData)) )
  911. goto LocalAllocErr;
  912. // decode the request
  913. if( !CryptDecodeObject(dwEncodingType,
  914. X509_CERT_REQUEST_TO_BE_SIGNED,
  915. pCertBlob->pbData,
  916. pCertBlob->cbData,
  917. 0,
  918. pReqInfo,
  919. &cbData))
  920. goto CryptDecodeObjectErr;
  921. }
  922. goto Found;
  923. }
  924. }
  925. //we give up
  926. goto NoMatchErr;
  927. Found:
  928. //fill in the output if required; Free the resources
  929. if(pdwMsgAndCertEncodingType)
  930. *pdwMsgAndCertEncodingType=dwEncodingType;
  931. if(pdwContentType)
  932. *pdwContentType=dwContentType;
  933. if(phCertStore)
  934. *phCertStore=hCertStore;
  935. else
  936. {
  937. if(hCertStore)
  938. CertCloseStore(hCertStore, 0);
  939. }
  940. if(phMsg)
  941. *phMsg=hMsg;
  942. else
  943. {
  944. if(hMsg)
  945. CryptMsgClose(hMsg);
  946. }
  947. if(ppvContext)
  948. {
  949. //only one of pCertContext or pCRLContext or pCRLContext is set
  950. if(pCertContext)
  951. *ppvContext=pCertContext;
  952. else
  953. {
  954. if(pCRLContext)
  955. *ppvContext=pCRLContext;
  956. else if(pReqInfo)
  957. *ppvContext=pReqInfo;
  958. else
  959. *ppvContext=pCTLContext;
  960. }
  961. }
  962. else
  963. {
  964. if(pCertContext)
  965. CertFreeCertificateContext(pCertContext);
  966. if(pCRLContext)
  967. CertFreeCRLContext(pCRLContext);
  968. if(pCTLContext)
  969. CertFreeCTLContext(pCTLContext);
  970. if(pReqInfo)
  971. LocalFree(pReqInfo);
  972. }
  973. fResult=TRUE;
  974. CommonReturn:
  975. if(pbPKCS7)
  976. {
  977. if(TRUE==fEmbedded)
  978. free(pbPKCS7);
  979. }
  980. return fResult;
  981. ErrorReturn:
  982. //relaset the stores and reset the local parameters
  983. if(hCertStore)
  984. CertCloseStore(hCertStore, 0);
  985. if(hMsg)
  986. CryptMsgClose(hMsg);
  987. if(pCertContext)
  988. CertFreeCertificateContext(pCertContext);
  989. if(pCRLContext)
  990. CertFreeCRLContext(pCRLContext);
  991. if(pCTLContext)
  992. CertFreeCTLContext(pCTLContext);
  993. fResult=FALSE;
  994. goto CommonReturn;
  995. SET_ERROR(NoMatchErr,CRYPT_E_NO_MATCH);
  996. SET_ERROR(LocalAllocErr, ERROR_OUTOFMEMORY);
  997. TRACE_ERROR(CryptDecodeObjectErr);
  998. TRACE_ERROR(CryptMsgOpenErr);
  999. TRACE_ERROR(CryptMsgGetParamErr);
  1000. TRACE_ERROR(CertOpenStoreErr);
  1001. }
  1002. //-------------------------------------------------------------------------
  1003. //
  1004. // CryptQueryObject takes a CERT_BLOB or a file name and returns the
  1005. // information about the content in the blob or in the file.
  1006. //
  1007. // Parameters:
  1008. // INPUT dwObjectType:
  1009. // Indicate the type of the object. Should be one of the
  1010. // following:
  1011. // CERT_QUERY_OBJECT_FILE
  1012. // CERT_QUERY_OBJECT_BLOB
  1013. //
  1014. // INPUT pvObject:
  1015. // If dwObjectType == CERT_QUERY_OBJECT_FILE, it is a
  1016. // LPWSTR, that is, the pointer to a wchar file name
  1017. // if dwObjectType == CERT_QUERY_OBJECT_BLOB, it is a
  1018. // PCERT_BLOB, that is, a pointer to a CERT_BLOB
  1019. //
  1020. // INPUT dwExpectedContentTypeFlags:
  1021. // Indicate the expected contenet type.
  1022. // Can be one of the following:
  1023. // CERT_QUERY_CONTENT_FLAG_ALL (the content can be any type)
  1024. // CERT_QUERY_CONTENT_FLAG_CERT
  1025. // CERT_QUERY_CONTENT_FLAG_CTL
  1026. // CERT_QUERY_CONTENT_FLAG_CRL
  1027. // CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
  1028. // CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
  1029. // CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
  1030. // CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
  1031. // CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
  1032. // CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
  1033. // CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
  1034. // CERT_QUERY_CONTENT_FLAG_PKCS10
  1035. // CERT_QUERY_CONTENT_FLAG_PFX
  1036. // CERT_QUERY_CONTENT_FLAG_CERT_PAIR
  1037. //
  1038. // INPUT dwExpectedFormatTypeFlags:
  1039. // Indicate the expected format type.
  1040. // Can be one of the following:
  1041. // CERT_QUERY_FORMAT_FLAG_ALL (the content can be any format)
  1042. // CERT_QUERY_FORMAT_FLAG_BINARY
  1043. // CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
  1044. // CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED
  1045. //
  1046. //
  1047. // INPUT dwFlags
  1048. // Reserved flag. Should always set to 0
  1049. //
  1050. // OUTPUT pdwMsgAndCertEncodingType
  1051. // Optional output. If NULL != pdwMsgAndCertEncodingType,
  1052. // it contains the encoding type of the content as any
  1053. // combination of the following:
  1054. // X509_ASN_ENCODING
  1055. // PKCS_7_ASN_ENCODING
  1056. //
  1057. // OUTPUT pdwContentType
  1058. // Optional output. If NULL!=pdwContentType, it contains
  1059. // the content type as one of the the following:
  1060. // CERT_QUERY_CONTENT_CERT
  1061. // CERT_QUERY_CONTENT_CTL
  1062. // CERT_QUERY_CONTENT_CRL
  1063. // CERT_QUERY_CONTENT_SERIALIZED_STORE
  1064. // CERT_QUERY_CONTENT_SERIALIZED_CERT
  1065. // CERT_QUERY_CONTENT_SERIALIZED_CTL
  1066. // CERT_QUERY_CONTENT_SERIALIZED_CRL
  1067. // CERT_QUERY_CONTENT_PKCS7_SIGNED
  1068. // CERT_QUERY_CONTENT_PKCS7_UNSIGNED
  1069. // CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
  1070. // CERT_QUERY_CONTENT_PKCS10
  1071. // CERT_QUERY_CONTENT_PFX
  1072. // CERT_QUERY_CONTENT_CERT_PAIR
  1073. //
  1074. // OUTPUT pdwFormatType
  1075. // Optional output. If NULL !=pdwFormatType, it
  1076. // contains the format type of the content as one of the
  1077. // following:
  1078. // CERT_QUERY_FORMAT_BINARY
  1079. // CERT_QUERY_FORMAT_BASE64_ENCODED
  1080. // CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED
  1081. //
  1082. //
  1083. // OUTPUT phCertStore
  1084. // Optional output. If NULL !=phStore,
  1085. // it contains a cert store that includes all of certificates,
  1086. // CRL, and CTL in the object if the object content type is
  1087. // one of the following:
  1088. // CERT_QUERY_CONTENT_CERT
  1089. // CERT_QUERY_CONTENT_CTL
  1090. // CERT_QUERY_CONTENT_CRL
  1091. // CERT_QUERY_CONTENT_SERIALIZED_STORE
  1092. // CERT_QUERY_CONTENT_SERIALIZED_CERT
  1093. // CERT_QUERY_CONTENT_SERIALIZED_CTL
  1094. // CERT_QUERY_CONTENT_SERIALIZED_CRL
  1095. // CERT_QUERY_CONTENT_PKCS7_SIGNED
  1096. // CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
  1097. // CERT_QUERY_CONTENT_CERT_PAIR
  1098. //
  1099. // Caller should free *phCertStore via CertCloseStore.
  1100. //
  1101. //
  1102. // OUTPUT phMsg Optional output. If NULL != phMsg,
  1103. // it contains a handle to a opened message if
  1104. // the content type is one of the following:
  1105. // CERT_QUERY_CONTENT_PKCS7_SIGNED
  1106. // CERT_QUERY_CONTENT_PKCS7_UNSIGNED
  1107. // CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
  1108. //
  1109. // Caller should free *phMsg via CryptMsgClose.
  1110. //
  1111. // OUTPUT pContext Optional output. If NULL != pContext,
  1112. // it contains either a PCCERT_CONTEXT or PCCRL_CONTEXT,
  1113. // or PCCTL_CONTEXT based on the content type.
  1114. //
  1115. // If the content type is CERT_QUERY_CONTENT_CERT or
  1116. // CERT_QUERY_CONTENT_SERIALIZED_CERT, it is a PCCERT_CONTEXT;
  1117. // Caller should free the pContext via CertFreeCertificateContext.
  1118. //
  1119. // If the content type is CERT_QUERY_CONTENT_CRL or
  1120. // CERT_QUERY_CONTENT_SERIALIZED_CRL, it is a PCCRL_CONTEXT;
  1121. // Caller should free the pContext via CertFreeCRLContext.
  1122. //
  1123. // If the content type is CERT_QUERY_CONTENT_CTL or
  1124. // CERT_QUERY_CONTENT_SERIALIZED_CTL, it is a PCCTL_CONTEXT;
  1125. // Caller should free the pContext via CertFreeCTLContext.
  1126. //
  1127. // If the *pbObject is of type CERT_QUERY_CONTENT_PKCS10 or CERT_QUERY_CONTENT_PFX, CryptQueryObject
  1128. // will not return anything in *phCertstore, *phMsg, or *ppvContext.
  1129. //--------------------------------------------------------------------------
  1130. BOOL
  1131. WINAPI
  1132. CryptQueryObject(DWORD dwObjectType,
  1133. const void *pvObject,
  1134. DWORD dwExpectedContentTypeFlags,
  1135. DWORD dwExpectedFormatTypeFlags,
  1136. DWORD dwFlags,
  1137. DWORD *pdwMsgAndCertEncodingType,
  1138. DWORD *pdwContentType,
  1139. DWORD *pdwFormatType,
  1140. HCERTSTORE *phCertStore,
  1141. HCRYPTMSG *phMsg,
  1142. const void **ppvContext)
  1143. {
  1144. BOOL fResult=FALSE;
  1145. DWORD err;
  1146. CERT_BLOB CertBlob;
  1147. DWORD cbData=0;
  1148. BYTE *pbData=NULL;
  1149. BYTE *pbToDecode=NULL;
  1150. DWORD cbToDecode=0;
  1151. DWORD cbDecodedData=0;
  1152. BYTE *pbDecodedData=NULL;
  1153. HRESULT hr=S_OK;
  1154. DWORD dwFormatType=0;
  1155. __try {
  1156. //check input parameters
  1157. if(NULL==pvObject)
  1158. goto InvalidArgErr;
  1159. //make sure we have a correct dwFormatTypeFlag
  1160. if(0==(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_ALL))
  1161. goto InvalidArgErr;
  1162. //make sure we have a correct dwContentTypeFlag
  1163. if(0==(dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_ALL))
  1164. goto InvalidArgErr;
  1165. //NULL out local variables
  1166. memset(&CertBlob, 0, sizeof(CERT_BLOB));
  1167. //get the BLOB
  1168. if(CERT_QUERY_OBJECT_FILE == dwObjectType)
  1169. {
  1170. if(S_OK!=(hr=RetrieveBLOBFromFile((LPWSTR)pvObject, &cbData, &pbData)))
  1171. goto RetrieveBLOBFromFileErr;
  1172. }
  1173. else
  1174. {
  1175. if(CERT_QUERY_OBJECT_BLOB == dwObjectType)
  1176. {
  1177. cbData=((PCERT_BLOB)pvObject)->cbData;
  1178. pbData=((PCERT_BLOB)pvObject)->pbData;
  1179. }
  1180. else
  1181. goto InvalidArgErr;
  1182. }
  1183. //make sure the input are valid
  1184. if(0==cbData || NULL==pbData)
  1185. goto InvalidArgErr;
  1186. //assume the BLOBs are ANSCII
  1187. CertBlob.cbData=cbData;
  1188. CertBlob.pbData=pbData;
  1189. //binary decoding
  1190. if(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)
  1191. {
  1192. if(I_CryptQueryObject(
  1193. &CertBlob,
  1194. (CERT_QUERY_OBJECT_FILE == dwObjectType) ? (LPWSTR)pvObject : NULL,
  1195. dwExpectedContentTypeFlags,
  1196. dwExpectedFormatTypeFlags,
  1197. dwFlags,
  1198. pdwMsgAndCertEncodingType,
  1199. pdwContentType,
  1200. pdwFormatType,
  1201. phCertStore,
  1202. phMsg,
  1203. ppvContext))
  1204. {
  1205. dwFormatType=CERT_QUERY_FORMAT_BINARY;
  1206. goto Done;
  1207. }
  1208. }
  1209. if(dwExpectedFormatTypeFlags &
  1210. CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED)
  1211. {
  1212. if (ASN_ASCII_HEX_PREFIX_LEN < cbData &&
  1213. 0 == _strnicmp((char *) pbData, ASN_ASCII_HEX_PREFIX,
  1214. ASN_ASCII_HEX_PREFIX_LEN))
  1215. {
  1216. dwFormatType=CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED;
  1217. if (!DecodeAsciiHex(
  1218. (char *) (pbData + ASN_ASCII_HEX_PREFIX_LEN),
  1219. cbData - ASN_ASCII_HEX_PREFIX_LEN,
  1220. &pbDecodedData,
  1221. &cbDecodedData
  1222. ))
  1223. goto InvalidAsciiHex;
  1224. CertBlob.cbData=cbDecodedData;
  1225. CertBlob.pbData=pbDecodedData;
  1226. if(I_CryptQueryObject(
  1227. &CertBlob,
  1228. NULL,
  1229. dwExpectedContentTypeFlags,
  1230. dwExpectedFormatTypeFlags,
  1231. dwFlags,
  1232. pdwMsgAndCertEncodingType,
  1233. pdwContentType,
  1234. pdwFormatType,
  1235. phCertStore,
  1236. phMsg,
  1237. ppvContext))
  1238. {
  1239. goto Done;
  1240. } else {
  1241. goto I_CryptQueryObjectErr;
  1242. }
  1243. }
  1244. }
  1245. if(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED)
  1246. {
  1247. pbToDecode = pbData;
  1248. cbToDecode = cbData;
  1249. if(!DecodeBlobA((CHAR *)pbToDecode, cbToDecode, &pbDecodedData, &cbDecodedData))
  1250. {
  1251. LPWSTR pwszUnicode = (LPWSTR) pbData;
  1252. DWORD cchUnicode = cbData / sizeof(WCHAR);
  1253. if(!POINTER_IS_ALIGNED(pwszUnicode, sizeof(WCHAR)) ||
  1254. !DecodeBlobW(pwszUnicode, cchUnicode, &pbDecodedData, &cbDecodedData))
  1255. {
  1256. //now we are conviced the BLOB is not base64 encoded
  1257. goto NoMatchErr;
  1258. }
  1259. }
  1260. //the BLOB has been properly decoded
  1261. dwFormatType=CERT_QUERY_FORMAT_BASE64_ENCODED;
  1262. //make sure the base64 decode routine worked
  1263. if(0==cbDecodedData || NULL==pbDecodedData)
  1264. goto BadEncodeErr;
  1265. CertBlob.cbData=cbDecodedData;
  1266. CertBlob.pbData=pbDecodedData;
  1267. //try the base64 decoded BLOB
  1268. if(!I_CryptQueryObject(
  1269. &CertBlob,
  1270. NULL,
  1271. dwExpectedContentTypeFlags,
  1272. dwExpectedFormatTypeFlags,
  1273. dwFlags,
  1274. pdwMsgAndCertEncodingType,
  1275. pdwContentType,
  1276. pdwFormatType,
  1277. phCertStore,
  1278. phMsg,
  1279. ppvContext))
  1280. goto I_CryptQueryObjectErr;
  1281. }
  1282. else
  1283. {
  1284. goto NoMatchErr;
  1285. }
  1286. Done:
  1287. //return the FormatType
  1288. if(NULL != pdwFormatType)
  1289. *pdwFormatType = dwFormatType;
  1290. fResult=TRUE;
  1291. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1292. err = GetExceptionCode();
  1293. goto ExceptionErr;
  1294. }
  1295. CommonReturn:
  1296. //free memory
  1297. if(CERT_QUERY_OBJECT_FILE == dwObjectType)
  1298. {
  1299. if(pbData)
  1300. UnmapViewOfFile(pbData);
  1301. }
  1302. if(pbDecodedData)
  1303. free(pbDecodedData);
  1304. return fResult;
  1305. ErrorReturn:
  1306. fResult=FALSE;
  1307. goto CommonReturn;
  1308. SET_ERROR_VAR(RetrieveBLOBFromFileErr, hr);
  1309. SET_ERROR(InvalidArgErr,E_INVALIDARG);
  1310. TRACE_ERROR(I_CryptQueryObjectErr);
  1311. SET_ERROR(NoMatchErr, CRYPT_E_NO_MATCH);
  1312. SET_ERROR(BadEncodeErr, CRYPT_E_BAD_ENCODE);
  1313. TRACE_ERROR(InvalidAsciiHex);
  1314. SET_ERROR_VAR(ExceptionErr, err);
  1315. }