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.

720 lines
16 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: PublicKey.cpp
  4. Content: Implementation of CPublicKey.
  5. History: 06-15-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "PublicKey.h"
  10. #include "Common.h"
  11. #include "Convert.h"
  12. #include "OID.h"
  13. #include "EncodedData.h"
  14. ////////////////////////////////////////////////////////////////////////////////
  15. //
  16. // Exported functions.
  17. //
  18. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  19. Function : CreatePublicKeyObject
  20. Synopsis : Create and initialize an CPublicKey object.
  21. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
  22. to initialize the IPublicKey object.
  23. IPublicKey ** ppIPublicKey - Pointer to pointer IPublicKey object.
  24. Remark :
  25. ------------------------------------------------------------------------------*/
  26. HRESULT CreatePublicKeyObject (PCCERT_CONTEXT pCertContext,
  27. IPublicKey ** ppIPublicKey)
  28. {
  29. HRESULT hr = S_OK;
  30. CComObject<CPublicKey> * pCPublicKey = NULL;
  31. DebugTrace("Entering CreatePublicKeyObject().\n");
  32. //
  33. // Sanity check.
  34. //
  35. ATLASSERT(pCertContext);
  36. ATLASSERT(ppIPublicKey);
  37. try
  38. {
  39. //
  40. // Create the object. Note that the ref count will still be 0
  41. // after the object is created.
  42. //
  43. if (FAILED(hr = CComObject<CPublicKey>::CreateInstance(&pCPublicKey)))
  44. {
  45. DebugTrace("Error [%#x]: CComObject<CPublicKey>::CreateInstance() failed.\n", hr);
  46. goto ErrorExit;
  47. }
  48. //
  49. // Initialize object.
  50. //
  51. if (FAILED(hr = pCPublicKey->Init(pCertContext)))
  52. {
  53. DebugTrace("Error [%#x]: pCPublicKey->Init() failed.\n", hr);
  54. goto ErrorExit;
  55. }
  56. //
  57. // Return interface pointer to caller.
  58. //
  59. if (FAILED(hr = pCPublicKey->QueryInterface(ppIPublicKey)))
  60. {
  61. DebugTrace("Error [%#x]: pCPublicKey->QueryInterface() failed.\n", hr);
  62. goto ErrorExit;
  63. }
  64. }
  65. catch(...)
  66. {
  67. hr = E_POINTER;
  68. DebugTrace("Exception: invalid parameter.\n");
  69. goto ErrorExit;
  70. }
  71. CommonExit:
  72. DebugTrace("Leaving CreatePublicKeyObject().\n");
  73. return hr;
  74. ErrorExit:
  75. //
  76. // Sanity check.
  77. //
  78. ATLASSERT(FAILED(hr));
  79. if (pCPublicKey)
  80. {
  81. delete pCPublicKey;
  82. }
  83. goto CommonExit;
  84. }
  85. ////////////////////////////////////////////////////////////////////////////////
  86. //
  87. // CPublicKey
  88. //
  89. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  90. Function : CPublicKey::get_Algorithm
  91. Synopsis : Return the algorithm OID object.
  92. Parameter: IOID ** pVal - Pointer to pointer IOID to receive the interface
  93. pointer.
  94. Remark :
  95. ------------------------------------------------------------------------------*/
  96. STDMETHODIMP CPublicKey::get_Algorithm(IOID ** pVal)
  97. {
  98. HRESULT hr = S_OK;
  99. DebugTrace("Entering CPublicKey::get_Algorithm().\n");
  100. try
  101. {
  102. //
  103. // Lock access to this object.
  104. //
  105. m_Lock.Lock();
  106. //
  107. // Check parameters.
  108. //
  109. if (NULL == pVal)
  110. {
  111. hr = E_INVALIDARG;
  112. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  113. goto ErrorExit;
  114. }
  115. //
  116. // Sanity check.
  117. //
  118. ATLASSERT(m_pIOID);
  119. //
  120. // Return interface pointer to user.
  121. //
  122. if (FAILED(hr = m_pIOID->QueryInterface(pVal)))
  123. {
  124. DebugTrace("Error [%#x]: m_pIOID->QueryInterface() failed.\n", hr);
  125. goto ErrorExit;
  126. }
  127. }
  128. catch(...)
  129. {
  130. hr = E_POINTER;
  131. DebugTrace("Exception: invalid parameter.\n");
  132. goto ErrorExit;
  133. }
  134. UnlockExit:
  135. //
  136. // Unlock access to this object.
  137. //
  138. m_Lock.Unlock();
  139. DebugTrace("Leaving CPublicKey::get_Algorithm().\n");
  140. return hr;
  141. ErrorExit:
  142. //
  143. // Sanity check.
  144. //
  145. ATLASSERT(FAILED(hr));
  146. ReportError(hr);
  147. goto UnlockExit;
  148. }
  149. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  150. Function : CPublicKey::get_Length
  151. Synopsis : Return the public key length.
  152. Parameter: long * pVal - Pointer to long to receive the value.
  153. Remark :
  154. ------------------------------------------------------------------------------*/
  155. STDMETHODIMP CPublicKey::get_Length(long * pVal)
  156. {
  157. HRESULT hr = S_OK;
  158. DebugTrace("Entering CPublicKey::get_Length().\n");
  159. try
  160. {
  161. //
  162. // Lock access to this object.
  163. //
  164. m_Lock.Lock();
  165. //
  166. // Check parameters.
  167. //
  168. if (NULL == pVal)
  169. {
  170. hr = E_INVALIDARG;
  171. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  172. goto ErrorExit;
  173. }
  174. *pVal = (long) m_dwKeyLength;
  175. }
  176. catch(...)
  177. {
  178. hr = E_POINTER;
  179. DebugTrace("Exception: invalid parameter.\n");
  180. goto ErrorExit;
  181. }
  182. UnlockExit:
  183. //
  184. // Unlock access to this object.
  185. //
  186. m_Lock.Unlock();
  187. DebugTrace("Leaving CPublicKey::get_Length().\n");
  188. return hr;
  189. ErrorExit:
  190. //
  191. // Sanity check.
  192. //
  193. ATLASSERT(FAILED(hr));
  194. ReportError(hr);
  195. goto UnlockExit;
  196. }
  197. #if (0)
  198. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  199. Function : CPublicKey::get_Exponent
  200. Synopsis : Return the public key exponent.
  201. Parameter: long * pVal - Pointer to long to receive the value.
  202. Remark :
  203. ------------------------------------------------------------------------------*/
  204. STDMETHODIMP CPublicKey::get_Exponent(long * pVal)
  205. {
  206. HRESULT hr = S_OK;
  207. DebugTrace("Entering CPublicKey::get_Exponent().\n");
  208. try
  209. {
  210. //
  211. // Lock access to this object.
  212. //
  213. m_Lock.Lock();
  214. //
  215. // Sanity check.
  216. //
  217. ATLASSERT(m_pPublicKeyValues);
  218. *pVal = (long) m_pPublicKeyValues->rsapubkey.pubexp;
  219. }
  220. catch(...)
  221. {
  222. hr = E_POINTER;
  223. DebugTrace("Exception: invalid parameter.\n");
  224. goto ErrorExit;
  225. }
  226. UnlockExit:
  227. //
  228. // Unlock access to this object.
  229. //
  230. m_Lock.Unlock();
  231. DebugTrace("Leaving CPublicKey::get_Exponent().\n");
  232. return hr;
  233. ErrorExit:
  234. //
  235. // Sanity check.
  236. //
  237. ATLASSERT(FAILED(hr));
  238. ReportError(hr);
  239. goto UnlockExit;
  240. }
  241. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  242. Function : CPublicKey::get_Modulus
  243. Synopsis : Return the public key modulus.
  244. Parameter: CAPICOM_ENCODING_TYPE EncodingType - ENcoding type.
  245. BSTR * pVal - Pointer to BSTR to receive the value.
  246. Remark :
  247. ------------------------------------------------------------------------------*/
  248. STDMETHODIMP CPublicKey::get_Modulus(CAPICOM_ENCODING_TYPE EncodingType,
  249. BSTR * pVal)
  250. {
  251. HRESULT hr = S_OK;
  252. CRYPT_DATA_BLOB ModulusBlob = {0, NULL};
  253. DebugTrace("Entering CPublicKey::get_Modulus().\n");
  254. try
  255. {
  256. //
  257. // Lock access to this object.
  258. //
  259. m_Lock.Lock();
  260. //
  261. // Sanity check.
  262. //
  263. ATLASSERT(m_pPublicKeyValues);
  264. //
  265. // Initialize the blob.
  266. //
  267. ModulusBlob.cbData = m_pPublicKeyValues->rsapubkey.bitlen / 8;
  268. ModulusBlob.pbData = m_pPublicKeyValues->modulus;
  269. //
  270. // Return data to caller.
  271. //
  272. if (FAILED(hr = ::ExportData(ModulusBlob, EncodingType, pVal)))
  273. {
  274. DebugTrace("Error [%#x]: ExportData() failed.\n", hr);
  275. goto ErrorExit;
  276. }
  277. }
  278. catch(...)
  279. {
  280. hr = E_POINTER;
  281. DebugTrace("Exception: invalid parameter.\n");
  282. goto ErrorExit;
  283. }
  284. UnlockExit:
  285. //
  286. // Unlock access to this object.
  287. //
  288. m_Lock.Unlock();
  289. DebugTrace("Leaving CPublicKey::get_Modulus().\n");
  290. return hr;
  291. ErrorExit:
  292. //
  293. // Sanity check.
  294. //
  295. ATLASSERT(FAILED(hr));
  296. ReportError(hr);
  297. goto UnlockExit;
  298. }
  299. #endif
  300. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  301. Function : CPublicKey::get_EncodedKey
  302. Synopsis : Return the encoded public key key object.
  303. Parameter: IEncodedData ** pVal - Pointer to pointer IEncodedData to receive
  304. the interface pointer.
  305. Remark :
  306. ------------------------------------------------------------------------------*/
  307. STDMETHODIMP CPublicKey::get_EncodedKey(IEncodedData ** pVal)
  308. {
  309. HRESULT hr = S_OK;
  310. DebugTrace("Entering CPublicKey::get_EncodedKey().\n");
  311. try
  312. {
  313. //
  314. // Lock access to this object.
  315. //
  316. m_Lock.Lock();
  317. //
  318. // Check parameters.
  319. //
  320. if (NULL == pVal)
  321. {
  322. hr = E_INVALIDARG;
  323. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  324. goto ErrorExit;
  325. }
  326. //
  327. // Sanity check.
  328. //
  329. ATLASSERT(m_pIEncodedKey);
  330. //
  331. // Return interface pointer to user.
  332. //
  333. if (FAILED(hr = m_pIEncodedKey->QueryInterface(pVal)))
  334. {
  335. DebugTrace("Error [%#x]: m_pIEncodedKey->QueryInterface() failed.\n", hr);
  336. goto ErrorExit;
  337. }
  338. }
  339. catch(...)
  340. {
  341. hr = E_POINTER;
  342. DebugTrace("Exception: invalid parameter.\n");
  343. goto ErrorExit;
  344. }
  345. UnlockExit:
  346. //
  347. // Unlock access to this object.
  348. //
  349. m_Lock.Unlock();
  350. DebugTrace("Leaving CPublicKey::get_EncodedKey().\n");
  351. return hr;
  352. ErrorExit:
  353. //
  354. // Sanity check.
  355. //
  356. ATLASSERT(FAILED(hr));
  357. ReportError(hr);
  358. goto UnlockExit;
  359. }
  360. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  361. Function : CPublicKey::get_EncodedParameters
  362. Synopsis : Return the encoded algorithm parameters key object.
  363. Parameter: IEncodedData ** pVal - Pointer to pointer IEncodedData to receive
  364. the interface pointer.
  365. Remark :
  366. ------------------------------------------------------------------------------*/
  367. STDMETHODIMP CPublicKey::get_EncodedParameters(IEncodedData ** pVal)
  368. {
  369. HRESULT hr = S_OK;
  370. DebugTrace("Entering CPublicKey::get_EncodedParameters().\n");
  371. try
  372. {
  373. //
  374. // Lock access to this object.
  375. //
  376. m_Lock.Lock();
  377. //
  378. // Check parameters.
  379. //
  380. if (NULL == pVal)
  381. {
  382. hr = E_INVALIDARG;
  383. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  384. goto ErrorExit;
  385. }
  386. //
  387. // Sanity check.
  388. //
  389. ATLASSERT(m_pIEncodedParams);
  390. //
  391. // Return interface pointer to user.
  392. //
  393. if (FAILED(hr = m_pIEncodedParams->QueryInterface(pVal)))
  394. {
  395. DebugTrace("Error [%#x]: m_pIEncodedParams->QueryInterface() failed.\n", hr);
  396. goto ErrorExit;
  397. }
  398. }
  399. catch(...)
  400. {
  401. hr = E_POINTER;
  402. DebugTrace("Exception: invalid parameter.\n");
  403. goto ErrorExit;
  404. }
  405. UnlockExit:
  406. //
  407. // Unlock access to this object.
  408. //
  409. m_Lock.Unlock();
  410. DebugTrace("Leaving CPublicKey::get_EncodedParameters().\n");
  411. return hr;
  412. ErrorExit:
  413. //
  414. // Sanity check.
  415. //
  416. ATLASSERT(FAILED(hr));
  417. ReportError(hr);
  418. goto UnlockExit;
  419. }
  420. ////////////////////////////////////////////////////////////////////////////////
  421. //
  422. // Private methods.
  423. //
  424. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  425. Function : CPublicKey::Init
  426. Synopsis : Initialize the object.
  427. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
  428. to initialize the object.
  429. Remark : This method is not part of the COM interface (it is a normal C++
  430. member function). We need it to initialize the object created
  431. internally by us with CERT_ExtendedProperty.
  432. Since it is only a normal C++ member function, this function can
  433. only be called from a C++ class pointer, not an interface pointer.
  434. ------------------------------------------------------------------------------*/
  435. STDMETHODIMP CPublicKey::Init (PCCERT_CONTEXT pCertContext)
  436. {
  437. HRESULT hr = S_OK;
  438. DWORD dwKeyLength = 0;
  439. CComPtr<IOID> pIOID = NULL;
  440. CComPtr<IEncodedData> pIEncodedKey = NULL;
  441. CComPtr<IEncodedData> pIEncodedParams = NULL;
  442. PCERT_PUBLIC_KEY_INFO pKeyInfo;
  443. DebugTrace("Entering CPublicKey::Init().\n");
  444. //
  445. // Sanity check.
  446. //
  447. ATLASSERT(pCertContext);
  448. //
  449. // Access the public key info structure.
  450. //
  451. pKeyInfo = &pCertContext->pCertInfo->SubjectPublicKeyInfo;
  452. #if (0)
  453. //
  454. // Decode the public key.
  455. //
  456. LPSTR pszStructType = NULL;
  457. CRYPT_DATA_BLOB PublicKeyBlob = {0, NULL};
  458. PUBLIC_KEY_VALUES * pPublicKeyValues = NULL;
  459. if (0 == ::strcmp(szOID_RSA_RSA, pKeyInfo->Algorithm.pszObjId))
  460. {
  461. pszStructType = (LPSTR) RSA_CSP_PUBLICKEYBLOB;
  462. }
  463. else if (0 == ::strcmp(szOID_X957_DSA, pKeyInfo->Algorithm.pszObjId))
  464. {
  465. pszStructType = (LPSTR) X509_DSS_PUBLICKEY;
  466. }
  467. else
  468. {
  469. hr = CAPICOM_E_NOT_SUPPORTED;
  470. DebugTrace("Error [%#x]: Public Key algorithm (%s) not supported.\n", hr, pKeyInfo->Algorithm.pszObjId);
  471. goto ErrorExit;
  472. }
  473. if (FAILED(hr = ::DecodeObject((LPCSTR) pszStructType,
  474. pKeyInfo->PublicKey.pbData,
  475. pKeyInfo->PublicKey.cbData,
  476. &PublicKeyBlob)))
  477. {
  478. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  479. goto ErrorExit;
  480. }
  481. pPublicKeyValues = (PUBLIC_KEY_VALUES *) PublicKeyBlob.pbData;
  482. #endif
  483. //
  484. // Create the embeded IOID object for algorithm.
  485. //
  486. if (FAILED(hr = ::CreateOIDObject(pKeyInfo->Algorithm.pszObjId, TRUE, &pIOID)))
  487. {
  488. DebugTrace("Error [%#x]: CreateOIDObject() failed.\n", hr);
  489. goto ErrorExit;
  490. }
  491. //
  492. // Create the embeded IEncodeData object for the public key value.
  493. //
  494. if (FAILED(hr = ::CreateEncodedDataObject(pKeyInfo->Algorithm.pszObjId,
  495. (DATA_BLOB *) &pKeyInfo->PublicKey,
  496. &pIEncodedKey)))
  497. {
  498. DebugTrace("Error [%#x]: CreateEncodedDataObject() failed for public key.\n", hr);
  499. goto ErrorExit;
  500. }
  501. //
  502. // Create the embeded IEncodeData object for the algorithm parameters.
  503. //
  504. if (FAILED(hr = ::CreateEncodedDataObject(pKeyInfo->Algorithm.pszObjId,
  505. &pKeyInfo->Algorithm.Parameters,
  506. &pIEncodedParams)))
  507. {
  508. DebugTrace("Error [%#x]: CreateEncodedDataObject() failed for algorithm parameters.\n", hr);
  509. goto ErrorExit;
  510. }
  511. //
  512. // Get key length.
  513. //
  514. if (0 == (dwKeyLength = ::CertGetPublicKeyLength(CAPICOM_ASN_ENCODING, pKeyInfo)))
  515. {
  516. hr = HRESULT_FROM_WIN32(::GetLastError());
  517. DebugTrace("Error [%#x]: CertGetPublicKeyLength() failed.\n", hr);
  518. goto ErrorExit;
  519. }
  520. //
  521. // Reset.
  522. //
  523. m_pIOID = pIOID;
  524. m_dwKeyLength = dwKeyLength;
  525. m_pIEncodedKey = pIEncodedKey;
  526. m_pIEncodedParams = pIEncodedParams;
  527. CommonExit:
  528. DebugTrace("Leaving CPublicKey::Init().\n");
  529. return hr;
  530. ErrorExit:
  531. //
  532. // Sanity check.
  533. //
  534. ATLASSERT(FAILED(hr));
  535. goto CommonExit;
  536. }