Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

662 lines
19 KiB

  1. // CreatingKeyDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include "keyobjs.h"
  6. #include "NKChseCA.h"
  7. #include "NKDN.h"
  8. #include "NKDN2.h"
  9. #include "NKKyInfo.h"
  10. #include "NKUsrInf.h"
  11. #include "Creating.h"
  12. #include "certcli.h"
  13. #include "OnlnAuth.h"
  14. #include "intrlkey.h"
  15. #define SECURITY_WIN32
  16. extern "C"
  17. {
  18. #include <wincrypt.h>
  19. #include <Sslsp.h>
  20. #include <sspi.h>
  21. #include <issperr.h>
  22. }
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. UINT MyThreadProc( LPVOID pParam );
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CCreateKeyProgThread thread controller
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CCreatingKeyDlg dialog
  33. //----------------------------------------------------------------
  34. CCreatingKeyDlg::CCreatingKeyDlg(CWnd* pParent /*=NULL*/)
  35. : CDialog(CCreatingKeyDlg::IDD, pParent),
  36. m_cbPrivateKey( 0 ),
  37. m_pPrivateKey( NULL ),
  38. m_cbCertificate( 0 ),
  39. m_pCertificate( NULL ),
  40. m_cbCertificateRequest( 0 ),
  41. m_pCertificateRequest( NULL ),
  42. m_pKey( NULL ),
  43. m_pService( NULL ),
  44. m_fResubmitKey( FALSE ),
  45. m_fRenewExistingKey( FALSE ),
  46. m_fGenerateKeyPair( FALSE )
  47. {
  48. //{{AFX_DATA_INIT(CCreatingKeyDlg)
  49. m_sz_message = _T("");
  50. //}}AFX_DATA_INIT
  51. }
  52. //----------------------------------------------------------------
  53. CCreatingKeyDlg::~CCreatingKeyDlg()
  54. {
  55. // now that I'm adding a header in front of the requests, we need
  56. // to dispose of it here.
  57. if ( m_pCertificateRequest )
  58. GlobalFree( m_pCertificateRequest );
  59. m_pCertificateRequest = NULL;
  60. }
  61. //----------------------------------------------------------------
  62. void CCreatingKeyDlg::DoDataExchange(CDataExchange* pDX)
  63. {
  64. CDialog::DoDataExchange(pDX);
  65. //{{AFX_DATA_MAP(CCreatingKeyDlg)
  66. DDX_Control(pDX, IDC_MESSAGE, m_cstatic_message);
  67. DDX_Control(pDX, IDOK, m_btn_ok);
  68. DDX_Control(pDX, IDC_GRINDER_ANIMATION, m_animation);
  69. DDX_Text(pDX, IDC_MESSAGE, m_sz_message);
  70. //}}AFX_DATA_MAP
  71. }
  72. //----------------------------------------------------------------
  73. BEGIN_MESSAGE_MAP(CCreatingKeyDlg, CDialog)
  74. //{{AFX_MSG_MAP(CCreatingKeyDlg)
  75. // NOTE: the ClassWizard will add message map macros here
  76. //}}AFX_MSG_MAP
  77. END_MESSAGE_MAP()
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CCreatingKeyDlg message handlers
  80. //----------------------------------------------------------------
  81. // override virtual oninitdialog
  82. BOOL CCreatingKeyDlg::OnInitDialog( )
  83. {
  84. // tell the user that we are generating the new key request
  85. // might as well do that here, since it is first
  86. m_sz_message.LoadString( IDS_GRIND_GENERATING );
  87. // call the base oninit
  88. CDialog::OnInitDialog();
  89. // disable the ok button
  90. m_btn_ok.EnableWindow( FALSE );
  91. // tell the animation control to set itself up
  92. CString szAnimName;
  93. szAnimName.LoadString(IDS_CREATING_ANIMATION);
  94. m_animation.Open( IDR_AVI_CREATING_KEY );
  95. // start up the worker thread
  96. AfxBeginThread( (AFX_THREADPROC)MyThreadProc, this);
  97. // return 0 to say we set the default item
  98. // return 1 to just select the default default item
  99. return 1;
  100. }
  101. //----------------------------------------------------------------
  102. UINT MyThreadProc( LPVOID pParam )
  103. {
  104. CCreatingKeyDlg* pDlg = (CCreatingKeyDlg*)pParam;
  105. BOOL fSuccess = TRUE;
  106. // this thread needs its own coinitialize
  107. HRESULT hRes = CoInitialize(NULL);
  108. if ( FAILED(hRes) )
  109. return GetLastError();
  110. // if the flag is set, generate the key pair
  111. if ( pDlg->m_fGenerateKeyPair )
  112. fSuccess = pDlg->FGenerateKeyPair();
  113. // do the work that needs to get done
  114. if ( fSuccess )
  115. {
  116. // if the request was generated, go to post
  117. pDlg->PostGenerateKeyPair();
  118. }
  119. else
  120. {
  121. // we weren't able to generate the keypair. Leave.
  122. AfxMessageBox( IDS_GEN_KEYPAIR_ERR );
  123. pDlg->EndDialog( IDCANCEL );
  124. }
  125. // return
  126. return 0;
  127. }
  128. //------------------------------------------------------------------------------
  129. void CCreatingKeyDlg::PostGenerateKeyPair()
  130. {
  131. BOOL fPlacedRequest = TRUE;
  132. // first we create the new key object and fill it in as best we can
  133. if ( !m_pKey )
  134. {
  135. ASSERT( !m_fRenewExistingKey );
  136. ASSERT( !m_fResubmitKey );
  137. try
  138. {
  139. CreateNewKey();
  140. }
  141. catch (CException e)
  142. {
  143. AfxMessageBox( IDS_GEN_KEYPAIR_ERR );
  144. EndDialog( IDCANCEL );
  145. return;
  146. }
  147. }
  148. // if we are renewing an existing key, target the key appropriately
  149. if ( m_fRenewExistingKey )
  150. RetargetKey();
  151. // if resubmitting the key, do so
  152. if ( m_fResubmitKey )
  153. {
  154. // tell the user that we are attempting to submit the request
  155. m_sz_message.LoadString( IDS_GRIND_RESUBMITTING );
  156. m_cstatic_message.SetWindowText(m_sz_message);
  157. // submit the request
  158. SubmitRequestToAuthority();
  159. }
  160. else
  161. // send the request off to the online service, if that was chosen.
  162. if ( m_ppage_Choose_CA && m_ppage_Choose_CA->m_nkca_radio == 1 )
  163. {
  164. // tell the user that we are attempting to submit the request
  165. m_sz_message.LoadString( IDS_GRIND_SUBMITTING );
  166. m_cstatic_message.SetWindowText(m_sz_message);
  167. // submit the request
  168. SubmitRequestToAuthority();
  169. }
  170. else
  171. // if targeted as such, write it to the file
  172. {
  173. // write the request out
  174. fPlacedRequest = WriteRequestToFile();
  175. }
  176. // one final show string
  177. // NOTE: cannot use UpdateData because we are in a different
  178. // thread than the dialog. UpdateData crashes.
  179. if ( fPlacedRequest )
  180. m_cstatic_message.SetWindowText(m_sz_message);
  181. else
  182. {
  183. m_sz_message.LoadString( IDS_IO_ERROR );
  184. m_cstatic_message.SetWindowText(m_sz_message);
  185. }
  186. // activate the ok button so we can close
  187. m_btn_ok.EnableWindow( TRUE );
  188. // stop the avi from spinning. That would give the wrong impression
  189. m_animation.Stop();
  190. }
  191. //------------------------------------------------------------------------------
  192. BOOL CCreatingKeyDlg::RetargetKey()
  193. {
  194. ASSERT( m_ppage_Choose_CA );
  195. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)m_pKey->m_pCertificateRequest;
  196. // if we are sending the key to an online authority, record which one
  197. if ( m_ppage_Choose_CA->m_nkca_radio == 1 )
  198. {
  199. // get the path of the authority dll
  200. CString szCA;
  201. if ( m_ppage_Choose_CA->GetSelectedCA(szCA) == ERROR_SUCCESS )
  202. {
  203. // fill in the rest of the request header, indicating the online authority
  204. pHeader->fReqSentToOnlineCA = TRUE;
  205. strncpy( pHeader->chCA, szCA, MAX_PATH-1 );
  206. }
  207. }
  208. else
  209. {
  210. // clear it for the file
  211. pHeader->fReqSentToOnlineCA = FALSE;
  212. }
  213. return TRUE;
  214. }
  215. //------------------------------------------------------------------------------
  216. void CCreatingKeyDlg::CreateNewKey()
  217. {
  218. // create the new key object
  219. m_pKey = m_pService->PNewKey();
  220. // put in the name of the key
  221. m_pKey->SetName( m_ppage_Key_Info->m_nkki_sz_name );
  222. // put in the password too
  223. m_pKey->m_szPassword = m_ppage_Key_Info->m_nkki_sz_password;
  224. // set the private data into place
  225. ASSERT( m_cbPrivateKey );
  226. ASSERT( m_pPrivateKey );
  227. m_pKey->m_cbPrivateKey = m_cbPrivateKey;
  228. m_pKey->m_pPrivateKey = m_pPrivateKey;
  229. // set the request into place
  230. // not quite as simple because now we have the header that goes in first.
  231. ASSERT( m_cbCertificateRequest );
  232. ASSERT( m_pCertificateRequest );
  233. // allocate the the request pointer - include space for the header
  234. DWORD cbRequestAndHeader = m_cbCertificateRequest + sizeof(KeyRequestHeader);
  235. m_pKey->m_cbCertificateRequest = cbRequestAndHeader;
  236. m_pKey->m_pCertificateRequest = GlobalAlloc( GPTR, cbRequestAndHeader );
  237. ASSERT( m_pKey->m_pCertificateRequest );
  238. if ( !m_pKey->m_pCertificateRequest ) AfxThrowMemoryException();
  239. // fill in the basic header. Assume there is no online ca for now
  240. ZeroMemory( m_pKey->m_pCertificateRequest, sizeof(KeyRequestHeader) );
  241. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)m_pKey->m_pCertificateRequest;
  242. pHeader->Identifier = REQUEST_HEADER_IDENTIFIER; // required
  243. pHeader->Version = REQUEST_HEADER_CURVERSION; // required
  244. pHeader->cbSizeOfHeader = sizeof(KeyRequestHeader); // required
  245. pHeader->cbRequestSize = m_cbCertificateRequest; // required
  246. // copy over the request data
  247. memcpy( (PUCHAR)m_pKey->m_pCertificateRequest + sizeof(KeyRequestHeader),
  248. (PUCHAR)m_pCertificateRequest, m_cbCertificateRequest );
  249. // if we are sending the key to an online authority, record which one
  250. if ( m_ppage_Choose_CA->m_nkca_radio == 1 )
  251. {
  252. // get the path of the authority dll
  253. CString szCA;
  254. if ( m_ppage_Choose_CA->GetSelectedCA(szCA) == ERROR_SUCCESS )
  255. {
  256. // fill in the rest of the request header, indicating the online authority
  257. pHeader->fReqSentToOnlineCA = TRUE;
  258. strncpy( pHeader->chCA, szCA, MAX_PATH-1 );
  259. }
  260. }
  261. }
  262. //------------------------------------------------------------------------------
  263. BOOL CCreatingKeyDlg::SubmitRequestToAuthority()
  264. {
  265. DWORD err;
  266. BOOL fAnswer = FALSE;
  267. HINSTANCE hLibrary = NULL;
  268. PUCHAR pEncoded;
  269. DWORD cbEncoded = m_pKey->m_cbCertificateRequest;
  270. PUCHAR pResponse;
  271. HRESULT hErr;
  272. LPTSTR szTCert;
  273. CString szRawCert;
  274. BSTR bstrCert = NULL;
  275. BSTR bstrDisposition = NULL;
  276. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)m_pKey->m_pCertificateRequest;
  277. // make sure the header is a valid version (the K2 alpha/beta1 version is no
  278. // longer valid because the interface to the CA server has totally changed.
  279. // specifically we now track GUIDs instead of dll paths
  280. if ( pHeader->Version < REQUEST_HEADER_K2B2VERSION )
  281. {
  282. m_sz_message.LoadString( IDS_CA_ERROR );
  283. AfxMessageBox( IDS_INVALID_CA_REQUEST_OLD );
  284. return FALSE;
  285. }
  286. // initialize the authority object
  287. // prepare the authority object
  288. COnlineAuthority authority;
  289. if ( !authority.FInitSZ(pHeader->chCA) )
  290. {
  291. m_sz_message.LoadString( IDS_CA_ERROR );
  292. AfxMessageBox( IDS_CA_NO_INTERFACE );
  293. return FALSE;
  294. }
  295. // get the previously set up configuration string
  296. BSTR bstrConfig = NULL;
  297. if ( !authority.FGetPropertyString( &bstrConfig ) )
  298. {
  299. m_sz_message.LoadString( IDS_CA_ERROR );
  300. AfxMessageBox( IDS_CA_NO_INTERFACE );
  301. return FALSE;
  302. }
  303. // YES - I HAVE tried to pass this in as binary, but that doesn't seem to work right now.
  304. // generate a base-64 encoded request
  305. DWORD cbReq = m_pKey->m_cbCertificateRequest;
  306. PUCHAR preq = PCreateEncodedRequest( m_pKey->m_pCertificateRequest, &cbReq, FALSE );
  307. preq[cbReq] = 0;
  308. // Great. Now this needs to be unicode.
  309. OLECHAR* poch = NULL;
  310. // get the number of characters in the encoded request, plus some
  311. DWORD cchReq = _tcslen((PCHAR)preq) + 60;
  312. poch = (OLECHAR*)GlobalAlloc( GPTR, cchReq * 2 );
  313. // unicodize the name into the buffer
  314. if ( poch )
  315. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (PCHAR)preq, -1,
  316. poch, cchReq );
  317. // prepare the BSTR containing the request
  318. BSTR bstrRequest = NULL;
  319. bstrRequest = SysAllocString(poch);
  320. // cleanup
  321. GlobalFree( poch );
  322. // prepare the extra attributes string
  323. BSTR bstrAttrib = NULL;
  324. WORD zero = 0;
  325. bstrAttrib = SysAllocString(&zero);
  326. LONG longDisposition;
  327. // if this is the first time for this cert, call the submit method
  328. if ( !pHeader->fWaitingForApproval )
  329. {
  330. // set the flag
  331. pHeader->fReqSentToOnlineCA = TRUE;
  332. // make the call
  333. hErr = authority.pIRequest->Submit(
  334. // CR_IN_BINARY | CR_IN_PKCS10,
  335. CR_IN_BASE64HEADER | CR_IN_PKCS10,
  336. bstrRequest,
  337. bstrAttrib,
  338. bstrConfig,
  339. &longDisposition);
  340. // get the full error message text
  341. authority.pIRequest->GetDispositionMessage( &bstrDisposition );
  342. // get the string out and put it in m_sz_message
  343. BuildAuthErrorMessage( bstrDisposition, hErr );
  344. // no matter what, try to get the request ID
  345. authority.pIRequest->GetRequestId( &pHeader->longRequestID );
  346. }
  347. else
  348. // if it has already been submitted, call the pending method
  349. {
  350. // make the call
  351. hErr = authority.pIRequest->RetrievePending(
  352. pHeader->longRequestID,
  353. bstrConfig,
  354. &longDisposition);
  355. // get the full error message text
  356. authority.pIRequest->GetDispositionMessage( &bstrDisposition );
  357. // get the string out and put it in m_sz_message
  358. BuildAuthErrorMessage( bstrDisposition, hErr );
  359. }
  360. // do the appropriate thing depending on the disposition of the response
  361. switch( longDisposition )
  362. {
  363. case CR_DISP_INCOMPLETE:
  364. case CR_DISP_ERROR:
  365. case CR_DISP_DENIED:
  366. // error message obtained via BuildAuthErrorMessage above
  367. break;
  368. case CR_DISP_UNDER_SUBMISSION:
  369. // we need to try again later
  370. m_sz_message.LoadString( IDS_GRIND_DELAYED );
  371. // set the waiting for response flag
  372. pHeader->fWaitingForApproval = TRUE;
  373. break;
  374. case CR_DISP_ISSUED_OUT_OF_BAND:
  375. case CR_DISP_ISSUED:
  376. // get the certificate
  377. hErr = authority.pIRequest->GetCertificate( CR_OUT_BASE64HEADER, &bstrCert);
  378. if ( FAILED(hErr) )
  379. {
  380. // get the detailed error disposition string - reuse bstrAttrib
  381. authority.pIRequest->GetDispositionMessage( &bstrDisposition );
  382. // get the string out and put it in m_sz_message
  383. BuildAuthErrorMessage( bstrDisposition, hErr );
  384. break;
  385. }
  386. // make sure the "waiting" flag is cleared
  387. pHeader->fWaitingForApproval = FALSE;
  388. // extract the certificate from the bstr
  389. szRawCert = bstrCert;
  390. szTCert = szRawCert.GetBuffer(szRawCert.GetLength()+1);
  391. // great. The last thing left is to uudecode the data we got
  392. uudecode_cert( szTCert, &m_pKey->m_cbCertificate );
  393. //copy it into place
  394. if ( m_pKey->m_pCertificate )
  395. GlobalFree( m_pKey->m_pCertificate );
  396. m_pKey->m_pCertificate = GlobalAlloc( GPTR, m_pKey->m_cbCertificate );
  397. CopyMemory( m_pKey->m_pCertificate, szTCert, m_pKey->m_cbCertificate );
  398. szRawCert.ReleaseBuffer(0);
  399. // tell the key it is done
  400. // success! Let the user know about it
  401. m_sz_message.LoadString( IDS_GRIND_SUCCESS );
  402. // cleanup
  403. fAnswer = TRUE;
  404. break;
  405. };
  406. // clean up all the bstrings
  407. if ( bstrCert ) SysFreeString( bstrCert );
  408. if ( bstrConfig ) SysFreeString( bstrConfig );
  409. if ( bstrRequest ) SysFreeString( bstrRequest );
  410. if ( bstrAttrib ) SysFreeString( bstrAttrib );
  411. if ( bstrDisposition ) SysFreeString( bstrDisposition );
  412. // return the answer
  413. return fAnswer;
  414. }
  415. //------------------------------------------------------------------------------
  416. void CCreatingKeyDlg::BuildAuthErrorMessage( BSTR bstrMesage, HRESULT hErr )
  417. {
  418. // set the header to the message first
  419. m_sz_message.LoadString( IDS_GRIND_ONLINE_FAILURE );
  420. // add the specific message from the certificate authority
  421. if ( bstrMesage )
  422. m_sz_message += bstrMesage;
  423. // get the error code part going too.
  424. CString szErr;
  425. szErr.LoadString( IDS_ERR_GENERIC_ERRCODE );
  426. // put it all together
  427. m_sz_message.Format( "%s%s%x", m_sz_message, szErr, hErr );
  428. }
  429. //------------------------------------------------------------------------------
  430. BOOL CCreatingKeyDlg::WriteRequestToFile()
  431. {
  432. // fill in a admin info structure
  433. ADMIN_INFO info;
  434. info.pName = &m_ppage_User_Info->m_nkui_sz_name;
  435. info.pEmail = &m_ppage_User_Info->m_nkui_sz_email;
  436. info.pPhone = &m_ppage_User_Info->m_nkui_sz_phone;
  437. if ( m_ppage_DN )
  438. {
  439. info.pCommonName = &m_ppage_DN->m_nkdn_sz_CN;
  440. info.pOrgUnit = &m_ppage_DN->m_nkdn_sz_OU;
  441. info.pOrg = &m_ppage_DN->m_nkdn_sz_O;
  442. info.pLocality = &m_ppage_DN2->m_nkdn2_sz_L;
  443. info.pState = &m_ppage_DN2->m_nkdn2_sz_S;
  444. info.pCountry = &m_ppage_DN2->m_nkdn2_sz_C;
  445. }
  446. else
  447. {
  448. info.pCommonName = NULL;
  449. info.pOrgUnit = NULL;
  450. info.pOrg = NULL;
  451. info.pLocality = NULL;
  452. info.pState = NULL;
  453. info.pCountry = NULL;
  454. }
  455. // tell the key to write itself out to the disk
  456. if ( !m_pKey->FOutputRequestFile( m_ppage_Choose_CA->m_nkca_sz_file, FALSE, &info ) )
  457. return FALSE;
  458. // tell the user its there
  459. m_sz_message.LoadString( IDS_GRIND_FILE );
  460. m_sz_message += m_ppage_Choose_CA->m_nkca_sz_file;
  461. // success
  462. return TRUE;
  463. }
  464. //------------------------------------------------------------------------------
  465. BOOL CCreatingKeyDlg::FGenerateKeyPair()
  466. {
  467. BOOL fSuccess = FALSE;
  468. CString szDistinguishedName;
  469. SSL_CREDENTIAL_CERTIFICATE certs;
  470. LPTSTR pSzDN, pSzPassword;
  471. BOOL fAddComma = FALSE;
  472. // generate the distinguished name string
  473. try
  474. {
  475. szDistinguishedName.Empty();
  476. // we should never put an empty parameter in the list
  477. // start with the country code
  478. if ( !m_ppage_DN2->m_nkdn2_sz_C.IsEmpty() )
  479. {
  480. szDistinguishedName = SZ_KEY_COUNTRY;
  481. szDistinguishedName += m_ppage_DN2->m_nkdn2_sz_C;
  482. fAddComma = TRUE;
  483. }
  484. // now add on the state/province
  485. if ( !m_ppage_DN2->m_nkdn2_sz_S.IsEmpty() )
  486. {
  487. if ( fAddComma )
  488. szDistinguishedName += ",";
  489. szDistinguishedName += SZ_KEY_STATE;
  490. szDistinguishedName += m_ppage_DN2->m_nkdn2_sz_S;
  491. fAddComma = TRUE;
  492. }
  493. // now add on the locality
  494. if ( !m_ppage_DN2->m_nkdn2_sz_L.IsEmpty() )
  495. {
  496. if ( fAddComma )
  497. szDistinguishedName += ",";
  498. szDistinguishedName += SZ_KEY_LOCALITY;
  499. szDistinguishedName += m_ppage_DN2->m_nkdn2_sz_L;
  500. fAddComma = TRUE;
  501. }
  502. // now add on the organization
  503. if ( !m_ppage_DN->m_nkdn_sz_O.IsEmpty() )
  504. {
  505. if ( fAddComma )
  506. szDistinguishedName += ",";
  507. szDistinguishedName += SZ_KEY_ORGANIZATION;
  508. szDistinguishedName += m_ppage_DN->m_nkdn_sz_O;
  509. fAddComma = TRUE;
  510. }
  511. // now add on the organizational unit (optional)
  512. if ( !m_ppage_DN->m_nkdn_sz_OU.IsEmpty() )
  513. {
  514. if ( fAddComma )
  515. szDistinguishedName += ",";
  516. szDistinguishedName += SZ_KEY_ORGUNIT;
  517. szDistinguishedName += m_ppage_DN->m_nkdn_sz_OU;
  518. fAddComma = TRUE;
  519. }
  520. // now add on the common name (netaddress)
  521. if ( !m_ppage_DN->m_nkdn_sz_CN.IsEmpty() )
  522. {
  523. if ( fAddComma )
  524. szDistinguishedName += ",";
  525. szDistinguishedName += SZ_KEY_COMNAME;
  526. szDistinguishedName += m_ppage_DN->m_nkdn_sz_CN;
  527. fAddComma = TRUE;
  528. }
  529. }
  530. catch( CException e )
  531. {
  532. return FALSE;
  533. }
  534. // prep the strings - we need a pointer to the data
  535. pSzDN = szDistinguishedName.GetBuffer( szDistinguishedName.GetLength()+2 );
  536. pSzPassword = m_ppage_Key_Info->m_nkki_sz_password.GetBuffer(
  537. m_ppage_Key_Info->m_nkki_sz_password.GetLength()+2 );
  538. // zero out the certs
  539. ZeroMemory( &certs, sizeof(certs) );
  540. // generate the key pair
  541. fSuccess = SslGenerateKeyPair( &certs, pSzDN, pSzPassword, m_ppage_Key_Info->m_nBits );
  542. // release the string buffers
  543. m_ppage_Key_Info->m_nkki_sz_password.ReleaseBuffer( -1 );
  544. szDistinguishedName.ReleaseBuffer( -1 );
  545. // if generating the key pair failed, leave now
  546. if ( !fSuccess )
  547. {
  548. return FALSE;
  549. }
  550. // store away the cert and the key
  551. m_cbPrivateKey = certs.cbPrivateKey;
  552. m_pPrivateKey = certs.pPrivateKey;
  553. m_cbCertificateRequest = certs.cbCertificate;
  554. m_pCertificateRequest = certs.pCertificate;
  555. // return the success flag
  556. return fSuccess;
  557. }