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.

1484 lines
49 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: nscp.cpp
  8. //
  9. // Contents: PFX: Personal Information Exchange.
  10. //
  11. // Functions:
  12. //
  13. // History: 02-Jun-97 mattt created
  14. //
  15. //--------------------------------------------------------------------------
  16. #include "global.hxx"
  17. #include <wincrypt.h>
  18. #include "shacomm.h"
  19. #include "des.h"
  20. #include "tripldes.h"
  21. #include "modes.h"
  22. #define _PFX_SOURCE_
  23. #include "dbgdef.h"
  24. extern "C" {
  25. #include "pfxnscp.h" // ASN1 generated
  26. }
  27. #include "pfxhelp.h"
  28. #include "pfxcrypt.h"
  29. #include "pfxcmn.h"
  30. #define DES_BLOCKLEN 8
  31. ///////////////////////////////////////////////////////////////////////////////////
  32. // OLD PKCS #12 Object Identifiers - these are for supporting the old netscape file format
  33. #define OLD_szOID_PKCS_12_OIDs szOID_PKCS_12 ".5" // 1.2.840.113549.1.12.5
  34. #define OLD_szOID_PKCS_12_PbeIds OLD_szOID_PKCS_12_OIDs ".1"
  35. #define OLD_szOID_PKCS_12_pbeWithSHA1And128BitRC4 OLD_szOID_PKCS_12_PbeIds ".1"
  36. #define OLD_szOID_PKCS_12_pbeWithSHA1And40BitRC4 OLD_szOID_PKCS_12_PbeIds ".2"
  37. #define OLD_szOID_PKCS_12_pbeWithSHA1AndTripleDES OLD_szOID_PKCS_12_PbeIds ".3"
  38. #define OLD_szOID_PKCS_12_pbeWithSHA1And128BitRC2 OLD_szOID_PKCS_12_PbeIds ".4"
  39. #define OLD_szOID_PKCS_12_pbeWithSHA1And40BitRC2 OLD_szOID_PKCS_12_PbeIds ".5"
  40. #define OLD_szOID_PKCS_12_EnvelopingIds OLD_szOID_PKCS_12_OIDs ".2"
  41. #define OLD_szOID_PKCS_12_rsaEncryptionWith128BitRC4 OLD_szOID_PKCS_12_EnvelopingIds ".1"
  42. #define OLD_szOID_PKCS_12_rsaEncryptionWith40BitRC4 OLD_szOID_PKCS_12_EnvelopingIds ".2"
  43. #define OLD_szOID_PKCS_12_rsaEncryptionWithTripleDES OLD_szOID_PKCS_12_EnvelopingIds ".3"
  44. #define OLD_szOID_PKCS_12_SignatureIds OLD_szOID_PKCS_12_OIDs ".3"
  45. #define OLD_szOID_PKCS_12_rsaSignatureWithSHA1Digest OLD_szOID_PKCS_12_SignatureIds ".1"
  46. #define OLD_szOID_PKCS_12_ModeIDs OLD_szOID_PKCS_12 ".1" // 1.2.840.113549.1.12.1
  47. #define OLD_szOID_PKCS_12_PubKeyMode OLD_szOID_PKCS_12_ModeIDs ".1" // 1.2.840.113549.1.12.1.1
  48. #define OLD_szOID_PKCS_12_PasswdMode OLD_szOID_PKCS_12_ModeIDs ".2" // 1.2.840.113549.1.12.1.2
  49. #define OLD_szOID_PKCS_12_offlineTransportMode OLD_szOID_PKCS_12_ModeIds ".1" // obsolete
  50. #define OLD_szOID_PKCS_12_onlineTransportMode OLD_szOID_PKCS_12_ModeIds ".2" // obsolete
  51. #define OLD_szOID_PKCS_12_EspvkIDs OLD_szOID_PKCS_12 ".2" // 1.2.840.113549.1.12.2
  52. #define OLD_szOID_PKCS_12_KeyShrouding OLD_szOID_PKCS_12_EspvkIDs ".1" // 1.2.840.113549.1.12.2.1
  53. #define OLD_szOID_PKCS_12_BagIDs OLD_szOID_PKCS_12 ".3" // obsolete
  54. #define OLD_szOID_PKCS_12_KeyBagIDs OLD_szOID_PKCS_12_BagIDs ".1" // obsolete
  55. #define OLD_szOID_PKCS_12_CertCrlBagIDs OLD_szOID_PKCS_12_BagIDs ".2" // obsolete
  56. #define OLD_szOID_PKCS_12_SecretBagIDs OLD_szOID_PKCS_12_BagIDs ".3" // obsolete
  57. #define OLD_szOID_PKCS_12_SafeCntIDs OLD_szOID_PKCS_12_BagIDs ".4" // obsolete
  58. #define OLD_szOID_PKCS_12_ShrKeyBagIDs OLD_szOID_PKCS_12_BagIDs ".5" // obsolete
  59. #define OLD_szOID_PKCS_12_CertBagIDs OLD_szOID_PKCS_12 ".4" // obsolete
  60. #define OLD_szOID_PKCS_12_x509CertCrlBagIDs OLD_szOID_PKCS_12_CertBagIDs ".1" // obsolete
  61. #define OLD_szOID_PKCS_12_sdsiCertBagIDs OLD_szOID_PKCS_12_CertBagIDs ".2" // obsolete
  62. static HCRYPTASN1MODULE hNSCPAsn1Module;
  63. // fwd
  64. //BOOL FNSCPDumpSafeCntsToHPFX(SafeContents* pSafeCnts, HPFX hpfx);
  65. BOOL InitNSCP()
  66. {
  67. #ifdef OSS_CRYPT_ASN1
  68. if (0 == (hNSCPAsn1Module = I_CryptInstallAsn1Module(pfxnscp, 0, NULL)) )
  69. return FALSE;
  70. #else
  71. PFXNSCP_Module_Startup();
  72. if (0 == (hNSCPAsn1Module = I_CryptInstallAsn1Module(
  73. PFXNSCP_Module, 0, NULL))) {
  74. PFXNSCP_Module_Cleanup();
  75. return FALSE;
  76. }
  77. #endif // OSS_CRYPT_ASN1
  78. return TRUE;
  79. }
  80. BOOL TerminateNSCP()
  81. {
  82. I_CryptUninstallAsn1Module(hNSCPAsn1Module);
  83. #ifndef OSS_CRYPT_ASN1
  84. PFXNSCP_Module_Cleanup();
  85. #endif // OSS_CRYPT_ASN1
  86. return TRUE;
  87. }
  88. static inline ASN1decoding_t GetDecoder(void)
  89. {
  90. return I_CryptGetAsn1Decoder(hNSCPAsn1Module);
  91. }
  92. //+-------------------------------------------------------------------------
  93. // Function: INSCP_Asn1ToObjectID
  94. //
  95. // Synopsis: Convert a dotted string oid to an ASN1 ObjectID
  96. //
  97. // Returns: FALSE iff failed
  98. //--------------------------------------------------------------------------
  99. BOOL
  100. INSCP_Asn1ToObjectID(
  101. IN OID oid,
  102. OUT ObjectID *pooid
  103. )
  104. {
  105. BOOL fRet;
  106. pooid->count = 16;
  107. if (!PkiAsn1ToObjectIdentifier(
  108. oid,
  109. &pooid->count,
  110. pooid->value))
  111. goto PkiAsn1ToObjectIdentifierError;
  112. fRet = TRUE;
  113. CommonReturn:
  114. return fRet;
  115. ErrorReturn:
  116. SetLastError(CRYPT_E_OID_FORMAT);
  117. fRet = FALSE;
  118. goto CommonReturn;
  119. TRACE_ERROR(PkiAsn1ToObjectIdentifierError)
  120. }
  121. //+-------------------------------------------------------------------------
  122. // Function: INSCP_Asn1FromObjectID
  123. //
  124. // Synopsis: Convert an ASN1 ObjectID to a dotted string oid
  125. //
  126. // Returns: FALSE iff failed
  127. //--------------------------------------------------------------------------
  128. BOOL
  129. INSCP_Asn1FromObjectID(
  130. IN ObjectID *pooid,
  131. OUT OID *poid
  132. )
  133. {
  134. BOOL fRet;
  135. OID oid = NULL;
  136. DWORD cb;
  137. if (!PkiAsn1FromObjectIdentifier(
  138. pooid->count,
  139. pooid->value,
  140. NULL,
  141. &cb))
  142. goto PkiAsn1FromObjectIdentifierSizeError;
  143. if (NULL == (oid = (OID)SSAlloc( cb)))
  144. goto OidAllocError;
  145. if (!PkiAsn1FromObjectIdentifier(
  146. pooid->count,
  147. pooid->value,
  148. oid,
  149. &cb))
  150. goto PkiAsn1FromObjectIdentifierError;
  151. fRet = TRUE;
  152. CommonReturn:
  153. *poid = oid;
  154. return fRet;
  155. ErrorReturn:
  156. SSFree(oid);
  157. fRet = FALSE;
  158. goto CommonReturn;
  159. TRACE_ERROR(OidAllocError)
  160. SET_ERROR(PkiAsn1FromObjectIdentifierSizeError , CRYPT_E_OID_FORMAT)
  161. SET_ERROR(PkiAsn1FromObjectIdentifierError , CRYPT_E_OID_FORMAT)
  162. }
  163. //+-------------------------------------------------------------------------
  164. // Function: INSCP_EqualObjectIDs
  165. //
  166. // Compare 2 OSS object id's.
  167. //
  168. // Returns: FALSE iff !equal
  169. //--------------------------------------------------------------------------
  170. BOOL
  171. WINAPI
  172. INSCP_EqualObjectIDs(
  173. IN ObjectID *poid1,
  174. IN ObjectID *poid2)
  175. {
  176. BOOL fRet;
  177. DWORD i;
  178. PDWORD pdw1;
  179. PDWORD pdw2;
  180. if (poid1->count != poid2->count)
  181. goto Unequal;
  182. for (i=poid1->count, pdw1=poid1->value, pdw2=poid2->value;
  183. (i>0) && (*pdw1==*pdw2);
  184. i--, pdw1++, pdw2++)
  185. ;
  186. if (i>0)
  187. goto Unequal;
  188. fRet = TRUE; // equal
  189. CommonReturn:
  190. return fRet;
  191. Unequal:
  192. fRet = FALSE; // !equal
  193. goto CommonReturn;
  194. }
  195. //+ --------------------------------------------------------------
  196. // in NSCP's initial implementation of PFX020, this
  197. // is the algorithm they used to derive a key from a password.
  198. // ACTUALLY, they have two slightly different methods of generating
  199. // a key, this is the one needed to decrypt the baggage.
  200. // We include it so we can interoperate.
  201. BOOL NCSPDeriveBaggageDecryptionKey(
  202. LPCWSTR szPassword,
  203. int iPKCS5Iterations,
  204. PBYTE pbPKCS5Salt,
  205. DWORD cbPKCS5Salt,
  206. PBYTE pbDerivedMaterial,
  207. DWORD cbDerivedMaterial)
  208. {
  209. BOOL fRet = TRUE;
  210. LPSTR szASCIIPassword = NULL;
  211. DWORD cbASCIIPassword = 0;
  212. DWORD i;
  213. BYTE paddedPKCS5Salt[20];
  214. BYTE *pbTempPKCS5Salt = NULL;
  215. DWORD cbTempPKCS5Salt = 0;
  216. BYTE rgbPKCS5Key[A_SHA_DIGEST_LEN];
  217. // for some reason the password is used as ASCII in this key derivation
  218. // so change it from unicode to ASCII
  219. if (0 == (cbASCIIPassword = WideCharToMultiByte(
  220. CP_ACP,
  221. 0,
  222. szPassword,
  223. -1,
  224. NULL,
  225. 0,
  226. NULL,
  227. NULL))) {
  228. goto ErrorReturn;
  229. }
  230. if (NULL == (szASCIIPassword = (LPSTR) SSAlloc(cbASCIIPassword)))
  231. goto ErrorReturn;
  232. if (0 == (cbASCIIPassword = WideCharToMultiByte(
  233. CP_ACP,
  234. 0,
  235. szPassword,
  236. -1,
  237. szASCIIPassword,
  238. cbASCIIPassword,
  239. NULL,
  240. NULL))) {
  241. goto ErrorReturn;
  242. }
  243. // get rid of the NULL character, Netscape doesn't include it
  244. cbASCIIPassword--;
  245. // because of a Netscape bug the minimum length of password + salt is 20,
  246. // if the password + salt is less than 20 they pad with 0's.
  247. // so, check to see if the password + salt is less than 20, if so then pad the
  248. // salt since it will be appended to the password.
  249. if (cbASCIIPassword+cbPKCS5Salt < 20) {
  250. // reset the pbPKCS5Salt pointer to a local buffer
  251. // which is padded with 0's, and adjust cbPKCS5Salt
  252. memset(paddedPKCS5Salt, 0, 20);
  253. memcpy(paddedPKCS5Salt, pbPKCS5Salt, cbPKCS5Salt);
  254. pbTempPKCS5Salt = paddedPKCS5Salt;
  255. cbTempPKCS5Salt = 20 - cbASCIIPassword;
  256. }
  257. else {
  258. pbTempPKCS5Salt = pbPKCS5Salt;
  259. cbTempPKCS5Salt = cbPKCS5Salt;
  260. }
  261. // use PKCS#5 to generate initial bit stream (seed)
  262. if (!PKCS5_GenKey(
  263. iPKCS5Iterations,
  264. (BYTE *)szASCIIPassword,
  265. cbASCIIPassword,
  266. pbTempPKCS5Salt,
  267. cbTempPKCS5Salt,
  268. rgbPKCS5Key))
  269. goto Ret;
  270. // if there isn't engough key material, then use PHash to generate more
  271. if (cbDerivedMaterial > sizeof(rgbPKCS5Key))
  272. {
  273. // P_hash (secret, seed) = HMAC_hash (secret, A(0) + seed),
  274. // HMAC_hash (secret, A(1) + seed),
  275. // HMAC_hash (secret, A(2) + seed),
  276. // HMAC_hash (secret, A(3) + seed) ...
  277. // where
  278. // A(0) = seed
  279. // A(i) = HMAC_hash(secret, A(i-1))
  280. // seed = PKCS5 salt for PKCS5 PBE param
  281. // secret = normal PKCS5 hashed key
  282. if (!P_Hash (
  283. rgbPKCS5Key,
  284. sizeof(rgbPKCS5Key),
  285. pbPKCS5Salt,
  286. cbPKCS5Salt,
  287. pbDerivedMaterial, // output
  288. cbDerivedMaterial, // # of output bytes requested
  289. TRUE) ) // NSCP compat mode?
  290. goto Ret;
  291. }
  292. else
  293. {
  294. // we already have enough bits to satisfy the request
  295. CopyMemory(pbDerivedMaterial, rgbPKCS5Key, cbDerivedMaterial);
  296. }
  297. goto Ret;
  298. ErrorReturn:
  299. fRet = FALSE;
  300. Ret:
  301. if (szASCIIPassword)
  302. SSFree(szASCIIPassword);
  303. return fRet;
  304. }
  305. // this function will create a SAFE_BAG structure contained in a single buffer
  306. // for the given encoded private key, friendly name, and local key ID
  307. static
  308. BOOL
  309. SetupKeyBag (
  310. SAFE_BAG **ppKeyBag,
  311. DWORD dwLocalKeyID,
  312. BYTE *pbFriendlyName,
  313. DWORD cbFriendlyName,
  314. BYTE *pbEncodedPrivateKey,
  315. DWORD cbEncodedPrivateKey
  316. )
  317. {
  318. BOOL fRet = TRUE;
  319. SAFE_BAG *pSafeBag;
  320. DWORD cbBytesNeeded = sizeof(SAFE_BAG);
  321. DWORD dwKeyID = 0;
  322. CRYPT_ATTR_BLOB keyID;
  323. CERT_NAME_VALUE wideFriendlyName;
  324. BYTE *pbEncodedLocalKeyID = NULL;
  325. DWORD cbEncodedLocalKeyID = 0;
  326. BYTE *pbEncodedFriendlyName = NULL;
  327. DWORD cbEncodedFriendlyName = 0;
  328. BYTE *pbCurrentBufferLocation = NULL;
  329. keyID.pbData = (BYTE *) &dwKeyID;
  330. keyID.cbData = sizeof(DWORD);
  331. dwKeyID = dwLocalKeyID;
  332. // calculate the size needed for a buffer to fit all the SAFE_BAG information
  333. cbBytesNeeded += strlen(szOID_PKCS_12_KEY_BAG) + 1;
  334. cbBytesNeeded += cbEncodedPrivateKey;
  335. cbBytesNeeded += sizeof(CRYPT_ATTRIBUTE) * 2;
  336. cbBytesNeeded += strlen(szOID_PKCS_12_LOCAL_KEY_ID) + 1;
  337. cbBytesNeeded += sizeof(CRYPT_ATTR_BLOB);
  338. // encode the keyID attribute
  339. if (!CryptEncodeObject(
  340. X509_ASN_ENCODING,
  341. X509_OCTET_STRING,
  342. &keyID,
  343. NULL,
  344. &cbEncodedLocalKeyID)) {
  345. goto ErrorReturn;
  346. }
  347. if (NULL == (pbEncodedLocalKeyID = (BYTE *) SSAlloc(cbEncodedLocalKeyID)))
  348. goto ErrorReturn;
  349. cbBytesNeeded += cbEncodedLocalKeyID;
  350. if (!CryptEncodeObject(
  351. X509_ASN_ENCODING,
  352. X509_OCTET_STRING,
  353. &keyID,
  354. pbEncodedLocalKeyID,
  355. &cbEncodedLocalKeyID)) {
  356. goto ErrorReturn;
  357. }
  358. cbBytesNeeded += strlen(szOID_PKCS_12_FRIENDLY_NAME_ATTR) + 1;
  359. cbBytesNeeded += sizeof(CRYPT_ATTR_BLOB);
  360. // encode the friendly name attribute
  361. wideFriendlyName.dwValueType = CERT_RDN_BMP_STRING;
  362. wideFriendlyName.Value.pbData = pbFriendlyName;
  363. wideFriendlyName.Value.cbData = 0;
  364. if (!CryptEncodeObject(
  365. X509_ASN_ENCODING,
  366. X509_UNICODE_ANY_STRING,
  367. (void *)&wideFriendlyName,
  368. NULL,
  369. &cbEncodedFriendlyName)) {
  370. goto ErrorReturn;
  371. }
  372. if (NULL == (pbEncodedFriendlyName = (BYTE *) SSAlloc(cbEncodedFriendlyName)))
  373. goto ErrorReturn;
  374. cbBytesNeeded += cbEncodedFriendlyName;
  375. if (!CryptEncodeObject(
  376. X509_ASN_ENCODING,
  377. X509_UNICODE_ANY_STRING,
  378. (void *)&wideFriendlyName,
  379. pbEncodedFriendlyName,
  380. &cbEncodedFriendlyName)) {
  381. goto ErrorReturn;
  382. }
  383. // now allocate space for the all the SAFE_BAG data and copy the data into the buffer
  384. if (NULL == (pSafeBag = (SAFE_BAG *) SSAlloc(cbBytesNeeded)))
  385. goto ErrorReturn;
  386. memset(pSafeBag, 0, cbBytesNeeded);
  387. // set current buffer location to be at the end of the SAFE_BAG
  388. // structure which is at the head of the buffer
  389. pbCurrentBufferLocation = ((BYTE *) pSafeBag) + sizeof(SAFE_BAG);
  390. // copy key bag type OID
  391. pSafeBag->pszBagTypeOID = (LPSTR) pbCurrentBufferLocation;
  392. strcpy((LPSTR) pbCurrentBufferLocation, szOID_PKCS_12_KEY_BAG);
  393. pbCurrentBufferLocation += strlen(szOID_PKCS_12_KEY_BAG) + 1;
  394. // copy the private key
  395. pSafeBag->BagContents.pbData = pbCurrentBufferLocation;
  396. pSafeBag->BagContents.cbData = cbEncodedPrivateKey;
  397. memcpy(pbCurrentBufferLocation, pbEncodedPrivateKey, cbEncodedPrivateKey);
  398. pbCurrentBufferLocation += cbEncodedPrivateKey;
  399. // create space for the attributes array
  400. pSafeBag->Attributes.cAttr = 2;
  401. pSafeBag->Attributes.rgAttr = (CRYPT_ATTRIBUTE *) pbCurrentBufferLocation;
  402. pbCurrentBufferLocation += sizeof(CRYPT_ATTRIBUTE) * 2;
  403. // copy the local key ID attribute and value
  404. pSafeBag->Attributes.rgAttr[0].pszObjId = (LPSTR) pbCurrentBufferLocation;
  405. strcpy((LPSTR) pbCurrentBufferLocation, szOID_PKCS_12_LOCAL_KEY_ID);
  406. pbCurrentBufferLocation += strlen(szOID_PKCS_12_LOCAL_KEY_ID) + 1;
  407. pSafeBag->Attributes.rgAttr[0].cValue = 1;
  408. pSafeBag->Attributes.rgAttr[0].rgValue = (CRYPT_ATTR_BLOB *) pbCurrentBufferLocation;
  409. pbCurrentBufferLocation += sizeof(CRYPT_ATTR_BLOB);
  410. pSafeBag->Attributes.rgAttr[0].rgValue->cbData = cbEncodedLocalKeyID;
  411. pSafeBag->Attributes.rgAttr[0].rgValue->pbData = pbCurrentBufferLocation;
  412. memcpy(pbCurrentBufferLocation, pbEncodedLocalKeyID, cbEncodedLocalKeyID);
  413. pbCurrentBufferLocation += cbEncodedLocalKeyID;
  414. // copy the friendly name attribute and value
  415. pSafeBag->Attributes.rgAttr[1].pszObjId = (LPSTR) pbCurrentBufferLocation;
  416. strcpy((LPSTR) pbCurrentBufferLocation, szOID_PKCS_12_FRIENDLY_NAME_ATTR);
  417. pbCurrentBufferLocation += strlen(szOID_PKCS_12_FRIENDLY_NAME_ATTR) + 1;
  418. pSafeBag->Attributes.rgAttr[1].cValue = 1;
  419. pSafeBag->Attributes.rgAttr[1].rgValue = (CRYPT_ATTR_BLOB *) pbCurrentBufferLocation;
  420. pbCurrentBufferLocation += sizeof(CRYPT_ATTR_BLOB);
  421. pSafeBag->Attributes.rgAttr[1].rgValue->cbData = cbEncodedFriendlyName;
  422. pSafeBag->Attributes.rgAttr[1].rgValue->pbData = pbCurrentBufferLocation;
  423. memcpy(pbCurrentBufferLocation, pbEncodedFriendlyName, cbEncodedFriendlyName);
  424. *ppKeyBag = pSafeBag;
  425. goto Ret;
  426. ErrorReturn:
  427. fRet = FALSE;
  428. Ret:
  429. if (pbEncodedLocalKeyID)
  430. SSFree(pbEncodedLocalKeyID);
  431. if (pbEncodedFriendlyName)
  432. SSFree(pbEncodedFriendlyName);
  433. return fRet;
  434. }
  435. // this function will extract a private key from the baggage structure handed in
  436. // and put the private key in a SAFE_BAG structure, where all the data of the
  437. // SAFE_BAG is contained in a single in a single buffer
  438. static
  439. BOOL
  440. ExtractKeyFromBaggage(
  441. Baggage baggage,
  442. SAFE_BAG **ppKeyBag,
  443. LPCWSTR szPassword,
  444. DWORD dwLocalKeyID,
  445. BYTE **ppbCertThumbprint
  446. )
  447. {
  448. BOOL fRet = TRUE;
  449. DWORD dwErr;
  450. DWORD cbEncryptedPrivateKeyInfoStruct = 0;
  451. CRYPT_ENCRYPTED_PRIVATE_KEY_INFO *pEncryptedPrivateKeyInfoStruct = NULL;
  452. BYTE rgbDerivedKeyMatl[40]; // 320 bits is enough for 128 bit key, 64 bit IV
  453. DWORD cbEncodedPrivateKeyInfoStruct = 0;
  454. BYTE *pbEncodedPrivateKeyInfoStruct = NULL;
  455. PBEParameter *pPBEParameter = NULL;
  456. ASN1decoding_t pDec = GetDecoder();
  457. // there should only be one baggage item
  458. if (baggage.count != 1)
  459. goto SetPFXDecodeError;
  460. // there should only be one private key
  461. if (baggage.value->espvks.count != 1)
  462. goto SetPFXDecodeError;
  463. // decode the PKCS8, which is actually stored in the espvkCipherText field
  464. // of the ESPVK structure. it's a Netscape thing man!!!!
  465. if (!CryptDecodeObject(X509_ASN_ENCODING,
  466. PKCS_ENCRYPTED_PRIVATE_KEY_INFO,
  467. (BYTE *) baggage.value->espvks.value->espvkCipherText.value,
  468. baggage.value->espvks.value->espvkCipherText.length,
  469. CRYPT_DECODE_NOCOPY_FLAG,
  470. NULL,
  471. &cbEncryptedPrivateKeyInfoStruct))
  472. goto SetPFXDecodeError;
  473. if (NULL == (pEncryptedPrivateKeyInfoStruct = (CRYPT_ENCRYPTED_PRIVATE_KEY_INFO *)
  474. SSAlloc(cbEncryptedPrivateKeyInfoStruct)))
  475. goto SetPFXDecodeError;
  476. if (!CryptDecodeObject(X509_ASN_ENCODING,
  477. PKCS_ENCRYPTED_PRIVATE_KEY_INFO,
  478. (BYTE *) baggage.value->espvks.value->espvkCipherText.value,
  479. baggage.value->espvks.value->espvkCipherText.length,
  480. CRYPT_DECODE_NOCOPY_FLAG,
  481. pEncryptedPrivateKeyInfoStruct,
  482. &cbEncryptedPrivateKeyInfoStruct))
  483. goto SetPFXDecodeError;
  484. // verify that the algorithm is the one we expect
  485. if (strcmp("1.2.840.113549.1.12.5.1.3", pEncryptedPrivateKeyInfoStruct->EncryptionAlgorithm.pszObjId) != 0)
  486. goto SetPFXDecodeError;
  487. if (0 != PkiAsn1Decode(
  488. pDec,
  489. (void **)&pPBEParameter,
  490. PBEParameter_PDU,
  491. pEncryptedPrivateKeyInfoStruct->EncryptionAlgorithm.Parameters.pbData,
  492. pEncryptedPrivateKeyInfoStruct->EncryptionAlgorithm.Parameters.cbData))
  493. goto SetPFXDecodeError;
  494. // derive the key to be used for decrypting,
  495. if (!NCSPDeriveBaggageDecryptionKey(
  496. szPassword,
  497. pPBEParameter->iterationCount,
  498. pPBEParameter->salt.value, // pkcs5 salt
  499. pPBEParameter->salt.length,
  500. rgbDerivedKeyMatl,
  501. 40)) { // 192 bits for triple des - 3key, and 64 bit IV ---- for some reason netscape asks for
  502. // 40 bytes of key material, then uses the first 192 bits for key and last 64 bits for IV,
  503. // skipping 64 bits in between. who knows why they do these things!!
  504. goto ErrorReturn;
  505. }
  506. // decrypt the private key
  507. {
  508. DWORD dwDataPos;
  509. DWORD cbToBeDec = pEncryptedPrivateKeyInfoStruct->EncryptedPrivateKey.cbData;
  510. DES3TABLE des3Table;
  511. BYTE des3Fdbk [DES_BLOCKLEN];
  512. // key setup
  513. tripledes3key(&des3Table, rgbDerivedKeyMatl);
  514. CopyMemory(des3Fdbk, &rgbDerivedKeyMatl[40 - sizeof(des3Fdbk)], sizeof(des3Fdbk)); // fdbk is last chunk
  515. cbEncodedPrivateKeyInfoStruct =
  516. ((pEncryptedPrivateKeyInfoStruct->EncryptedPrivateKey.cbData + 7) / 8) * 8;
  517. if (NULL == (pbEncodedPrivateKeyInfoStruct = (BYTE *) SSAlloc(cbEncodedPrivateKeyInfoStruct)))
  518. goto ErrorReturn;
  519. for (dwDataPos=0; cbToBeDec > 0; dwDataPos += DES_BLOCKLEN, cbToBeDec -= DES_BLOCKLEN)
  520. {
  521. BYTE rgbDec[DES_BLOCKLEN];
  522. CBC(
  523. tripledes,
  524. DES_BLOCKLEN,
  525. rgbDec,
  526. &(pEncryptedPrivateKeyInfoStruct->EncryptedPrivateKey.pbData[dwDataPos]),
  527. (void *) &des3Table,
  528. DECRYPT,
  529. des3Fdbk);
  530. CopyMemory(&pbEncodedPrivateKeyInfoStruct[dwDataPos], rgbDec, DES_BLOCKLEN);
  531. }
  532. }
  533. // set up the SAFE_BAG to be returned
  534. if (!SetupKeyBag(
  535. ppKeyBag,
  536. dwLocalKeyID,
  537. (BYTE *) baggage.value->espvks.value->espvkData.nickname.value,
  538. baggage.value->espvks.value->espvkData.nickname.length,
  539. pbEncodedPrivateKeyInfoStruct,
  540. cbEncodedPrivateKeyInfoStruct)) {
  541. goto ErrorReturn;
  542. }
  543. // copy the cert thumbprint
  544. assert(baggage.value->espvks.value->espvkData.assocCerts.count == 1);
  545. if (NULL == (*ppbCertThumbprint = (BYTE *)
  546. SSAlloc(baggage.value->espvks.value->espvkData.assocCerts.value->digest.length)))
  547. goto ErrorReturn;
  548. memcpy(
  549. *ppbCertThumbprint,
  550. baggage.value->espvks.value->espvkData.assocCerts.value->digest.value,
  551. baggage.value->espvks.value->espvkData.assocCerts.value->digest.length);
  552. goto Ret;
  553. SetPFXDecodeError:
  554. SetLastError(CRYPT_E_BAD_ENCODE);
  555. ErrorReturn:
  556. fRet = FALSE;
  557. Ret:
  558. // save last error from TLS madness
  559. dwErr = GetLastError();
  560. if (pEncryptedPrivateKeyInfoStruct)
  561. SSFree(pEncryptedPrivateKeyInfoStruct);
  562. if (pbEncodedPrivateKeyInfoStruct)
  563. SSFree(pbEncodedPrivateKeyInfoStruct);
  564. PkiAsn1FreeDecoded(pDec, pPBEParameter, PBEParameter_PDU);
  565. // save last error from TLS madness
  566. SetLastError(dwErr);
  567. return fRet;
  568. }
  569. // this function will take a SafeContents structure and format it as an array
  570. // array of SAFE_BAGs with all the date for the SAGE_BAGs containted in a single
  571. // buffer. it also adds the local key ID attribute to the cert which has
  572. // the same thumbprint as the thumbprint passed in
  573. static
  574. BOOL
  575. SetupCertBags(
  576. SafeContents *pSafeCnts,
  577. SAFE_BAG **ppCertBags,
  578. DWORD *pcNumCertBags,
  579. DWORD dwLocalKeyID,
  580. BYTE *pbCertThumbprint
  581. )
  582. {
  583. BOOL fRet = TRUE;
  584. DWORD dwErr;
  585. SAFE_BAG *pSafeBags = NULL;
  586. DWORD cNumSafeBags = 0;
  587. DWORD cbBytesNeeded = 0;
  588. BYTE *pbCurrentBufferLocation = NULL;
  589. X509Bag *pX509Bag = NULL;
  590. CertCRLBag *pCertCRLBag = NULL;
  591. HCERTSTORE hCertStore = NULL;
  592. CRYPT_DATA_BLOB cryptDataBlob;
  593. PCCERT_CONTEXT pCertContext = NULL;
  594. DWORD dwSafeBagIndex = 0;
  595. DWORD dwKeyID = 0;
  596. CRYPT_ATTR_BLOB keyID;
  597. DWORD cbEncodedLocalKeyID = 0;
  598. BYTE *pbEncodedLocalKeyID = NULL;
  599. ASN1decoding_t pDec = GetDecoder();
  600. keyID.pbData = (BYTE *) &dwKeyID;
  601. keyID.cbData = sizeof(DWORD);
  602. dwKeyID = dwLocalKeyID;
  603. // decode the safe bag content, should be a CertCrlBag
  604. assert(pSafeCnts->count == 1);
  605. if (0 != PkiAsn1Decode(
  606. pDec,
  607. (void **)&pCertCRLBag,
  608. CertCRLBag_PDU,
  609. (BYTE *) pSafeCnts->value->safeBagContent.value,
  610. pSafeCnts->value->safeBagContent.length))
  611. goto SetPFXDecodeError;
  612. // decode the X509bag
  613. assert(pCertCRLBag->count == 1);
  614. if (0 != PkiAsn1Decode(
  615. pDec,
  616. (void **)&pX509Bag,
  617. X509Bag_PDU,
  618. (BYTE *) pCertCRLBag->value[0].value.value,
  619. pCertCRLBag->value[0].value.length))
  620. goto SetPFXDecodeError;
  621. // encode the keyID so it is ready to be added to a SAFE_BAGs attributes
  622. if (!CryptEncodeObject(
  623. X509_ASN_ENCODING,
  624. X509_OCTET_STRING,
  625. &keyID,
  626. NULL,
  627. &cbEncodedLocalKeyID)) {
  628. goto ErrorReturn;
  629. }
  630. if (NULL == (pbEncodedLocalKeyID = (BYTE *) SSAlloc(cbEncodedLocalKeyID)))
  631. goto ErrorReturn;
  632. if (!CryptEncodeObject(
  633. X509_ASN_ENCODING,
  634. X509_OCTET_STRING,
  635. &keyID,
  636. pbEncodedLocalKeyID,
  637. &cbEncodedLocalKeyID)) {
  638. goto ErrorReturn;
  639. }
  640. // open a cert store with the SignedData buffer we got from the SafeContents passed in,
  641. // this will allow access to all the certs as X509 encoded blobs, and it
  642. // will give access to the thumbprints so a cert can be matched with the
  643. // private key
  644. cryptDataBlob.pbData = (BYTE *) pX509Bag->certOrCRL.content.value;
  645. cryptDataBlob.cbData = pX509Bag->certOrCRL.content.length;
  646. hCertStore = CertOpenStore(
  647. CERT_STORE_PROV_PKCS7,
  648. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  649. NULL,
  650. 0,
  651. &cryptDataBlob);
  652. if (NULL == hCertStore) {
  653. goto ErrorReturn;
  654. }
  655. // calculate how much space is needed to fit the array of SAFE_BAGs and
  656. // all their data into one contiguous buffer
  657. while (NULL != (pCertContext = CertEnumCertificatesInStore(
  658. hCertStore,
  659. pCertContext))) {
  660. DWORD cbEncodedCertBag = 0;
  661. cNumSafeBags++;
  662. cbBytesNeeded += sizeof(SAFE_BAG);
  663. // get the size for wrapping an encoded cert into an encoded cert bag
  664. if (!MakeEncodedCertBag(
  665. pCertContext->pbCertEncoded,
  666. pCertContext->cbCertEncoded,
  667. NULL,
  668. &cbEncodedCertBag)) {
  669. goto ErrorReturn;
  670. }
  671. cbBytesNeeded += cbEncodedCertBag;
  672. cbBytesNeeded += strlen(szOID_PKCS_12_CERT_BAG) + 1;
  673. }
  674. // add bytes to cbBytesNeeded so there is enough space to add the
  675. // LocalKeyID attribute to ONE of the certificates
  676. cbBytesNeeded += sizeof(CRYPT_ATTRIBUTE);
  677. cbBytesNeeded += sizeof(CRYPT_ATTR_BLOB);
  678. cbBytesNeeded += strlen(szOID_PKCS_12_LOCAL_KEY_ID) + 1;
  679. cbBytesNeeded += cbEncodedLocalKeyID;
  680. // allocate the one big buffer
  681. if (NULL == (pSafeBags = (SAFE_BAG *) SSAlloc(cbBytesNeeded)))
  682. goto ErrorReturn;
  683. memset(pSafeBags, 0, cbBytesNeeded);
  684. // set the current buffer location to the end of the SAFE_BAG array which
  685. // is at the head of the buffer
  686. pbCurrentBufferLocation = ((BYTE *) pSafeBags) + (sizeof(SAFE_BAG) * cNumSafeBags);
  687. // get the X509 blob for each cert and fill in the array of SAFE_BAGs
  688. pCertContext = NULL;
  689. dwSafeBagIndex = 0;
  690. while (NULL != (pCertContext = CertEnumCertificatesInStore(
  691. hCertStore,
  692. pCertContext))) {
  693. BYTE *pbLocalThumbprint = NULL;
  694. DWORD cbLocalThumbprint = 0;
  695. BYTE *pbEncodedCertBag = NULL;
  696. DWORD cbEncodedCertBag = 0;
  697. // copy the bag type OID
  698. pSafeBags[dwSafeBagIndex].pszBagTypeOID = (LPSTR) pbCurrentBufferLocation;
  699. strcpy((LPSTR)pbCurrentBufferLocation, szOID_PKCS_12_CERT_BAG);
  700. pbCurrentBufferLocation += strlen(szOID_PKCS_12_CERT_BAG) + 1;
  701. // wrap the encoded cert into an encoded certbag
  702. // get the size for wrapping an encoded cert into an encoded cert bag
  703. if (!MakeEncodedCertBag(
  704. pCertContext->pbCertEncoded,
  705. pCertContext->cbCertEncoded,
  706. NULL,
  707. &cbEncodedCertBag)) {
  708. goto ErrorReturn;
  709. }
  710. if (NULL == (pbEncodedCertBag = (BYTE *) SSAlloc(cbEncodedCertBag)))
  711. goto ErrorReturn;
  712. if (!MakeEncodedCertBag(
  713. pCertContext->pbCertEncoded,
  714. pCertContext->cbCertEncoded,
  715. pbEncodedCertBag,
  716. &cbEncodedCertBag)) {
  717. SSFree(pbEncodedCertBag);
  718. goto ErrorReturn;
  719. }
  720. // copy the encoded certbag
  721. pSafeBags[dwSafeBagIndex].BagContents.cbData = cbEncodedCertBag;
  722. pSafeBags[dwSafeBagIndex].BagContents.pbData = pbCurrentBufferLocation;
  723. memcpy(pbCurrentBufferLocation, pbEncodedCertBag, cbEncodedCertBag);
  724. pbCurrentBufferLocation += cbEncodedCertBag;
  725. // we don't need the encoded cert bag anymore
  726. SSFree(pbEncodedCertBag);
  727. // check to see if this cert is the cert that matches the private key by
  728. // comparing the thumbprints
  729. // Get the thumbprint
  730. if (!CertGetCertificateContextProperty(
  731. pCertContext,
  732. CERT_SHA1_HASH_PROP_ID,
  733. NULL,
  734. &cbLocalThumbprint)) {
  735. CertFreeCertificateContext(pCertContext);
  736. goto ErrorReturn;
  737. }
  738. if (NULL == (pbLocalThumbprint = (BYTE *) SSAlloc(cbLocalThumbprint))) {
  739. CertFreeCertificateContext(pCertContext);
  740. goto ErrorReturn;
  741. }
  742. if (!CertGetCertificateContextProperty(
  743. pCertContext,
  744. CERT_SHA1_HASH_PROP_ID,
  745. pbLocalThumbprint,
  746. &cbLocalThumbprint)) {
  747. CertFreeCertificateContext(pCertContext);
  748. SSFree(pbLocalThumbprint);
  749. goto ErrorReturn;
  750. }
  751. // compare thumbprints
  752. if (memcmp(pbCertThumbprint, pbLocalThumbprint, cbLocalThumbprint) == 0) {
  753. // the thumbprints match so add a single attribute with a single value which
  754. pSafeBags[dwSafeBagIndex].Attributes.cAttr = 1;
  755. pSafeBags[dwSafeBagIndex].Attributes.rgAttr = (CRYPT_ATTRIBUTE *) pbCurrentBufferLocation;
  756. pbCurrentBufferLocation += sizeof(CRYPT_ATTRIBUTE);
  757. pSafeBags[dwSafeBagIndex].Attributes.rgAttr[0].pszObjId = (LPSTR) pbCurrentBufferLocation;
  758. strcpy((LPSTR) pbCurrentBufferLocation, szOID_PKCS_12_LOCAL_KEY_ID);
  759. pbCurrentBufferLocation += strlen(szOID_PKCS_12_LOCAL_KEY_ID) + 1;
  760. pSafeBags[dwSafeBagIndex].Attributes.rgAttr[0].cValue = 1;
  761. pSafeBags[dwSafeBagIndex].Attributes.rgAttr[0].rgValue = (CRYPT_ATTR_BLOB *) pbCurrentBufferLocation;
  762. pbCurrentBufferLocation += sizeof(CRYPT_ATTR_BLOB);
  763. pSafeBags[dwSafeBagIndex].Attributes.rgAttr[0].rgValue[0].cbData = cbEncodedLocalKeyID;
  764. pSafeBags[dwSafeBagIndex].Attributes.rgAttr[0].rgValue[0].pbData = pbCurrentBufferLocation;
  765. memcpy(pbCurrentBufferLocation, pbEncodedLocalKeyID, cbEncodedLocalKeyID);
  766. pbCurrentBufferLocation += cbEncodedLocalKeyID;
  767. }
  768. else {
  769. // otherwise the certificate bag has no attributes in it
  770. pSafeBags[dwSafeBagIndex].Attributes.cAttr = 0;
  771. pSafeBags[dwSafeBagIndex].Attributes.rgAttr = NULL;
  772. }
  773. SSFree(pbLocalThumbprint);
  774. dwSafeBagIndex++;
  775. }
  776. // return the safe bag array and the number of safe bags in the array
  777. *ppCertBags = pSafeBags;
  778. *pcNumCertBags = cNumSafeBags;
  779. goto Ret;
  780. SetPFXDecodeError:
  781. SetLastError(CRYPT_E_BAD_ENCODE);
  782. ErrorReturn:
  783. fRet = FALSE;
  784. if (pSafeBags)
  785. SSFree(pSafeBags);
  786. *ppCertBags = NULL;
  787. *pcNumCertBags = 0;
  788. Ret:
  789. // save last error from TLS madness
  790. dwErr = GetLastError();
  791. PkiAsn1FreeDecoded(pDec, pCertCRLBag, CertCRLBag_PDU);
  792. PkiAsn1FreeDecoded(pDec, pX509Bag, X509Bag_PDU);
  793. if (pbEncodedLocalKeyID)
  794. SSFree(pbEncodedLocalKeyID);
  795. if (hCertStore)
  796. CertCloseStore(hCertStore, 0);
  797. // save last error from TLS madness
  798. SetLastError(dwErr);
  799. return fRet;
  800. }
  801. // this function will calculate the number of bytes needed for an
  802. // attribute
  803. static
  804. DWORD
  805. CalculateSizeOfAttributes(
  806. CRYPT_ATTRIBUTES *pAttributes
  807. )
  808. {
  809. DWORD cbBytesNeeded = 0;
  810. DWORD i,j;
  811. for (i=0; i<pAttributes->cAttr; i++) {
  812. cbBytesNeeded += sizeof(CRYPT_ATTRIBUTE);
  813. cbBytesNeeded += strlen(pAttributes->rgAttr[i].pszObjId) + 1;
  814. for (j=0; j<pAttributes->rgAttr[i].cValue; j++) {
  815. cbBytesNeeded += sizeof(CRYPT_ATTR_BLOB);
  816. cbBytesNeeded += pAttributes->rgAttr[i].rgValue[j].cbData;
  817. }
  818. }
  819. return cbBytesNeeded;
  820. }
  821. // this function will take two SAFE_BAG arrays and concatenate them into
  822. // a SAFE_CONTENT structure. also, the SAFE_CONTENT structure and all
  823. // it's supporting data will be in a single contiguous buffer
  824. static
  825. BOOL
  826. ConcatenateSafeBagsIntoSafeContents(
  827. SAFE_BAG *pSafeBagArray1,
  828. DWORD cSafeBagArray1,
  829. SAFE_BAG *pSafeBagArray2,
  830. DWORD cSafeBagArray2,
  831. SAFE_CONTENTS **ppSafeContents
  832. )
  833. {
  834. BOOL fRet = TRUE;
  835. DWORD cbBytesNeeded = 0;
  836. DWORD i,j;
  837. SAFE_CONTENTS *pSafeContents = NULL;
  838. DWORD dwSafeBagIndex = 0;
  839. BYTE *pbCurrentBufferLocation = NULL;
  840. cbBytesNeeded += sizeof(SAFE_CONTENTS);
  841. cbBytesNeeded += sizeof(SAFE_BAG) * (cSafeBagArray1 + cSafeBagArray2);
  842. for (i=0; i<cSafeBagArray1; i++) {
  843. cbBytesNeeded += strlen(pSafeBagArray1[i].pszBagTypeOID) + 1;
  844. cbBytesNeeded += pSafeBagArray1[i].BagContents.cbData;
  845. cbBytesNeeded += CalculateSizeOfAttributes(&pSafeBagArray1[i].Attributes);
  846. }
  847. for (i=0; i<cSafeBagArray2; i++) {
  848. cbBytesNeeded += strlen(pSafeBagArray2[i].pszBagTypeOID) + 1;
  849. cbBytesNeeded += pSafeBagArray2[i].BagContents.cbData;
  850. cbBytesNeeded += CalculateSizeOfAttributes(&pSafeBagArray2[i].Attributes);
  851. }
  852. if (NULL == (pSafeContents = (SAFE_CONTENTS *) SSAlloc(cbBytesNeeded)))
  853. goto ErrorReturn;
  854. memset(pSafeContents, 0, cbBytesNeeded);
  855. pbCurrentBufferLocation = ((BYTE *) pSafeContents) + sizeof(SAFE_CONTENTS);
  856. pSafeContents->cSafeBags = cSafeBagArray1 + cSafeBagArray2;
  857. pSafeContents->pSafeBags = (SAFE_BAG *) pbCurrentBufferLocation;
  858. pbCurrentBufferLocation += sizeof(SAFE_BAG) * (cSafeBagArray1 + cSafeBagArray2);
  859. for (i=0; i<cSafeBagArray1; i++) {
  860. pSafeContents->pSafeBags[dwSafeBagIndex].pszBagTypeOID = (LPSTR) pbCurrentBufferLocation;
  861. strcpy((LPSTR) pbCurrentBufferLocation, pSafeBagArray1[i].pszBagTypeOID);
  862. pbCurrentBufferLocation += strlen(pSafeBagArray1[i].pszBagTypeOID) + 1;
  863. pSafeContents->pSafeBags[dwSafeBagIndex].BagContents.cbData = pSafeBagArray1[i].BagContents.cbData;
  864. pSafeContents->pSafeBags[dwSafeBagIndex].BagContents.pbData = pbCurrentBufferLocation;
  865. memcpy(pbCurrentBufferLocation, pSafeBagArray1[i].BagContents.pbData, pSafeBagArray1[i].BagContents.cbData);
  866. pbCurrentBufferLocation += pSafeBagArray1[i].BagContents.cbData;
  867. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.cAttr = pSafeBagArray1[i].Attributes.cAttr;
  868. if (pSafeBagArray1[i].Attributes.cAttr != 0) {
  869. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr = (CRYPT_ATTRIBUTE *) pbCurrentBufferLocation;
  870. pbCurrentBufferLocation += sizeof(CRYPT_ATTRIBUTE) * pSafeBagArray1[i].Attributes.cAttr;
  871. }
  872. else {
  873. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr = NULL;
  874. }
  875. for (j=0; j<pSafeBagArray1[i].Attributes.cAttr; j++) {
  876. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].pszObjId = (LPSTR) pbCurrentBufferLocation;
  877. strcpy((LPSTR) pbCurrentBufferLocation, pSafeBagArray1[i].Attributes.rgAttr[j].pszObjId);
  878. pbCurrentBufferLocation += strlen(pSafeBagArray1[i].Attributes.rgAttr[j].pszObjId) + 1;
  879. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].cValue = 1;
  880. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue = (CRYPT_ATTR_BLOB *) pbCurrentBufferLocation;
  881. pbCurrentBufferLocation += sizeof(CRYPT_ATTR_BLOB);
  882. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue[0].cbData =
  883. pSafeBagArray1[i].Attributes.rgAttr[j].rgValue[0].cbData;
  884. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue[0].pbData = pbCurrentBufferLocation;
  885. memcpy(
  886. pbCurrentBufferLocation,
  887. pSafeBagArray1[i].Attributes.rgAttr[j].rgValue[0].pbData,
  888. pSafeBagArray1[i].Attributes.rgAttr[j].rgValue[0].cbData);
  889. pbCurrentBufferLocation += pSafeBagArray1[i].Attributes.rgAttr[j].rgValue[0].cbData;
  890. }
  891. dwSafeBagIndex++;
  892. }
  893. for (i=0; i<cSafeBagArray2; i++) {
  894. pSafeContents->pSafeBags[dwSafeBagIndex].pszBagTypeOID = (LPSTR) pbCurrentBufferLocation;
  895. strcpy((LPSTR) pbCurrentBufferLocation, pSafeBagArray2[i].pszBagTypeOID);
  896. pbCurrentBufferLocation += strlen(pSafeBagArray2[i].pszBagTypeOID) + 1;
  897. pSafeContents->pSafeBags[dwSafeBagIndex].BagContents.cbData = pSafeBagArray2[i].BagContents.cbData;
  898. pSafeContents->pSafeBags[dwSafeBagIndex].BagContents.pbData = pbCurrentBufferLocation;
  899. memcpy(pbCurrentBufferLocation, pSafeBagArray2[i].BagContents.pbData, pSafeBagArray2[i].BagContents.cbData);
  900. pbCurrentBufferLocation += pSafeBagArray2[i].BagContents.cbData;
  901. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.cAttr = pSafeBagArray2[i].Attributes.cAttr;
  902. if (pSafeBagArray2[i].Attributes.cAttr != 0) {
  903. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr = (CRYPT_ATTRIBUTE *) pbCurrentBufferLocation;
  904. pbCurrentBufferLocation += sizeof(CRYPT_ATTRIBUTE) * pSafeBagArray2[i].Attributes.cAttr;
  905. }
  906. else {
  907. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr = NULL;
  908. }
  909. for (j=0; j<pSafeBagArray2[i].Attributes.cAttr; j++) {
  910. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].pszObjId = (LPSTR) pbCurrentBufferLocation;
  911. strcpy((LPSTR) pbCurrentBufferLocation, pSafeBagArray2[i].Attributes.rgAttr[j].pszObjId);
  912. pbCurrentBufferLocation += strlen(pSafeBagArray2[i].Attributes.rgAttr[j].pszObjId) + 1;
  913. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].cValue = 1;
  914. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue = (CRYPT_ATTR_BLOB *) pbCurrentBufferLocation;
  915. pbCurrentBufferLocation += sizeof(CRYPT_ATTR_BLOB);
  916. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue[0].cbData =
  917. pSafeBagArray2[i].Attributes.rgAttr[j].rgValue[0].cbData;
  918. pSafeContents->pSafeBags[dwSafeBagIndex].Attributes.rgAttr[j].rgValue[0].pbData = pbCurrentBufferLocation;
  919. memcpy(
  920. pbCurrentBufferLocation,
  921. pSafeBagArray2[i].Attributes.rgAttr[j].rgValue[0].pbData,
  922. pSafeBagArray2[i].Attributes.rgAttr[j].rgValue[0].cbData);
  923. pbCurrentBufferLocation += pSafeBagArray2[i].Attributes.rgAttr[j].rgValue[0].cbData;
  924. }
  925. dwSafeBagIndex++;
  926. }
  927. *ppSafeContents = pSafeContents;
  928. goto Ret;
  929. ErrorReturn:
  930. fRet = FALSE;
  931. Ret:
  932. return fRet;
  933. }
  934. BOOL
  935. PFXAPI
  936. NSCPImportBlob
  937. (
  938. LPCWSTR szPassword,
  939. PBYTE pbIn,
  940. DWORD cbIn,
  941. SAFE_CONTENTS **ppSafeContents
  942. )
  943. {
  944. BOOL fRet = TRUE;
  945. DWORD dwErr;
  946. int iEncrType;
  947. OID oid = NULL;
  948. PFX *psPfx = NULL;
  949. EncryptedData *pEncrData = NULL;
  950. RSAData *pRSAData = NULL;
  951. PBEParameter *pPBEParameter = NULL;
  952. SafeContents *pSafeCnts = NULL;
  953. AuthenticatedSafe *pAuthSafe = NULL;
  954. SAFE_BAG *pKeyBag = NULL;
  955. SAFE_BAG *pCertBag = NULL;
  956. BYTE *pCertThumbprint = NULL;
  957. DWORD cNumCertBags = 0;
  958. ASN1decoding_t pDec = GetDecoder();
  959. // Crack the PFX blob
  960. if (0 != PkiAsn1Decode(
  961. pDec,
  962. (void **)&psPfx,
  963. PFX_PDU,
  964. pbIn,
  965. cbIn))
  966. goto SetPFXDecodeError;
  967. // info blurted into psPfx(PFX) - ensure content present
  968. if (0 == (psPfx->authSafe.bit_mask & content_present))
  969. goto SetPFXDecodeError;
  970. // UNDONE: tear apart MACData
  971. // Check authsafe(ContentInfo)
  972. // could be data/signeddata
  973. // UNDONE: only support szOID_RSA_data
  974. if (!INSCP_Asn1FromObjectID( &psPfx->authSafe.contentType, &oid))
  975. goto ErrorReturn;
  976. if (0 != strcmp( oid, szOID_RSA_data))
  977. goto SetPFXDecodeError;
  978. SSFree(oid);
  979. oid = NULL;
  980. // content is data: decode
  981. if (0 != PkiAsn1Decode(
  982. pDec,
  983. (void **)&pRSAData,
  984. RSAData_PDU,
  985. (BYTE *) psPfx->authSafe.content.value,
  986. psPfx->authSafe.content.length))
  987. goto SetPFXDecodeError;
  988. // now we have octet string: this is an encoded authSafe
  989. if (0 != PkiAsn1Decode(
  990. pDec,
  991. (void **)&pAuthSafe,
  992. AuthenticatedSafe_PDU,
  993. pRSAData->value,
  994. pRSAData->length))
  995. goto SetPFXDecodeError;
  996. // check version of the safe
  997. if (pAuthSafe->bit_mask & version_present)
  998. #ifdef OSS_CRYPT_ASN1
  999. if (pAuthSafe->version != v1)
  1000. #else
  1001. if (pAuthSafe->version != Version_v1)
  1002. #endif // OSS_CRYPT_ASN1
  1003. goto SetPFXDecodeError;
  1004. // require (officially optional) pieces
  1005. // NSCP: transport mode is used but count is encoded incorrectly
  1006. // if (0 == (pAuthSafe->bit_mask & transportMode_present))
  1007. // goto PFXDecodeError;
  1008. if (0 == (pAuthSafe->bit_mask & privacySalt_present))
  1009. goto SetPFXDecodeError;
  1010. if (0 == (pAuthSafe->bit_mask & baggage_present))
  1011. goto SetPFXDecodeError;
  1012. // could be encryptedData/envelopedData
  1013. // UNDONE: only support szOID_RSA_encryptedData
  1014. if (!INSCP_Asn1FromObjectID( &pAuthSafe->safe.contentType, &oid))
  1015. goto ErrorReturn;
  1016. if (0 != strcmp( oid, szOID_RSA_encryptedData))
  1017. goto SetPFXDecodeError;
  1018. SSFree(oid);
  1019. oid = NULL;
  1020. //
  1021. // we have pAuthSafe->safe data as RSA_encryptedData
  1022. // we have pAuthSafe->privacySalt to help us decrypt it
  1023. // we have pAuthSafe->baggage
  1024. // decode content to encryptedData
  1025. if (0 != PkiAsn1Decode(
  1026. pDec,
  1027. (void **)&pEncrData,
  1028. EncryptedData_PDU,
  1029. (BYTE *) pAuthSafe->safe.content.value,
  1030. pAuthSafe->safe.content.length))
  1031. goto SetPFXDecodeError;
  1032. // chk version
  1033. if (pEncrData->version != 0)
  1034. goto SetPFXDecodeError;
  1035. // chk content present, type
  1036. if (0 == (pEncrData->encryptedContentInfo.bit_mask & encryptedContent_present))
  1037. goto SetPFXDecodeError;
  1038. if (!INSCP_Asn1FromObjectID(&pEncrData->encryptedContentInfo.contentType, &oid))
  1039. goto ErrorReturn;
  1040. if (0 != strcmp( oid, szOID_RSA_data))
  1041. goto SetPFXDecodeError;
  1042. SSFree(oid);
  1043. oid = NULL;
  1044. // chk encr alg present, type
  1045. if (0 == (pEncrData->encryptedContentInfo.contentEncryptionAlg.bit_mask & parameters_present))
  1046. goto SetPFXDecodeError;
  1047. if (!INSCP_Asn1FromObjectID(&pEncrData->encryptedContentInfo.contentEncryptionAlg.algorithm, &oid))
  1048. goto ErrorReturn;
  1049. if (0 != PkiAsn1Decode(
  1050. pDec,
  1051. (void **)&pPBEParameter,
  1052. PBEParameter_PDU,
  1053. (BYTE *) pEncrData->encryptedContentInfo.contentEncryptionAlg.parameters.value,
  1054. pEncrData->encryptedContentInfo.contentEncryptionAlg.parameters.length))
  1055. goto SetPFXDecodeError;
  1056. if (0 == strcmp( oid, OLD_szOID_PKCS_12_pbeWithSHA1And40BitRC2))
  1057. {
  1058. iEncrType = RC2_40;
  1059. }
  1060. else if (0 == strcmp( oid, OLD_szOID_PKCS_12_pbeWithSHA1And40BitRC4))
  1061. {
  1062. iEncrType = RC4_40;
  1063. }
  1064. else if (0 == strcmp( oid, OLD_szOID_PKCS_12_pbeWithSHA1And128BitRC2))
  1065. {
  1066. iEncrType = RC2_128;
  1067. }
  1068. else if (0 == strcmp( oid, OLD_szOID_PKCS_12_pbeWithSHA1And128BitRC4))
  1069. {
  1070. iEncrType = RC4_128;
  1071. }
  1072. else if (0 == strcmp( oid, OLD_szOID_PKCS_12_pbeWithSHA1AndTripleDES))
  1073. {
  1074. iEncrType = TripleDES;
  1075. }
  1076. else
  1077. goto SetPFXAlgIDError;
  1078. SSFree(oid);
  1079. oid = NULL;
  1080. // DECRYPT encryptedData
  1081. if (!NSCPPasswordDecryptData(
  1082. iEncrType,
  1083. szPassword,
  1084. pAuthSafe->privacySalt.value, // privacy salt
  1085. pAuthSafe->privacySalt.length/8,
  1086. pPBEParameter->iterationCount,
  1087. pPBEParameter->salt.value, // pkcs5 salt
  1088. pPBEParameter->salt.length,
  1089. &pEncrData->encryptedContentInfo.encryptedContent.value,
  1090. (PDWORD)&pEncrData->encryptedContentInfo.encryptedContent.length))
  1091. goto SetPFXDecryptError;
  1092. // decode plaintext encryptedData
  1093. if (0 != PkiAsn1Decode(
  1094. pDec,
  1095. (void **)&pSafeCnts,
  1096. SafeContents_PDU,
  1097. pEncrData->encryptedContentInfo.encryptedContent.value,
  1098. pEncrData->encryptedContentInfo.encryptedContent.length))
  1099. goto SetPFXDecodeError;
  1100. // get private keys out of baggage
  1101. if (!ExtractKeyFromBaggage(
  1102. pAuthSafe->baggage,
  1103. &pKeyBag,
  1104. szPassword,
  1105. 1, // this parameter is the Local Key ID to add to the key bags attributes
  1106. &pCertThumbprint)) {
  1107. goto ErrorReturn;
  1108. }
  1109. // set up the cert bag
  1110. if (!SetupCertBags(
  1111. pSafeCnts,
  1112. &pCertBag,
  1113. &cNumCertBags,
  1114. 1, // this parameter is the Local Key ID to add to the cert bags attributes
  1115. pCertThumbprint)) {
  1116. goto ErrorReturn;
  1117. }
  1118. ConcatenateSafeBagsIntoSafeContents(
  1119. pKeyBag,
  1120. 1,
  1121. pCertBag,
  1122. cNumCertBags,
  1123. ppSafeContents);
  1124. goto Ret;
  1125. SetPFXAlgIDError:
  1126. SetLastError(NTE_BAD_ALGID);
  1127. goto ErrorReturn;
  1128. SetPFXDecodeError:
  1129. SetLastError(CRYPT_E_BAD_ENCODE);
  1130. goto ErrorReturn;
  1131. SetPFXDecryptError:
  1132. SetLastError(NTE_FAIL);
  1133. goto ErrorReturn;
  1134. ErrorReturn:
  1135. fRet = FALSE;
  1136. Ret:
  1137. // save last error from TLS madness
  1138. dwErr = GetLastError();
  1139. PkiAsn1FreeDecoded(pDec, psPfx, PFX_PDU);
  1140. PkiAsn1FreeDecoded(pDec, pRSAData, RSAData_PDU);
  1141. PkiAsn1FreeDecoded(pDec, pAuthSafe, AuthenticatedSafe_PDU);
  1142. PkiAsn1FreeDecoded(pDec, pEncrData, EncryptedData_PDU);
  1143. PkiAsn1FreeDecoded(pDec, pPBEParameter, PBEParameter_PDU);
  1144. PkiAsn1FreeDecoded(pDec, pSafeCnts, SafeContents_PDU);
  1145. if (oid != NULL)
  1146. SSFree(oid);
  1147. if (pKeyBag)
  1148. SSFree(pKeyBag);
  1149. if (pCertBag)
  1150. SSFree(pCertBag);
  1151. if (pCertThumbprint)
  1152. SSFree(pCertThumbprint);
  1153. // save last error from TLS madness
  1154. SetLastError(dwErr);
  1155. return fRet; // return bogus handle
  1156. }
  1157. BOOL
  1158. PFXAPI
  1159. IsNetscapePFXBlob(CRYPT_DATA_BLOB* pPFX)
  1160. {
  1161. PFX *psPfx = NULL;
  1162. ASN1decoding_t pDec = GetDecoder();
  1163. // Crack the PFX blob
  1164. if (0 == PkiAsn1Decode(
  1165. pDec,
  1166. (void **)&psPfx,
  1167. PFX_PDU,
  1168. pPFX->pbData,
  1169. pPFX->cbData))
  1170. {
  1171. PkiAsn1FreeDecoded(pDec, psPfx, PFX_PDU);
  1172. return TRUE;
  1173. }
  1174. return FALSE;
  1175. }
  1176. /*
  1177. BOOL FNSCPDumpSafeCntsToHPFX(SafeContents* pSafeCnts, HPFX hpfx)
  1178. {
  1179. PPFX_INFO ppfx = (PPFX_INFO)hpfx;
  1180. // sort and dump bags into correct areas
  1181. ObjectID oKeyBag, oCertBag;
  1182. DWORD dw;
  1183. ZeroMemory(&oKeyBag, sizeof(ObjectID));
  1184. ZeroMemory(&oCertBag, sizeof(ObjectID));
  1185. if (!INSCP_Asn1ToObjectID( &szOID_PKCS_12_KeyBagIDs, &oKeyBag))
  1186. return FALSE;
  1187. if (!INSCP_Asn1ToObjectID( &szOID_PKCS_12_CertCrlBagIDs, &oCertBag))
  1188. return FALSE;
  1189. for (dw=pSafeCnts->count; dw>0; --dw)
  1190. {
  1191. if (INSCP_EqualObjectIDs(&pSafeCnts->value->safeBagType,
  1192. &oKeyBag) )
  1193. {
  1194. // inc size
  1195. ppfx->cKeys++;
  1196. if (ppfx->rgKeys)
  1197. ppfx->rgKeys = (void**)SSReAlloc(ppfx->rgKeys, ppfx->cKeys * sizeof(SafeBag*));
  1198. else
  1199. ppfx->rgKeys = (void**)SSAlloc(ppfx->cKeys * sizeof(SafeBag*));
  1200. // assign to keys
  1201. ppfx->rgKeys[ppfx->cKeys-1] = &pSafeCnts->value[dw];
  1202. }
  1203. else if (INSCP_EqualObjectIDs(&pSafeCnts->value->safeBagType,
  1204. &oCertBag) )
  1205. {
  1206. // inc size
  1207. ppfx->cCertcrls++;
  1208. if (ppfx->rgCertcrls)
  1209. ppfx->rgCertcrls = (void**)SSReAlloc(ppfx->rgCertcrls, ppfx->cCertcrls * sizeof(SafeBag*));
  1210. else
  1211. ppfx->rgCertcrls = (void**)SSAlloc(ppfx->cCertcrls * sizeof(SafeBag*));
  1212. // assign to certs/crls
  1213. ppfx->rgCertcrls[ppfx->cCertcrls-1] = &pSafeCnts->value[dw];
  1214. }
  1215. else
  1216. {
  1217. // inc size
  1218. ppfx->cSecrets++;
  1219. if (ppfx->rgSecrets)
  1220. ppfx->rgSecrets = (void**)SSReAlloc(ppfx->rgSecrets, ppfx->cSecrets * sizeof(SafeBag*));
  1221. else
  1222. ppfx->rgSecrets = (void**)SSAlloc(ppfx->cSecrets * sizeof(SafeBag*));
  1223. // assign to safebag
  1224. ppfx->rgSecrets[ppfx->cSecrets-1] = &pSafeCnts->value[dw];
  1225. }
  1226. }
  1227. return TRUE;
  1228. }
  1229. */