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.

1161 lines
32 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1996
  6. //
  7. // File: oidenc.c
  8. //
  9. // Contents: SCHANNEL encode/decode functions
  10. //
  11. // ASN.1 implementation uses the Asn1 compiler.
  12. //
  13. // Functions: InitSchannelAsn1
  14. // ShutdownSchannelAsn1
  15. //
  16. // History: 03-Dec-98 philh changed to use msasn1
  17. //
  18. //--------------------------------------------------------------------------
  19. #include <spbase.h>
  20. #include <pkiasn1.h>
  21. #include <crypttls.h>
  22. #include <oidenc.h>
  23. #include "asn1enc.h"
  24. // Nonstandard extension, function/data pointer conversion in expression
  25. #pragma warning (disable: 4152)
  26. VOID
  27. ReverseMemCopy(
  28. PUCHAR Dest,
  29. PUCHAR Source,
  30. ULONG Size) ;
  31. #define PRIVATE_KEY_TAG "private-key"
  32. // All the *pvInfo extra stuff needs to be aligned
  33. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  34. static HCRYPTASN1MODULE hAsn1Module;
  35. //+-------------------------------------------------------------------------
  36. // Function: GetEncoder/GetDecoder
  37. //
  38. // Synopsis: Initialize thread local storage for the asn libs
  39. //
  40. // Returns: pointer to an initialized Asn1 encoder/decoder data
  41. // structures
  42. //--------------------------------------------------------------------------
  43. static ASN1encoding_t GetEncoder(void)
  44. {
  45. return I_CryptGetAsn1Encoder(hAsn1Module);
  46. }
  47. static ASN1decoding_t GetDecoder(void)
  48. {
  49. return I_CryptGetAsn1Decoder(hAsn1Module);
  50. }
  51. //+-------------------------------------------------------------------------
  52. // Asn1 SCHANNEL Private Encode/Decode functions
  53. //--------------------------------------------------------------------------
  54. BOOL
  55. WINAPI
  56. Asn1RSAPublicEncode(
  57. IN DWORD dwCertEncodingType,
  58. IN LPCSTR lpszStructType,
  59. IN PUBLICKEYSTRUC *pbKeyStruc,
  60. OUT BYTE *pbEncoded,
  61. IN OUT DWORD *pcbEncoded
  62. );
  63. BOOL
  64. WINAPI
  65. Asn1PrivateKeyFileEncode(
  66. IN DWORD dwCertEncodingType,
  67. IN LPCSTR lpszStructType,
  68. IN PPRIVATE_KEY_FILE_ENCODE pKey,
  69. OUT BYTE *pbEncoded,
  70. IN OUT DWORD *pcbEncoded
  71. );
  72. BOOL
  73. WINAPI
  74. Asn1PrivateKeyFileDecode(
  75. IN DWORD dwCertEncodingType,
  76. IN LPCSTR lpszStructType,
  77. IN const BYTE *pbEncoded,
  78. IN DWORD cbEncoded,
  79. IN DWORD dwFlags,
  80. OUT PPRIVATE_KEY_FILE_ENCODE pKey,
  81. IN OUT DWORD *pcbKey
  82. );
  83. BOOL
  84. WINAPI
  85. Asn1PrivateKeyInfoEncode(
  86. IN DWORD dwCertEncodingType,
  87. IN LPCSTR lpszStructType,
  88. IN BLOBHEADER * pKey,
  89. OUT BYTE *pbEncoded,
  90. IN OUT DWORD *pcbEncoded
  91. );
  92. BOOL
  93. WINAPI
  94. Asn1PrivateKeyInfoDecode(
  95. IN DWORD dwCertEncodingType,
  96. IN LPCSTR lpszStructType,
  97. IN const BYTE *pbEncoded,
  98. IN DWORD cbEncoded,
  99. IN DWORD dwFlags,
  100. OUT BLOBHEADER * pKey,
  101. IN OUT DWORD *pcbKey
  102. );
  103. static BOOL WINAPI Asn1X509CtlUsageDecode(
  104. IN DWORD dwCertEncodingType,
  105. IN LPCSTR lpszStructType,
  106. IN const BYTE *pbEncoded,
  107. IN DWORD cbEncoded,
  108. IN DWORD dwFlags,
  109. OUT PCTL_USAGE pInfo,
  110. IN OUT DWORD *pcbInfo
  111. );
  112. static const CRYPT_OID_FUNC_ENTRY SchannelEncodeFuncTable[] = {
  113. szPrivateKeyFileEncode, Asn1PrivateKeyFileEncode,
  114. szPrivateKeyInfoEncode, Asn1PrivateKeyInfoEncode,
  115. szOID_RSA_RSA_Public, Asn1RSAPublicEncode
  116. };
  117. #define SCHANNEL_ENCODE_FUNC_COUNT (sizeof(SchannelEncodeFuncTable) / \
  118. sizeof(SchannelEncodeFuncTable[0]))
  119. static const CRYPT_OID_FUNC_ENTRY SchannelDecodeFuncTable[] = {
  120. szPrivateKeyFileEncode, Asn1PrivateKeyFileDecode,
  121. szPrivateKeyInfoEncode, Asn1PrivateKeyInfoDecode,
  122. X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageDecode
  123. };
  124. #define SCHANNEL_DECODE_FUNC_COUNT (sizeof(SchannelDecodeFuncTable) / \
  125. sizeof(SchannelDecodeFuncTable[0]))
  126. //+-------------------------------------------------------------------------
  127. // Dll initialization
  128. //--------------------------------------------------------------------------
  129. BOOL
  130. WINAPI
  131. InitSchannelAsn1(
  132. HMODULE hModule)
  133. {
  134. ASN1ENC_Module_Startup();
  135. if (0 == (hAsn1Module = I_CryptInstallAsn1Module(ASN1ENC_Module, 0, NULL)))
  136. {
  137. return FALSE;
  138. }
  139. if (!CryptInstallOIDFunctionAddress(
  140. hModule,
  141. X509_ASN_ENCODING,
  142. CRYPT_OID_DECODE_OBJECT_FUNC,
  143. SCHANNEL_DECODE_FUNC_COUNT,
  144. SchannelDecodeFuncTable,
  145. 0))
  146. {
  147. return FALSE;
  148. }
  149. if (!CryptInstallOIDFunctionAddress(
  150. hModule,
  151. X509_ASN_ENCODING,
  152. CRYPT_OID_ENCODE_OBJECT_FUNC,
  153. SCHANNEL_ENCODE_FUNC_COUNT,
  154. SchannelEncodeFuncTable,
  155. 0))
  156. {
  157. return FALSE;
  158. }
  159. return TRUE;
  160. }
  161. BOOL
  162. WINAPI
  163. ShutdownSchannelAsn1()
  164. {
  165. if (hAsn1Module)
  166. {
  167. I_CryptUninstallAsn1Module(hAsn1Module);
  168. ASN1ENC_Module_Cleanup();
  169. hAsn1Module = 0;
  170. }
  171. return TRUE;
  172. }
  173. //+-------------------------------------------------------------------------
  174. // Encode an Asn1 formatted info structure
  175. //
  176. // Called by the Asn1X509*Encode() functions.
  177. //--------------------------------------------------------------------------
  178. static BOOL Asn1InfoEncode(
  179. IN int pdunum,
  180. IN void *pAsn1Info,
  181. OUT BYTE *pbEncoded,
  182. IN OUT DWORD *pcbEncoded
  183. )
  184. {
  185. ASN1encoding_t Encoder;
  186. if((Encoder = GetEncoder()) == NULL)
  187. {
  188. return FALSE;
  189. }
  190. return PkiAsn1EncodeInfo(
  191. Encoder,
  192. pdunum,
  193. pAsn1Info,
  194. pbEncoded,
  195. pcbEncoded);
  196. }
  197. //+-------------------------------------------------------------------------
  198. // Encode an Asn1 formatted info structure
  199. //
  200. // Called by the Asn1X509*Encode() functions.
  201. //--------------------------------------------------------------------------
  202. static BOOL Asn1InfoEncodeAndAlloc(
  203. IN int pdunum,
  204. IN void *pAsn1Info,
  205. OUT BYTE **ppEncoded,
  206. IN OUT DWORD *pcbEncoded
  207. )
  208. {
  209. ASN1encoding_t Encoder;
  210. if((Encoder = GetEncoder()) == NULL)
  211. {
  212. return FALSE;
  213. }
  214. if(!PkiAsn1EncodeInfo(
  215. Encoder,
  216. pdunum,
  217. pAsn1Info,
  218. NULL,
  219. pcbEncoded))
  220. {
  221. return FALSE;
  222. }
  223. *ppEncoded = SPExternalAlloc(*pcbEncoded);
  224. if(*ppEncoded == NULL)
  225. {
  226. return FALSE;
  227. }
  228. if(!PkiAsn1EncodeInfo(
  229. Encoder,
  230. pdunum,
  231. pAsn1Info,
  232. *ppEncoded,
  233. pcbEncoded))
  234. {
  235. SPExternalFree(*ppEncoded);
  236. return FALSE;
  237. }
  238. return TRUE;
  239. }
  240. //+-------------------------------------------------------------------------
  241. // Decode into an allocated, Asn1 formatted info structure
  242. //
  243. // Called by the Asn1X509*Decode() functions.
  244. //--------------------------------------------------------------------------
  245. static BOOL Asn1InfoDecodeAndAlloc(
  246. IN int pdunum,
  247. IN const BYTE *pbEncoded,
  248. IN DWORD cbEncoded,
  249. OUT void **ppAsn1Info
  250. )
  251. {
  252. ASN1decoding_t Decoder;
  253. if((Decoder = GetDecoder()) == NULL)
  254. {
  255. return FALSE;
  256. }
  257. return PkiAsn1DecodeAndAllocInfo(
  258. Decoder,
  259. pdunum,
  260. pbEncoded,
  261. cbEncoded,
  262. ppAsn1Info);
  263. }
  264. //+-------------------------------------------------------------------------
  265. // Free an allocated, Asn1 formatted info structure
  266. //
  267. // Called by the Asn1X509*Decode() functions.
  268. //--------------------------------------------------------------------------
  269. static void Asn1InfoFree(
  270. IN int pdunum,
  271. IN void *pAsn1Info
  272. )
  273. {
  274. ASN1decoding_t Decoder;
  275. if((Decoder = GetDecoder()) == NULL)
  276. {
  277. return;
  278. }
  279. if (pAsn1Info)
  280. {
  281. DWORD dwErr = GetLastError();
  282. // TlsGetValue globbers LastError
  283. PkiAsn1FreeInfo(Decoder, pdunum, pAsn1Info);
  284. SetLastError(dwErr);
  285. }
  286. }
  287. SP_STATUS
  288. RsaPublicKeyFromCert(
  289. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  290. BLOBHEADER *pBlob,
  291. PDWORD pcbBlob)
  292. {
  293. SP_STATUS pctRet;
  294. if(!CryptDecodeObject(X509_ASN_ENCODING,
  295. RSA_CSP_PUBLICKEYBLOB,
  296. pPublicKeyInfo->PublicKey.pbData,
  297. pPublicKeyInfo->PublicKey.cbData,
  298. 0,
  299. pBlob,
  300. pcbBlob))
  301. {
  302. pctRet = GetLastError();
  303. return SP_LOG_RESULT(pctRet);
  304. }
  305. return PCT_ERR_OK;
  306. }
  307. /*****************************************************************************/
  308. SP_STATUS
  309. DssPublicKeyFromCert(
  310. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  311. BLOBHEADER *pBlob,
  312. PDWORD pcbBlob)
  313. {
  314. CRYPT_UINT_BLOB *pPublic = NULL;
  315. DWORD cbPublic;
  316. CERT_DSS_PARAMETERS *pParams = NULL;
  317. DWORD cbParams;
  318. DSSPUBKEY *pDssPubKey = NULL;
  319. DSSSEED *pSeed = NULL;
  320. PBYTE pbData = NULL;
  321. DWORD cbBlob;
  322. DWORD cbRequired;
  323. DWORD cbPadding;
  324. SP_STATUS pctRet;
  325. //
  326. // Estimate size of DSS public key blob.
  327. //
  328. if(!CryptDecodeObject(X509_ASN_ENCODING,
  329. X509_DSS_PUBLICKEY,
  330. pPublicKeyInfo->PublicKey.pbData,
  331. pPublicKeyInfo->PublicKey.cbData,
  332. 0,
  333. NULL,
  334. &cbPublic))
  335. {
  336. pctRet = GetLastError();
  337. return SP_LOG_RESULT(pctRet);
  338. }
  339. if(!CryptDecodeObject(X509_ASN_ENCODING,
  340. X509_DSS_PARAMETERS,
  341. pPublicKeyInfo->Algorithm.Parameters.pbData,
  342. pPublicKeyInfo->Algorithm.Parameters.cbData,
  343. 0,
  344. NULL,
  345. &cbParams))
  346. {
  347. pctRet = GetLastError();
  348. return SP_LOG_RESULT(pctRet);
  349. }
  350. cbBlob = sizeof(BLOBHEADER) +
  351. sizeof(DSSPUBKEY) +
  352. cbPublic +
  353. cbParams +
  354. sizeof(DSSSEED);
  355. if(pBlob == NULL)
  356. {
  357. *pcbBlob = cbBlob;
  358. return PCT_ERR_OK;
  359. }
  360. if(*pcbBlob < cbBlob)
  361. {
  362. *pcbBlob = cbBlob;
  363. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  364. }
  365. //
  366. // Decode public key info.
  367. //
  368. pPublic = SPExternalAlloc(cbPublic + cbParams);
  369. if(pPublic == NULL)
  370. {
  371. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  372. }
  373. pParams = (CERT_DSS_PARAMETERS *)((PBYTE)pPublic + cbPublic);
  374. if(!CryptDecodeObject(X509_ASN_ENCODING,
  375. X509_DSS_PUBLICKEY,
  376. pPublicKeyInfo->PublicKey.pbData,
  377. pPublicKeyInfo->PublicKey.cbData,
  378. 0,
  379. pPublic,
  380. &cbPublic))
  381. {
  382. pctRet = SP_LOG_RESULT(GetLastError());
  383. goto cleanup;
  384. }
  385. if(!CryptDecodeObject(X509_ASN_ENCODING,
  386. X509_DSS_PARAMETERS,
  387. pPublicKeyInfo->Algorithm.Parameters.pbData,
  388. pPublicKeyInfo->Algorithm.Parameters.cbData,
  389. 0,
  390. pParams,
  391. &cbParams))
  392. {
  393. pctRet = SP_LOG_RESULT(GetLastError());
  394. goto cleanup;
  395. }
  396. //
  397. // Double check size of memory allocated for blob. The G and Y
  398. // components may need to be padded out a little bit, but this
  399. // should always be less than the overhead in the params structure.
  400. // It doesn't hurt to make sure, though.
  401. //
  402. cbRequired = sizeof(BLOBHEADER) +
  403. sizeof(DSSPUBKEY) +
  404. pParams->p.cbData +
  405. pParams->q.cbData +
  406. max(pParams->p.cbData, pParams->g.cbData) +
  407. max(pParams->p.cbData, pPublic->cbData) +
  408. sizeof(DSSSEED);
  409. if(cbBlob < cbRequired)
  410. {
  411. *pcbBlob = cbRequired;
  412. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  413. }
  414. //
  415. // Build PUBLICKEYBLOB
  416. //
  417. pBlob->bType = PUBLICKEYBLOB;
  418. pBlob->bVersion = CUR_BLOB_VERSION;
  419. pBlob->reserved = 0;
  420. pBlob->aiKeyAlg = CALG_DSS_SIGN;
  421. pDssPubKey = (DSSPUBKEY *)(pBlob + 1);
  422. pDssPubKey->magic = MAGIC_DSS1;
  423. pDssPubKey->bitlen = pPublic->cbData * 8;
  424. pbData = (PBYTE)(pDssPubKey + 1);
  425. CopyMemory(pbData, pParams->p.pbData, pParams->p.cbData);
  426. pbData += pParams->p.cbData;
  427. CopyMemory(pbData, pParams->q.pbData, pParams->q.cbData);
  428. pbData += pParams->q.cbData;
  429. CopyMemory(pbData, pParams->g.pbData, pParams->g.cbData);
  430. pbData += pParams->g.cbData;
  431. if(pParams->g.cbData < pParams->p.cbData)
  432. {
  433. cbPadding = pParams->p.cbData - pParams->g.cbData;
  434. ZeroMemory(pbData, cbPadding);
  435. pbData += cbPadding;
  436. }
  437. CopyMemory(pbData, pPublic->pbData, pPublic->cbData);
  438. pbData += pPublic->cbData;
  439. if(pPublic->cbData < pParams->p.cbData)
  440. {
  441. cbPadding = pParams->p.cbData - pPublic->cbData;
  442. ZeroMemory(pbData, cbPadding);
  443. pbData += cbPadding;
  444. }
  445. pSeed = (DSSSEED *)pbData;
  446. pSeed->counter = 0xffffffff;
  447. ZeroMemory(pSeed->seed, sizeof(pSeed->seed));
  448. pbData += sizeof(DSSSEED);
  449. *pcbBlob = (DWORD)((PBYTE)pbData - (PBYTE)pBlob);
  450. pctRet = PCT_ERR_OK;
  451. cleanup:
  452. if(pPublic) SPExternalFree(pPublic);
  453. return pctRet;
  454. }
  455. #define my_isdigit(ch) ((ch >= '0') && (ch <= '9'))
  456. //+-------------------------------------------------------------------------
  457. // Convert the ascii string ("1.2.9999") to Asn1's Object Identifier
  458. // represented as an array of unsigned longs.
  459. //
  460. // Returns TRUE for a successful conversion.
  461. //--------------------------------------------------------------------------
  462. BOOL
  463. WINAPI
  464. OIDFromString(
  465. IN LPCSTR pszObjId,
  466. IN OUT unsigned short *pCount,
  467. OUT unsigned long rgulValue[]
  468. )
  469. {
  470. BOOL fResult = TRUE;
  471. unsigned short c = 0;
  472. LPSTR psz = (LPSTR) pszObjId;
  473. if (psz) {
  474. unsigned short cMax = *pCount;
  475. unsigned long *pul = rgulValue;
  476. while (*psz != '\0' && c++ < cMax) {
  477. *pul = 0;
  478. while (my_isdigit(*psz))
  479. {
  480. *pul = ((*pul) * 10) + (*psz++) - '0';
  481. }
  482. pul++;
  483. if (*psz != '.')
  484. break;
  485. psz++;
  486. }
  487. if (*psz != '\0')
  488. fResult = FALSE;
  489. }
  490. *pCount = c;
  491. return fResult;
  492. }
  493. BOOL
  494. WINAPI
  495. Asn1PrivateKeyInfoEncode(
  496. IN DWORD dwCertEncodingType,
  497. IN LPCSTR lpszStructType,
  498. IN BLOBHEADER * pKey,
  499. OUT BYTE *pbEncoded,
  500. IN OUT DWORD *pcbEncoded
  501. )
  502. {
  503. PrivateKeyInfo KeyInfo;
  504. BOOL fRet;
  505. UNREFERENCED_PARAMETER(dwCertEncodingType);
  506. UNREFERENCED_PARAMETER(lpszStructType);
  507. // First encode the private key data, depending on
  508. // the algorithm.
  509. switch(pKey->aiKeyAlg)
  510. {
  511. case CALG_RSA_SIGN:
  512. case CALG_RSA_KEYX:
  513. {
  514. RSAPUBKEY *pRsaPub = (RSAPUBKEY *)(pKey+1);
  515. RSAPrivateKey RsaPrivate;
  516. PBYTE pbRsaBlob, pbRsaBlobSav;
  517. PBYTE pbDataBlob = NULL, pbDataBlobSav;
  518. DWORD dwDataBlob = 0;
  519. // Covert the RSA key into the RSAPrivateKey structure
  520. RsaPrivate.version = 0;
  521. dwDataBlob = (9 * (pRsaPub->bitlen/16)) + 7 ;
  522. pbDataBlobSav = pbDataBlob = SPExternalAlloc(dwDataBlob);
  523. if(pbDataBlob == NULL)
  524. {
  525. return FALSE;
  526. }
  527. //Copy Modulus
  528. *pbDataBlob = 0;
  529. pbRsaBlobSav = pbRsaBlob = (PBYTE)(pRsaPub+1);
  530. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/8);
  531. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/8);
  532. RsaPrivate.modulus.value = pbDataBlob;
  533. RsaPrivate.modulus.length = (pRsaPub->bitlen/8) + 1;
  534. pbDataBlob += (pRsaPub->bitlen/8) + 1;
  535. pbRsaBlob += (pRsaPub->bitlen/8);
  536. RsaPrivate.publicExponent = pRsaPub->pubexp;
  537. //Copy Prime1
  538. *pbDataBlob = 0;
  539. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16);
  540. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
  541. RsaPrivate.prime1.value = pbDataBlob;
  542. RsaPrivate.prime1.length = (pRsaPub->bitlen/16) + 1;
  543. pbDataBlob += (pRsaPub->bitlen/16) + 1;
  544. pbRsaBlob += (pRsaPub->bitlen/16);
  545. //Copy Prime2
  546. *pbDataBlob = 0;
  547. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16);
  548. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
  549. RsaPrivate.prime2.value = pbDataBlob;
  550. RsaPrivate.prime2.length = (pRsaPub->bitlen/16) + 1;
  551. pbDataBlob += (pRsaPub->bitlen/16) + 1;
  552. pbRsaBlob += (pRsaPub->bitlen/16);
  553. //Copy exponent1
  554. *pbDataBlob = 0;
  555. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16);
  556. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
  557. RsaPrivate.exponent1.value = pbDataBlob;
  558. RsaPrivate.exponent1.length = (pRsaPub->bitlen/16) + 1;
  559. pbDataBlob += (pRsaPub->bitlen/16) + 1;
  560. pbRsaBlob += (pRsaPub->bitlen/16);
  561. //Copy exponent2
  562. *pbDataBlob = 0;
  563. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16);
  564. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
  565. RsaPrivate.exponent2.value = pbDataBlob;
  566. RsaPrivate.exponent2.length = (pRsaPub->bitlen/16) + 1;
  567. pbDataBlob += (pRsaPub->bitlen/16) + 1;
  568. pbRsaBlob += (pRsaPub->bitlen/16);
  569. //Copy coefficient
  570. *pbDataBlob = 0;
  571. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16);
  572. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
  573. RsaPrivate.coefficient.value = pbDataBlob;
  574. RsaPrivate.coefficient.length = (pRsaPub->bitlen/16) + 1;
  575. pbDataBlob += (pRsaPub->bitlen/16) + 1;
  576. pbRsaBlob += (pRsaPub->bitlen/16);
  577. //Copy privateExponent
  578. *pbDataBlob = 0;
  579. CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/8);
  580. PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/8);
  581. RsaPrivate.privateExponent.value = pbDataBlob;
  582. RsaPrivate.privateExponent.length = (pRsaPub->bitlen/8) + 1;
  583. pbDataBlob += (pRsaPub->bitlen/8) + 1;
  584. pbRsaBlob += (pRsaPub->bitlen/8);
  585. fRet = Asn1InfoEncodeAndAlloc(RSAPrivateKey_PDU,
  586. &RsaPrivate,
  587. &KeyInfo.privateKey.value,
  588. &KeyInfo.privateKey.length);
  589. SPExternalFree(pbDataBlobSav);
  590. if(!fRet)
  591. {
  592. return FALSE;
  593. }
  594. KeyInfo.privateKeyAlgorithm.bit_mask = 0;
  595. KeyInfo.privateKeyAlgorithm.algorithm.count =sizeof(KeyInfo.privateKeyAlgorithm.algorithm.value)/sizeof(KeyInfo.privateKeyAlgorithm.algorithm.value[0]);
  596. fRet = OIDFromString( szOID_RSA_RSA,
  597. &KeyInfo.privateKeyAlgorithm.algorithm.count,
  598. KeyInfo.privateKeyAlgorithm.algorithm.value);
  599. if(!fRet)
  600. {
  601. SPExternalFree(KeyInfo.privateKey.value);
  602. return FALSE;
  603. }
  604. break;
  605. }
  606. default:
  607. return FALSE;
  608. }
  609. // Set up the KeyInfo struct
  610. KeyInfo.bit_mask = 0;
  611. KeyInfo.version = 0;
  612. fRet = Asn1InfoEncode(
  613. PrivateKeyInfo_PDU,
  614. &KeyInfo,
  615. pbEncoded,
  616. pcbEncoded
  617. );
  618. SPExternalFree(KeyInfo.privateKey.value);
  619. return fRet;
  620. }
  621. BOOL
  622. WINAPI
  623. Asn1PrivateKeyFileEncode(
  624. IN DWORD dwCertEncodingType,
  625. IN LPCSTR lpszStructType,
  626. IN PPRIVATE_KEY_FILE_ENCODE pKey,
  627. OUT BYTE *pbEncoded,
  628. IN OUT DWORD *pcbEncoded
  629. )
  630. {
  631. PrivateKeyFile File;
  632. BOOL fRet;
  633. UNREFERENCED_PARAMETER(dwCertEncodingType);
  634. UNREFERENCED_PARAMETER(lpszStructType);
  635. File.privateKey.privateKey.value = pKey->EncryptedBlob.pbData;
  636. File.privateKey.privateKey.length = pKey->EncryptedBlob.cbData;
  637. File.privateKey.privateKeyAlgorithm.bit_mask = 0;
  638. File.privateKey.privateKeyAlgorithm.algorithm.count = sizeof(File.privateKey.privateKeyAlgorithm.algorithm.value)/sizeof(File.privateKey.privateKeyAlgorithm.algorithm.value[0]);
  639. OIDFromString( pKey->Alg.pszObjId,
  640. &File.privateKey.privateKeyAlgorithm.algorithm.count,
  641. File.privateKey.privateKeyAlgorithm.algorithm.value);
  642. File.name.value = (ASN1octet_t *)PRIVATE_KEY_TAG;
  643. File.name.length = lstrlen(PRIVATE_KEY_TAG);
  644. fRet = Asn1InfoEncode(
  645. PrivateKeyFile_PDU,
  646. &File,
  647. pbEncoded,
  648. pcbEncoded
  649. );
  650. return fRet;
  651. }
  652. BOOL
  653. WINAPI
  654. Asn1PrivateKeyInfoDecode(
  655. IN DWORD dwCertEncodingType,
  656. IN LPCSTR lpszStructType,
  657. IN const BYTE *pbEncoded,
  658. IN DWORD cbEncoded,
  659. IN DWORD dwFlags,
  660. OUT BLOBHEADER *pKey,
  661. IN OUT DWORD *pcbKey
  662. )
  663. {
  664. PrivateKeyInfo *pKeyInfo = NULL;
  665. DWORD cbKey;
  666. DWORD cbMod;
  667. BOOL fResult = FALSE;
  668. UNREFERENCED_PARAMETER(dwCertEncodingType);
  669. UNREFERENCED_PARAMETER(lpszStructType);
  670. UNREFERENCED_PARAMETER(dwFlags);
  671. // Now crack the key info
  672. fResult = Asn1InfoDecodeAndAlloc(PrivateKeyInfo_PDU,
  673. pbEncoded,
  674. cbEncoded,
  675. (void **)&pKeyInfo);
  676. if(!fResult)
  677. {
  678. return FALSE;
  679. }
  680. fResult = FALSE;
  681. do
  682. {
  683. USHORT cbOID;
  684. DWORD psOID[16];
  685. cbOID = sizeof(psOID)/sizeof(psOID[0]);
  686. OIDFromString( szOID_RSA_RSA,
  687. &cbOID,
  688. psOID);
  689. if((cbOID == pKeyInfo->privateKeyAlgorithm.algorithm.count) &&
  690. (memcmp(pKeyInfo->privateKeyAlgorithm.algorithm.value, psOID, cbOID*sizeof(psOID[0]))==0))
  691. {
  692. RSAPUBKEY * pRsaPub;
  693. RSAPrivateKey * pRsaPrivate = NULL;
  694. PBYTE pbCurrent;
  695. RSAPrivateKey RsaPrivate;
  696. fResult = Asn1InfoDecodeAndAlloc(RSAPrivateKey_PDU,
  697. pKeyInfo->privateKey.value,
  698. pKeyInfo->privateKey.length,
  699. (void **)&pRsaPrivate);
  700. if(!fResult)
  701. {
  702. break;
  703. }
  704. RsaPrivate = *pRsaPrivate;
  705. // We successfully decrypted an RSA Private Key,
  706. // so now turn it into a pRsaPub;
  707. // Make some adjustmenst to the lengths of things if we have leading zeros
  708. if(RsaPrivate.modulus.length && (0 == *(PBYTE)RsaPrivate.modulus.value))
  709. {
  710. RsaPrivate.modulus.value++;
  711. RsaPrivate.modulus.length--;
  712. }
  713. if(RsaPrivate.prime1.length && (0 == *(PBYTE)RsaPrivate.prime1.value))
  714. {
  715. RsaPrivate.prime1.value++;
  716. RsaPrivate.prime1.length--;
  717. }
  718. if(RsaPrivate.prime2.length && (0 == *(PBYTE)RsaPrivate.prime2.value))
  719. {
  720. RsaPrivate.prime2.value++;
  721. RsaPrivate.prime2.length--;
  722. }
  723. if(RsaPrivate.exponent1.length && (0 == *(PBYTE)RsaPrivate.exponent1.value))
  724. {
  725. RsaPrivate.exponent1.value++;
  726. RsaPrivate.exponent1.length--;
  727. }
  728. if(RsaPrivate.exponent2.length && (0 == *(PBYTE)RsaPrivate.exponent2.value))
  729. {
  730. RsaPrivate.exponent2.value++;
  731. RsaPrivate.exponent2.length--;
  732. }
  733. if(RsaPrivate.coefficient.length && (0 == *(PBYTE)RsaPrivate.coefficient.value))
  734. {
  735. RsaPrivate.coefficient.value++;
  736. RsaPrivate.coefficient.length--;
  737. }
  738. if(RsaPrivate.privateExponent.length && (0 == *(PBYTE)RsaPrivate.privateExponent.value))
  739. {
  740. RsaPrivate.privateExponent.value++;
  741. RsaPrivate.privateExponent.length--;
  742. }
  743. cbMod = (RsaPrivate.modulus.length + sizeof(DWORD) - 1) & ~(sizeof(DWORD)-1);
  744. cbKey = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (cbMod*9)/2;
  745. if(pKey == NULL)
  746. {
  747. *pcbKey = cbKey;
  748. fResult = TRUE;
  749. Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate);
  750. break;
  751. }
  752. // we're actually unpacking this key.
  753. if(*pcbKey < cbKey)
  754. {
  755. fResult = FALSE;
  756. Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate);
  757. break;
  758. }
  759. pKey->bType = PRIVATEKEYBLOB;
  760. pKey->bVersion = 2;
  761. pKey->reserved = 0;
  762. pKey->aiKeyAlg = CALG_RSA_KEYX;
  763. pRsaPub = (RSAPUBKEY *)(pKey+1);
  764. pRsaPub->magic = ((DWORD)'R'+((DWORD)'S'<<8)+((DWORD)'A'<<16)+((DWORD)'2'<<24));
  765. pRsaPub->bitlen = cbMod*8;
  766. pRsaPub->pubexp = RsaPrivate.publicExponent;
  767. pbCurrent = (PBYTE)(pRsaPub + 1);
  768. ReverseMemCopy(pbCurrent, RsaPrivate.modulus.value, RsaPrivate.modulus.length);
  769. pbCurrent += cbMod;
  770. ReverseMemCopy(pbCurrent, RsaPrivate.prime1.value, RsaPrivate.prime1.length);
  771. pbCurrent += cbMod/2;
  772. ReverseMemCopy(pbCurrent, RsaPrivate.prime2.value, RsaPrivate.prime2.length);
  773. pbCurrent += cbMod/2;
  774. ReverseMemCopy(pbCurrent, RsaPrivate.exponent1.value, RsaPrivate.exponent1.length);
  775. pbCurrent += cbMod/2;
  776. ReverseMemCopy(pbCurrent, RsaPrivate.exponent2.value, RsaPrivate.exponent2.length);
  777. pbCurrent += cbMod/2;
  778. ReverseMemCopy(pbCurrent, RsaPrivate.coefficient.value, RsaPrivate.coefficient.length);
  779. pbCurrent += cbMod/2;
  780. ReverseMemCopy(pbCurrent, RsaPrivate.privateExponent.value, RsaPrivate.privateExponent.length);
  781. pbCurrent += cbMod;
  782. *pcbKey = cbKey;
  783. Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate);
  784. }
  785. }while(FALSE);
  786. Asn1InfoFree(PrivateKeyInfo_PDU, pKeyInfo);
  787. return fResult;
  788. }
  789. BOOL
  790. WINAPI
  791. Asn1PrivateKeyFileDecode(
  792. IN DWORD dwCertEncodingType,
  793. IN LPCSTR lpszStructType,
  794. IN const BYTE *pbEncoded,
  795. IN DWORD cbEncoded,
  796. IN DWORD dwFlags,
  797. OUT PPRIVATE_KEY_FILE_ENCODE pKey,
  798. IN OUT DWORD *pcbKey
  799. )
  800. {
  801. PrivateKeyFile *pFile = NULL;
  802. DWORD cbPrivateKeyStruct;
  803. BOOL fResult = FALSE;
  804. UNREFERENCED_PARAMETER(dwCertEncodingType);
  805. UNREFERENCED_PARAMETER(lpszStructType);
  806. UNREFERENCED_PARAMETER(dwFlags);
  807. // Decode the file
  808. if(!Asn1InfoDecodeAndAlloc(PrivateKeyFile_PDU,
  809. pbEncoded,
  810. cbEncoded,
  811. (void **)&pFile))
  812. {
  813. return FALSE;
  814. }
  815. cbPrivateKeyStruct = pFile->privateKey.privateKey.length + sizeof(PRIVATE_KEY_FILE_ENCODE);
  816. if(pKey == NULL)
  817. {
  818. *pcbKey = cbPrivateKeyStruct;
  819. fResult = TRUE;
  820. }
  821. else
  822. {
  823. if(*pcbKey < cbPrivateKeyStruct)
  824. {
  825. fResult = FALSE;
  826. }
  827. else
  828. {
  829. pKey->EncryptedBlob.cbData = pFile->privateKey.privateKey.length;
  830. pKey->EncryptedBlob.pbData = (PBYTE)(pKey + 1);
  831. pKey->EncryptedBlob.cUnusedBits = 0;
  832. CopyMemory(pKey->EncryptedBlob.pbData, pFile->privateKey.privateKey.value, pKey->EncryptedBlob.cbData);
  833. fResult = TRUE;
  834. }
  835. }
  836. Asn1InfoFree(PrivateKeyFile_PDU, pFile);
  837. return fResult;
  838. }
  839. BOOL
  840. WINAPI
  841. Asn1RSAPublicEncode(
  842. IN DWORD dwCertEncodingType,
  843. IN LPCSTR lpszStructType,
  844. IN PUBLICKEYSTRUC *pbKeyStruc,
  845. OUT BYTE *pbEncoded,
  846. IN OUT DWORD *pcbEncoded
  847. )
  848. {
  849. UNREFERENCED_PARAMETER(lpszStructType);
  850. return CryptEncodeObject(dwCertEncodingType,
  851. RSA_CSP_PUBLICKEYBLOB,
  852. pbKeyStruc,
  853. pbEncoded,
  854. pcbEncoded);
  855. }
  856. static void Asn1X509GetObjId(
  857. IN ObjectID *pAsn1,
  858. IN DWORD dwFlags,
  859. OUT LPSTR *ppszObjId,
  860. IN OUT BYTE **ppbExtra,
  861. IN OUT LONG *plRemainExtra
  862. )
  863. {
  864. LONG lRemainExtra = *plRemainExtra;
  865. BYTE *pbExtra = *ppbExtra;
  866. LONG lAlignExtra;
  867. DWORD cbObjId;
  868. UNREFERENCED_PARAMETER(dwFlags);
  869. cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
  870. PkiAsn1FromObjectIdentifier(
  871. pAsn1->count,
  872. pAsn1->value,
  873. (LPSTR) pbExtra,
  874. &cbObjId
  875. );
  876. lAlignExtra = INFO_LEN_ALIGN(cbObjId);
  877. lRemainExtra -= lAlignExtra;
  878. if (lRemainExtra >= 0) {
  879. if(cbObjId) {
  880. *ppszObjId = (LPSTR) pbExtra;
  881. } else
  882. *ppszObjId = NULL;
  883. pbExtra += lAlignExtra;
  884. }
  885. *plRemainExtra = lRemainExtra;
  886. *ppbExtra = pbExtra;
  887. }
  888. static void Asn1X509GetCtlUsage(
  889. IN EnhancedKeyUsage *pAsn1,
  890. IN DWORD dwFlags,
  891. OUT PCTL_USAGE pUsage,
  892. IN OUT BYTE **ppbExtra,
  893. IN OUT LONG *plRemainExtra
  894. )
  895. {
  896. LONG lRemainExtra = *plRemainExtra;
  897. BYTE *pbExtra = *ppbExtra;
  898. LONG lAlignExtra;
  899. DWORD cId;
  900. UsageIdentifier *pAsn1Id;
  901. LPSTR *ppszId;
  902. cId = pAsn1->count;
  903. lAlignExtra = INFO_LEN_ALIGN(cId * sizeof(LPSTR));
  904. lRemainExtra -= lAlignExtra;
  905. if (lRemainExtra >= 0) {
  906. pUsage->cUsageIdentifier = cId;
  907. ppszId = (LPSTR *) pbExtra;
  908. pUsage->rgpszUsageIdentifier = ppszId;
  909. pbExtra += lAlignExtra;
  910. } else
  911. ppszId = NULL;
  912. pAsn1Id = pAsn1->value;
  913. for ( ; cId > 0; cId--, pAsn1Id++, ppszId++)
  914. Asn1X509GetObjId(pAsn1Id, dwFlags, ppszId, &pbExtra, &lRemainExtra);
  915. *plRemainExtra = lRemainExtra;
  916. *ppbExtra = pbExtra;
  917. }
  918. //+-------------------------------------------------------------------------
  919. // CTL Usage (Enhanced Key Usage) Decode (Asn1 X509)
  920. //--------------------------------------------------------------------------
  921. static BOOL WINAPI Asn1X509CtlUsageDecode(
  922. IN DWORD dwCertEncodingType,
  923. IN LPCSTR lpszStructType,
  924. IN const BYTE *pbEncoded,
  925. IN DWORD cbEncoded,
  926. IN DWORD dwFlags,
  927. OUT PCTL_USAGE pInfo,
  928. IN OUT DWORD *pcbInfo
  929. )
  930. {
  931. BOOL fResult;
  932. EnhancedKeyUsage *pAsn1Info = NULL;
  933. BYTE *pbExtra;
  934. LONG lRemainExtra;
  935. UNREFERENCED_PARAMETER(dwCertEncodingType);
  936. UNREFERENCED_PARAMETER(lpszStructType);
  937. if (pInfo == NULL)
  938. *pcbInfo = 0;
  939. if (!Asn1InfoDecodeAndAlloc(
  940. EnhancedKeyUsage_PDU,
  941. pbEncoded,
  942. cbEncoded,
  943. (void **) &pAsn1Info))
  944. goto ErrorReturn;
  945. // for lRemainExtra < 0, LENGTH_ONLY calculation
  946. lRemainExtra = (LONG) *pcbInfo - sizeof(CTL_USAGE);
  947. if (lRemainExtra < 0) {
  948. pbExtra = NULL;
  949. } else
  950. pbExtra = (BYTE *) pInfo + sizeof(CTL_USAGE);
  951. Asn1X509GetCtlUsage(pAsn1Info, dwFlags, pInfo, &pbExtra, &lRemainExtra);
  952. if (lRemainExtra >= 0)
  953. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  954. else {
  955. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  956. if (pInfo) goto LengthError;
  957. }
  958. fResult = TRUE;
  959. goto CommonReturn;
  960. LengthError:
  961. SetLastError((DWORD) ERROR_MORE_DATA);
  962. fResult = FALSE;
  963. goto CommonReturn;
  964. ErrorReturn:
  965. *pcbInfo = 0;
  966. fResult = FALSE;
  967. CommonReturn:
  968. Asn1InfoFree(EnhancedKeyUsage_PDU, pAsn1Info);
  969. return fResult;
  970. }