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.

1769 lines
48 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File: gencert.cpp
  6. //
  7. // Contents:
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #include "pch.cpp"
  13. #include "misc.h"
  14. #include "utils.h"
  15. #include "gencert.h"
  16. #include "globals.h"
  17. #ifndef UNICODE
  18. const DWORD dwCertRdnValueType = CERT_RDN_PRINTABLE_STRING;
  19. #else
  20. const DWORD dwCertRdnValueType = CERT_RDN_UNICODE_STRING;
  21. #endif
  22. #ifndef CertStrToName
  23. //
  24. // Function prototype not found in wincrypt.h or anywhere but
  25. // is in crypt32.lib
  26. //
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. BOOL WINAPI
  31. CertStrToNameA(
  32. DWORD dwCertEncodingType, // in
  33. LPCSTR pszX500, // in
  34. DWORD dwStrType, // in
  35. void* pvReserved, // in, optional
  36. BYTE* pbEncoded, // out
  37. DWORD* pcbEncoded, // in/out
  38. LPCSTR* ppszError // out, optional
  39. );
  40. CertStrToNameW(
  41. DWORD dwCertEncodingType, // in
  42. LPCWSTR pszX500, // in
  43. DWORD dwStrType, // in
  44. void* pvReserved, // in, optional
  45. BYTE* pbEncoded, // out
  46. DWORD* pcbEncoded, // in/out
  47. LPCWSTR* ppszError // out, optional
  48. );
  49. #ifdef UNICODE
  50. #define CertStrToName CertStrToNameW
  51. #else
  52. #define CertStrToName CertStrToNameA
  53. #endif
  54. #ifdef __cplusplus
  55. }
  56. #endif
  57. #endif
  58. /*******************************************************************************************
  59. Function:
  60. LSEncryptBase64EncodeHWID()
  61. Description:
  62. Encrypt using license server private key then base64 encode the hardware ID
  63. Arguments:
  64. IN PHWID - pointer to HWID to be encrypt/encoded
  65. OUT DWORD* cbBase64EncodeHwid - size of pointer to encrypted/encoded string
  66. OUT PBYTE* szBase64EncodeHwid - Pointer to encrypted/encoded string.
  67. Returns:
  68. TRUE if successful, FALSE otherwise, call GetLastError() for detail.
  69. *******************************************************************************************/
  70. BOOL
  71. TLSEncryptBase64EncodeHWID(
  72. PHWID pHwid,
  73. DWORD* cbBase64EncodeHwid,
  74. PBYTE* szBase64EncodeHwid
  75. )
  76. {
  77. DWORD status=ERROR_SUCCESS;
  78. //
  79. // Encrypt HWID
  80. //
  81. BYTE tmp_pbEncryptedHwid[sizeof(HWID)*2+2];
  82. DWORD tmp_cbEncryptedHwid=sizeof(tmp_pbEncryptedHwid);
  83. do {
  84. memset(tmp_pbEncryptedHwid, 0, sizeof(tmp_pbEncryptedHwid));
  85. if((status=LicenseEncryptHwid(
  86. pHwid,
  87. &tmp_cbEncryptedHwid,
  88. tmp_pbEncryptedHwid,
  89. g_cbSecretKey,
  90. g_pbSecretKey) != LICENSE_STATUS_OK))
  91. {
  92. break;
  93. }
  94. //
  95. // BASE64 Encode Encrypted HWID - printable char. string
  96. //
  97. if((status=LSBase64Encode(
  98. tmp_pbEncryptedHwid,
  99. tmp_cbEncryptedHwid,
  100. NULL,
  101. cbBase64EncodeHwid)) != ERROR_SUCCESS)
  102. {
  103. break;
  104. }
  105. *szBase64EncodeHwid=(PBYTE)AllocateMemory(*cbBase64EncodeHwid*(sizeof(TCHAR)+1));
  106. if(*szBase64EncodeHwid == NULL)
  107. {
  108. SetLastError(status = ERROR_OUTOFMEMORY);
  109. break;
  110. }
  111. // base64 encoding
  112. status=LSBase64Encode(
  113. tmp_pbEncryptedHwid,
  114. tmp_cbEncryptedHwid,
  115. (TCHAR *)*szBase64EncodeHwid,
  116. cbBase64EncodeHwid);
  117. } while(FALSE);
  118. return status == ERROR_SUCCESS;
  119. }
  120. /*******************************************************************************************/
  121. DWORD
  122. TLSAddCertAuthorityInfoAccess(
  123. LPTSTR szIssuerDnsName,
  124. PCERT_EXTENSION pExtension
  125. )
  126. /*
  127. */
  128. {
  129. LSCERT_AUTHORITY_INFO_ACCESS certInfoAccess;
  130. LSCERT_ACCESS_DESCRIPTION certAcccessDesc;
  131. certAcccessDesc.pszAccessMethod=szOID_X509_ACCESS_PKIX_OCSP;
  132. certAcccessDesc.AccessLocation.dwAltNameChoice = LSCERT_ALT_NAME_DNS_NAME;
  133. certAcccessDesc.AccessLocation.pwszDNSName = szIssuerDnsName;
  134. certInfoAccess.cAccDescr = 1;
  135. certInfoAccess.rgAccDescr = &certAcccessDesc;
  136. pExtension->pszObjId = szOID_X509_AUTHORITY_ACCESS_INFO;
  137. pExtension->fCritical = TRUE;
  138. return TLSCryptEncodeObject(
  139. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  140. szOID_X509_AUTHORITY_ACCESS_INFO,
  141. &certInfoAccess,
  142. &pExtension->Value.pbData,
  143. &pExtension->Value.cbData
  144. );
  145. }
  146. ///////////////////////////////////////////////////////////////////////////////
  147. DWORD
  148. TLSAddCertAuthorityKeyIdExtension(
  149. LPTSTR szIssuer,
  150. ULARGE_INTEGER* CertSerialNumber,
  151. PCERT_EXTENSION pExtension
  152. )
  153. /*
  154. */
  155. {
  156. //
  157. // Use CERT_AUTHORITY_KEY_ID2_INFO
  158. // some structure not defined in SP3's wincrypt.h
  159. //
  160. LSCERT_ALT_NAME_ENTRY certAltNameEntry;
  161. LSCERT_AUTHORITY_KEY_ID2_INFO authKeyId2Info;
  162. memset(&authKeyId2Info, 0, sizeof(authKeyId2Info));
  163. authKeyId2Info.AuthorityCertSerialNumber.cbData = sizeof(ULARGE_INTEGER);
  164. authKeyId2Info.AuthorityCertSerialNumber.pbData = (PBYTE)CertSerialNumber;
  165. memset(&certAltNameEntry, 0, sizeof(certAltNameEntry));
  166. certAltNameEntry.dwAltNameChoice=CERT_ALT_NAME_DIRECTORY_NAME; //LSCERT_ALT_NAME_RFC822_NAME;
  167. certAltNameEntry.DirectoryName.cbData = (_tcslen(szIssuer) + 1) * sizeof(TCHAR);
  168. certAltNameEntry.DirectoryName.pbData = (PBYTE)szIssuer;
  169. authKeyId2Info.AuthorityCertIssuer.cAltEntry=1;
  170. authKeyId2Info.AuthorityCertIssuer.rgAltEntry=&certAltNameEntry;
  171. pExtension->pszObjId = szOID_X509_AUTHORITY_KEY_ID2;
  172. pExtension->fCritical = TRUE;
  173. return TLSCryptEncodeObject(
  174. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  175. szOID_X509_AUTHORITY_KEY_ID2,
  176. &authKeyId2Info,
  177. &pExtension->Value.pbData,
  178. &pExtension->Value.cbData
  179. );
  180. }
  181. ///////////////////////////////////////////////////////////////////////////////
  182. DWORD
  183. TLSExportPublicKey(
  184. IN HCRYPTPROV hCryptProv,
  185. IN DWORD dwKeyType,
  186. IN OUT PDWORD pcbByte,
  187. IN OUT PCERT_PUBLIC_KEY_INFO *ppbByte
  188. )
  189. /*
  190. */
  191. {
  192. BOOL bRetCode=TRUE;
  193. *pcbByte=0;
  194. *ppbByte=NULL;
  195. bRetCode = CryptExportPublicKeyInfo(
  196. hCryptProv,
  197. dwKeyType,
  198. X509_ASN_ENCODING,
  199. NULL,
  200. pcbByte);
  201. if(bRetCode == FALSE)
  202. goto cleanup;
  203. if((*ppbByte=(PCERT_PUBLIC_KEY_INFO)AllocateMemory(*pcbByte)) == NULL)
  204. {
  205. bRetCode = FALSE;
  206. goto cleanup;
  207. }
  208. bRetCode = CryptExportPublicKeyInfo(
  209. hCryptProv,
  210. dwKeyType,
  211. X509_ASN_ENCODING,
  212. *ppbByte,
  213. pcbByte);
  214. if(bRetCode == FALSE)
  215. {
  216. FreeMemory(*ppbByte);
  217. *pcbByte = 0;
  218. }
  219. cleanup:
  220. return (bRetCode) ? ERROR_SUCCESS : GetLastError();
  221. }
  222. ///////////////////////////////////////////////////////////////////////////////
  223. DWORD
  224. TLSCryptEncodeObject(
  225. IN DWORD dwEncodingType,
  226. IN LPCSTR lpszStructType,
  227. IN const void * pvStructInfo,
  228. OUT PBYTE* ppbEncoded,
  229. OUT DWORD* pcbEncoded
  230. )
  231. /*
  232. Description:
  233. Allocate memory and encode object, wrapper for CryptEncodeObject()
  234. */
  235. {
  236. DWORD dwStatus = ERROR_SUCCESS;
  237. if(!CryptEncodeObject(dwEncodingType, lpszStructType, pvStructInfo, NULL, pcbEncoded) ||
  238. (*ppbEncoded=(PBYTE)AllocateMemory(*pcbEncoded)) == NULL ||
  239. !CryptEncodeObject(dwEncodingType, lpszStructType, pvStructInfo, *ppbEncoded, pcbEncoded))
  240. {
  241. dwStatus=GetLastError();
  242. }
  243. return dwStatus;
  244. }
  245. //////////////////////////////////////////////////////////////////////
  246. DWORD
  247. TLSCryptSignAndEncodeCertificate(
  248. IN HCRYPTPROV hCryptProv,
  249. IN DWORD dwKeySpec,
  250. IN PCERT_INFO pCertInfo,
  251. IN PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
  252. IN OUT PBYTE* ppbEncodedCert,
  253. IN OUT PDWORD pcbEncodedCert
  254. )
  255. /*
  256. */
  257. {
  258. BOOL bRetCode;
  259. bRetCode = CryptSignAndEncodeCertificate(
  260. hCryptProv,
  261. dwKeySpec,
  262. X509_ASN_ENCODING,
  263. X509_CERT_TO_BE_SIGNED,
  264. pCertInfo,
  265. pSignatureAlgorithm,
  266. NULL,
  267. NULL,
  268. pcbEncodedCert);
  269. if(bRetCode == FALSE && GetLastError() != ERROR_MORE_DATA)
  270. goto cleanup;
  271. *ppbEncodedCert=(PBYTE)AllocateMemory(*pcbEncodedCert);
  272. if(*ppbEncodedCert == FALSE)
  273. goto cleanup;
  274. bRetCode = CryptSignAndEncodeCertificate(
  275. hCryptProv,
  276. AT_SIGNATURE,
  277. X509_ASN_ENCODING,
  278. X509_CERT_TO_BE_SIGNED,
  279. pCertInfo,
  280. pSignatureAlgorithm,
  281. NULL,
  282. *ppbEncodedCert,
  283. pcbEncodedCert);
  284. if(bRetCode == FALSE)
  285. {
  286. FreeMemory(*ppbEncodedCert);
  287. *pcbEncodedCert = 0;
  288. }
  289. cleanup:
  290. return (bRetCode) ? ERROR_SUCCESS : GetLastError();
  291. }
  292. ////////////////////////////////////////////////////////////////////////
  293. #define MAX_NUM_CERT_BLOBS 200 // actually, we can't go over 10.
  294. DWORD
  295. TLSVerifyProprietyChainedCertificate(
  296. HCRYPTPROV hCryptProv,
  297. PBYTE pbCert,
  298. DWORD cbCert
  299. )
  300. /*++
  301. --*/
  302. {
  303. DWORD dwStatus=ERROR_SUCCESS;
  304. PCert_Chain pCertChain = (PCert_Chain)pbCert;
  305. UNALIGNED Cert_Blob *pCertificate = NULL;
  306. PCCERT_CONTEXT pIssuerCert = NULL;
  307. PCCERT_CONTEXT pSubjectCert = NULL;
  308. DWORD dwVerifyFlag = CERT_DATE_DONT_VALIDATE;
  309. int i;
  310. if( pCertChain == NULL || cbCert <= 0 ||
  311. MAX_CERT_CHAIN_VERSION < GET_CERTIFICATE_VERSION(pCertChain->dwVersion) ||
  312. pCertChain->dwNumCertBlobs > MAX_NUM_CERT_BLOBS ||
  313. pCertChain->dwNumCertBlobs <= 1 ) // must have at least two certificates
  314. {
  315. SetLastError(dwStatus = TLS_E_INVALID_DATA);
  316. return dwStatus;
  317. }
  318. //
  319. // Verify input data before actually allocate memory
  320. //
  321. pCertificate = (PCert_Blob)&(pCertChain->CertBlob[0]);
  322. for(i=0; i < pCertChain->dwNumCertBlobs; i++)
  323. {
  324. if (((PBYTE)pCertificate > (cbCert + pbCert - sizeof(Cert_Blob))) ||
  325. (pCertificate->cbCert == 0) ||
  326. (pCertificate->cbCert > (DWORD)((pbCert + cbCert) - pCertificate->abCert)))
  327. {
  328. return (LICENSE_STATUS_INVALID_INPUT);
  329. }
  330. pCertificate = (PCert_Blob)(pCertificate->abCert + pCertificate->cbCert);
  331. }
  332. //
  333. // First certificate is root certificate
  334. //
  335. pCertificate = (PCert_Blob)&(pCertChain->CertBlob[0]);
  336. pIssuerCert = CertCreateCertificateContext(
  337. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  338. &(pCertificate->abCert[0]),
  339. pCertificate->cbCert
  340. );
  341. if(pIssuerCert == NULL)
  342. {
  343. dwStatus = GetLastError(); // just for debugging.
  344. goto cleanup;
  345. }
  346. dwStatus = ERROR_SUCCESS;
  347. pSubjectCert = CertDuplicateCertificateContext(pIssuerCert);
  348. for(i=0; i < pCertChain->dwNumCertBlobs; i++)
  349. {
  350. if(pSubjectCert == NULL)
  351. {
  352. dwStatus = GetLastError();
  353. break;
  354. }
  355. //
  356. // verify subject's certificate
  357. dwVerifyFlag = CERT_STORE_SIGNATURE_FLAG;
  358. if(CertVerifySubjectCertificateContext(
  359. pSubjectCert,
  360. pIssuerCert,
  361. &dwVerifyFlag
  362. ) == FALSE)
  363. {
  364. dwStatus = GetLastError();
  365. break;
  366. }
  367. if(dwVerifyFlag != 0)
  368. {
  369. // signature verification failed.
  370. dwStatus = TLS_E_INVALID_DATA;
  371. break;
  372. }
  373. if(CertFreeCertificateContext(pIssuerCert) == FALSE)
  374. {
  375. dwStatus = GetLastError();
  376. break;
  377. }
  378. pIssuerCert = pSubjectCert;
  379. pCertificate = (PCert_Blob)(pCertificate->abCert + pCertificate->cbCert);
  380. pSubjectCert = CertCreateCertificateContext(
  381. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  382. &(pCertificate->abCert[0]),
  383. pCertificate->cbCert
  384. );
  385. }
  386. cleanup:
  387. if(pSubjectCert != NULL)
  388. {
  389. CertFreeCertificateContext(pSubjectCert);
  390. }
  391. if(pIssuerCert != NULL)
  392. {
  393. CertFreeCertificateContext(pIssuerCert);
  394. }
  395. return dwStatus;
  396. }
  397. ////////////////////////////////////////////////////////////////////////
  398. BOOL IsHydraClientCertficate( PCERT_INFO pCertInfo )
  399. {
  400. CERT_EXTENSION UNALIGNED * pCertExtension=pCertInfo->rgExtension;
  401. DWORD dwVersion = TERMSERV_CERT_VERSION_UNKNOWN;
  402. DWORD UNALIGNED * pdwVersion;
  403. for(DWORD i=0; i < pCertInfo->cExtension; i++, pCertExtension++)
  404. {
  405. if(strcmp(pCertExtension->pszObjId, szOID_PKIX_HYDRA_CERT_VERSION) == 0)
  406. {
  407. pdwVersion = (DWORD UNALIGNED *) pCertExtension->Value.pbData;
  408. if(pCertExtension->Value.cbData == sizeof(DWORD) &&
  409. *pdwVersion <= TERMSERV_CERT_VERSION_CURRENT)
  410. {
  411. dwVersion = *pdwVersion;
  412. break;
  413. }
  414. }
  415. }
  416. return (dwVersion == TERMSERV_CERT_VERSION_UNKNOWN) ? FALSE : TRUE;
  417. }
  418. ////////////////////////////////////////////////////////////////////////
  419. DWORD
  420. ChainProprietyCert(
  421. HCRYPTPROV hCryptProv,
  422. HCERTSTORE hCertStore,
  423. PCCERT_CONTEXT pCertContext,
  424. PCert_Chain pCertChain,
  425. DWORD* dwCertOffset,
  426. DWORD dwBufSize)
  427. {
  428. DWORD dwStatus = ERROR_SUCCESS;
  429. DWORD dwFlags;
  430. PCCERT_CONTEXT pCertIssuer=NULL;
  431. pCertIssuer=NULL;
  432. dwFlags = CERT_STORE_SIGNATURE_FLAG;
  433. //
  434. // Get the issuer's certificate from store
  435. //
  436. pCertIssuer = CertGetIssuerCertificateFromStore(
  437. hCertStore,
  438. pCertContext,
  439. pCertIssuer,
  440. &dwFlags
  441. );
  442. if(pCertIssuer != NULL)
  443. {
  444. if(dwFlags & CERT_STORE_SIGNATURE_FLAG)
  445. {
  446. // invalid signature
  447. dwStatus = TLS_E_INVALID_DATA;
  448. }
  449. else
  450. {
  451. //
  452. // Recursively find the issuer of the issuer's certificate
  453. //
  454. dwStatus = ChainProprietyCert(
  455. hCryptProv,
  456. hCertStore,
  457. pCertIssuer,
  458. pCertChain,
  459. dwCertOffset,
  460. dwBufSize
  461. );
  462. }
  463. }
  464. else
  465. {
  466. dwStatus = GetLastError();
  467. if(dwStatus != CRYPT_E_SELF_SIGNED)
  468. {
  469. goto cleanup;
  470. }
  471. //
  472. // Verify issuer's certificate
  473. //
  474. if(CryptVerifyCertificateSignature(
  475. hCryptProv,
  476. X509_ASN_ENCODING,
  477. pCertContext->pbCertEncoded,
  478. pCertContext->cbCertEncoded,
  479. &pCertContext->pCertInfo->SubjectPublicKeyInfo))
  480. {
  481. dwStatus=ERROR_SUCCESS;
  482. }
  483. }
  484. if(dwStatus == ERROR_SUCCESS)
  485. {
  486. //
  487. // Push certificate into propriety certificate chain
  488. //
  489. if((*dwCertOffset + pCertContext->cbCertEncoded) >= dwBufSize)
  490. {
  491. dwStatus = ERROR_MORE_DATA;
  492. goto cleanup;
  493. }
  494. (pCertChain->dwNumCertBlobs)++;
  495. UNALIGNED Cert_Blob *pCertBlob = (PCert_Blob)((PBYTE)&(pCertChain->CertBlob) + *dwCertOffset);
  496. pCertBlob->cbCert = pCertContext->cbCertEncoded;
  497. memcpy( &(pCertBlob->abCert),
  498. pCertContext->pbCertEncoded,
  499. pCertContext->cbCertEncoded);
  500. *dwCertOffset += (sizeof(pCertBlob->cbCert) + pCertContext->cbCertEncoded);
  501. }
  502. cleanup:
  503. if(pCertIssuer != NULL)
  504. {
  505. CertFreeCertificateContext(pCertIssuer);
  506. }
  507. return dwStatus;
  508. }
  509. ////////////////////////////////////////////////////////////////////////
  510. DWORD
  511. TLSChainProprietyCertificate(
  512. HCRYPTPROV hCryptProv,
  513. BOOL bTemp,
  514. PBYTE pbLicense,
  515. DWORD cbLicense,
  516. PBYTE* pbChained,
  517. DWORD* cbChained
  518. )
  519. {
  520. HCERTSTORE hCertStore=NULL;
  521. DWORD dwStatus=ERROR_SUCCESS;
  522. CRYPT_DATA_BLOB Serialized;
  523. PCCERT_CONTEXT pCertContext=NULL;
  524. PCCERT_CONTEXT pPrevCertContext=NULL;
  525. PCERT_INFO pCertInfo;
  526. BOOL bFound=FALSE;
  527. Serialized.pbData = pbLicense;
  528. Serialized.cbData = cbLicense;
  529. DWORD dwCertOffset = 0;
  530. PCert_Chain pCertChain;
  531. DWORD numCerts=0;
  532. DWORD cbSize=0;
  533. if(hCryptProv == NULL)
  534. {
  535. SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
  536. goto cleanup;
  537. }
  538. hCertStore=CertOpenStore(
  539. sz_CERT_STORE_PROV_PKCS7,
  540. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  541. hCryptProv,
  542. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  543. &Serialized
  544. );
  545. if(!hCertStore)
  546. {
  547. dwStatus=GetLastError();
  548. goto cleanup;
  549. }
  550. //
  551. // Get number of certificate and estimated size first - save memory
  552. //
  553. do {
  554. pCertContext = CertEnumCertificatesInStore(
  555. hCertStore,
  556. pPrevCertContext
  557. );
  558. if(pCertContext == NULL)
  559. {
  560. dwStatus = GetLastError();
  561. if(dwStatus != CRYPT_E_NOT_FOUND)
  562. goto cleanup;
  563. dwStatus = ERROR_SUCCESS;
  564. break;
  565. }
  566. numCerts++;
  567. cbSize += pCertContext->cbCertEncoded;
  568. pPrevCertContext = pCertContext;
  569. } while(TRUE);
  570. *cbChained = cbSize + numCerts * sizeof(Cert_Blob) + sizeof(Cert_Chain);
  571. //
  572. // Allocate memory for our propriety certificate chain
  573. //
  574. pCertChain=(PCert_Chain)LocalAlloc(LPTR, *cbChained);
  575. if(pCertChain == NULL)
  576. {
  577. dwStatus = GetLastError();
  578. goto cleanup;
  579. }
  580. pCertChain->dwVersion = CERT_CHAIN_VERSION_2 | ((bTemp) ? 0x80000000 : 0);
  581. //
  582. // Enumerate license in certificate to find actual client license.
  583. //
  584. pPrevCertContext = NULL;
  585. do {
  586. pCertContext=CertEnumCertificatesInStore(hCertStore, pPrevCertContext);
  587. if(pCertContext == NULL)
  588. {
  589. // end certificate in store or error
  590. if((dwStatus=GetLastError()) != CRYPT_E_NOT_FOUND)
  591. goto cleanup;
  592. dwStatus = ERROR_SUCCESS;
  593. break;
  594. }
  595. pPrevCertContext = pCertContext;
  596. if(IsHydraClientCertficate(pCertContext->pCertInfo))
  597. {
  598. bFound = TRUE;
  599. }
  600. } while(bFound == FALSE);
  601. if(bFound == FALSE)
  602. {
  603. dwStatus = ERROR_INVALID_PARAMETER;
  604. goto cleanup;
  605. }
  606. //
  607. // Recusively chain certificate in backward.
  608. //
  609. dwStatus = ChainProprietyCert(
  610. hCryptProv,
  611. hCertStore,
  612. pCertContext,
  613. pCertChain,
  614. &dwCertOffset,
  615. *cbChained);
  616. *pbChained = (PBYTE)pCertChain;
  617. cleanup:
  618. if(hCertStore)
  619. CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
  620. return dwStatus;
  621. }
  622. ///////////////////////////////////////////////////////////////////////////////
  623. DWORD
  624. TLSCertSetCertRdnStr(
  625. IN OUT CERT_NAME_BLOB* pCertNameBlob,
  626. IN LPTSTR szRdn
  627. )
  628. /*
  629. Abstract:
  630. Add RDN into certificate
  631. Parameter:
  632. pCertNameBlob -
  633. szRdn - RDN to be added, see CertStrToName() for help
  634. Returns:
  635. ERROR_INVALID_PARAMETER
  636. Memory allocation failed.
  637. Error returns from CertStrToName()
  638. */
  639. {
  640. if(pCertNameBlob == NULL)
  641. return ERROR_INVALID_PARAMETER;
  642. BOOL bRetCode=TRUE;
  643. bRetCode = CertStrToName(
  644. X509_ASN_ENCODING,
  645. szRdn,
  646. CERT_X500_NAME_STR | CERT_SIMPLE_NAME_STR,
  647. NULL,
  648. pCertNameBlob->pbData,
  649. &pCertNameBlob->cbData,
  650. NULL
  651. );
  652. if(bRetCode != TRUE)
  653. goto cleanup;
  654. pCertNameBlob->pbData = (PBYTE)AllocateMemory(pCertNameBlob->cbData);
  655. if(pCertNameBlob->pbData == NULL)
  656. goto cleanup;
  657. bRetCode = CertStrToName(
  658. X509_ASN_ENCODING,
  659. szRdn,
  660. CERT_X500_NAME_STR | CERT_SIMPLE_NAME_STR,
  661. NULL,
  662. pCertNameBlob->pbData,
  663. &pCertNameBlob->cbData,
  664. NULL
  665. );
  666. cleanup:
  667. return (bRetCode) ? ERROR_SUCCESS : GetLastError();
  668. }
  669. ///////////////////////////////////////////////////////////////////////////////
  670. DWORD
  671. TLSCertSetCertRdnName(
  672. IN OUT CERT_NAME_BLOB* pCertNameBlob,
  673. IN CERT_NAME_INFO* pRdn
  674. )
  675. /*
  676. Abstract:
  677. Add RDN into certificate
  678. Parameters:
  679. pCertNameBlob -
  680. pRdn -
  681. Returns
  682. ERROR_INVALID_PARAMETER
  683. Error code from CryptEncodeObject()
  684. Memory allocation fail.
  685. */
  686. {
  687. if(pCertNameBlob == NULL || pRdn == NULL)
  688. return ERROR_INVALID_PARAMETER;
  689. //
  690. // CertStrToName() not defined in SP3 build environment
  691. //
  692. return TLSCryptEncodeObject(
  693. CRYPT_ASN_ENCODING,
  694. X509_NAME,
  695. pRdn,
  696. &pCertNameBlob->pbData,
  697. &pCertNameBlob->cbData
  698. );
  699. }
  700. //////////////////////////////////////////////////////////////////////////
  701. DWORD
  702. TLSSetCertRdn(
  703. PCERT_NAME_BLOB pCertNameBlob,
  704. PTLSClientCertRDN pLsCertRdn
  705. )
  706. /*
  707. */
  708. {
  709. DWORD dwStatus=ERROR_SUCCESS;
  710. switch(pLsCertRdn->type)
  711. {
  712. case LSCERT_RDN_STRING_TYPE:
  713. dwStatus = TLSCertSetCertRdnStr(
  714. pCertNameBlob,
  715. pLsCertRdn->szRdn
  716. );
  717. break;
  718. case LSCERT_RDN_NAME_INFO_TYPE:
  719. dwStatus = TLSCertSetCertRdnName(
  720. pCertNameBlob,
  721. pLsCertRdn->pCertNameInfo
  722. );
  723. break;
  724. case LSCERT_RDN_NAME_BLOB_TYPE:
  725. *pCertNameBlob = *pLsCertRdn->pNameBlob;
  726. break;
  727. case LSCERT_CLIENT_INFO_TYPE:
  728. {
  729. PBYTE szBase64EncodeHwid=NULL;
  730. DWORD cbBase64EncodeHwid=0;
  731. if(!TLSEncryptBase64EncodeHWID(
  732. pLsCertRdn->ClientInfo.pClientID,
  733. &cbBase64EncodeHwid,
  734. &szBase64EncodeHwid))
  735. {
  736. TLSLogEvent(
  737. EVENTLOG_ERROR_TYPE,
  738. TLS_E_GENERATECLIENTELICENSE,
  739. dwStatus=TLS_E_ENCRYPTHWID,
  740. GetLastError()
  741. );
  742. break;
  743. }
  744. CERT_RDN_ATTR rgNameAttr[] = {
  745. {
  746. OID_SUBJECT_CLIENT_COMPUTERNAME,
  747. dwCertRdnValueType,
  748. _tcslen(pLsCertRdn->ClientInfo.szMachineName) * sizeof(TCHAR),
  749. (UCHAR *)pLsCertRdn->ClientInfo.szMachineName
  750. },
  751. {
  752. OID_SUBJECT_CLIENT_USERNAME,
  753. dwCertRdnValueType,
  754. _tcslen(pLsCertRdn->ClientInfo.szUserName) * sizeof(TCHAR),
  755. (UCHAR *)pLsCertRdn->ClientInfo.szUserName
  756. },
  757. {
  758. OID_SUBJECT_CLIENT_HWID,
  759. dwCertRdnValueType,
  760. cbBase64EncodeHwid*sizeof(TCHAR),
  761. (UCHAR *)szBase64EncodeHwid
  762. }
  763. };
  764. CERT_RDN rgRDN[] = {
  765. sizeof(rgNameAttr)/sizeof(rgNameAttr[0]),
  766. &rgNameAttr[0]
  767. };
  768. CERT_NAME_INFO Name = {1, rgRDN};
  769. dwStatus = TLSCertSetCertRdnName(
  770. pCertNameBlob,
  771. &Name
  772. );
  773. FreeMemory(szBase64EncodeHwid);
  774. }
  775. break;
  776. default:
  777. dwStatus = ERROR_INVALID_PARAMETER;
  778. }
  779. return dwStatus;
  780. }
  781. //////////////////////////////////////////////////////////////////////////
  782. DWORD
  783. TLSGenerateCertificate(
  784. HCRYPTPROV hCryptProv,
  785. DWORD dwKeySpec,
  786. ULARGE_INTEGER* pCertSerialNumber,
  787. PTLSClientCertRDN pCertIssuer,
  788. PTLSClientCertRDN pCertSubject,
  789. FILETIME* ftNotBefore,
  790. FILETIME* ftNotAfter,
  791. PCERT_PUBLIC_KEY_INFO pSubjectPublicKey,
  792. DWORD dwNumExtensions,
  793. PCERT_EXTENSION pCertExtensions,
  794. PDWORD pcbEncodedCert,
  795. PBYTE* ppbEncodedCert
  796. )
  797. /*
  798. */
  799. {
  800. DWORD dwStatus=ERROR_SUCCESS;
  801. CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm={ szOID_OIWSEC_sha1RSASign, 0, 0 };
  802. CERT_INFO CertInfo;
  803. PCERT_PUBLIC_KEY_INFO pbPublicKeyInfo=NULL;
  804. DWORD cbPublicKeyInfo=0;
  805. memset(&CertInfo, 0, sizeof(CERT_INFO));
  806. CertInfo.dwVersion = CERT_V3;
  807. CertInfo.SerialNumber.cbData = sizeof(*pCertSerialNumber);
  808. CertInfo.SerialNumber.pbData = (PBYTE)pCertSerialNumber;
  809. CertInfo.SignatureAlgorithm = SignatureAlgorithm;
  810. dwStatus = TLSSetCertRdn(
  811. &CertInfo.Issuer,
  812. pCertIssuer
  813. );
  814. if(dwStatus != ERROR_SUCCESS)
  815. {
  816. TLSLogEvent(
  817. EVENTLOG_ERROR_TYPE,
  818. TLS_E_GENERATECLIENTELICENSE,
  819. TLS_E_SETCERTISSUER,
  820. dwStatus
  821. );
  822. goto cleanup;
  823. }
  824. CertInfo.NotBefore = *ftNotBefore;
  825. CertInfo.NotAfter = *ftNotAfter;
  826. dwStatus = TLSSetCertRdn(
  827. &CertInfo.Subject,
  828. pCertSubject
  829. );
  830. if(dwStatus != ERROR_SUCCESS)
  831. {
  832. TLSLogEvent(
  833. EVENTLOG_ERROR_TYPE,
  834. TLS_E_GENERATECLIENTELICENSE,
  835. TLS_E_SETCERTSUBJECT,
  836. dwStatus
  837. );
  838. goto cleanup;
  839. }
  840. if(pSubjectPublicKey)
  841. {
  842. CertInfo.SubjectPublicKeyInfo = *pSubjectPublicKey;
  843. }
  844. else
  845. {
  846. dwStatus = TLSExportPublicKey(
  847. hCryptProv,
  848. dwKeySpec,
  849. &cbPublicKeyInfo,
  850. &pbPublicKeyInfo
  851. );
  852. if(dwStatus != ERROR_SUCCESS)
  853. {
  854. TLSLogEvent(
  855. EVENTLOG_ERROR_TYPE,
  856. TLS_E_GENERATECLIENTELICENSE,
  857. TLS_E_EXPORT_KEY,
  858. dwStatus
  859. );
  860. goto cleanup;
  861. }
  862. CertInfo.SubjectPublicKeyInfo = *pbPublicKeyInfo;
  863. }
  864. CertInfo.cExtension = dwNumExtensions;
  865. CertInfo.rgExtension = pCertExtensions;
  866. dwStatus = TLSCryptSignAndEncodeCertificate(
  867. hCryptProv,
  868. dwKeySpec,
  869. &CertInfo,
  870. &SignatureAlgorithm,
  871. ppbEncodedCert,
  872. pcbEncodedCert
  873. );
  874. if(dwStatus != ERROR_SUCCESS)
  875. {
  876. TLSLogEvent(
  877. EVENTLOG_ERROR_TYPE,
  878. TLS_E_GENERATECLIENTELICENSE,
  879. TLS_E_SIGNENCODECERT,
  880. dwStatus
  881. );
  882. }
  883. cleanup:
  884. if(pbPublicKeyInfo)
  885. {
  886. FreeMemory(pbPublicKeyInfo);
  887. }
  888. if(pCertIssuer->type != LSCERT_RDN_NAME_BLOB_TYPE)
  889. {
  890. FreeMemory(CertInfo.Issuer.pbData);
  891. }
  892. if(pCertSubject->type != LSCERT_RDN_NAME_BLOB_TYPE)
  893. {
  894. FreeMemory(CertInfo.Subject.pbData);
  895. }
  896. return dwStatus;
  897. }
  898. //////////////////////////////////////////////////////////////////////
  899. DWORD
  900. TLSCreateSelfSignCertificate(
  901. IN HCRYPTPROV hCryptProv,
  902. IN DWORD dwKeySpec,
  903. IN PBYTE pbSPK,
  904. IN DWORD cbSPK,
  905. IN DWORD dwNumExtensions,
  906. IN PCERT_EXTENSION pCertExtension,
  907. OUT PDWORD cbEncoded,
  908. OUT PBYTE* pbEncoded
  909. )
  910. /*
  911. */
  912. {
  913. DWORD dwStatus=ERROR_SUCCESS;
  914. DWORD index;
  915. #define MAX_EXTENSIONS_IN_SELFSIGN 40
  916. SYSTEMTIME sysTime;
  917. FILETIME ftTime;
  918. CERT_EXTENSION rgExtension[MAX_EXTENSIONS_IN_SELFSIGN];
  919. int iExtCount=0, iExtNotFreeCount=0;
  920. FILETIME ftNotBefore;
  921. FILETIME ftNotAfter;
  922. ULARGE_INTEGER ulSerialNumber;
  923. TLSClientCertRDN certRdn;
  924. CERT_BASIC_CONSTRAINTS2_INFO basicConstraint;
  925. // modify here is we want to set to different issuer name
  926. LPTSTR szIssuerName;
  927. szIssuerName = g_szComputerName;
  928. //static LPTSTR pszEnforce=L"Enforce";
  929. CERT_RDN_ATTR rgNameAttr[] = {
  930. {
  931. szOID_COMMON_NAME,
  932. dwCertRdnValueType,
  933. _tcslen(szIssuerName) * sizeof(TCHAR),
  934. (UCHAR *)szIssuerName
  935. },
  936. //#if ENFORCE_LICENSING
  937. // {
  938. // szOID_BUSINESS_CATEGORY,
  939. // dwCertRdnValueType,
  940. // _tcslen(pszEnforce) * sizeof(TCHAR),
  941. // (UCHAR *)pszEnforce
  942. // },
  943. //#endif
  944. {
  945. szOID_LOCALITY_NAME,
  946. dwCertRdnValueType,
  947. _tcslen(g_pszScope) * sizeof(TCHAR),
  948. (UCHAR *)g_pszScope
  949. }
  950. };
  951. CERT_RDN rgRDN[] = { sizeof(rgNameAttr)/sizeof(rgNameAttr[0]), &rgNameAttr[0] };
  952. CERT_NAME_INFO Name = {1, rgRDN};
  953. certRdn.type = LSCERT_RDN_NAME_INFO_TYPE;
  954. certRdn.pCertNameInfo = &Name;
  955. memset(rgExtension, 0, sizeof(rgExtension));
  956. //
  957. // Set validity of self sign certificate
  958. //
  959. //
  960. // If system time is not in sync, this will cause server
  961. // can't request cert. from license server
  962. //
  963. memset(&sysTime, 0, sizeof(sysTime));
  964. GetSystemTime(&sysTime);
  965. sysTime.wYear = 1970;
  966. if(TLSSystemTimeToFileTime(&sysTime, &ftNotBefore) == FALSE)
  967. {
  968. dwStatus = GetLastError();
  969. goto cleanup;
  970. }
  971. //
  972. // draft-ietf-pkix-ipki-part1-06.txt section 4.1.2.5.1
  973. // where year is greater or equal to 50, the year shall be interpreted as 19YY; and
  974. // where year is less than 50, the year shall be interpreted as 20YY
  975. //
  976. sysTime.wYear = PERMANENT_CERT_EXPIRE_DATE;
  977. if(TLSSystemTimeToFileTime(&sysTime, &ftNotAfter) == FALSE)
  978. {
  979. dwStatus = GetLastError();
  980. goto cleanup;
  981. }
  982. ulSerialNumber.LowPart = ftNotBefore.dwLowDateTime;
  983. ulSerialNumber.HighPart = ftNotBefore.dwHighDateTime;
  984. //
  985. // Add basic constrains extension to indicate this is a CA certificate
  986. //
  987. rgExtension[iExtCount].pszObjId = szOID_BASIC_CONSTRAINTS2;
  988. rgExtension[iExtCount].fCritical = FALSE;
  989. basicConstraint.fCA = TRUE; // act as CA
  990. basicConstraint.fPathLenConstraint = TRUE;
  991. basicConstraint.dwPathLenConstraint = 0; // can only issue certificates
  992. // to end-entities and not to further CAs
  993. dwStatus=TLSCryptEncodeObject(
  994. X509_ASN_ENCODING,
  995. szOID_BASIC_CONSTRAINTS2,
  996. &basicConstraint,
  997. &(rgExtension[iExtCount].Value.pbData),
  998. &(rgExtension[iExtCount].Value.cbData)
  999. );
  1000. if(dwStatus != ERROR_SUCCESS)
  1001. {
  1002. TLSLogEvent(
  1003. EVENTLOG_ERROR_TYPE,
  1004. TLS_E_GENERATECLIENTELICENSE,
  1005. TLS_E_SIGNENCODECERT,
  1006. dwStatus
  1007. );
  1008. goto cleanup;
  1009. }
  1010. iExtCount++;
  1011. //
  1012. // From here - extension memory should not be free
  1013. //
  1014. if(pbSPK != NULL && cbSPK != 0)
  1015. {
  1016. rgExtension[iExtCount].pszObjId = szOID_PKIS_TLSERVER_SPK_OID;
  1017. rgExtension[iExtCount].fCritical = FALSE;
  1018. rgExtension[iExtCount].Value.pbData = pbSPK;
  1019. rgExtension[iExtCount].Value.cbData = cbSPK;
  1020. iExtNotFreeCount++;
  1021. iExtCount++;
  1022. }
  1023. for(index = 0;
  1024. index < dwNumExtensions;
  1025. index ++, iExtCount++, iExtNotFreeCount++ )
  1026. {
  1027. rgExtension[iExtCount] = pCertExtension[index];
  1028. }
  1029. dwStatus = TLSGenerateCertificate(
  1030. hCryptProv,
  1031. dwKeySpec,
  1032. &ulSerialNumber,
  1033. &certRdn,
  1034. &certRdn,
  1035. &ftNotBefore,
  1036. &ftNotAfter,
  1037. NULL,
  1038. iExtCount,
  1039. rgExtension,
  1040. cbEncoded,
  1041. pbEncoded
  1042. );
  1043. cleanup:
  1044. //
  1045. // Don't free memory for SPK and extensions...
  1046. //
  1047. for(int i=0; i < iExtCount - iExtNotFreeCount; i++)
  1048. {
  1049. FreeMemory(rgExtension[i].Value.pbData);
  1050. }
  1051. return (dwStatus != ERROR_SUCCESS) ? TLS_E_CREATE_SELFSIGN_CERT : ERROR_SUCCESS;
  1052. }
  1053. ////////////////////////////////////////////////////////////////////////////
  1054. DWORD
  1055. TLSGenerateSingleCertificate(
  1056. IN HCRYPTPROV hCryptProv,
  1057. IN PCERT_NAME_BLOB pIssuerRdn,
  1058. IN PTLSClientCertRDN pSubjectRdn,
  1059. IN PCERT_PUBLIC_KEY_INFO pSubjectPublicKeyInfo,
  1060. IN PTLSDBLICENSEDPRODUCT pLicProduct,
  1061. OUT PBYTE* ppbEncodedCert,
  1062. IN PDWORD pcbEncodedCert
  1063. )
  1064. /*
  1065. */
  1066. {
  1067. DWORD dwStatus = ERROR_SUCCESS;
  1068. #define MAX_CLIENT_EXTENSION 10
  1069. CERT_EXTENSION CertExtension[MAX_CLIENT_EXTENSION];
  1070. DWORD dwNumExtensions=0;
  1071. DWORD currentCertVersion=TERMSERV_CERT_VERSION_CURRENT;
  1072. TLSClientCertRDN IssuerRdn;
  1073. #if ENFORCE_LICENSING
  1074. //
  1075. // Use certificate that CH gets for us
  1076. //
  1077. IssuerRdn.type = LSCERT_RDN_NAME_BLOB_TYPE;
  1078. //IssuerRdn.pNameBlob = &g_LicenseCertContext->pCertInfo->Subject;
  1079. IssuerRdn.pNameBlob = pIssuerRdn;
  1080. #else
  1081. LPTSTR szIssuerName;
  1082. // modify here if we want to set to different issuer name
  1083. szIssuerName = g_szComputerName;
  1084. CERT_RDN_ATTR rgNameAttr[] = {
  1085. {
  1086. OID_ISSUER_LICENSE_SERVER_NAME,
  1087. dwCertRdnValueType,
  1088. _tcslen(szIssuerName) * sizeof(TCHAR),
  1089. (UCHAR *)szIssuerName
  1090. },
  1091. {
  1092. OID_ISSUER_LICENSE_SERVER_SCOPE,
  1093. dwCertRdnValueType,
  1094. _tcslen(g_pszScope) * sizeof(TCHAR),
  1095. (UCHAR *)g_pszScope
  1096. }
  1097. };
  1098. CERT_RDN rgRDN[] = {
  1099. sizeof(rgNameAttr)/sizeof(rgNameAttr[0]),
  1100. &rgNameAttr[0]
  1101. };
  1102. CERT_NAME_INFO Name = {1, rgRDN};
  1103. IssuerRdn.type = LSCERT_RDN_NAME_INFO_TYPE;
  1104. IssuerRdn.pCertNameInfo = &Name;
  1105. #endif
  1106. //------------------------------------------------------------------------------------------
  1107. // add extension to certificate
  1108. // WARNING : End of routine free memory allocated for extension's pbData, skip those
  1109. // that can't be free, for example, version stamp extension. all these is just
  1110. // to keep memory fragmentaion low
  1111. //------------------------------------------------------------------------------------------
  1112. //
  1113. // DO NOT FREE pbData on first two extensions
  1114. //
  1115. // Hydra Certificate version stamp - DO NOT FREE
  1116. memset(&CertExtension, 0, sizeof(CertExtension));
  1117. dwNumExtensions = 0;
  1118. //
  1119. // Add License Server Info
  1120. //
  1121. CertExtension[dwNumExtensions].pszObjId = szOID_PKIX_HYDRA_CERT_VERSION;
  1122. CertExtension[dwNumExtensions].fCritical = TRUE;
  1123. CertExtension[dwNumExtensions].Value.cbData = sizeof(DWORD);
  1124. CertExtension[dwNumExtensions].Value.pbData = (PBYTE)&currentCertVersion;
  1125. dwNumExtensions++;
  1126. // manufacturer's name, no encoding - DO NOT FREE
  1127. CertExtension[dwNumExtensions].pszObjId = szOID_PKIX_MANUFACTURER;
  1128. CertExtension[dwNumExtensions].fCritical = TRUE;
  1129. CertExtension[dwNumExtensions].Value.cbData = (_tcslen(pLicProduct->szCompanyName)+1) * sizeof(TCHAR);
  1130. CertExtension[dwNumExtensions].Value.pbData = (PBYTE)pLicProduct->szCompanyName;
  1131. dwNumExtensions++;
  1132. //
  1133. // MS Licensed Product Info, no encoding
  1134. //
  1135. LICENSED_VERSION_INFO LicensedInfo;
  1136. memset(&LicensedInfo, 0, sizeof(LicensedInfo));
  1137. LicensedInfo.wMajorVersion = HIWORD(pLicProduct->dwProductVersion);
  1138. LicensedInfo.wMinorVersion = LOWORD(pLicProduct->dwProductVersion);
  1139. LicensedInfo.dwFlags = (pLicProduct->bTemp) ? LICENSED_VERSION_TEMPORARY : 0;
  1140. DWORD dwLSVersionMajor;
  1141. DWORD dwLSVersionMinor;
  1142. dwLSVersionMajor = GET_SERVER_MAJOR_VERSION(TLS_CURRENT_VERSION);
  1143. dwLSVersionMinor = GET_SERVER_MINOR_VERSION(TLS_CURRENT_VERSION);
  1144. LicensedInfo.dwFlags |= ((dwLSVersionMajor << 4 | dwLSVersionMinor) << 16);
  1145. if(TLSIsBetaNTServer() == FALSE)
  1146. {
  1147. LicensedInfo.dwFlags |= LICENSED_VERSION_RTM;
  1148. }
  1149. #if ENFORCE_LICENSING
  1150. LicensedInfo.dwFlags |= LICENSE_ISSUER_ENFORCE_TYPE;
  1151. #endif
  1152. CertExtension[dwNumExtensions].pszObjId = szOID_PKIX_LICENSED_PRODUCT_INFO;
  1153. CertExtension[dwNumExtensions].fCritical = TRUE;
  1154. dwStatus=LSLicensedProductInfoToExtension(
  1155. 1,
  1156. pLicProduct->dwPlatformID,
  1157. pLicProduct->dwLanguageID,
  1158. (PBYTE)pLicProduct->szRequestProductId,
  1159. (_tcslen(pLicProduct->szRequestProductId) + 1) * sizeof(TCHAR),
  1160. (PBYTE)pLicProduct->szLicensedProductId,
  1161. (_tcslen(pLicProduct->szLicensedProductId) + 1) * sizeof(TCHAR),
  1162. &LicensedInfo,
  1163. 1,
  1164. &(CertExtension[dwNumExtensions].Value.pbData),
  1165. &(CertExtension[dwNumExtensions].Value.cbData)
  1166. );
  1167. if(dwStatus != ERROR_SUCCESS)
  1168. goto cleanup;
  1169. dwNumExtensions++;
  1170. //
  1171. // Add license server info into extension
  1172. //
  1173. CertExtension[dwNumExtensions].pszObjId = szOID_PKIX_MS_LICENSE_SERVER_INFO;
  1174. CertExtension[dwNumExtensions].fCritical = TRUE;
  1175. dwStatus=LSMsLicenseServerInfoToExtension(
  1176. g_szComputerName,
  1177. (LPTSTR)g_pszServerPid,
  1178. g_pszScope,
  1179. &(CertExtension[dwNumExtensions].Value.pbData),
  1180. &(CertExtension[dwNumExtensions].Value.cbData)
  1181. );
  1182. if(dwStatus != ERROR_SUCCESS)
  1183. goto cleanup;
  1184. dwNumExtensions++;
  1185. //
  1186. // Add policy module specific extension
  1187. if( pLicProduct->pbPolicyData != NULL && pLicProduct->cbPolicyData != 0 )
  1188. {
  1189. CertExtension[dwNumExtensions].pszObjId = szOID_PKIS_PRODUCT_SPECIFIC_OID;
  1190. CertExtension[dwNumExtensions].fCritical = TRUE;
  1191. CertExtension[dwNumExtensions].Value.pbData = pLicProduct->pbPolicyData;
  1192. CertExtension[dwNumExtensions].Value.cbData = pLicProduct->cbPolicyData;
  1193. dwNumExtensions++;
  1194. }
  1195. //
  1196. // Add CertAuthorityKeyId2Info for certificate chain
  1197. dwStatus=TLSAddCertAuthorityKeyIdExtension(
  1198. g_szComputerName,
  1199. &pLicProduct->ulSerialNumber,
  1200. CertExtension + dwNumExtensions
  1201. );
  1202. if(dwStatus != ERROR_SUCCESS)
  1203. goto cleanup;
  1204. dwNumExtensions++;
  1205. // Add Access info
  1206. dwStatus = TLSGenerateCertificate(
  1207. hCryptProv,
  1208. AT_SIGNATURE,
  1209. &pLicProduct->ulSerialNumber,
  1210. &IssuerRdn,
  1211. pSubjectRdn,
  1212. &pLicProduct->NotBefore,
  1213. &pLicProduct->NotAfter,
  1214. pLicProduct->pSubjectPublicKeyInfo,
  1215. dwNumExtensions,
  1216. CertExtension,
  1217. pcbEncodedCert,
  1218. ppbEncodedCert
  1219. );
  1220. cleanup:
  1221. // Extensions. DO NOT FREE first two extensions
  1222. for(int i=2; i < dwNumExtensions; i++)
  1223. {
  1224. FreeMemory(CertExtension[i].Value.pbData);
  1225. }
  1226. return (dwStatus != ERROR_SUCCESS) ? TLS_E_CREATE_CERT : ERROR_SUCCESS;
  1227. }
  1228. ////////////////////////////////////////////////////////////
  1229. DWORD
  1230. TLSGenerateClientCertificate(
  1231. IN HCRYPTPROV hCryptProv,
  1232. IN DWORD dwNumLicensedProduct,
  1233. IN PTLSDBLICENSEDPRODUCT pLicProduct,
  1234. IN WORD wLicenseChainDetail,
  1235. OUT PBYTE* ppbEncodedCert,
  1236. OUT PDWORD pcbEncodedCert
  1237. )
  1238. /*++
  1239. ++*/
  1240. {
  1241. DWORD dwStatus = ERROR_SUCCESS;
  1242. HCERTSTORE hStore = NULL;
  1243. PCCERT_CONTEXT pCertContext = NULL;
  1244. PBYTE pbCert=NULL;
  1245. DWORD cbCert=NULL;
  1246. DWORD index;
  1247. TLSClientCertRDN clientCertRdn;
  1248. PCERT_NAME_BLOB pIssuerNameBlob = NULL;
  1249. //
  1250. // Create a in-memory store
  1251. //
  1252. hStore=CertOpenStore(
  1253. CERT_STORE_PROV_MEMORY,
  1254. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1255. hCryptProv,
  1256. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  1257. NULL
  1258. );
  1259. if(!hStore)
  1260. {
  1261. TLSLogEvent(
  1262. EVENTLOG_ERROR_TYPE,
  1263. TLS_E_GENERATECLIENTELICENSE,
  1264. TLS_E_OPEN_CERT_STORE,
  1265. dwStatus=GetLastError()
  1266. );
  1267. goto cleanup;
  1268. }
  1269. #ifndef ENFORCE_LICENSING
  1270. pIssuerNameBlob = &g_SelfSignCertContext->pCertInfo->Subject;
  1271. #else
  1272. if( g_SelfSignCertContext == NULL )
  1273. {
  1274. TLSASSERT(FALSE);
  1275. dwStatus = TLS_E_INTERNAL;
  1276. goto cleanup;
  1277. }
  1278. if(g_bHasHydraCert && g_hCaStore && wLicenseChainDetail == LICENSE_DETAIL_DETAIL)
  1279. {
  1280. pIssuerNameBlob = &g_LicenseCertContext->pCertInfo->Subject;
  1281. }
  1282. else
  1283. {
  1284. pIssuerNameBlob = &g_SelfSignCertContext->pCertInfo->Subject;
  1285. }
  1286. #endif
  1287. //
  1288. // Generate client certificate and add to certstore
  1289. //
  1290. for(index = 0; index < dwNumLicensedProduct; index++)
  1291. {
  1292. if(pCertContext != NULL)
  1293. {
  1294. //
  1295. // Need to keep one pCertContext for later use
  1296. //
  1297. CertFreeCertificateContext(pCertContext);
  1298. pCertContext = NULL;
  1299. }
  1300. clientCertRdn.type = LSCERT_CLIENT_INFO_TYPE;
  1301. clientCertRdn.ClientInfo.szUserName = pLicProduct[index].szUserName;
  1302. clientCertRdn.ClientInfo.szMachineName = pLicProduct[index].szMachineName;
  1303. clientCertRdn.ClientInfo.pClientID = &pLicProduct[index].ClientHwid;
  1304. dwStatus = TLSGenerateSingleCertificate(
  1305. hCryptProv,
  1306. pIssuerNameBlob,
  1307. &clientCertRdn,
  1308. pLicProduct[index].pSubjectPublicKeyInfo,
  1309. pLicProduct+index,
  1310. &pbCert,
  1311. &cbCert
  1312. );
  1313. if(dwStatus != ERROR_SUCCESS)
  1314. {
  1315. break;
  1316. }
  1317. //
  1318. // Add certificate to store
  1319. //
  1320. pCertContext = CertCreateCertificateContext(
  1321. X509_ASN_ENCODING,
  1322. pbCert,
  1323. cbCert
  1324. );
  1325. if(pCertContext == NULL)
  1326. {
  1327. TLSLogEvent(
  1328. EVENTLOG_ERROR_TYPE,
  1329. TLS_E_GENERATECLIENTELICENSE,
  1330. TLS_E_CREATE_CERTCONTEXT,
  1331. dwStatus=GetLastError()
  1332. );
  1333. break;
  1334. }
  1335. //
  1336. // always start from empty so CERT_STORE_ADD_ALWAYS
  1337. //
  1338. if(!CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_ALWAYS, NULL))
  1339. {
  1340. TLSLogEvent(
  1341. EVENTLOG_ERROR_TYPE,
  1342. TLS_E_GENERATECLIENTELICENSE,
  1343. TLS_E_ADD_CERT_TO_STORE,
  1344. dwStatus=GetLastError()
  1345. );
  1346. break;
  1347. }
  1348. FreeMemory(pbCert);
  1349. pbCert = NULL;
  1350. }
  1351. if(dwStatus == ERROR_SUCCESS)
  1352. {
  1353. #ifndef ENFORCE_LICENSING
  1354. //
  1355. // Add license server's certificate
  1356. if(!CertAddCertificateContextToStore(hStore, g_LicenseCertContext, CERT_STORE_ADD_ALWAYS, NULL))
  1357. {
  1358. TLSLogEvent(
  1359. EVENTLOG_ERROR_TYPE,
  1360. TLS_E_GENERATECLIENTELICENSE,
  1361. TLS_E_ADD_CERT_TO_STORE,
  1362. dwStatus=GetLastError()
  1363. );
  1364. goto cleanup;
  1365. }
  1366. #else
  1367. //
  1368. // we don't support LICENSE_DETAIL_MODERATE at this time, treat it as LICENSE_DETAIL_SIMPLE
  1369. //
  1370. if(g_bHasHydraCert && g_hCaStore && wLicenseChainDetail == LICENSE_DETAIL_DETAIL)
  1371. {
  1372. //
  1373. // Chain issuer certificate with client certificate
  1374. //
  1375. if(!TLSChainIssuerCertificate(hCryptProv, g_hCaStore, hStore, pCertContext))
  1376. {
  1377. TLSLogEvent(
  1378. EVENTLOG_ERROR_TYPE,
  1379. TLS_E_GENERATECLIENTELICENSE,
  1380. TLS_E_ADD_CERT_TO_STORE,
  1381. dwStatus=GetLastError()
  1382. );
  1383. goto cleanup;
  1384. }
  1385. }
  1386. else
  1387. {
  1388. //
  1389. // Add license server's certificate
  1390. if(!CertAddCertificateContextToStore(hStore, g_SelfSignCertContext, CERT_STORE_ADD_ALWAYS, NULL))
  1391. {
  1392. TLSLogEvent(
  1393. EVENTLOG_ERROR_TYPE,
  1394. TLS_E_GENERATECLIENTELICENSE,
  1395. TLS_E_ADD_CERT_TO_STORE,
  1396. dwStatus=GetLastError()
  1397. );
  1398. goto cleanup;
  1399. }
  1400. }
  1401. #endif
  1402. CRYPT_DATA_BLOB saveBlob;
  1403. memset(&saveBlob, 0, sizeof(saveBlob));
  1404. // save certificate into memory
  1405. if(!CertSaveStore(hStore,
  1406. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1407. LICENSE_BLOB_SAVEAS_TYPE,
  1408. CERT_STORE_SAVE_TO_MEMORY,
  1409. &saveBlob,
  1410. 0) && (dwStatus=GetLastError()) != ERROR_MORE_DATA)
  1411. {
  1412. TLSLogEvent(
  1413. EVENTLOG_ERROR_TYPE,
  1414. TLS_E_GENERATECLIENTELICENSE,
  1415. TLS_E_SAVE_STORE,
  1416. dwStatus=GetLastError()
  1417. );
  1418. goto cleanup;
  1419. }
  1420. if(!(saveBlob.pbData = (PBYTE)AllocateMemory(saveBlob.cbData)))
  1421. {
  1422. dwStatus=TLS_E_ALLOCATE_MEMORY;
  1423. goto cleanup;
  1424. }
  1425. // save certificate into memory
  1426. if(!CertSaveStore(hStore,
  1427. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1428. LICENSE_BLOB_SAVEAS_TYPE,
  1429. CERT_STORE_SAVE_TO_MEMORY,
  1430. &saveBlob,
  1431. 0))
  1432. {
  1433. TLSLogEvent(
  1434. EVENTLOG_ERROR_TYPE,
  1435. TLS_E_GENERATECLIENTELICENSE,
  1436. TLS_E_SAVE_STORE,
  1437. dwStatus=GetLastError()
  1438. );
  1439. goto cleanup;
  1440. }
  1441. *ppbEncodedCert = saveBlob.pbData;
  1442. *pcbEncodedCert = saveBlob.cbData;
  1443. }
  1444. cleanup:
  1445. FreeMemory(pbCert);
  1446. if(pCertContext)
  1447. {
  1448. CertFreeCertificateContext(pCertContext);
  1449. }
  1450. if(hStore)
  1451. {
  1452. CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
  1453. }
  1454. return dwStatus;
  1455. }