Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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