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.

646 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: attrbute.cpp
  8. //
  9. // Contents:
  10. // Encode/Decode APIs
  11. //
  12. // ASN.1 implementation uses the OSS compiler.
  13. //
  14. // Functions: CryptEncodeObject
  15. // CryptDecodeObject
  16. //
  17. // History: 29-Feb-96 philh created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include "stdafx.h"
  21. #include <windows.h>
  22. #include <wincrypt.h>
  23. #include <malloc.h>
  24. #include "xenroll.h"
  25. #include "cenroll.h"
  26. #include "ossconv.h"
  27. #include "ossutil.h"
  28. #include "asn1util.h"
  29. #include "crypttls.h"
  30. extern "C"
  31. {
  32. #include "xasn.h"
  33. }
  34. // All the *pvInfo extra stuff needs to be aligned
  35. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  36. HCRYPTOSSGLOBAL hX509OssGlobal;
  37. //+-------------------------------------------------------------------------
  38. // Function: GetPog
  39. //
  40. // Synopsis: Initialize thread local storage for the asn libs
  41. //
  42. // Returns: pointer to an initialized OssGlobal data structure
  43. //--------------------------------------------------------------------------
  44. static inline POssGlobal GetPog(void)
  45. {
  46. return I_CryptGetOssGlobal(hX509OssGlobal);
  47. }
  48. //+-------------------------------------------------------------------------
  49. // Cert allocation and free functions
  50. //--------------------------------------------------------------------------
  51. static void *CertAlloc(
  52. IN size_t cbBytes
  53. )
  54. {
  55. void *pv;
  56. pv = malloc(cbBytes);
  57. if (pv == NULL)
  58. SetLastError((DWORD) E_OUTOFMEMORY);
  59. return pv;
  60. }
  61. static void CertFree(
  62. IN void *pv
  63. )
  64. {
  65. free(pv);
  66. }
  67. //+-------------------------------------------------------------------------
  68. // Encode an OSS formatted info structure
  69. //
  70. // Called by the OssX509*Encode() functions.
  71. //--------------------------------------------------------------------------
  72. static BOOL OssInfoEncode(
  73. IN int pdunum,
  74. IN void *pOssInfo,
  75. OUT BYTE *pbEncoded,
  76. IN OUT DWORD *pcbEncoded
  77. )
  78. {
  79. return OssUtilEncodeInfo(
  80. GetPog(),
  81. pdunum,
  82. pOssInfo,
  83. pbEncoded,
  84. pcbEncoded);
  85. }
  86. //+-------------------------------------------------------------------------
  87. // Decode into an allocated, OSS formatted info structure
  88. //
  89. // Called by the OssX509*Decode() functions.
  90. //--------------------------------------------------------------------------
  91. static BOOL OssInfoDecodeAndAlloc(
  92. IN int pdunum,
  93. IN const BYTE *pbEncoded,
  94. IN DWORD cbEncoded,
  95. OUT void **ppOssInfo
  96. )
  97. {
  98. return OssUtilDecodeAndAllocInfo(
  99. GetPog(),
  100. pdunum,
  101. pbEncoded,
  102. cbEncoded,
  103. ppOssInfo);
  104. }
  105. //+-------------------------------------------------------------------------
  106. // Free an allocated, OSS formatted info structure
  107. //
  108. // Called by the OssX509*Decode() functions.
  109. //--------------------------------------------------------------------------
  110. static void OssInfoFree(
  111. IN int pdunum,
  112. IN void *pOssInfo
  113. )
  114. {
  115. if (pOssInfo) {
  116. DWORD dwErr = GetLastError();
  117. // TlsGetValue globbers LastError
  118. OssUtilFreeInfo(GetPog(), pdunum, pOssInfo);
  119. SetLastError(dwErr);
  120. }
  121. }
  122. //+-------------------------------------------------------------------------
  123. // OSS X509 v3 ASN.1 Set / Get functions
  124. //
  125. // Called by the OSS X509 encode/decode functions.
  126. //
  127. // Assumption: all types are UNBOUNDED.
  128. //
  129. // The Get functions decrement *plRemainExtra and advance
  130. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  131. // with the length calculation but stop doing any copies.
  132. // The functions don't return an error for a negative *plRemainExtra.
  133. //--------------------------------------------------------------------------
  134. //+-------------------------------------------------------------------------
  135. // Set/Get Object Identifier string
  136. //--------------------------------------------------------------------------
  137. static BOOL OssX509SetObjId(
  138. IN LPSTR pszObjId,
  139. OUT ObjectID *pOss
  140. )
  141. {
  142. pOss->count = sizeof(pOss->value) / sizeof(pOss->value[0]);
  143. if (OssConvToObjectIdentifier(pszObjId, &pOss->count, pOss->value))
  144. return TRUE;
  145. else {
  146. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  147. return FALSE;
  148. }
  149. }
  150. static void OssX509GetObjId(
  151. IN ObjectID *pOss,
  152. IN DWORD /*dwFlags*/,
  153. OUT LPSTR *ppszObjId,
  154. IN OUT BYTE **ppbExtra,
  155. IN OUT LONG *plRemainExtra
  156. )
  157. {
  158. LONG lRemainExtra = *plRemainExtra;
  159. BYTE *pbExtra = *ppbExtra;
  160. LONG lAlignExtra;
  161. DWORD cbObjId;
  162. cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
  163. OssConvFromObjectIdentifier(
  164. pOss->count,
  165. pOss->value,
  166. (LPSTR) pbExtra,
  167. &cbObjId
  168. );
  169. lAlignExtra = INFO_LEN_ALIGN(cbObjId);
  170. lRemainExtra -= lAlignExtra;
  171. if (lRemainExtra >= 0) {
  172. if(cbObjId) {
  173. *ppszObjId = (LPSTR) pbExtra;
  174. } else
  175. *ppszObjId = NULL;
  176. pbExtra += lAlignExtra;
  177. }
  178. *plRemainExtra = lRemainExtra;
  179. *ppbExtra = pbExtra;
  180. }
  181. static BOOL WINAPI OssX509CtlUsageEncode(
  182. IN DWORD dwCertEncodingType,
  183. IN LPCSTR lpszStructType,
  184. IN PCTL_USAGE pInfo,
  185. OUT BYTE *pbEncoded,
  186. IN OUT DWORD *pcbEncoded
  187. );
  188. static BOOL WINAPI OssX509CtlUsageDecode(
  189. IN DWORD dwCertEncodingType,
  190. IN LPCSTR lpszStructType,
  191. IN const BYTE *pbEncoded,
  192. IN DWORD cbEncoded,
  193. IN DWORD dwFlags,
  194. OUT PCTL_USAGE pInfo,
  195. IN OUT DWORD *pcbInfo
  196. );
  197. static BOOL WINAPI OssRequestInfoDecode(
  198. IN DWORD dwCertEncodingType,
  199. IN LPCSTR lpszStructType,
  200. IN const BYTE *pbEncoded,
  201. IN DWORD cbEncoded,
  202. IN DWORD dwFlags,
  203. OUT RequestFlags * pInfo,
  204. IN OUT DWORD *pcbInfo
  205. );
  206. static BOOL WINAPI OssRequestInfoEncode(
  207. IN DWORD dwCertEncodingType,
  208. IN LPCSTR lpszStructType,
  209. IN RequestFlags * pInfo,
  210. OUT BYTE *pbEncoded,
  211. IN OUT DWORD *pcbEncoded
  212. );
  213. static BOOL WINAPI OssCSPProviderEncode(
  214. IN DWORD dwCertEncodingType,
  215. IN LPCSTR lpszStructType,
  216. IN PCRYPT_CSP_PROVIDER pCSPProvider,
  217. OUT BYTE *pbEncoded,
  218. IN OUT DWORD *pcbEncoded
  219. );
  220. static BOOL WINAPI OssNameValueEncode(
  221. IN DWORD dwCertEncodingType,
  222. IN LPCSTR lpszStructType,
  223. IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
  224. OUT BYTE *pbEncoded,
  225. IN OUT DWORD *pcbEncoded
  226. );
  227. static const CRYPT_OID_FUNC_ENTRY X509EncodeFuncTable[] = {
  228. X509_ENHANCED_KEY_USAGE, OssX509CtlUsageEncode,
  229. XENROLL_REQUEST_INFO, OssRequestInfoEncode,
  230. szOID_ENROLLMENT_CSP_PROVIDER, OssCSPProviderEncode,
  231. szOID_ENROLLMENT_NAME_VALUE_PAIR, OssNameValueEncode,
  232. };
  233. #define X509_ENCODE_FUNC_COUNT (sizeof(X509EncodeFuncTable) / \
  234. sizeof(X509EncodeFuncTable[0]))
  235. static const CRYPT_OID_FUNC_ENTRY X509DecodeFuncTable[] = {
  236. X509_ENHANCED_KEY_USAGE, OssX509CtlUsageDecode,
  237. XENROLL_REQUEST_INFO, OssRequestInfoDecode
  238. };
  239. #define X509_DECODE_FUNC_COUNT (sizeof(X509DecodeFuncTable) / \
  240. sizeof(X509DecodeFuncTable[0]))
  241. extern BOOL OssLoad();
  242. extern void OssUnload();
  243. //+-------------------------------------------------------------------------
  244. // Dll initialization
  245. //--------------------------------------------------------------------------
  246. BOOL AsnInit(
  247. HMODULE hInst)
  248. {
  249. if (0 == (hX509OssGlobal = I_CryptInstallOssGlobal(xasn, 0, NULL)))
  250. goto Error;
  251. if (!OssLoad())
  252. goto Error;
  253. if (!CryptInstallOIDFunctionAddress(
  254. hInst,
  255. X509_ASN_ENCODING,
  256. CRYPT_OID_ENCODE_OBJECT_FUNC,
  257. X509_ENCODE_FUNC_COUNT,
  258. X509EncodeFuncTable,
  259. 0)) // dwFlags
  260. goto Error;
  261. if (!CryptInstallOIDFunctionAddress(
  262. hInst,
  263. X509_ASN_ENCODING,
  264. CRYPT_OID_DECODE_OBJECT_FUNC,
  265. X509_DECODE_FUNC_COUNT,
  266. X509DecodeFuncTable,
  267. 0)) // dwFlags
  268. goto Error;
  269. return TRUE;
  270. Error:
  271. return FALSE;
  272. }
  273. typedef BOOL (WINAPI *PFN_CRYPT_UNINSTALL_OSS_GLOBAL)(
  274. IN HCRYPTOSSGLOBAL hOssGlobal
  275. );
  276. void AsnTerm()
  277. {
  278. HMODULE hDll = NULL;
  279. OssUnload();
  280. hDll = GetModuleHandleA("crypt32.dll");
  281. if (NULL != hDll) {
  282. PFN_CRYPT_UNINSTALL_OSS_GLOBAL pfnCryptUninstallOssGlobal;
  283. pfnCryptUninstallOssGlobal = (PFN_CRYPT_UNINSTALL_OSS_GLOBAL) GetProcAddress(hDll, "I_CryptUninstallOssGlobal");
  284. if (NULL != pfnCryptUninstallOssGlobal) {
  285. pfnCryptUninstallOssGlobal(hX509OssGlobal);
  286. }
  287. }
  288. }
  289. //+-------------------------------------------------------------------------
  290. // OSS X509 v3 ASN.1 Set / Get functions
  291. //
  292. // Called by the OSS X509 encode/decode functions.
  293. //
  294. // Assumption: all types are UNBOUNDED.
  295. //
  296. // The Get functions decrement *plRemainExtra and advance
  297. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  298. // with the length calculation but stop doing any copies.
  299. // The functions don't return an error for a negative *plRemainExtra.
  300. //--------------------------------------------------------------------------
  301. //+-------------------------------------------------------------------------
  302. // Set/Free/Get CTL Usage object identifiers
  303. //--------------------------------------------------------------------------
  304. static BOOL OssX509SetCtlUsage(
  305. IN PCTL_USAGE pUsage,
  306. OUT EnhancedKeyUsage *pOss
  307. )
  308. {
  309. DWORD cId;
  310. LPSTR *ppszId;
  311. UsageIdentifier *pOssId;
  312. pOss->count = 0;
  313. pOss->value = NULL;
  314. cId = pUsage->cUsageIdentifier;
  315. if (0 == cId)
  316. return TRUE;
  317. pOssId = (UsageIdentifier *) CertAlloc(cId * sizeof(UsageIdentifier));
  318. if (pOssId == NULL)
  319. return FALSE;
  320. pOss->count = cId;
  321. pOss->value = pOssId;
  322. ppszId = pUsage->rgpszUsageIdentifier;
  323. for ( ; cId > 0; cId--, ppszId++, pOssId++) {
  324. if (!OssX509SetObjId(*ppszId, pOssId))
  325. return FALSE;
  326. }
  327. return TRUE;
  328. }
  329. static void OssX509FreeCtlUsage(
  330. IN EnhancedKeyUsage *pOss)
  331. {
  332. if (pOss->value) {
  333. CertFree(pOss->value);
  334. pOss->value = NULL;
  335. }
  336. }
  337. static void OssX509GetCtlUsage(
  338. IN EnhancedKeyUsage *pOss,
  339. IN DWORD dwFlags,
  340. OUT PCTL_USAGE pUsage,
  341. IN OUT BYTE **ppbExtra,
  342. IN OUT LONG *plRemainExtra
  343. )
  344. {
  345. LONG lRemainExtra = *plRemainExtra;
  346. BYTE *pbExtra = *ppbExtra;
  347. LONG lAlignExtra;
  348. DWORD cId;
  349. UsageIdentifier *pOssId;
  350. LPSTR *ppszId;
  351. cId = pOss->count;
  352. lAlignExtra = INFO_LEN_ALIGN(cId * sizeof(LPSTR));
  353. lRemainExtra -= lAlignExtra;
  354. if (lRemainExtra >= 0) {
  355. pUsage->cUsageIdentifier = cId;
  356. ppszId = (LPSTR *) pbExtra;
  357. pUsage->rgpszUsageIdentifier = ppszId;
  358. pbExtra += lAlignExtra;
  359. } else
  360. ppszId = NULL;
  361. pOssId = pOss->value;
  362. for ( ; cId > 0; cId--, pOssId++, ppszId++)
  363. OssX509GetObjId(pOssId, dwFlags, ppszId, &pbExtra, &lRemainExtra);
  364. *plRemainExtra = lRemainExtra;
  365. *ppbExtra = pbExtra;
  366. }
  367. //+-------------------------------------------------------------------------
  368. // CTL Usage (Enhanced Key Usage) Encode (OSS X509)
  369. //--------------------------------------------------------------------------
  370. static BOOL WINAPI OssX509CtlUsageEncode(
  371. IN DWORD /*dwCertEncodingType*/,
  372. IN LPCSTR /*lpszStructType*/,
  373. IN PCTL_USAGE pInfo,
  374. OUT BYTE *pbEncoded,
  375. IN OUT DWORD *pcbEncoded
  376. )
  377. {
  378. BOOL fResult;
  379. EnhancedKeyUsage OssInfo;
  380. if (!OssX509SetCtlUsage(pInfo, &OssInfo)) {
  381. *pcbEncoded = 0;
  382. fResult = FALSE;
  383. } else
  384. fResult = OssInfoEncode(
  385. EnhancedKeyUsage_PDU,
  386. &OssInfo,
  387. pbEncoded,
  388. pcbEncoded
  389. );
  390. OssX509FreeCtlUsage(&OssInfo);
  391. return fResult;
  392. }
  393. //+-------------------------------------------------------------------------
  394. // CTL Usage (Enhanced Key Usage) Decode (OSS X509)
  395. //--------------------------------------------------------------------------
  396. static BOOL WINAPI OssX509CtlUsageDecode(
  397. IN DWORD /*dwCertEncodingType*/,
  398. IN LPCSTR /*lpszStructType*/,
  399. IN const BYTE *pbEncoded,
  400. IN DWORD cbEncoded,
  401. IN DWORD dwFlags,
  402. OUT PCTL_USAGE pInfo,
  403. IN OUT DWORD *pcbInfo
  404. )
  405. {
  406. BOOL fResult;
  407. EnhancedKeyUsage *pOssInfo = NULL;
  408. BYTE *pbExtra;
  409. LONG lRemainExtra;
  410. if (pInfo == NULL)
  411. *pcbInfo = 0;
  412. if (!OssInfoDecodeAndAlloc(
  413. EnhancedKeyUsage_PDU,
  414. pbEncoded,
  415. cbEncoded,
  416. (void **) &pOssInfo))
  417. goto ErrorReturn;
  418. // for lRemainExtra < 0, LENGTH_ONLY calculation
  419. lRemainExtra = (LONG) *pcbInfo - sizeof(CTL_USAGE);
  420. if (lRemainExtra < 0) {
  421. pbExtra = NULL;
  422. } else
  423. pbExtra = (BYTE *) pInfo + sizeof(CTL_USAGE);
  424. OssX509GetCtlUsage(pOssInfo, dwFlags, pInfo, &pbExtra, &lRemainExtra);
  425. if (lRemainExtra >= 0)
  426. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  427. else {
  428. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  429. if (pInfo) goto LengthError;
  430. }
  431. fResult = TRUE;
  432. goto CommonReturn;
  433. LengthError:
  434. SetLastError((DWORD) ERROR_MORE_DATA);
  435. fResult = FALSE;
  436. goto CommonReturn;
  437. ErrorReturn:
  438. *pcbInfo = 0;
  439. fResult = FALSE;
  440. CommonReturn:
  441. OssInfoFree(EnhancedKeyUsage_PDU, pOssInfo);
  442. return fResult;
  443. }
  444. //+-------------------------------------------------------------------------
  445. // Request Info Encode
  446. //--------------------------------------------------------------------------
  447. static BOOL WINAPI OssRequestInfoEncode(
  448. IN DWORD /*dwCertEncodingType*/,
  449. IN LPCSTR /*lpszStructType*/,
  450. IN RequestFlags * pInfo,
  451. OUT BYTE *pbEncoded,
  452. IN OUT DWORD *pcbEncoded
  453. )
  454. {
  455. BOOL fResult;
  456. fResult = OssInfoEncode(
  457. RequestFlags_PDU,
  458. pInfo,
  459. pbEncoded,
  460. pcbEncoded
  461. );
  462. return fResult;
  463. }
  464. //+-------------------------------------------------------------------------
  465. // Request Info Decode
  466. //--------------------------------------------------------------------------
  467. static BOOL WINAPI OssRequestInfoDecode(
  468. IN DWORD /*dwCertEncodingType*/,
  469. IN LPCSTR /*lpszStructType*/,
  470. IN const BYTE *pbEncoded,
  471. IN DWORD cbEncoded,
  472. IN DWORD /*dwFlags*/,
  473. OUT RequestFlags * pInfo,
  474. IN OUT DWORD *pcbInfo
  475. )
  476. {
  477. BOOL fResult;
  478. RequestFlags * pOss = NULL;
  479. if (NULL == pInfo || NULL == pcbInfo)
  480. goto ParamError;
  481. if(*pcbInfo < sizeof(RequestFlags))
  482. goto LengthError;
  483. else if (!OssInfoDecodeAndAlloc(
  484. RequestFlags_PDU,
  485. pbEncoded,
  486. cbEncoded,
  487. (void **) &pOss) || NULL == pOss)
  488. goto ErrorReturn;
  489. memcpy(pInfo, pOss, sizeof(RequestFlags));
  490. fResult = TRUE;
  491. goto CommonReturn;
  492. ParamError:
  493. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  494. fResult = FALSE;
  495. goto CommonReturn;
  496. LengthError:
  497. SetLastError((DWORD) ERROR_MORE_DATA);
  498. fResult = FALSE;
  499. goto CommonReturn;
  500. ErrorReturn:
  501. *pcbInfo = 0;
  502. fResult = FALSE;
  503. CommonReturn:
  504. if (NULL != pOss)
  505. {
  506. OssInfoFree(RequestFlags_PDU, pOss);
  507. }
  508. return fResult;
  509. }
  510. static BOOL WINAPI OssCSPProviderEncode(
  511. IN DWORD /*dwCertEncodingType*/,
  512. IN LPCSTR /*lpszStructType*/,
  513. IN PCRYPT_CSP_PROVIDER pCSPProvider,
  514. OUT BYTE *pbEncoded,
  515. IN OUT DWORD *pcbEncoded
  516. )
  517. {
  518. BOOL fResult;
  519. CSPProvider CspProvider;
  520. CspProvider.keySpec = (int) pCSPProvider->dwKeySpec;
  521. CspProvider.cspName.length = (DWORD)wcslen(pCSPProvider->pwszProviderName);
  522. CspProvider.cspName.value = pCSPProvider->pwszProviderName;
  523. OssUtilSetBitString(&pCSPProvider->Signature, &CspProvider.signature.length, &CspProvider.signature.value);
  524. fResult = OssInfoEncode(
  525. CSPProvider_PDU,
  526. &CspProvider,
  527. pbEncoded,
  528. pcbEncoded
  529. );
  530. return fResult;
  531. }
  532. static BOOL WINAPI OssNameValueEncode(
  533. IN DWORD /*dwCertEncodingType*/,
  534. IN LPCSTR /*lpszStructType*/,
  535. IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
  536. OUT BYTE *pbEncoded,
  537. IN OUT DWORD *pcbEncoded
  538. )
  539. {
  540. BOOL fResult;
  541. EnrollmentNameValuePair NameValue;
  542. NameValue.name.length = (DWORD)wcslen(pNameValue->pwszName);
  543. NameValue.name.value = pNameValue->pwszName;
  544. NameValue.value.length = (DWORD)wcslen(pNameValue->pwszValue);
  545. NameValue.value.value = pNameValue->pwszValue;
  546. fResult = OssInfoEncode(
  547. EnrollmentNameValuePair_PDU,
  548. &NameValue,
  549. pbEncoded,
  550. pcbEncoded
  551. );
  552. return fResult;
  553. }