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.

1843 lines
55 KiB

  1. // Cspi.cpp -- Schlumberger Cryptographic Service Provider Interface definition
  2. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  3. // 1999. This computer program includes Confidential, Proprietary
  4. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  5. // use, disclosure, and/or reproduction is prohibited unless authorized
  6. // in writing. All Rights Reserved.
  7. // Don't allow the min & max macros in WINDEF.H to be defined so the
  8. // min/max methods declared in limits are accessible.
  9. #define NOMINMAX
  10. #if defined(_UNICODE)
  11. #if !defined(UNICODE)
  12. #define UNICODE
  13. #endif //!UNICODE
  14. #endif //_UNICODE
  15. #if defined(UNICODE)
  16. #if !defined(_UNICODE)
  17. #define _UNICODE
  18. #endif //!_UNICODE
  19. #endif //UNICODE
  20. #include "stdafx.h"
  21. #include <memory> // for auto_ptr
  22. #include <limits>
  23. #include <string>
  24. #include <vector>
  25. #include <functional>
  26. #include <algorithm>
  27. #include <numeric>
  28. #include <stddef.h>
  29. #include <rpc.h>
  30. #include <SCardLib.h>
  31. #include <scuOsExc.h>
  32. #include <pkiExc.h>
  33. #include "Guard.h"
  34. #include "slbCsp.h"
  35. #include "CspProfile.h"
  36. #include "CryptCtx.h"
  37. #include "SesKeyCtx.h"
  38. #include "PubKeyCtx.h"
  39. #include "HashCtx.h"
  40. #include "CSpec.h"
  41. #include "Blob.h"
  42. #include "Cspi.h"
  43. #include "StResource.h"
  44. #include "scarderr.h" // must be last for now
  45. using namespace std;
  46. using namespace scu;
  47. #define HANDLEID_CRYPT_CONTEXT 17
  48. static CHandleList hlCryptContexts(HANDLEID_CRYPT_CONTEXT);
  49. #if defined(_DEBUG)
  50. #define CSPI_DEFINE_ROUTINE_NAME(sRoutine) \
  51. LPCTSTR cspi_sRoutine = sRoutine
  52. #define CSPI_TRACE_ROUTINE(sFlag) \
  53. TRACE(TEXT("%s %s, Thread Id %08X\n"), cspi_sRoutine, \
  54. sFlag, GetCurrentThreadId());
  55. #else
  56. #define CSPI_DEFINE_ROUTINE_NAME(sRoutine)
  57. #define CSPI_TRACE_ROUTINE(sFlag)
  58. #endif // defined(_DEBUG)
  59. typedef DWORD CapiError;
  60. #define CSPI_TRY(Routine) \
  61. { \
  62. bool cspi_fExceptionCaught = false; \
  63. CapiError cspi_ce = AsCapiError(ERROR_SUCCESS); \
  64. \
  65. { \
  66. AFX_MANAGE_STATE(AfxGetStaticModuleState()); \
  67. \
  68. CSPI_DEFINE_ROUTINE_NAME(TEXT(#Routine)); \
  69. CSPI_TRACE_ROUTINE(TEXT("Begin")); \
  70. \
  71. CWaitCursor cspi_wc; \
  72. \
  73. try
  74. #define CSPI_CATCH(fStatus) \
  75. catch (scu::Exception const &rExc) \
  76. { \
  77. cspi_fExceptionCaught = true; \
  78. cspi_ce = AsCapiError(rExc); \
  79. } \
  80. \
  81. catch (std::bad_alloc const &rExc) \
  82. { \
  83. cspi_fExceptionCaught = true; \
  84. cspi_ce = AsCapiError(rExc); \
  85. } \
  86. \
  87. catch (DWORD dwError) \
  88. { \
  89. cspi_fExceptionCaught = true; \
  90. cspi_ce = AsCapiError(dwError); \
  91. } \
  92. \
  93. catch (...) \
  94. { \
  95. cspi_fExceptionCaught = true; \
  96. cspi_ce = AsCapiError(NTE_FAIL); \
  97. } \
  98. \
  99. CSPI_TRACE_ROUTINE(TEXT("End")); \
  100. \
  101. (fStatus) = cspi_fExceptionCaught \
  102. ? CRYPT_FAILED \
  103. : CRYPT_SUCCEED; \
  104. } \
  105. \
  106. SetLastError(cspi_ce); \
  107. \
  108. }
  109. namespace
  110. { // Helper routines
  111. template<class CauseCode>
  112. struct ErrorCodeMap
  113. {
  114. typename CauseCode m_cc;
  115. DWORD m_dwErrorCode;
  116. };
  117. template<class CauseCode>
  118. DWORD
  119. FindErrorCode(ErrorCodeMap<typename CauseCode> const *pFirst,
  120. ErrorCodeMap<typename CauseCode> const *pLast,
  121. typename CauseCode cc)
  122. {
  123. bool fFound = false;
  124. DWORD dwErrorCode = NTE_FAIL;
  125. for (ErrorCodeMap<CauseCode> const *p = pFirst;
  126. !fFound && (p < pLast); p++)
  127. {
  128. if (p->m_cc == cc)
  129. {
  130. dwErrorCode = p->m_dwErrorCode;
  131. fFound = true;
  132. }
  133. }
  134. return dwErrorCode;
  135. }
  136. ErrorCodeMap<cci::CauseCode> CciErrorMap[] =
  137. {
  138. { cci::ccBadKeySpec, SCARD_E_INVALID_VALUE },
  139. { cci::ccBadPinLength, SCARD_E_INVALID_VALUE },
  140. { cci::ccNoCertificate, SCARD_E_NO_SUCH_CERTIFICATE },
  141. { cci::ccNotPersonalized, SCARD_E_UNSUPPORTED_FEATURE },
  142. { cci::ccOutOfPrivateKeySlots, NTE_TOKEN_KEYSET_STORAGE_FULL },
  143. { cci::ccOutOfSymbolTableSpace, NTE_TOKEN_KEYSET_STORAGE_FULL },
  144. { cci::ccOutOfSymbolTableEntries, NTE_TOKEN_KEYSET_STORAGE_FULL },
  145. };
  146. ErrorCodeMap<iop::CSmartCard::CauseCode> SmartCardErrorMap[] =
  147. {
  148. { iop::CSmartCard::ccAccessConditionsNotMet, SCARD_W_SECURITY_VIOLATION },
  149. { iop::CSmartCard::ccAlgorithmIdNotSupported, CRYPT_E_UNKNOWN_ALGO },
  150. { iop::CSmartCard::ccAuthenticationFailed, SCARD_W_WRONG_CHV },
  151. { iop::CSmartCard::ccChvVerificationFailedMoreAttempts,
  152. SCARD_W_WRONG_CHV },
  153. { iop::CSmartCard::ccDataPossiblyCorrupted, ERROR_FILE_CORRUPT },
  154. { iop::CSmartCard::ccFileExists, ERROR_FILE_EXISTS },
  155. { iop::CSmartCard::ccInsufficientSpace, NTE_TOKEN_KEYSET_STORAGE_FULL },
  156. { iop::CSmartCard::ccOutOfSpaceToCreateFile, NTE_TOKEN_KEYSET_STORAGE_FULL },
  157. { iop::CSmartCard::ccKeyBlocked, SCARD_W_CHV_BLOCKED },
  158. { iop::CSmartCard::ccNoAccess, SCARD_W_SECURITY_VIOLATION },
  159. { iop::CSmartCard::ccReturnedDataCorrupted, ERROR_FILE_CORRUPT },
  160. { iop::CSmartCard::ccTimeOut, E_UNEXPECTED },
  161. { iop::CSmartCard::ccUnidentifiedTechnicalProblem, E_UNEXPECTED },
  162. { iop::CSmartCard::ccVerificationFailed, SCARD_W_WRONG_CHV },
  163. };
  164. ErrorCodeMap<iop::CauseCode> IopErrorMap[] =
  165. {
  166. { iop::ccAlgorithmIdNotSupported, CRYPT_E_UNKNOWN_ALGO },
  167. { iop::ccInvalidParameter, E_INVALIDARG },
  168. { iop::ccNoResponseAvailable, E_UNEXPECTED },
  169. { iop::ccResourceManagerDisabled, SCARD_E_NO_SERVICE },
  170. { iop::ccUnknownCard, SCARD_E_UNKNOWN_CARD },
  171. { iop::ccUnsupportedCommand, SCARD_E_UNSUPPORTED_FEATURE },
  172. };
  173. bool
  174. IsHResult(DWORD dwError)
  175. {
  176. return (0 != HRESULT_SEVERITY(static_cast<HRESULT>(dwError)))
  177. ? true
  178. : false;
  179. }
  180. CapiError
  181. AsCapiError(HRESULT hr)
  182. {
  183. // If the HRESULT has been converted from a Win32 error code
  184. // (WIN32 facility), then convert it back to a Win32 error
  185. // code. These types of HRESULTs confuse WinLogon, according
  186. // to Doug Barlow (Microsoft)
  187. return (FACILITY_WIN32 == HRESULT_FACILITY(hr))
  188. ? HRESULT_CODE(hr)
  189. : static_cast<DWORD>(hr);
  190. }
  191. CapiError
  192. AsCapiError(DWORD dwError)
  193. {
  194. if (IsHResult(dwError))
  195. dwError = AsCapiError(static_cast<HRESULT>(dwError));
  196. return dwError;
  197. }
  198. CapiError
  199. AsCapiError(cci::Exception const &rExc)
  200. {
  201. return AsCapiError(FindErrorCode(CciErrorMap,
  202. (CciErrorMap +
  203. (sizeof CciErrorMap /
  204. sizeof *CciErrorMap)),
  205. rExc.Cause()));
  206. }
  207. CapiError
  208. AsCapiError(iop::Exception const &rExc)
  209. {
  210. return AsCapiError(FindErrorCode(IopErrorMap,
  211. (IopErrorMap +
  212. (sizeof IopErrorMap /
  213. sizeof *IopErrorMap)),
  214. rExc.Cause()));
  215. }
  216. CapiError
  217. AsCapiError(scu::OsException const &rExc)
  218. {
  219. return AsCapiError(rExc.Cause());
  220. }
  221. CapiError
  222. AsCapiError(iop::CSmartCard::Exception const &rExc)
  223. {
  224. return AsCapiError(FindErrorCode(SmartCardErrorMap,
  225. (SmartCardErrorMap +
  226. (sizeof SmartCardErrorMap /
  227. sizeof *SmartCardErrorMap)),
  228. rExc.Cause()));
  229. }
  230. CapiError
  231. AsCapiError(pki::Exception const &rExc)
  232. {
  233. return AsCapiError(ERROR_INVALID_PARAMETER);
  234. }
  235. CapiError
  236. AsCapiError(scu::Exception const &rExc)
  237. {
  238. using namespace scu;
  239. CapiError ce;
  240. switch (rExc.Facility())
  241. {
  242. case Exception::fcCCI:
  243. ce = AsCapiError(static_cast<cci::Exception const &>(rExc));
  244. break;
  245. case Exception::fcIOP:
  246. ce = AsCapiError(static_cast<iop::Exception const &>(rExc));
  247. break;
  248. case Exception::fcOS:
  249. ce = AsCapiError(static_cast<scu::OsException const &>(rExc));
  250. break;
  251. case Exception::fcPKI:
  252. ce = AsCapiError(static_cast<pki::Exception const &>(rExc));
  253. break;
  254. case Exception::fcSmartCard:
  255. ce = AsCapiError(static_cast<iop::CSmartCard::Exception const &>(rExc));
  256. break;
  257. default:
  258. ce = AsCapiError(E_UNEXPECTED);
  259. break;
  260. }
  261. return ce;
  262. }
  263. CapiError
  264. AsCapiError(std::bad_alloc const &rExc)
  265. {
  266. return AsCapiError(NTE_NO_MEMORY);
  267. }
  268. void
  269. Assign(void *pvDestination,
  270. DWORD *pcbDestinationLength,
  271. void const *pvSource,
  272. size_t cSourceLength)
  273. {
  274. DWORD dwError = ERROR_SUCCESS;
  275. if (pcbDestinationLength)
  276. {
  277. if (numeric_limits<DWORD>::max() >= cSourceLength)
  278. {
  279. if (pvSource)
  280. {
  281. if (pvDestination)
  282. {
  283. if (*pcbDestinationLength >= cSourceLength)
  284. CopyMemory(pvDestination, pvSource, cSourceLength);
  285. else
  286. dwError = ERROR_MORE_DATA;
  287. }
  288. }
  289. *pcbDestinationLength = cSourceLength;
  290. }
  291. else
  292. dwError = ERROR_INVALID_PARAMETER;
  293. }
  294. else
  295. dwError = ERROR_INVALID_PARAMETER;
  296. if (ERROR_SUCCESS != dwError)
  297. throw scu::OsException(dwError);
  298. }
  299. void
  300. Assign(void *pvDestination,
  301. DWORD *pcbDestinationLength,
  302. LPCTSTR pvSource
  303. )
  304. {
  305. DWORD dwError = ERROR_SUCCESS;
  306. if (pcbDestinationLength)
  307. {
  308. // We want the number of characters including NULL
  309. DWORD cSourceLength = _tcslen(pvSource) + 1;
  310. if (numeric_limits<DWORD>::max() >= cSourceLength)
  311. {
  312. if (pvSource)
  313. {
  314. if (pvDestination)
  315. {
  316. if (*pcbDestinationLength >= cSourceLength)
  317. {
  318. char *sTarget = (char *)pvDestination;
  319. for(int i =0; i<cSourceLength; i++)
  320. sTarget[i] = static_cast<char>(*(pvSource+i));
  321. }
  322. else
  323. dwError = ERROR_MORE_DATA;
  324. }
  325. }
  326. *pcbDestinationLength = cSourceLength;
  327. }
  328. else
  329. dwError = ERROR_INVALID_PARAMETER;
  330. }
  331. else
  332. dwError = ERROR_INVALID_PARAMETER;
  333. if (ERROR_SUCCESS != dwError)
  334. throw scu::OsException(dwError);
  335. }
  336. void
  337. Assign(void *pvDestination,
  338. DWORD *pcbDestinationLength,
  339. Blob const &rblob)
  340. {
  341. Assign(pvDestination, pcbDestinationLength,
  342. rblob.data(), rblob.length());
  343. }
  344. void
  345. Assign(void *pvDestination,
  346. DWORD cbDestinationLength,
  347. Blob const &rblob)
  348. {
  349. if (cbDestinationLength < rblob.length())
  350. throw scu::OsException(ERROR_INTERNAL_ERROR);
  351. Assign(pvDestination, &cbDestinationLength,
  352. rblob.data(), rblob.length());
  353. }
  354. // Helper to BufferLengthRequired to compare length of strings.
  355. struct LengthIsLess
  356. : public binary_function<string const &, string const &, bool>
  357. {
  358. public:
  359. explicit
  360. LengthIsLess()
  361. {};
  362. result_type
  363. operator()(first_argument_type lhs,
  364. second_argument_type rhs) const
  365. {
  366. return lhs.length() < rhs.length();
  367. }
  368. };
  369. // Return the data buffer length required to hold the largest
  370. // string in the vector.
  371. DWORD
  372. BufferLengthRequired(vector<string> const &rvs)
  373. {
  374. DWORD dwRequiredLength = 0;
  375. vector<string>::const_iterator
  376. itLongestString(max_element(rvs.begin(), rvs.end(),
  377. LengthIsLess()));
  378. if (rvs.end() != itLongestString)
  379. dwRequiredLength = itLongestString->length() + 1;
  380. return dwRequiredLength;
  381. }
  382. // Helper to enumerate the container names for the given context,
  383. // returning the result in user parameters pbData and pdwDataLen.
  384. void
  385. EnumContainers(Guarded<CryptContext *> &rgpCtx,
  386. BYTE *pbData,
  387. DWORD *pdwDataLen,
  388. bool fFirst)
  389. {
  390. DWORD dwError = ERROR_SUCCESS;
  391. string sName;
  392. DWORD dwReturnLength = 0;
  393. void const *pvReturnData = 0;
  394. if (!pbData)
  395. {
  396. // Return the buffer size required for the longest string
  397. auto_ptr<ContainerEnumerator> apce;
  398. if (!fFirst)
  399. apce = auto_ptr<ContainerEnumerator>(new ContainerEnumerator(rgpCtx->CntrEnumerator(false)));
  400. else
  401. apce = auto_ptr<ContainerEnumerator>(new ContainerEnumerator(rgpCtx->CntrEnumerator(true)));
  402. vector<string>::const_iterator &rit = apce->Iterator();
  403. if(apce->Names().end() != rit)
  404. {
  405. dwReturnLength = BufferLengthRequired(apce->Names());
  406. if (0 == dwReturnLength)
  407. dwError = ERROR_NO_MORE_ITEMS;
  408. }
  409. else
  410. dwError = ERROR_NO_MORE_ITEMS;
  411. }
  412. else
  413. {
  414. ContainerEnumerator ce(rgpCtx->CntrEnumerator(fFirst));
  415. vector<string>::const_iterator &rit = ce.Iterator();
  416. if (ce.Names().end() != rit)
  417. {
  418. sName = *rit++;
  419. dwReturnLength = sName.length() + 1;
  420. pvReturnData = sName.c_str();
  421. if (dwReturnLength > *pdwDataLen)
  422. {
  423. // tell'em the size required for the longest name
  424. pbData = 0;
  425. dwReturnLength =
  426. BufferLengthRequired(ce.Names());
  427. dwError = ERROR_MORE_DATA;
  428. }
  429. else
  430. rgpCtx->CntrEnumerator(ce);
  431. }
  432. else
  433. dwError = ERROR_NO_MORE_ITEMS;
  434. }
  435. if ((ERROR_SUCCESS != dwError) &&
  436. (ERROR_MORE_DATA != dwError))
  437. throw scu::OsException(dwError);
  438. Assign(pbData, pdwDataLen, pvReturnData, dwReturnLength);
  439. }
  440. bool
  441. FlagsAreSet(DWORD dwFlags,
  442. DWORD dwFlagsToTestFor)
  443. {
  444. return (dwFlags & dwFlagsToTestFor)
  445. ? true
  446. : false;
  447. }
  448. void
  449. Pin(Guarded<CryptContext *> const &rgpCtx,
  450. char const *pszPin)
  451. {
  452. // TO DO: Should forward PIN setting to aux context
  453. // when this context is ephemeral.
  454. if (rgpCtx->IsEphemeral())
  455. throw scu::OsException(ERROR_INVALID_PARAMETER);
  456. // TO DO: UNICODE ?
  457. rgpCtx->Pin(User, pszPin);
  458. }
  459. // Throw if more than dwValidFlags are set in dwFlags
  460. void
  461. ValidateFlags(DWORD dwFlags,
  462. DWORD dwValidFlags)
  463. {
  464. if (dwFlags & ~dwValidFlags)
  465. throw scu::OsException(NTE_BAD_FLAGS);
  466. }
  467. class StaleContainerKeyAccumulator
  468. : public binary_function<vector<AdaptiveContainerRegistrar::EnrolleeType>,
  469. AdaptiveContainerRegistrar::RegistryType::CollectionType::value_type,
  470. vector<AdaptiveContainerRegistrar::EnrolleeType> >
  471. {
  472. public:
  473. explicit
  474. StaleContainerKeyAccumulator()
  475. {}
  476. result_type
  477. operator()(first_argument_type &rvStaleCntrs,
  478. second_argument_type const &rvt) const
  479. {
  480. if (!rvt.second->CardContext(false))
  481. rvStaleCntrs.push_back(rvt.second);
  482. return rvStaleCntrs;
  483. }
  484. private:
  485. };
  486. bool FindCryptCtxForACntr(HAdaptiveContainer &rhAdptCntr)
  487. {
  488. bool fRetValue = false;
  489. for(int i = 0; i< hlCryptContexts.Count();i++)
  490. {
  491. CryptContext *pCryptCtx = static_cast<CryptContext *>
  492. (hlCryptContexts.GetQuietly(hlCryptContexts.IndexHandle(i)));
  493. if( pCryptCtx && pCryptCtx->AdaptiveContainer() == rhAdptCntr)
  494. {
  495. fRetValue = true;
  496. }
  497. }
  498. return fRetValue;
  499. }
  500. void CollectRegistryGarbage()
  501. {
  502. Guarded<Lockable *> guard(&AdaptiveContainerRegistrar::Registry()); // serialize registry access
  503. AdaptiveContainerRegistrar::ConstRegistryType &rRegistry =
  504. AdaptiveContainerRegistrar::Registry();
  505. AdaptiveContainerRegistrar::ConstRegistryType::CollectionType
  506. &rcollection = rRegistry();
  507. vector<AdaptiveContainerRegistrar::EnrolleeType>
  508. vStaleCntrs(accumulate(rcollection.begin(), rcollection.end(),
  509. vector<AdaptiveContainerRegistrar::EnrolleeType>(),
  510. StaleContainerKeyAccumulator()));
  511. for (vector<AdaptiveContainerRegistrar::EnrolleeType>::iterator iCurrent(vStaleCntrs.begin());
  512. iCurrent != vStaleCntrs.end(); ++iCurrent)
  513. {
  514. //Lookup the CryptContext list to see if any of these
  515. //stale container are referenced. If not, remove them
  516. //to avoid memory leaks.
  517. if(!FindCryptCtxForACntr(HAdaptiveContainer(*iCurrent)))
  518. {
  519. //Remove the adaptive container from the registry
  520. AdaptiveContainerKey aKey(HCardContext(0),
  521. (*iCurrent)->Name());
  522. AdaptiveContainerRegistrar::Discard(aKey);
  523. }
  524. }
  525. }
  526. } // namespace
  527. ////////////////////////// BEGIN CSP INTERFACE /////////////////////////////
  528. //
  529. // See MSDN for documentation on these interfaces.
  530. //
  531. SLBCSPAPI
  532. CPAcquireContext(OUT HCRYPTPROV *phProv,
  533. IN LPCTSTR pszContainer,
  534. IN DWORD dwFlags,
  535. IN PVTableProvStruc pVTable)
  536. {
  537. BOOL fSts = CRYPT_FAILED;
  538. SecureArray<char> sac(80);
  539. CSPI_TRY(CPAcquireContext)
  540. {
  541. Guard<Lockable> grdMaster(TheMasterLock());
  542. CSpec cspec(pszContainer
  543. ? AsCCharP(pszContainer)
  544. : "");
  545. ValidateFlags(dwFlags, (CRYPT_VERIFYCONTEXT |
  546. CRYPT_NEWKEYSET |
  547. CRYPT_MACHINE_KEYSET |
  548. CRYPT_DELETEKEYSET |
  549. CRYPT_SILENT));
  550. if (!phProv)
  551. throw scu::OsException(ERROR_INVALID_PARAMETER);
  552. bool const fMakeEphemeral = FlagsAreSet(dwFlags,
  553. CRYPT_VERIFYCONTEXT);
  554. bool const fGuiEnabled = !(FlagsAreSet(dwFlags, CRYPT_SILENT) ||
  555. (cspec.CardId().empty() &&
  556. fMakeEphemeral));
  557. bool const fCreateContainer = FlagsAreSet(dwFlags, CRYPT_NEWKEYSET);
  558. auto_ptr<CryptContext> apCtx(new CryptContext(cspec, pVTable,
  559. fGuiEnabled,
  560. fCreateContainer,
  561. fMakeEphemeral));
  562. if (FlagsAreSet(dwFlags, CRYPT_DELETEKEYSET))
  563. apCtx->RemoveContainer();
  564. else
  565. {
  566. *phProv =
  567. static_cast<HCRYPTPROV>(hlCryptContexts.Add(apCtx.get()));
  568. apCtx.release();
  569. }
  570. }
  571. CSPI_CATCH(fSts);
  572. return fSts;
  573. }
  574. SLBCSPAPI
  575. CPGetProvParam(IN HCRYPTPROV hProv,
  576. IN DWORD dwParam,
  577. IN BYTE *pbData,
  578. IN OUT DWORD *pdwDataLen,
  579. IN DWORD dwFlags)
  580. {
  581. using namespace ProviderProfile;
  582. BOOL fSts = CRYPT_FAILED;
  583. CSPI_TRY(CPGetProvParam)
  584. {
  585. Guard<Lockable> grdMaster(TheMasterLock());
  586. Guarded<CryptContext *>
  587. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  588. switch (dwParam)
  589. {
  590. case PP_CONTAINER:
  591. case PP_UNIQUE_CONTAINER:
  592. {
  593. ValidateFlags(dwFlags, 0);
  594. HAdaptiveContainer hacntr = gpCtx->AdaptiveContainer();
  595. if (!hacntr)
  596. throw scu::OsException(ERROR_INVALID_PARAMETER);
  597. string sName(hacntr->TheCContainer()->Name());
  598. Assign(pbData, pdwDataLen, sName.c_str(),
  599. sName.length() + 1);
  600. }
  601. break;
  602. case PP_ENUMALGS:
  603. case PP_ENUMALGS_EX:
  604. {
  605. ValidateFlags(dwFlags, CRYPT_FIRST);
  606. AlignedBlob abAlgInfo;
  607. gpCtx->EnumAlgorithms(dwParam, dwFlags, (0 != pbData),
  608. abAlgInfo);
  609. Assign(pbData, pdwDataLen, abAlgInfo.Data(),
  610. abAlgInfo.Length());
  611. }
  612. break;
  613. case PP_ENUMCONTAINERS:
  614. ValidateFlags(dwFlags, CRYPT_FIRST | CRYPT_MACHINE_KEYSET);
  615. EnumContainers(gpCtx, pbData, pdwDataLen,
  616. (CRYPT_FIRST & dwFlags));
  617. break;
  618. case PP_IMPTYPE:
  619. {
  620. ValidateFlags(dwFlags, 0);
  621. DWORD const dwImplType = CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE;
  622. Assign(pbData, pdwDataLen, &dwImplType,
  623. sizeof dwImplType);
  624. }
  625. break;
  626. case PP_NAME:
  627. {
  628. ValidateFlags(dwFlags, 0);
  629. CString sName(CspProfile::Instance().Name());
  630. Assign(pbData, pdwDataLen, (LPCTSTR)sName);
  631. }
  632. break;
  633. case PP_VERSION:
  634. {
  635. ValidateFlags(dwFlags, 0);
  636. VersionInfo const &ver = CspProfile::Instance().Version();
  637. DWORD dwVersion = (ver.m_dwMajor << 8) | ver.m_dwMinor;
  638. Assign(pbData, pdwDataLen, &dwVersion, sizeof dwVersion);
  639. }
  640. break;
  641. case PP_PROVTYPE:
  642. {
  643. ValidateFlags(dwFlags, 0);
  644. DWORD const dwType = CspProfile::Instance().Type();
  645. Assign(pbData, pdwDataLen, &dwType, sizeof dwType);
  646. }
  647. break;
  648. case PP_KEYX_KEYSIZE_INC: // fall-through
  649. case PP_SIG_KEYSIZE_INC:
  650. {
  651. ValidateFlags(dwFlags, 0);
  652. DWORD const dwIncrement = 0;
  653. Assign(pbData, pdwDataLen, &dwIncrement, sizeof dwIncrement);
  654. }
  655. break;
  656. case PP_ENUMEX_SIGNING_PROT:
  657. ValidateFlags(dwFlags, 0);
  658. if (CryptGetProvParam(gpCtx->AuxContext(), dwParam,
  659. pbData, pdwDataLen, dwFlags))
  660. throw scu::OsException(GetLastError());
  661. break;
  662. case PP_KEYSPEC:
  663. {
  664. ValidateFlags(dwFlags, 0);
  665. DWORD const dwKeySpec = AT_SIGNATURE | AT_KEYEXCHANGE;
  666. Assign(pbData, pdwDataLen, &dwKeySpec, sizeof
  667. dwKeySpec);
  668. }
  669. break;
  670. default:
  671. throw scu::OsException(NTE_BAD_TYPE);
  672. break;
  673. }
  674. }
  675. CSPI_CATCH(fSts);
  676. return fSts;
  677. }
  678. SLBCSPAPI
  679. CPReleaseContext(IN HCRYPTPROV hProv,
  680. IN DWORD dwFlags)
  681. {
  682. BOOL fSts = CRYPT_FAILED;
  683. CSPI_TRY(CPReleaseContext)
  684. {
  685. ValidateFlags(dwFlags, 0);
  686. Guard<Lockable> grdMaster(TheMasterLock());
  687. auto_ptr<CryptContext> apCtx(static_cast<CryptContext *>(hlCryptContexts.Close(hProv)));
  688. // TO DO: Verify current thread is this context's owning
  689. // thread *and* not currently in use; if not, return
  690. // ERROR_BUSY.
  691. //Garbage collection of unusable adaptive containers
  692. //that this or other threads may have left behind. An unusable
  693. //container is one which is not referenced by any of the
  694. //existing active crypt contexts.
  695. try
  696. {
  697. CollectRegistryGarbage();
  698. }
  699. catch(...)
  700. {
  701. //Don't let exceptions during garbage collection
  702. //propagate outside. These are likely due to other
  703. //problems which are better exposed with proper error
  704. //codes from other parts of the CSP.
  705. }
  706. }
  707. CSPI_CATCH(fSts);
  708. if ((CRYPT_SUCCEED == fSts) && (0 != dwFlags))
  709. fSts = false;
  710. return fSts;
  711. }
  712. SLBCSPAPI
  713. CPSetProvParam(IN HCRYPTPROV hProv,
  714. IN DWORD dwParam,
  715. IN BYTE *pbData,
  716. IN DWORD dwFlags)
  717. {
  718. BOOL fSts = CRYPT_FAILED;
  719. CSPI_TRY(CPSetProvParam)
  720. {
  721. Guard<Lockable> grdMaster(TheMasterLock());
  722. Guarded<CryptContext *>
  723. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  724. switch (dwParam)
  725. {
  726. case PP_KEYEXCHANGE_PIN: // fall-through
  727. case PP_SIGNATURE_PIN:
  728. Pin(gpCtx, reinterpret_cast<char *>(pbData));
  729. break;
  730. case PP_KEYSET_SEC_DESCR:
  731. // Ignore this option and return success.
  732. break;
  733. case PP_USE_HARDWARE_RNG:
  734. if (!CryptSetProvParam(gpCtx->AuxContext(), dwParam,
  735. pbData, dwFlags))
  736. throw scu::OsException(GetLastError());
  737. break;
  738. default:
  739. throw scu::OsException(ERROR_NOT_SUPPORTED);
  740. break;
  741. }
  742. }
  743. CSPI_CATCH(fSts);
  744. return fSts;
  745. }
  746. SLBCSPAPI
  747. CPDeriveKey(IN HCRYPTPROV hProv,
  748. IN ALG_ID Algid,
  749. IN HCRYPTHASH hHash,
  750. IN DWORD dwFlags,
  751. OUT HCRYPTKEY *phKey)
  752. {
  753. BOOL fSts = CRYPT_FAILED;
  754. CSPI_TRY(CPDeriveKey)
  755. {
  756. Guarded<CryptContext *>
  757. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  758. CHashContext *pHash = gpCtx->LookupHash(hHash);
  759. auto_ptr<CSessionKeyContext>
  760. apSessionKey(new CSessionKeyContext(gpCtx->AuxContext()));
  761. apSessionKey->Derive(Algid, pHash->HashHandleInAuxCSP(),
  762. dwFlags);
  763. *phKey = gpCtx->Add(apSessionKey);
  764. }
  765. CSPI_CATCH(fSts);
  766. return fSts;
  767. }
  768. SLBCSPAPI
  769. CPDestroyKey(IN HCRYPTPROV hProv,
  770. IN HCRYPTKEY hKey)
  771. {
  772. BOOL fSts = CRYPT_FAILED;
  773. // TO DO: Throw ERROR_BUSY if destroying thread is not the owning
  774. // thread OR some other thread has a handle to this key.
  775. CSPI_TRY(CPDestroyKey)
  776. {
  777. Guard<Lockable> grdMaster(TheMasterLock());
  778. Guarded<CryptContext *>
  779. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  780. // TO DO: Deleting the first handle usually fails for some reason.
  781. // For now, protect against the exception and carry on.
  782. try
  783. {
  784. auto_ptr<CKeyContext> apKey(gpCtx->CloseKey(hKey));
  785. }
  786. catch (...)
  787. {}
  788. }
  789. CSPI_CATCH(fSts);
  790. return fSts;
  791. }
  792. SLBCSPAPI
  793. CPDuplicateHash(IN HCRYPTPROV hProv,
  794. IN HCRYPTHASH hHash,
  795. IN DWORD *pdwReserved,
  796. IN DWORD dwFlags,
  797. OUT HCRYPTHASH *phDupHash)
  798. {
  799. BOOL fSts = CRYPT_FAILED;
  800. CSPI_TRY(CPDuplicateHash)
  801. {
  802. ValidateFlags(dwFlags, 0);
  803. Guard<Lockable> grdMaster(TheMasterLock());
  804. Guarded<CryptContext *>
  805. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  806. CHashContext *pHash = gpCtx->LookupHash(hHash);
  807. auto_ptr<CHashContext> apDupHash(pHash->Clone(pdwReserved, dwFlags));
  808. *phDupHash = gpCtx->Add(apDupHash);
  809. }
  810. CSPI_CATCH(fSts);
  811. return fSts;
  812. }
  813. SLBCSPAPI
  814. CPDuplicateKey(IN HCRYPTPROV hProv,
  815. IN HCRYPTKEY hKey,
  816. IN DWORD *pdwReserved,
  817. IN DWORD dwFlags,
  818. OUT HCRYPTKEY *phDupKey)
  819. {
  820. BOOL fSts = CRYPT_FAILED;
  821. CSPI_TRY(CPDuplicateKey)
  822. {
  823. ValidateFlags(dwFlags, 0);
  824. Guard<Lockable> grdMaster(TheMasterLock());
  825. Guarded<CryptContext *>
  826. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  827. CKeyContext *pKey = gpCtx->LookupKey(hKey);
  828. auto_ptr<CKeyContext> apDupKey(pKey->Clone(pdwReserved, dwFlags));
  829. *phDupKey = gpCtx->Add(apDupKey);
  830. }
  831. CSPI_CATCH(fSts);
  832. return fSts;
  833. }
  834. SLBCSPAPI
  835. CPExportKey(IN HCRYPTPROV hProv,
  836. IN HCRYPTKEY hKey,
  837. IN HCRYPTKEY hExpKey,
  838. IN DWORD dwBlobType,
  839. IN DWORD dwFlags,
  840. OUT BYTE *pbData,
  841. IN OUT DWORD *pdwDataLen)
  842. {
  843. BOOL fSts = CRYPT_FAILED;
  844. CSPI_TRY(CPExportKey)
  845. {
  846. ValidateFlags(dwFlags, 0);
  847. if (PRIVATEKEYBLOB == dwBlobType)
  848. throw scu::OsException(ERROR_INVALID_PARAMETER);
  849. Guard<Lockable> grdMaster(TheMasterLock());
  850. Guarded<CryptContext *>
  851. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  852. CKeyContext *pKey = gpCtx->LookupKey(hKey);
  853. if (KT_SESSIONKEY == pKey->TypeOfKey())
  854. {
  855. if ((SIMPLEBLOB != dwBlobType) &&
  856. (SYMMETRICWRAPKEYBLOB != dwBlobType))
  857. throw scu::OsException(NTE_BAD_TYPE);
  858. }
  859. else
  860. if (PUBLICKEYBLOB != dwBlobType)
  861. throw scu::OsException(NTE_BAD_TYPE);
  862. if (hExpKey && (PUBLICKEYBLOB == dwBlobType))
  863. throw scu::OsException(ERROR_INVALID_PARAMETER);
  864. CKeyContext *pExpKey = 0;
  865. if (SIMPLEBLOB != dwBlobType)
  866. {
  867. pExpKey = hExpKey
  868. ? gpCtx->LookupKey(hExpKey)
  869. : 0;
  870. }
  871. else
  872. {
  873. CPublicKeyContext *pPubExpKey = hExpKey
  874. ? gpCtx->LookupPublicKey(hExpKey)
  875. : 0;
  876. if (pPubExpKey)
  877. {
  878. if (!pPubExpKey->AuxKeyLoaded())
  879. pPubExpKey->AuxPublicKey(pPubExpKey->AsAlignedBlob(0, dwBlobType));
  880. }
  881. pExpKey = pPubExpKey;
  882. }
  883. HCRYPTKEY hAuxExpKey = pExpKey
  884. ? pExpKey->KeyHandleInAuxCSP()
  885. : 0;
  886. SecureArray<BYTE> abKey(pKey->AsAlignedBlob(hAuxExpKey, dwBlobType));
  887. Assign(pbData, pdwDataLen, abKey.data(), abKey.length());
  888. }
  889. CSPI_CATCH(fSts);
  890. return fSts;
  891. }
  892. SLBCSPAPI
  893. CPGenKey(IN HCRYPTPROV hProv,
  894. IN ALG_ID Algid,
  895. IN DWORD dwFlags,
  896. OUT HCRYPTKEY *phKey)
  897. {
  898. BOOL fSts = CRYPT_FAILED;
  899. CSPI_TRY(CPGenKey)
  900. {
  901. Guard<Lockable> grdMaster(TheMasterLock());
  902. Guarded<CryptContext *>
  903. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  904. if (FlagsAreSet(dwFlags, CRYPT_USER_PROTECTED) &&
  905. !gpCtx->GuiEnabled())
  906. throw scu::OsException(NTE_SILENT_CONTEXT);
  907. *phKey = gpCtx->GenerateKey(Algid, dwFlags);
  908. fSts = CRYPT_SUCCEED;
  909. }
  910. CSPI_CATCH(fSts);
  911. return fSts;
  912. }
  913. SLBCSPAPI
  914. CPGetKeyParam(IN HCRYPTPROV hProv,
  915. IN HCRYPTKEY hKey,
  916. IN DWORD dwParam,
  917. OUT BYTE *pbData,
  918. IN DWORD *pdwDataLen,
  919. IN DWORD dwFlags)
  920. {
  921. BOOL fSts = CRYPT_FAILED;
  922. CSPI_TRY(CPGetKeyParam)
  923. {
  924. Guard<Lockable> grdMaster(TheMasterLock());
  925. Guarded<CryptContext *>
  926. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  927. CKeyContext *pKey = gpCtx->LookupKey(hKey);
  928. ValidateFlags(dwFlags, 0);
  929. if (KT_PUBLICKEY == pKey->TypeOfKey())
  930. {
  931. // Public key
  932. CPublicKeyContext *pPubKey =
  933. static_cast<CPublicKeyContext *>(pKey);
  934. switch (dwParam)
  935. {
  936. case KP_ALGID:
  937. {
  938. pPubKey->VerifyKeyExists();
  939. ALG_ID algid;
  940. if (pPubKey->KeySpec() == AT_KEYEXCHANGE)
  941. algid = CALG_RSA_KEYX;
  942. else
  943. algid = CALG_RSA_SIGN;
  944. Assign(pbData, pdwDataLen, &algid, sizeof algid);
  945. }
  946. break;
  947. case KP_BLOCKLEN:
  948. {
  949. pPubKey->VerifyKeyExists();
  950. CPublicKeyContext::StrengthType stBlockLen =
  951. pPubKey->MaxStrength();
  952. Assign(pbData, pdwDataLen, &stBlockLen, sizeof stBlockLen);
  953. }
  954. break;
  955. case KP_KEYLEN:
  956. {
  957. pPubKey->VerifyKeyExists();
  958. DWORD dwKeyLen = pPubKey->MaxStrength(); // must be DWORD
  959. Assign(pbData, pdwDataLen, &dwKeyLen, sizeof dwKeyLen);
  960. }
  961. break;
  962. case KP_PERMISSIONS:
  963. {
  964. pPubKey->VerifyKeyExists();
  965. BYTE bPermissions = pPubKey->Permissions();
  966. Assign(pbData, pdwDataLen,
  967. &bPermissions, sizeof bPermissions);
  968. }
  969. break;
  970. case KP_CERTIFICATE:
  971. {
  972. CWaitCursor waitCursor;
  973. Blob const blob(pPubKey->Certificate());
  974. Assign(pbData, pdwDataLen, blob);
  975. }
  976. break;
  977. default:
  978. throw scu::OsException(NTE_BAD_TYPE);
  979. }
  980. }
  981. else
  982. {
  983. // session key
  984. CSessionKeyContext *pSessionKey =
  985. static_cast<CSessionKeyContext *>(pKey);
  986. if (!CryptGetKeyParam(pSessionKey->KeyHandleInAuxCSP(),
  987. dwParam, pbData, pdwDataLen, dwFlags))
  988. throw scu::OsException(GetLastError());
  989. }
  990. }
  991. CSPI_CATCH(fSts);
  992. return fSts;
  993. }
  994. SLBCSPAPI
  995. CPGenRandom(IN HCRYPTPROV hProv,
  996. IN DWORD dwLen,
  997. IN OUT BYTE *pbBuffer)
  998. {
  999. BOOL fSts = CRYPT_FAILED;
  1000. CSPI_TRY(CPGenRandom)
  1001. {
  1002. Guard<Lockable> grdMaster(TheMasterLock());
  1003. Guarded<CryptContext *>
  1004. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1005. if (!pbBuffer || (0 == dwLen))
  1006. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1007. HAdaptiveContainer hacntr = gpCtx->AdaptiveContainer();
  1008. if (!hacntr)
  1009. {
  1010. if (!CryptGenRandom(gpCtx->AuxContext(), dwLen, pbBuffer))
  1011. throw scu::OsException(GetLastError());
  1012. }
  1013. else
  1014. {
  1015. Secured<HAdaptiveContainer> hsacntr(hacntr);
  1016. hsacntr->TheCContainer()->Card()->GenRandom(dwLen, pbBuffer);
  1017. }
  1018. fSts = CRYPT_SUCCEED;
  1019. }
  1020. CSPI_CATCH(fSts);
  1021. return fSts;
  1022. }
  1023. SLBCSPAPI
  1024. CPGetUserKey(IN HCRYPTPROV hProv,
  1025. IN DWORD dwKeySpec,
  1026. OUT HCRYPTKEY *phUserKey)
  1027. {
  1028. BOOL fSts = CRYPT_FAILED;
  1029. CSPI_TRY(CPGetUserKey)
  1030. {
  1031. Guard<Lockable> grdMaster(TheMasterLock());
  1032. Guarded<CryptContext *>
  1033. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1034. // TO DO: This should really be a key pair, not public key.
  1035. CKeyContext *pKey = 0;
  1036. auto_ptr<CKeyContext>
  1037. apKey(new CPublicKeyContext(gpCtx->AuxContext(), **gpCtx,
  1038. dwKeySpec));
  1039. *phUserKey = gpCtx->Add(apKey);
  1040. fSts = CRYPT_SUCCEED;
  1041. }
  1042. CSPI_CATCH(fSts);
  1043. return fSts;
  1044. }
  1045. SLBCSPAPI
  1046. CPImportKey(IN HCRYPTPROV hProv,
  1047. IN CONST BYTE *pbData,
  1048. IN DWORD dwDataLen,
  1049. IN HCRYPTKEY hImpKey,
  1050. IN DWORD dwFlags,
  1051. OUT HCRYPTKEY *phKey)
  1052. {
  1053. BOOL fSts = CRYPT_FAILED;
  1054. CSPI_TRY(CPImportKey)
  1055. {
  1056. Guard<Lockable> grdMaster(TheMasterLock());
  1057. Guarded<CryptContext *>
  1058. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1059. if (!phKey)
  1060. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1061. // Conversion to do here
  1062. PUBLICKEYSTRUC const *pPubKey =
  1063. reinterpret_cast<PUBLICKEYSTRUC const *>(pbData);
  1064. if (CUR_BLOB_VERSION != pPubKey->bVersion) // 2
  1065. throw scu::OsException(NTE_BAD_VER);
  1066. switch(pPubKey->bType)
  1067. {
  1068. case PRIVATEKEYBLOB: // fall-through intentional
  1069. case PUBLICKEYBLOB:
  1070. {
  1071. DWORD dwKeySpec;
  1072. switch (pPubKey->aiKeyAlg)
  1073. {
  1074. case CALG_RSA_SIGN:
  1075. dwKeySpec = AT_SIGNATURE;
  1076. break;
  1077. case CALG_RSA_KEYX:
  1078. dwKeySpec = AT_KEYEXCHANGE;
  1079. break;
  1080. default:
  1081. throw scu::OsException(NTE_BAD_ALGID);
  1082. }
  1083. SecureArray<BYTE> blbMsKey(pbData, dwDataLen);
  1084. auto_ptr<CPublicKeyContext> apKey;
  1085. if (PRIVATEKEYBLOB == pPubKey->bType)
  1086. {
  1087. HCRYPTKEY hEncKey = hImpKey
  1088. ? gpCtx->LookupSessionKey(hImpKey)->KeyHandleInAuxCSP()
  1089. : 0;
  1090. ValidateFlags(dwFlags, CRYPT_EXPORTABLE);
  1091. apKey = gpCtx->ImportPrivateKey(blbMsKey,
  1092. dwKeySpec,
  1093. (dwFlags &
  1094. CRYPT_EXPORTABLE) != 0,
  1095. hEncKey);
  1096. }
  1097. else
  1098. {
  1099. if (0 != hImpKey)
  1100. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1101. ValidateFlags(dwFlags, 0);
  1102. apKey = gpCtx->ImportPublicKey(blbMsKey,
  1103. dwKeySpec);
  1104. }
  1105. *phKey = gpCtx->Add(apKey);
  1106. }
  1107. break;
  1108. case SIMPLEBLOB:
  1109. {
  1110. auto_ptr<CSessionKeyContext> apKey;
  1111. ALG_ID const *pAlgId =
  1112. reinterpret_cast<ALG_ID const *>(&pbData[sizeof BLOBHEADER]);
  1113. if (CALG_RSA_KEYX == *pAlgId)
  1114. {
  1115. // ignore hImp
  1116. apKey = gpCtx->UseSessionKey(pbData, dwDataLen, 0, dwFlags);
  1117. }
  1118. else
  1119. {
  1120. // if other algo then hImp shall specify a session key
  1121. if (!hImpKey)
  1122. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1123. // Find the handle in the Aux CSP corresponding
  1124. // to hImpKey which should have been previously
  1125. // imported in the CSP
  1126. CSessionKeyContext *pSessionKey =
  1127. gpCtx->LookupSessionKey(hImpKey);
  1128. apKey = gpCtx->UseSessionKey(pbData, dwDataLen,
  1129. pSessionKey->KeyHandleInAuxCSP(),
  1130. dwFlags);
  1131. }
  1132. *phKey = gpCtx->Add(apKey);
  1133. }
  1134. }
  1135. }
  1136. CSPI_CATCH(fSts);
  1137. return fSts;
  1138. }
  1139. SLBCSPAPI
  1140. CPSetKeyParam(IN HCRYPTPROV hProv,
  1141. IN HCRYPTKEY hKey,
  1142. IN DWORD dwParam,
  1143. IN BYTE *pbData,
  1144. IN DWORD dwFlags)
  1145. {
  1146. BOOL fSts = CRYPT_FAILED;
  1147. CSPI_TRY(CPSetKeyParam)
  1148. {
  1149. Guard<Lockable> grdMaster(TheMasterLock());
  1150. Guarded<CryptContext *>
  1151. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1152. CKeyContext *pKey = gpCtx->LookupKey(hKey);
  1153. switch (pKey->TypeOfKey())
  1154. {
  1155. case KT_PUBLICKEY:
  1156. {
  1157. CPublicKeyContext *pPubKey =
  1158. static_cast<CPublicKeyContext *>(pKey);
  1159. // Error return is a special case for KP_CERTIFICATE,
  1160. // see below.
  1161. if (KP_CERTIFICATE != dwParam)
  1162. ValidateFlags(dwFlags, 0);
  1163. switch(dwParam)
  1164. {
  1165. case KP_CERTIFICATE:
  1166. try
  1167. {
  1168. ValidateFlags(dwFlags, 0);
  1169. pPubKey->Certificate(pbData);
  1170. }
  1171. // Xenroll provided by Microsoft only recognizes
  1172. // SCARD_ errors when writing a certificate. It
  1173. // does, however, recognize all other errors when
  1174. // *not* writing a certificate. The MS
  1175. // OS/Security group recognizes Xenroll is in
  1176. // error but it will be some time, if ever, before
  1177. // it will be fixed. So, all errors are
  1178. // translated into SCARD_ errors at this point.
  1179. catch (scu::Exception const &rExc)
  1180. {
  1181. CapiError ce(AsCapiError(rExc));
  1182. if (NTE_TOKEN_KEYSET_STORAGE_FULL == ce)
  1183. ce = SCARD_E_WRITE_TOO_MANY;
  1184. else
  1185. if (FACILITY_SCARD != HRESULT_FACILITY(ce))
  1186. ce = SCARD_E_UNEXPECTED;
  1187. throw scu::OsException(ce);
  1188. }
  1189. catch (...)
  1190. {
  1191. throw scu::OsException(SCARD_E_UNEXPECTED);
  1192. }
  1193. break;
  1194. case KP_PERMISSIONS:
  1195. pPubKey->Permissions(*pbData);
  1196. break;
  1197. case PP_KEYEXCHANGE_PIN: // fall-through
  1198. case PP_SIGNATURE_PIN:
  1199. Pin(gpCtx, reinterpret_cast<char *>(pbData));
  1200. break;
  1201. default:
  1202. throw scu::OsException(ERROR_NOT_SUPPORTED);
  1203. break;
  1204. }
  1205. break;
  1206. }
  1207. case KT_SESSIONKEY:
  1208. {
  1209. CSessionKeyContext *pSessionKey =
  1210. static_cast<CSessionKeyContext*>(pKey);
  1211. if (!CryptSetKeyParam(pSessionKey->KeyHandleInAuxCSP(),
  1212. dwParam, pbData, dwFlags))
  1213. throw scu::OsException(GetLastError());
  1214. break;
  1215. }
  1216. default:
  1217. throw scu::OsException(ERROR_NOT_SUPPORTED);
  1218. break;
  1219. }
  1220. }
  1221. CSPI_CATCH(fSts);
  1222. return fSts;
  1223. }
  1224. SLBCSPAPI
  1225. CPEncrypt(IN HCRYPTPROV hProv,
  1226. IN HCRYPTKEY hKey,
  1227. IN HCRYPTHASH hHash,
  1228. IN BOOL Final,
  1229. IN DWORD dwFlags,
  1230. IN OUT BYTE *pbData,
  1231. IN OUT DWORD *pdwDataLen,
  1232. IN DWORD dwBufLen)
  1233. {
  1234. BOOL fSts = CRYPT_FAILED;
  1235. CSPI_TRY(CPEncrypt)
  1236. {
  1237. Guard<Lockable> grdMaster(TheMasterLock());
  1238. Guarded<CryptContext *>
  1239. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1240. CKeyContext *pKeyCtx = gpCtx->LookupKey(hKey);
  1241. ValidateFlags(dwFlags, CRYPT_OAEP);
  1242. HCRYPTHASH hAuxHash = hHash
  1243. ? gpCtx->LookupHash(hHash)->HashHandleInAuxCSP()
  1244. : NULL;
  1245. pKeyCtx->Encrypt(hAuxHash, Final, dwFlags, pbData, pdwDataLen,
  1246. dwBufLen);
  1247. }
  1248. CSPI_CATCH(fSts);
  1249. return fSts;
  1250. }
  1251. SLBCSPAPI
  1252. CPDecrypt(IN HCRYPTPROV hProv,
  1253. IN HCRYPTKEY hKey,
  1254. IN HCRYPTHASH hHash,
  1255. IN BOOL Final,
  1256. IN DWORD dwFlags,
  1257. IN OUT BYTE *pbData,
  1258. IN OUT DWORD *pdwDataLen)
  1259. {
  1260. BOOL fSts = CRYPT_FAILED;
  1261. CSPI_TRY(CPDecrypt)
  1262. {
  1263. Guard<Lockable> grdMaster(TheMasterLock());
  1264. Guarded<CryptContext *>
  1265. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1266. CSessionKeyContext *pSessionKey = gpCtx->LookupSessionKey(hKey);
  1267. ValidateFlags(dwFlags, CRYPT_OAEP);
  1268. if (hHash)
  1269. {
  1270. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1271. pSessionKey->Decrypt(pHash->HashHandleInAuxCSP(), Final,
  1272. dwFlags, pbData, pdwDataLen);
  1273. pHash->ExportFromAuxCSP();
  1274. }
  1275. else
  1276. pSessionKey->Decrypt(0, Final, dwFlags, pbData, pdwDataLen);
  1277. }
  1278. CSPI_CATCH(fSts);
  1279. return fSts;
  1280. }
  1281. SLBCSPAPI
  1282. CPCreateHash(
  1283. IN HCRYPTPROV hProv,
  1284. IN ALG_ID Algid,
  1285. IN HCRYPTKEY hKey,
  1286. IN DWORD dwFlags,
  1287. OUT HCRYPTHASH *phHash)
  1288. {
  1289. BOOL fSts = CRYPT_FAILED;
  1290. CSPI_TRY(CPCreateHash)
  1291. {
  1292. Guard<Lockable> grdMaster(TheMasterLock());
  1293. Guarded<CryptContext *>
  1294. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1295. ValidateFlags(dwFlags, 0);
  1296. auto_ptr<CHashContext> apHash(CHashContext::Make(Algid, **gpCtx));
  1297. apHash->ImportToAuxCSP();
  1298. *phHash = gpCtx->Add(apHash);
  1299. }
  1300. CSPI_CATCH(fSts);
  1301. return fSts;
  1302. }
  1303. SLBCSPAPI
  1304. CPDestroyHash(IN HCRYPTPROV hProv,
  1305. IN HCRYPTHASH hHash)
  1306. {
  1307. BOOL fSts = CRYPT_FAILED;
  1308. CSPI_TRY(CPDestroyHash)
  1309. {
  1310. Guard<Lockable> grdMaster(TheMasterLock());
  1311. Guarded<CryptContext *>
  1312. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1313. auto_ptr<CHashContext> apHash(gpCtx->CloseHash(hHash));
  1314. apHash->Close();
  1315. }
  1316. CSPI_CATCH(fSts);
  1317. return fSts;
  1318. }
  1319. SLBCSPAPI
  1320. CPGetHashParam(IN HCRYPTPROV hProv,
  1321. IN HCRYPTHASH hHash,
  1322. IN DWORD dwParam,
  1323. OUT BYTE *pbData,
  1324. IN DWORD *pdwDataLen,
  1325. IN DWORD dwFlags)
  1326. {
  1327. BOOL fSts = CRYPT_FAILED;
  1328. CSPI_TRY(CPGetHashParam)
  1329. {
  1330. Guard<Lockable> grdMaster(TheMasterLock());
  1331. Guarded<CryptContext *>
  1332. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1333. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1334. ValidateFlags(dwFlags, 0);
  1335. switch (dwParam)
  1336. {
  1337. case HP_ALGID:
  1338. {
  1339. ALG_ID const algid = pHash->AlgId();
  1340. Assign(pbData, pdwDataLen, &algid, sizeof algid);
  1341. }
  1342. break;
  1343. case HP_HASHSIZE:
  1344. {
  1345. CHashContext::SizeType const cLength = pHash->Length();
  1346. Assign(pbData, pdwDataLen, &cLength, sizeof cLength);
  1347. }
  1348. break;
  1349. case HP_HASHVAL:
  1350. {
  1351. Blob const blob(pHash->Value());
  1352. Assign(pbData, pdwDataLen, blob);
  1353. }
  1354. break;
  1355. default:
  1356. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1357. break;
  1358. }
  1359. }
  1360. CSPI_CATCH(fSts);
  1361. return fSts;
  1362. }
  1363. SLBCSPAPI
  1364. CPHashData(IN HCRYPTPROV hProv,
  1365. IN HCRYPTHASH hHash,
  1366. IN CONST BYTE *pbData,
  1367. IN DWORD dwDataLen,
  1368. IN DWORD dwFlags)
  1369. {
  1370. BOOL fSts = CRYPT_FAILED;
  1371. CSPI_TRY(CPHashData)
  1372. {
  1373. Guard<Lockable> grdMaster(TheMasterLock());
  1374. Guarded<CryptContext *>
  1375. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1376. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1377. if (!CryptHashData(pHash->HashHandleInAuxCSP(), pbData, dwDataLen,
  1378. dwFlags))
  1379. throw scu::OsException(GetLastError());
  1380. }
  1381. CSPI_CATCH(fSts);
  1382. return fSts;
  1383. }
  1384. SLBCSPAPI
  1385. CPHashSessionKey(IN HCRYPTPROV hProv,
  1386. IN HCRYPTHASH hHash,
  1387. IN HCRYPTKEY hKey,
  1388. IN DWORD dwFlags)
  1389. {
  1390. BOOL fSts = CRYPT_FAILED;
  1391. CSPI_TRY(CPHashSessionKey)
  1392. {
  1393. Guard<Lockable> grdMaster(TheMasterLock());
  1394. Guarded<CryptContext *>
  1395. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1396. CSessionKeyContext *pSessionKey = gpCtx->LookupSessionKey(hKey);
  1397. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1398. if (!CryptHashSessionKey(pHash->HashHandleInAuxCSP(),
  1399. pSessionKey->KeyHandleInAuxCSP(),
  1400. dwFlags))
  1401. throw scu::OsException(GetLastError());
  1402. pHash->ExportFromAuxCSP();
  1403. }
  1404. CSPI_CATCH(fSts);
  1405. return fSts;
  1406. }
  1407. SLBCSPAPI
  1408. CPSetHashParam(IN HCRYPTPROV hProv,
  1409. IN HCRYPTHASH hHash,
  1410. IN DWORD dwParam,
  1411. IN BYTE *pbData,
  1412. IN DWORD dwFlags)
  1413. {
  1414. BOOL fSts = CRYPT_FAILED;
  1415. CSPI_TRY(CPSetHashParam)
  1416. {
  1417. Guard<Lockable> grdMaster(TheMasterLock());
  1418. Guarded<CryptContext *>
  1419. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1420. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1421. if (!CryptSetHashParam(pHash->HashHandleInAuxCSP(), dwParam,
  1422. pbData, dwFlags))
  1423. throw scu::OsException(GetLastError());
  1424. }
  1425. CSPI_CATCH(fSts);
  1426. return fSts;
  1427. }
  1428. SLBCSPAPI
  1429. CPSignHash(IN HCRYPTPROV hProv,
  1430. IN HCRYPTHASH hHash,
  1431. IN DWORD dwKeySpec,
  1432. IN LPCTSTR szDescription,
  1433. IN DWORD dwFlags,
  1434. OUT BYTE *pbSignature,
  1435. IN OUT DWORD *pdwSigLen)
  1436. {
  1437. BOOL fSts = CRYPT_FAILED;
  1438. CSPI_TRY(CPSignHash)
  1439. {
  1440. Guard<Lockable> grdMaster(TheMasterLock());
  1441. Guarded<CryptContext *>
  1442. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1443. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1444. if (!pdwSigLen)
  1445. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1446. ValidateFlags(dwFlags, CRYPT_NOHASHOID);
  1447. // TO DO: This should really be a private key and
  1448. // avoid having to fetch the public key to get the modulus
  1449. CPublicKeyContext Key(gpCtx->AuxContext(), **gpCtx, dwKeySpec);
  1450. DWORD cSignatureLength =
  1451. Key.Strength() / numeric_limits<BYTE>::digits;
  1452. if (!pbSignature)
  1453. {
  1454. *pdwSigLen = cSignatureLength;
  1455. }
  1456. else if (*pdwSigLen < cSignatureLength)
  1457. {
  1458. *pdwSigLen = cSignatureLength;
  1459. throw scu::OsException(ERROR_MORE_DATA);
  1460. }
  1461. else
  1462. {
  1463. // Security: Support for the description parameter is
  1464. // removed due to security vulnerability.
  1465. if (szDescription)
  1466. throw scu::OsException(ERROR_INVALID_PARAMETER);
  1467. Blob SignedHash(Key.Sign(pHash, dwFlags & CRYPT_NOHASHOID));
  1468. memcpy(pbSignature, SignedHash.data(), SignedHash.length());
  1469. *pdwSigLen = SignedHash.length();
  1470. }
  1471. }
  1472. CSPI_CATCH(fSts);
  1473. return fSts;
  1474. }
  1475. SLBCSPAPI
  1476. CPVerifySignature(IN HCRYPTPROV hProv,
  1477. IN HCRYPTHASH hHash,
  1478. IN CONST BYTE *pbSignature,
  1479. IN DWORD dwSigLen,
  1480. IN HCRYPTKEY hPubKey,
  1481. IN LPCTSTR szDescription,
  1482. IN DWORD dwFlags)
  1483. {
  1484. BOOL fSts = CRYPT_FAILED;
  1485. CSPI_TRY(CPVerifySignature)
  1486. {
  1487. Guard<Lockable> grdMaster(TheMasterLock());
  1488. Guarded<CryptContext *>
  1489. gpCtx(static_cast<CryptContext *>(hlCryptContexts[hProv]));
  1490. CHashContext *pHash = gpCtx->LookupHash(hHash);
  1491. CPublicKeyContext *pKey = gpCtx->LookupPublicKey(hPubKey);
  1492. ValidateFlags(dwFlags, CRYPT_NOHASHOID);
  1493. pKey->VerifySignature(pHash->HashHandleInAuxCSP(),
  1494. pbSignature, dwSigLen,
  1495. szDescription, dwFlags);
  1496. }
  1497. CSPI_CATCH(fSts);
  1498. return fSts;
  1499. }