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.

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