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.

1157 lines
34 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: certhlpr.cpp
  8. //
  9. // Contents: import and export of private keys
  10. //
  11. // Functions: ImportExoprtDllMain
  12. // CryptImportPKCS8
  13. // CryptExportPKCS8
  14. //
  15. // History:
  16. //--------------------------------------------------------------------------
  17. #include "global.hxx"
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. #include "prvtkey.h"
  22. #ifdef __cplusplus
  23. } // Balance extern "C" above
  24. #endif
  25. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  26. static const BYTE NullDer[2] = {0x05, 0x00};
  27. static const CRYPT_OBJID_BLOB NullDerBlob = {2, (BYTE *)&NullDer[0]};
  28. static HCRYPTASN1MODULE hPrivateKeyAsn1Module;
  29. static HCRYPTOIDFUNCSET hEncodePrivKeyFuncSet;
  30. static HCRYPTOIDFUNCSET hDecodePrivKeyFuncSet;
  31. //+-------------------------------------------------------------------------
  32. // OSS ASN.1 PKCS#8 PrivateKey Encode / Decode functions
  33. //--------------------------------------------------------------------------
  34. static BOOL WINAPI OssRSAPrivateKeyStrucEncode(
  35. IN DWORD dwCertEncodingType,
  36. IN LPCSTR lpszStructType,
  37. IN BLOBHEADER *pBlobHeader,
  38. OUT BYTE *pbEncoded,
  39. IN OUT DWORD *pcbEncoded
  40. );
  41. static BOOL WINAPI OssRSAPrivateKeyStrucDecode(
  42. IN DWORD dwCertEncodingType,
  43. IN LPCSTR lpszStructType,
  44. IN const BYTE *pbEncoded,
  45. IN DWORD cbEncoded,
  46. IN DWORD dwFlags,
  47. OUT BLOBHEADER *pBlobHeader,
  48. IN OUT DWORD *pcbBlobHeader
  49. );
  50. static BOOL WINAPI OssPrivateKeyInfoEncode(
  51. IN DWORD dwCertEncodingType,
  52. IN LPCSTR lpszStructType,
  53. IN PCRYPT_PRIVATE_KEY_INFO pInfo,
  54. OUT BYTE *pbEncoded,
  55. IN OUT DWORD *pcbEncoded
  56. );
  57. static BOOL WINAPI OssPrivateKeyInfoDecode(
  58. IN DWORD dwCertEncodingType,
  59. IN LPCSTR lpszStructType,
  60. IN const BYTE *pbEncoded,
  61. IN DWORD cbEncoded,
  62. IN DWORD dwFlags,
  63. OUT PCRYPT_PRIVATE_KEY_INFO pInfo,
  64. IN OUT DWORD *pcbInfo
  65. );
  66. static BOOL WINAPI OssEncryptedPrivateKeyInfoEncode(
  67. IN DWORD dwCertEncodingType,
  68. IN LPCSTR lpszStructType,
  69. IN PCRYPT_ENCRYPTED_PRIVATE_KEY_INFO pInfo,
  70. OUT BYTE *pbEncoded,
  71. IN OUT DWORD *pcbEncoded
  72. );
  73. static BOOL WINAPI OssEncryptedPrivateKeyInfoDecode(
  74. IN DWORD dwCertEncodingType,
  75. IN LPCSTR lpszStructType,
  76. IN const BYTE *pbEncoded,
  77. IN DWORD cbEncoded,
  78. IN DWORD dwFlags,
  79. OUT PCRYPT_ENCRYPTED_PRIVATE_KEY_INFO pInfo,
  80. IN OUT DWORD *pcbInfo
  81. );
  82. static const CRYPT_OID_FUNC_ENTRY PrivateKeyEncodeFuncTable[] = {
  83. PKCS_RSA_PRIVATE_KEY, OssRSAPrivateKeyStrucEncode,
  84. PKCS_PRIVATE_KEY_INFO, OssPrivateKeyInfoEncode,
  85. PKCS_ENCRYPTED_PRIVATE_KEY_INFO, OssEncryptedPrivateKeyInfoEncode
  86. };
  87. #define PRIVATEKEY_ENCODE_FUNC_COUNT (sizeof(PrivateKeyEncodeFuncTable) / \
  88. sizeof(PrivateKeyEncodeFuncTable[0]))
  89. static const CRYPT_OID_FUNC_ENTRY PrivateKeyDecodeFuncTable[] = {
  90. PKCS_RSA_PRIVATE_KEY, OssRSAPrivateKeyStrucDecode,
  91. PKCS_PRIVATE_KEY_INFO, OssPrivateKeyInfoDecode,
  92. PKCS_ENCRYPTED_PRIVATE_KEY_INFO, OssEncryptedPrivateKeyInfoDecode,
  93. };
  94. #define PRIVATEKEY_DECODE_FUNC_COUNT (sizeof(PrivateKeyDecodeFuncTable) / \
  95. sizeof(PrivateKeyDecodeFuncTable[0]))
  96. BOOL
  97. WINAPI
  98. EncodeDecodeDllMain(
  99. HMODULE hInst,
  100. ULONG ul_reason_for_call,
  101. LPVOID lpReserved)
  102. {
  103. switch( ul_reason_for_call )
  104. {
  105. case DLL_PROCESS_ATTACH:
  106. if (NULL == (hEncodePrivKeyFuncSet = CryptInitOIDFunctionSet(
  107. CRYPT_OID_ENCODE_OBJECT_FUNC,
  108. 0)))
  109. goto ErrorReturn;
  110. if (NULL == (hDecodePrivKeyFuncSet = CryptInitOIDFunctionSet(
  111. CRYPT_OID_DECODE_OBJECT_FUNC,
  112. 0)))
  113. goto ErrorReturn;
  114. if (!CryptInstallOIDFunctionAddress(
  115. NULL, // hModule
  116. X509_ASN_ENCODING,
  117. CRYPT_OID_ENCODE_OBJECT_FUNC,
  118. PRIVATEKEY_ENCODE_FUNC_COUNT,
  119. PrivateKeyEncodeFuncTable,
  120. 0)) // dwFlags
  121. goto ErrorReturn;
  122. if (!CryptInstallOIDFunctionAddress(
  123. NULL, // hModule
  124. X509_ASN_ENCODING,
  125. CRYPT_OID_DECODE_OBJECT_FUNC,
  126. PRIVATEKEY_DECODE_FUNC_COUNT,
  127. PrivateKeyDecodeFuncTable,
  128. 0)) // dwFlags
  129. goto ErrorReturn;
  130. #ifdef OSS_CRYPT_ASN1
  131. if (0 == (hPrivateKeyAsn1Module =
  132. I_CryptInstallAsn1Module(prvtkey, 0, NULL)) )
  133. goto ErrorReturn;
  134. #else
  135. PRVTKEY_Module_Startup();
  136. if (0 == (hPrivateKeyAsn1Module = I_CryptInstallAsn1Module(
  137. PRVTKEY_Module, 0, NULL))) {
  138. PRVTKEY_Module_Cleanup();
  139. goto ErrorReturn;
  140. }
  141. #endif // OSS_CRYPT_ASN1
  142. break;
  143. case DLL_PROCESS_DETACH:
  144. I_CryptUninstallAsn1Module(hPrivateKeyAsn1Module);
  145. #ifndef OSS_CRYPT_ASN1
  146. PRVTKEY_Module_Cleanup();
  147. #endif // OSS_CRYPT_ASN1
  148. break;
  149. default:
  150. break;
  151. }
  152. return TRUE;
  153. ErrorReturn:
  154. return FALSE;
  155. }
  156. static inline ASN1encoding_t GetEncoder(void)
  157. {
  158. return I_CryptGetAsn1Encoder(hPrivateKeyAsn1Module);
  159. }
  160. static inline ASN1decoding_t GetDecoder(void)
  161. {
  162. return I_CryptGetAsn1Decoder(hPrivateKeyAsn1Module);
  163. }
  164. //+-------------------------------------------------------------------------
  165. // Encode an OSS formatted info structure
  166. //
  167. // Called by the OssX509*Encode() functions.
  168. //--------------------------------------------------------------------------
  169. static BOOL OssInfoEncode(
  170. IN int pdunum,
  171. IN void *pOssInfo,
  172. OUT BYTE *pbEncoded,
  173. IN OUT DWORD *pcbEncoded
  174. )
  175. {
  176. return PkiAsn1EncodeInfo(
  177. GetEncoder(),
  178. pdunum,
  179. pOssInfo,
  180. pbEncoded,
  181. pcbEncoded);
  182. }
  183. //+-------------------------------------------------------------------------
  184. // Decode into an allocated, OSS formatted info structure
  185. //
  186. // Called by the OssX509*Decode() functions.
  187. //--------------------------------------------------------------------------
  188. static BOOL OssInfoDecodeAndAlloc(
  189. IN int pdunum,
  190. IN const BYTE *pbEncoded,
  191. IN DWORD cbEncoded,
  192. OUT void **ppOssInfo
  193. )
  194. {
  195. return PkiAsn1DecodeAndAllocInfo(
  196. GetDecoder(),
  197. pdunum,
  198. pbEncoded,
  199. cbEncoded,
  200. ppOssInfo);
  201. }
  202. //+-------------------------------------------------------------------------
  203. // Free an allocated, OSS formatted info structure
  204. //
  205. // Called by the OssX509*Decode() functions.
  206. //--------------------------------------------------------------------------
  207. static void OssInfoFree(
  208. IN int pdunum,
  209. IN void *pOssInfo
  210. )
  211. {
  212. if (pOssInfo) {
  213. DWORD dwErr = GetLastError();
  214. // TlsGetValue globbers LastError
  215. PkiAsn1FreeInfo(GetDecoder(), pdunum, pOssInfo);
  216. SetLastError(dwErr);
  217. }
  218. }
  219. //+-------------------------------------------------------------------------
  220. // Set/Get CRYPT_DATA_BLOB (Octet String)
  221. //--------------------------------------------------------------------------
  222. static inline void OssX509SetOctetString(
  223. IN PCRYPT_DATA_BLOB pInfo,
  224. OUT OCTETSTRING *pOss
  225. )
  226. {
  227. pOss->value = pInfo->pbData;
  228. pOss->length = pInfo->cbData;
  229. }
  230. static inline void OssX509GetOctetString(
  231. IN OCTETSTRING *pOss,
  232. IN DWORD dwFlags,
  233. OUT PCRYPT_DATA_BLOB pInfo,
  234. IN OUT BYTE **ppbExtra,
  235. IN OUT LONG *plRemainExtra
  236. )
  237. {
  238. PkiAsn1GetOctetString(pOss->length, pOss->value, dwFlags,
  239. pInfo, ppbExtra, plRemainExtra);
  240. }
  241. //+-------------------------------------------------------------------------
  242. // Set/Get Object Identifier string
  243. //--------------------------------------------------------------------------
  244. static BOOL OssX509SetObjId(
  245. IN LPSTR pszObjId,
  246. OUT ObjectID *pOss
  247. )
  248. {
  249. pOss->count = sizeof(pOss->value) / sizeof(pOss->value[0]);
  250. if (PkiAsn1ToObjectIdentifier(pszObjId, &pOss->count, pOss->value))
  251. return TRUE;
  252. else {
  253. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  254. return FALSE;
  255. }
  256. }
  257. static void OssX509GetObjId(
  258. IN ObjectID *pOss,
  259. IN DWORD dwFlags,
  260. OUT LPSTR *ppszObjId,
  261. IN OUT BYTE **ppbExtra,
  262. IN OUT LONG *plRemainExtra
  263. )
  264. {
  265. LONG lRemainExtra = *plRemainExtra;
  266. BYTE *pbExtra = *ppbExtra;
  267. LONG lAlignExtra;
  268. DWORD cbObjId;
  269. cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
  270. PkiAsn1FromObjectIdentifier(
  271. pOss->count,
  272. pOss->value,
  273. (LPSTR) pbExtra,
  274. &cbObjId
  275. );
  276. lAlignExtra = INFO_LEN_ALIGN(cbObjId);
  277. lRemainExtra -= lAlignExtra;
  278. if (lRemainExtra >= 0) {
  279. if(cbObjId) {
  280. *ppszObjId = (LPSTR) pbExtra;
  281. } else
  282. *ppszObjId = NULL;
  283. pbExtra += lAlignExtra;
  284. }
  285. *plRemainExtra = lRemainExtra;
  286. *ppbExtra = pbExtra;
  287. }
  288. //+-------------------------------------------------------------------------
  289. // Set/Get "Any" DER BLOB
  290. //--------------------------------------------------------------------------
  291. static inline void OssX509SetAny(
  292. IN PCRYPT_OBJID_BLOB pInfo,
  293. OUT NOCOPYANY *pOss
  294. )
  295. {
  296. #ifdef OSS_CRYPT_ASN1
  297. PkiAsn1SetAny(pInfo, (OpenType *) pOss);
  298. #else
  299. PkiAsn1SetAny(pInfo, pOss);
  300. #endif // OSS_CRYPT_ASN1
  301. }
  302. static inline void OssX509GetAny(
  303. IN NOCOPYANY *pOss,
  304. IN DWORD dwFlags,
  305. OUT PCRYPT_OBJID_BLOB pInfo,
  306. IN OUT BYTE **ppbExtra,
  307. IN OUT LONG *plRemainExtra
  308. )
  309. {
  310. #ifdef OSS_CRYPT_ASN1
  311. PkiAsn1GetAny((OpenType *) pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
  312. #else
  313. PkiAsn1GetAny(pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
  314. #endif // OSS_CRYPT_ASN1
  315. }
  316. //+-------------------------------------------------------------------------
  317. // Set/Free/Get SeqOfAny
  318. //--------------------------------------------------------------------------
  319. static BOOL WINAPI OssX509SetSeqOfAny(
  320. IN DWORD cValue,
  321. IN PCRYPT_DER_BLOB pValue,
  322. #ifdef OSS_CRYPT_ASN1
  323. OUT unsigned int *pOssCount,
  324. #else
  325. OUT ASN1uint32_t *pOssCount,
  326. #endif // OSS_CRYPT_ASN1
  327. OUT NOCOPYANY **ppOssValue
  328. )
  329. {
  330. *pOssCount = 0;
  331. *ppOssValue = NULL;
  332. if (cValue > 0) {
  333. NOCOPYANY *pOssValue;
  334. pOssValue = (NOCOPYANY *) SSAlloc(cValue * sizeof(NOCOPYANY));
  335. if (pOssValue == NULL)
  336. return FALSE;
  337. memset(pOssValue, 0, cValue * sizeof(NOCOPYANY));
  338. *pOssCount = cValue;
  339. *ppOssValue = pOssValue;
  340. for ( ; cValue > 0; cValue--, pValue++, pOssValue++)
  341. OssX509SetAny(pValue, pOssValue);
  342. }
  343. return TRUE;
  344. }
  345. static void OssX509FreeSeqOfAny(
  346. IN NOCOPYANY *pOssValue
  347. )
  348. {
  349. if (pOssValue)
  350. SSFree(pOssValue);
  351. }
  352. static void OssX509GetSeqOfAny(
  353. IN unsigned int OssCount,
  354. IN NOCOPYANY *pOssValue,
  355. IN DWORD dwFlags,
  356. OUT DWORD *pcValue,
  357. OUT PCRYPT_DER_BLOB *ppValue,
  358. IN OUT BYTE **ppbExtra,
  359. IN OUT LONG *plRemainExtra
  360. )
  361. {
  362. LONG lAlignExtra;
  363. PCRYPT_ATTR_BLOB pValue;
  364. lAlignExtra = INFO_LEN_ALIGN(OssCount * sizeof(CRYPT_DER_BLOB));
  365. *plRemainExtra -= lAlignExtra;
  366. if (*plRemainExtra >= 0) {
  367. *pcValue = OssCount;
  368. pValue = (PCRYPT_DER_BLOB) *ppbExtra;
  369. *ppValue = pValue;
  370. *ppbExtra += lAlignExtra;
  371. } else
  372. pValue = NULL;
  373. for (; OssCount > 0; OssCount--, pOssValue++, pValue++)
  374. OssX509GetAny(pOssValue, dwFlags, pValue, ppbExtra, plRemainExtra);
  375. }
  376. //+-------------------------------------------------------------------------
  377. // Set/Free/Get CRYPT_ATTRIBUTE
  378. //--------------------------------------------------------------------------
  379. static BOOL WINAPI OssX509SetAttribute(
  380. IN PCRYPT_ATTRIBUTE pInfo,
  381. OUT Attribute *pOss
  382. )
  383. {
  384. memset(pOss, 0, sizeof(*pOss));
  385. if (!OssX509SetObjId(pInfo->pszObjId, &pOss->type))
  386. return FALSE;
  387. return OssX509SetSeqOfAny(
  388. pInfo->cValue,
  389. pInfo->rgValue,
  390. &pOss->values.count,
  391. &pOss->values.value);
  392. }
  393. static void OssX509FreeAttribute(
  394. IN OUT Attribute *pOss
  395. )
  396. {
  397. OssX509FreeSeqOfAny(pOss->values.value);
  398. }
  399. static void OssX509GetAttribute(
  400. IN Attribute *pOss,
  401. IN DWORD dwFlags,
  402. OUT PCRYPT_ATTRIBUTE pInfo,
  403. IN OUT BYTE **ppbExtra,
  404. IN OUT LONG *plRemainExtra
  405. )
  406. {
  407. OssX509GetObjId(&pOss->type, dwFlags,
  408. &pInfo->pszObjId, ppbExtra, plRemainExtra);
  409. OssX509GetSeqOfAny(pOss->values.count, pOss->values.value, dwFlags,
  410. &pInfo->cValue, &pInfo->rgValue, ppbExtra, plRemainExtra);
  411. }
  412. //+-------------------------------------------------------------------------
  413. // Set/Get CRYPT_ALGORITHM_IDENTIFIER
  414. //--------------------------------------------------------------------------
  415. static BOOL OssX509SetAlgorithm(
  416. IN PCRYPT_ALGORITHM_IDENTIFIER pInfo,
  417. OUT AlgorithmIdentifier *pOss
  418. )
  419. {
  420. memset(pOss, 0, sizeof(*pOss));
  421. if (pInfo->pszObjId) {
  422. if (!OssX509SetObjId(pInfo->pszObjId, &pOss->algorithm))
  423. return FALSE;
  424. if (pInfo->Parameters.cbData)
  425. OssX509SetAny(&pInfo->Parameters, &pOss->parameters);
  426. else
  427. // Per PKCS #1: default to the ASN.1 type NULL.
  428. OssX509SetAny((PCRYPT_OBJID_BLOB) &NullDerBlob, &pOss->parameters);
  429. pOss->bit_mask |= parameters_present;
  430. }
  431. return TRUE;
  432. }
  433. static void OssX509GetAlgorithm(
  434. IN AlgorithmIdentifier *pOss,
  435. IN DWORD dwFlags,
  436. OUT PCRYPT_ALGORITHM_IDENTIFIER pInfo,
  437. IN OUT BYTE **ppbExtra,
  438. IN OUT LONG *plRemainExtra
  439. )
  440. {
  441. if (*plRemainExtra >= 0)
  442. memset(pInfo, 0, sizeof(*pInfo));
  443. OssX509GetObjId(&pOss->algorithm, dwFlags, &pInfo->pszObjId,
  444. ppbExtra, plRemainExtra);
  445. if (pOss->bit_mask & parameters_present)
  446. OssX509GetAny(&pOss->parameters, dwFlags, &pInfo->Parameters,
  447. ppbExtra, plRemainExtra);
  448. }
  449. //+-------------------------------------------------------------------------
  450. // Helper function for Encode RSA Private Key
  451. //--------------------------------------------------------------------------
  452. static BOOL WINAPI AllocAndCopyHugeInteger(
  453. IN BYTE *pbHugeInteger,
  454. IN DWORD cbHugeInteger,
  455. OUT HUGEINTEGER *pHugeInteger
  456. )
  457. {
  458. BYTE *pbAllocBuffer = NULL;
  459. if (NULL == (pbAllocBuffer = (BYTE *) SSAlloc(cbHugeInteger + 1)))
  460. return FALSE;
  461. *pbAllocBuffer = 0;
  462. memcpy(pbAllocBuffer + 1, pbHugeInteger, cbHugeInteger);
  463. PkiAsn1ReverseBytes(pbAllocBuffer + 1, cbHugeInteger);
  464. pHugeInteger->length = cbHugeInteger + 1;
  465. pHugeInteger->value = pbAllocBuffer;
  466. return TRUE;
  467. }
  468. #ifndef RSA2
  469. #define RSA2 ((DWORD)'R'+((DWORD)'S'<<8)+((DWORD)'A'<<16)+((DWORD)'2'<<24))
  470. #endif
  471. //+-------------------------------------------------------------------------
  472. // Encode RSA Private Key
  473. //--------------------------------------------------------------------------
  474. static BOOL WINAPI OssRSAPrivateKeyStrucEncode(
  475. IN DWORD dwCertEncodingType,
  476. IN LPCSTR lpszStructType,
  477. IN BLOBHEADER *pBlobHeader,
  478. OUT BYTE *pbEncoded,
  479. IN OUT DWORD *pcbEncoded
  480. )
  481. {
  482. BOOL fResult;
  483. BYTE *pbKeyBlob;
  484. RSAPUBKEY *pRsaPubKey;
  485. BYTE *pbCurrentHugeInteger;
  486. DWORD cbHugeInteger;
  487. BYTE *pbAllocBuffer = NULL;
  488. RSAPrivateKey OssRSAPrivateKey;
  489. memset(&OssRSAPrivateKey, 0, (size_t) sizeof(RSAPrivateKey));
  490. // The CAPI RSA private key representation consists of the following sequence:
  491. // - BLOBHEADER blobheader;
  492. // - RSAPUBKEY rsapubkey;
  493. // - BYTE modulus[rsapubkey.bitlen/8];
  494. // - BYTE prime1[rsapubkey.bitlen/16];
  495. // - BYTE prime2[rsapubkey.bitlen/16];
  496. // - BYTE exponent1[rsapubkey.bitlen/16];
  497. // - BYTE exponent2[rsapubkey.bitlen/16];
  498. // - BYTE coefficient[rsapubkey.bitlen/16];
  499. // - BYTE privateExponent[rsapubkey.bitlen/8];
  500. pbKeyBlob = (BYTE *) pBlobHeader;
  501. pRsaPubKey = (RSAPUBKEY *) (pbKeyBlob + sizeof(BLOBHEADER));
  502. assert(pRsaPubKey->bitlen / 8 > 0);
  503. assert(pBlobHeader->bType == PRIVATEKEYBLOB);
  504. assert(pBlobHeader->bVersion == CUR_BLOB_VERSION);
  505. assert(pBlobHeader->aiKeyAlg == CALG_RSA_SIGN ||
  506. pBlobHeader->aiKeyAlg == CALG_RSA_KEYX);
  507. assert(pRsaPubKey->magic == RSA2);
  508. assert(pRsaPubKey->bitlen % 8 == 0);
  509. if (pBlobHeader->bType != PRIVATEKEYBLOB)
  510. goto InvalidArg;
  511. // PKCS #1 ASN.1 encode
  512. //
  513. // ASN.1 isn't reversing HUGE_INTEGERs. Also, after doing the
  514. // reversal insert a leading 0 byte to force it to always be treated
  515. // as an unsigned integer
  516. OssRSAPrivateKey.version = 0; // currently on version 0
  517. // MODULUS
  518. pbCurrentHugeInteger = pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY);
  519. cbHugeInteger = pRsaPubKey->bitlen / 8;
  520. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  521. cbHugeInteger,
  522. &(OssRSAPrivateKey.modulus)))
  523. goto ErrorReturn;
  524. // PUBLIC EXPONENT
  525. OssRSAPrivateKey.publicExponent = pRsaPubKey->pubexp;
  526. // PRIME1
  527. pbCurrentHugeInteger += cbHugeInteger;
  528. cbHugeInteger = pRsaPubKey->bitlen / 16;
  529. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  530. cbHugeInteger,
  531. &(OssRSAPrivateKey.prime1)))
  532. goto ErrorReturn;
  533. // PRIME2
  534. pbCurrentHugeInteger += cbHugeInteger;
  535. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  536. cbHugeInteger,
  537. &(OssRSAPrivateKey.prime2)))
  538. goto ErrorReturn;
  539. // EXPONENT1
  540. pbCurrentHugeInteger += cbHugeInteger;
  541. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  542. cbHugeInteger,
  543. &(OssRSAPrivateKey.exponent1)))
  544. goto ErrorReturn;
  545. // EXPONENT2
  546. pbCurrentHugeInteger += cbHugeInteger;
  547. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  548. cbHugeInteger,
  549. &(OssRSAPrivateKey.exponent2)))
  550. goto ErrorReturn;
  551. // COEFFICIENT
  552. pbCurrentHugeInteger += cbHugeInteger;
  553. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  554. cbHugeInteger,
  555. &(OssRSAPrivateKey.coefficient)))
  556. goto ErrorReturn;
  557. // PRIVATE EXPONENT
  558. pbCurrentHugeInteger += cbHugeInteger;
  559. cbHugeInteger = pRsaPubKey->bitlen / 8;
  560. if (!AllocAndCopyHugeInteger(pbCurrentHugeInteger,
  561. cbHugeInteger,
  562. &(OssRSAPrivateKey.privateExponent)))
  563. goto ErrorReturn;
  564. fResult = OssInfoEncode(
  565. RSAPrivateKey_PDU,
  566. &OssRSAPrivateKey,
  567. pbEncoded,
  568. pcbEncoded
  569. );
  570. goto CommonReturn;
  571. InvalidArg:
  572. SetLastError((DWORD) E_INVALIDARG);
  573. ErrorReturn:
  574. *pcbEncoded = 0;
  575. fResult = FALSE;
  576. CommonReturn:
  577. if (OssRSAPrivateKey.modulus.value)
  578. SSFree(OssRSAPrivateKey.modulus.value);
  579. if (OssRSAPrivateKey.prime1.value)
  580. SSFree(OssRSAPrivateKey.prime1.value);
  581. if (OssRSAPrivateKey.prime2.value)
  582. SSFree(OssRSAPrivateKey.prime2.value);
  583. if (OssRSAPrivateKey.exponent1.value)
  584. SSFree(OssRSAPrivateKey.exponent1.value);
  585. if (OssRSAPrivateKey.exponent2.value)
  586. SSFree(OssRSAPrivateKey.exponent2.value);
  587. if (OssRSAPrivateKey.coefficient.value)
  588. SSFree(OssRSAPrivateKey.coefficient.value);
  589. if (OssRSAPrivateKey.privateExponent.value)
  590. SSFree(OssRSAPrivateKey.privateExponent.value);
  591. return fResult;
  592. }
  593. //+-------------------------------------------------------------------------
  594. // Helper function for Decode RSA Private Key
  595. //--------------------------------------------------------------------------
  596. static BOOL WINAPI CopyHugeIntegerToByteArray(
  597. HUGEINTEGER *pHugeInteger,
  598. BYTE *pbBuffer,
  599. DWORD cbBuffer,
  600. BOOL fGetRidOfLeading0)
  601. {
  602. memset(pbBuffer, 0, (size_t) cbBuffer);
  603. DWORD cbHugeInteger = pHugeInteger->length;
  604. BYTE *pbHugeInteger = pHugeInteger->value;
  605. // get rid of leading zero on the huge integer
  606. if ((cbHugeInteger > 1) &&
  607. (*pbHugeInteger == 0) &&
  608. (fGetRidOfLeading0))
  609. {
  610. pbHugeInteger++;
  611. cbHugeInteger--;
  612. }
  613. else if ((cbHugeInteger > cbBuffer) &&
  614. (*pbHugeInteger != 0) &&
  615. (fGetRidOfLeading0))
  616. {
  617. //
  618. // THIS IS A UNSUPPORTED KEY FORMAT PROBLEM!!
  619. //
  620. SetLastError((DWORD) ERROR_UNSUPPORTED_TYPE);
  621. assert(0);
  622. return FALSE;
  623. }
  624. // verify there is enough space in pbBuffer to receive
  625. // the huge integer
  626. if (cbHugeInteger > cbBuffer)
  627. {
  628. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  629. assert(0);
  630. return FALSE;
  631. }
  632. // advance pbBuffer to the correct place within itself,
  633. // this will leave leading zeros at the beginning of the buffer
  634. /*else
  635. pbBuffer += (cbBuffer - cbHugeInteger);*/
  636. if (cbHugeInteger > 0) {
  637. memcpy(pbBuffer, pbHugeInteger, cbHugeInteger);
  638. // ASN.1 isn't reversing HUGEINTEGERs
  639. PkiAsn1ReverseBytes(pbBuffer, cbHugeInteger);
  640. }
  641. return TRUE;
  642. }
  643. //+-------------------------------------------------------------------------
  644. // Decode RSA Private Key
  645. //--------------------------------------------------------------------------
  646. static BOOL WINAPI OssRSAPrivateKeyStrucDecode(
  647. IN DWORD dwCertEncodingType,
  648. IN LPCSTR lpszStructType,
  649. IN const BYTE *pbEncoded,
  650. IN DWORD cbEncoded,
  651. IN DWORD dwFlags,
  652. OUT BLOBHEADER *pBlobHeader,
  653. IN OUT DWORD *pcbBlobHeader
  654. )
  655. {
  656. BOOL fResult;
  657. RSAPrivateKey *pOssPrivateKey = NULL;
  658. if (pBlobHeader == NULL)
  659. *pcbBlobHeader = 0;
  660. if ((fResult = OssInfoDecodeAndAlloc(
  661. RSAPrivateKey_PDU,
  662. pbEncoded,
  663. cbEncoded,
  664. (void **) &pOssPrivateKey))) {
  665. DWORD cbPrivateKeyStruc;
  666. BYTE *pbOssModulus;
  667. DWORD cbModulus;
  668. DWORD cbNonModulus;
  669. // Now convert the OSS RSA private key into CAPI's representation which
  670. // consists of the following sequence:
  671. // - BLOBHEADER blobheader;
  672. // - RSAPUBKEY rsapubkey;
  673. // - BYTE modulus[rsapubkey.bitlen/8];
  674. // - BYTE prime1[rsapubkey.bitlen/16];
  675. // - BYTE prime2[rsapubkey.bitlen/16];
  676. // - BYTE exponent1[rsapubkey.bitlen/16];
  677. // - BYTE exponent2[rsapubkey.bitlen/16];
  678. // - BYTE coefficient[rsapubkey.bitlen/16];
  679. // - BYTE privateExponent[rsapubkey.bitlen/8];
  680. cbModulus = pOssPrivateKey->modulus.length;
  681. pbOssModulus = pOssPrivateKey->modulus.value;
  682. // Strip off a leading 0 byte. Its there in the decoded ASN
  683. // integer for an unsigned integer with the leading bit set.
  684. if (cbModulus > 1 && *pbOssModulus == 0) {
  685. pbOssModulus++;
  686. cbModulus--;
  687. }
  688. cbNonModulus = (cbModulus / 2) + (cbModulus % 2);
  689. cbPrivateKeyStruc = sizeof(BLOBHEADER) + // length of BLOBHEADER
  690. sizeof(RSAPUBKEY) + // length of RSAPUBKEY
  691. (cbModulus * 2) + // length of modulus and privateExponent
  692. (cbNonModulus * 5); // length of prime1&2, exponent1&2, and coefficient
  693. if (*pcbBlobHeader < cbPrivateKeyStruc) {
  694. if (pBlobHeader) {
  695. fResult = FALSE;
  696. SetLastError((DWORD) ERROR_MORE_DATA);
  697. }
  698. } else {
  699. BYTE *pbKeyBlob = (BYTE *) pBlobHeader;
  700. RSAPUBKEY *pRsaPubKey =
  701. (RSAPUBKEY *) (pbKeyBlob + sizeof(PUBLICKEYSTRUC));
  702. BYTE *pbModulus = pbKeyBlob + sizeof(PUBLICKEYSTRUC) +
  703. sizeof(RSAPUBKEY);
  704. BYTE *pbCurrentPosition = NULL;
  705. pBlobHeader->bType = PRIVATEKEYBLOB;
  706. pBlobHeader->bVersion = CUR_BLOB_VERSION;
  707. pBlobHeader->reserved = 0;
  708. // Note: KEYX can also be used for doing a signature
  709. pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;
  710. pRsaPubKey->magic = RSA2;
  711. pRsaPubKey->bitlen = cbModulus * 8;
  712. pRsaPubKey->pubexp = pOssPrivateKey->publicExponent;
  713. // MODULUS
  714. if (cbModulus > 0) {
  715. memcpy(pbModulus, pbOssModulus, cbModulus);
  716. // ASN.1 isn't reversing HUGEINTEGERs
  717. PkiAsn1ReverseBytes(pbModulus, cbModulus);
  718. }
  719. // PRIME1
  720. pbCurrentPosition = pbModulus + cbModulus;
  721. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->prime1,
  722. pbCurrentPosition,
  723. cbNonModulus,
  724. (pOssPrivateKey->prime1.length - 1) == cbNonModulus))
  725. goto ErrorReturn;
  726. // PRIME2
  727. pbCurrentPosition += cbNonModulus;
  728. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->prime2,
  729. pbCurrentPosition,
  730. cbNonModulus,
  731. (pOssPrivateKey->prime2.length - 1) == cbNonModulus))
  732. goto ErrorReturn;
  733. // EXPONENT1
  734. pbCurrentPosition += cbNonModulus;
  735. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->exponent1,
  736. pbCurrentPosition,
  737. cbNonModulus,
  738. (pOssPrivateKey->exponent1.length - 1) == cbNonModulus))
  739. goto ErrorReturn;
  740. // EXPONENT2
  741. pbCurrentPosition += cbNonModulus;
  742. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->exponent2,
  743. pbCurrentPosition,
  744. cbNonModulus,
  745. (pOssPrivateKey->exponent2.length - 1) == cbNonModulus))
  746. goto ErrorReturn;
  747. // COEFFICIENT
  748. pbCurrentPosition += cbNonModulus;
  749. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->coefficient,
  750. pbCurrentPosition,
  751. cbNonModulus,
  752. (pOssPrivateKey->coefficient.length - 1) == cbNonModulus))
  753. goto ErrorReturn;
  754. // PRIVATE EXPONENT
  755. pbCurrentPosition += cbNonModulus;
  756. if (!CopyHugeIntegerToByteArray(&pOssPrivateKey->privateExponent,
  757. pbCurrentPosition,
  758. cbModulus,
  759. (pOssPrivateKey->privateExponent.length - 1) == cbModulus))
  760. goto ErrorReturn;
  761. }
  762. *pcbBlobHeader = cbPrivateKeyStruc;
  763. } else
  764. *pcbBlobHeader = 0;
  765. OssInfoFree(RSAPrivateKey_PDU, pOssPrivateKey);
  766. goto CommonReturn;
  767. ErrorReturn:
  768. *pcbBlobHeader = 0;
  769. fResult = FALSE;
  770. CommonReturn:
  771. return fResult;
  772. }
  773. //+-------------------------------------------------------------------------
  774. // Encode Private Key Info
  775. //--------------------------------------------------------------------------
  776. static BOOL WINAPI OssPrivateKeyInfoEncode(
  777. IN DWORD dwCertEncodingType,
  778. IN LPCSTR lpszStructType,
  779. IN PCRYPT_PRIVATE_KEY_INFO pInfo,
  780. OUT BYTE *pbEncoded,
  781. IN OUT DWORD *pcbEncoded
  782. )
  783. {
  784. BOOL fResult;
  785. PrivateKeyInfo OssPrivateKeyInfo;
  786. Attribute *pOssAttr = NULL;
  787. DWORD cAttr;
  788. PCRYPT_ATTRIBUTE pAttr;
  789. memset(&OssPrivateKeyInfo, 0, sizeof(PrivateKeyInfo));
  790. OssPrivateKeyInfo.version = pInfo->Version;
  791. if (!OssX509SetAlgorithm(&pInfo->Algorithm, &OssPrivateKeyInfo.privateKeyAlgorithm))
  792. goto ErrorReturn;
  793. OssX509SetOctetString(&pInfo->PrivateKey, &OssPrivateKeyInfo.privateKey);
  794. if (pInfo->pAttributes) {
  795. cAttr = pInfo->pAttributes->cAttr;
  796. pAttr = pInfo->pAttributes->rgAttr;
  797. OssPrivateKeyInfo.privateKeyAttributes.count = cAttr;
  798. OssPrivateKeyInfo.privateKeyAttributes.value = NULL;
  799. if (cAttr > 0) {
  800. pOssAttr = (Attribute *) SSAlloc(cAttr * sizeof(Attribute));
  801. if (pOssAttr == NULL)
  802. goto ErrorReturn;
  803. memset(pOssAttr, 0, cAttr * sizeof(Attribute));
  804. OssPrivateKeyInfo.privateKeyAttributes.value= pOssAttr;
  805. }
  806. for ( ; cAttr > 0; cAttr--, pAttr++, pOssAttr++) {
  807. if (!OssX509SetAttribute(pAttr, pOssAttr))
  808. goto ErrorReturn;
  809. }
  810. OssPrivateKeyInfo.bit_mask |= privateKeyAttributes_present;
  811. }
  812. fResult = OssInfoEncode(
  813. PrivateKeyInfo_PDU,
  814. &OssPrivateKeyInfo,
  815. pbEncoded,
  816. pcbEncoded
  817. );
  818. goto CommonReturn;
  819. ErrorReturn:
  820. *pcbEncoded = 0;
  821. fResult = FALSE;
  822. CommonReturn:
  823. if (OssPrivateKeyInfo.privateKeyAttributes.value) {
  824. pOssAttr = OssPrivateKeyInfo.privateKeyAttributes.value;
  825. cAttr = OssPrivateKeyInfo.privateKeyAttributes.count;
  826. for ( ; cAttr > 0; cAttr--, pOssAttr++)
  827. OssX509FreeAttribute(pOssAttr);
  828. SSFree(OssPrivateKeyInfo.privateKeyAttributes.value);
  829. }
  830. return fResult;
  831. }
  832. //+-------------------------------------------------------------------------
  833. // Decode Private Key Info
  834. //--------------------------------------------------------------------------
  835. static BOOL WINAPI OssPrivateKeyInfoDecode(
  836. IN DWORD dwCertEncodingType,
  837. IN LPCSTR lpszStructType,
  838. IN const BYTE *pbEncoded,
  839. IN DWORD cbEncoded,
  840. IN DWORD dwFlags,
  841. OUT PCRYPT_PRIVATE_KEY_INFO pInfo,
  842. IN OUT DWORD *pcbInfo
  843. )
  844. {
  845. BOOL fResult;
  846. PrivateKeyInfo *pPrivateKeyInfo = NULL;
  847. BYTE *pbExtra;
  848. LONG lRemainExtra;
  849. if (pInfo == NULL)
  850. *pcbInfo = 0;
  851. if (!OssInfoDecodeAndAlloc(
  852. PrivateKeyInfo_PDU,
  853. pbEncoded,
  854. cbEncoded,
  855. (void **) &pPrivateKeyInfo))
  856. goto EncodeError;
  857. // for lRemainExtra < 0, LENGTH_ONLY calculation
  858. lRemainExtra = (LONG) *pcbInfo - sizeof(CRYPT_PRIVATE_KEY_INFO);
  859. if (lRemainExtra < 0) {
  860. pbExtra = NULL;
  861. } else {
  862. // Default all optional fields to zero
  863. memset(pInfo, 0, sizeof(CRYPT_PRIVATE_KEY_INFO));
  864. // Update fields not needing extra memory after the CRYPT_PRIVATE_KEY_INFO
  865. pInfo->Version = pPrivateKeyInfo->version;
  866. pbExtra = (BYTE *) pInfo + sizeof(CRYPT_PRIVATE_KEY_INFO);
  867. }
  868. OssX509GetAlgorithm(&pPrivateKeyInfo->privateKeyAlgorithm, dwFlags,
  869. &pInfo->Algorithm, &pbExtra, &lRemainExtra);
  870. OssX509GetOctetString(&pPrivateKeyInfo->privateKey, dwFlags,
  871. &pInfo->PrivateKey, &pbExtra, &lRemainExtra);
  872. if (pPrivateKeyInfo->bit_mask & privateKeyAttributes_present) {
  873. DWORD cAttr;
  874. PCRYPT_ATTRIBUTE pAttr;
  875. Attribute *pOssAttr;
  876. LONG lAlignExtra;
  877. // put the CRYPT_ATTRIBUTES structure in the extra buffer space
  878. // and point pInfo->pAttributes to it
  879. if ((pbExtra) && (lRemainExtra >= sizeof(CRYPT_ATTRIBUTES))) {
  880. memset(pbExtra, 0, sizeof(CRYPT_ATTRIBUTES));
  881. pInfo->pAttributes = (PCRYPT_ATTRIBUTES) pbExtra;
  882. pbExtra += sizeof(CRYPT_ATTRIBUTES);
  883. }
  884. lRemainExtra -= sizeof(CRYPT_ATTRIBUTES);
  885. cAttr = pPrivateKeyInfo->privateKeyAttributes.count;
  886. lAlignExtra = INFO_LEN_ALIGN(cAttr * sizeof(CRYPT_ATTRIBUTE));
  887. lRemainExtra -= lAlignExtra;
  888. if (lRemainExtra >= 0) {
  889. pInfo->pAttributes->cAttr = cAttr;
  890. pAttr = (PCRYPT_ATTRIBUTE) pbExtra;
  891. pInfo->pAttributes->rgAttr = pAttr;
  892. pbExtra += lAlignExtra;
  893. } else
  894. pAttr = NULL;
  895. pOssAttr = pPrivateKeyInfo->privateKeyAttributes.value;
  896. for (; cAttr > 0; cAttr--, pAttr++, pOssAttr++)
  897. OssX509GetAttribute(pOssAttr, dwFlags,
  898. pAttr, &pbExtra, &lRemainExtra);
  899. }
  900. if (lRemainExtra >= 0)
  901. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  902. else {
  903. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  904. if (pInfo) goto LengthError;
  905. }
  906. fResult = TRUE;
  907. goto CommonReturn;
  908. LengthError:
  909. SetLastError((DWORD) ERROR_MORE_DATA);
  910. fResult = FALSE;
  911. goto CommonReturn;
  912. EncodeError:
  913. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  914. // ErrorReturn:
  915. *pcbInfo = 0;
  916. fResult = FALSE;
  917. CommonReturn:
  918. OssInfoFree(PrivateKeyInfo_PDU, pPrivateKeyInfo);
  919. return fResult;
  920. }
  921. //+-------------------------------------------------------------------------
  922. // Encode Encrypted Private Key Info
  923. //--------------------------------------------------------------------------
  924. static BOOL WINAPI OssEncryptedPrivateKeyInfoEncode(
  925. IN DWORD dwCertEncodingType,
  926. IN LPCSTR lpszStructType,
  927. IN PCRYPT_ENCRYPTED_PRIVATE_KEY_INFO pInfo,
  928. OUT BYTE *pbEncoded,
  929. IN OUT DWORD *pcbEncoded
  930. )
  931. {
  932. BOOL fResult;
  933. EncryptedPrivateKeyInfo OssEncryptedPrivateKeyInfo;
  934. memset(&OssEncryptedPrivateKeyInfo, 0, sizeof(EncryptedPrivateKeyInfo));
  935. if (!OssX509SetAlgorithm(&pInfo->EncryptionAlgorithm, &OssEncryptedPrivateKeyInfo.encryptionAlgorithm))
  936. goto ErrorReturn;
  937. OssX509SetOctetString(&pInfo->EncryptedPrivateKey, &OssEncryptedPrivateKeyInfo.encryptedData);
  938. fResult = OssInfoEncode(
  939. EncryptedPrivateKeyInfo_PDU,
  940. &OssEncryptedPrivateKeyInfo,
  941. pbEncoded,
  942. pcbEncoded
  943. );
  944. goto CommonReturn;
  945. ErrorReturn:
  946. *pcbEncoded = 0;
  947. fResult = FALSE;
  948. CommonReturn:
  949. return fResult;
  950. }
  951. //+-------------------------------------------------------------------------
  952. // Decode Encrypted Private Key Info
  953. //--------------------------------------------------------------------------
  954. static BOOL WINAPI OssEncryptedPrivateKeyInfoDecode(
  955. IN DWORD dwCertEncodingType,
  956. IN LPCSTR lpszStructType,
  957. IN const BYTE *pbEncoded,
  958. IN DWORD cbEncoded,
  959. IN DWORD dwFlags,
  960. OUT PCRYPT_ENCRYPTED_PRIVATE_KEY_INFO pInfo,
  961. IN OUT DWORD *pcbInfo
  962. )
  963. {
  964. BOOL fResult;
  965. EncryptedPrivateKeyInfo *pEncryptedPrivateKeyInfo = NULL;
  966. BYTE *pbExtra;
  967. LONG lRemainExtra;
  968. if (pInfo == NULL)
  969. *pcbInfo = 0;
  970. if (!OssInfoDecodeAndAlloc(
  971. EncryptedPrivateKeyInfo_PDU,
  972. pbEncoded,
  973. cbEncoded,
  974. (void **) &pEncryptedPrivateKeyInfo))
  975. goto EncodeError;
  976. // for lRemainExtra < 0, LENGTH_ONLY calculation
  977. lRemainExtra = (LONG) *pcbInfo - sizeof(CRYPT_ENCRYPTED_PRIVATE_KEY_INFO);
  978. if (lRemainExtra < 0) {
  979. pbExtra = NULL;
  980. } else {
  981. memset(pInfo, 0, sizeof(CRYPT_ENCRYPTED_PRIVATE_KEY_INFO));
  982. pbExtra = (BYTE *) pInfo + sizeof(CRYPT_ENCRYPTED_PRIVATE_KEY_INFO);
  983. }
  984. OssX509GetAlgorithm(&pEncryptedPrivateKeyInfo->encryptionAlgorithm, dwFlags,
  985. &pInfo->EncryptionAlgorithm, &pbExtra, &lRemainExtra);
  986. OssX509GetOctetString(&pEncryptedPrivateKeyInfo->encryptedData, dwFlags,
  987. &pInfo->EncryptedPrivateKey, &pbExtra, &lRemainExtra);
  988. if (lRemainExtra >= 0)
  989. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  990. else {
  991. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  992. if (pInfo) goto LengthError;
  993. }
  994. fResult = TRUE;
  995. goto CommonReturn;
  996. LengthError:
  997. SetLastError((DWORD) ERROR_MORE_DATA);
  998. fResult = FALSE;
  999. goto CommonReturn;
  1000. EncodeError:
  1001. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  1002. //ErrorReturn:
  1003. *pcbInfo = 0;
  1004. fResult = FALSE;
  1005. CommonReturn:
  1006. OssInfoFree(EncryptedPrivateKeyInfo_PDU, pEncryptedPrivateKeyInfo);
  1007. return fResult;
  1008. }