]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | /* | |
25 | * pkcs12Encode.h - P12Coder encoding engine. | |
26 | * | |
27 | * Unlike the decoding side of P12Coder, which can parse PFXs with | |
28 | * more or less arbitrary structures, this encoding engine has | |
29 | * a specific layout for what bags go where in the jungle of | |
30 | * SafeContents and ContentInfos. It would be impractical to allow | |
31 | * (or to expect) the app to specify this structure. | |
32 | * | |
33 | * The knowledge of how a PFX is built out of various components | |
34 | * is encapsulated in the authSafeBuild() member function. The rest | |
35 | * of the functions in this file are pretty much "PFX-structure- | |
36 | * agnostic", so if one wanted to change the overall PFX structure, | |
37 | * one would only have to focus on the authSafeBuild() function. | |
38 | */ | |
39 | ||
40 | #include "pkcs12Coder.h" | |
41 | #include "pkcs12Debug.h" | |
42 | #include "pkcs12Crypto.h" | |
43 | #include "pkcs12Templates.h" | |
44 | #include "pkcs12Utils.h" | |
45 | #include <Security/cssmerr.h> | |
46 | #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> | |
47 | #include <Security/oidsattr.h> | |
48 | ||
49 | void P12Coder::encode( | |
50 | CFDataRef *cpfx) // RETURNED | |
51 | { | |
52 | p12EncodeLog("encode top"); | |
53 | SecNssCoder localCdr; | |
54 | NSS_P12_DecodedPFX pfx; | |
55 | ||
56 | memset(&pfx, 0, sizeof(pfx)); | |
57 | p12IntToData(3, pfx.version, localCdr); | |
58 | authSafeBuild(pfx.authSafe, localCdr); | |
59 | macSignPfx(pfx, localCdr); | |
60 | CSSM_DATA derPfx = {0, NULL}; | |
61 | if(localCdr.encodeItem(&pfx, NSS_P12_DecodedPFXTemplate, derPfx)) { | |
62 | p12ErrorLog("Error encoding top-level pfx\n"); | |
63 | P12_THROW_ENCODE; | |
64 | } | |
65 | CFDataRef cp = CFDataCreate(NULL, derPfx.Data, derPfx.Length); | |
66 | *cpfx = cp; | |
67 | } | |
68 | ||
69 | void P12Coder::macSignPfx( | |
70 | NSS_P12_DecodedPFX &pfx, | |
71 | SecNssCoder &localCdr) | |
72 | { | |
73 | p12EncodeLog("macSignPfx"); | |
74 | NSS_P12_MacData *macData = localCdr.mallocn<NSS_P12_MacData>(); | |
75 | pfx.macData = macData; | |
76 | p12GenSalt(macData->macSalt, localCdr); | |
77 | p12IntToData(mMacIterCount, macData->iterations, localCdr); | |
78 | NSS_P7_DigestInfo &digInfo = macData->mac; | |
79 | ||
80 | /* this is not negotiable; it's the only one P12 allows */ | |
81 | localCdr.allocCopyItem(CSSMOID_SHA1, digInfo.digestAlgorithm.algorithm); | |
82 | /* null algorithm parameters */ | |
83 | p12NullAlgParams(digInfo.digestAlgorithm); | |
84 | ||
85 | const CSSM_DATA *macPhrase = getMacPassPhrase(); | |
86 | const CSSM_KEY *macPassKey = getMacPassKey(); | |
87 | if((macPhrase == NULL) && (macPassKey == NULL)) { | |
88 | p12ErrorLog("no passphrase set\n"); | |
89 | CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE); | |
90 | } | |
91 | ||
92 | CSSM_RETURN crtn = p12GenMac(mCspHand, | |
93 | *pfx.authSafe.content.data, | |
94 | CSSM_ALGID_SHA1, mMacIterCount, macData->macSalt, | |
95 | macPhrase, macPassKey, localCdr, digInfo.digest); | |
96 | if(crtn) { | |
97 | p12ErrorLog("Error generating PFX MAC\n"); | |
98 | CssmError::throwMe(crtn); | |
99 | } | |
100 | } | |
101 | ||
102 | /* | |
103 | * This is the heart of the encoding engine. All knowledge of | |
104 | * "what bags go where" is here. The PFX structure implemented here | |
105 | * is derived from empirical observation of PFXs obtained from | |
106 | * Mozilla 1.2b and from the DoD test vectors for "Conformance | |
107 | * Testing of Relying Party Client Certificate Path Processing | |
108 | * Logic", written by Cygnacom, Septemtber 28, 2001. | |
109 | * | |
110 | * The PFX structure is as follows: | |
111 | * | |
112 | * -- One AuthenticatedSafe element (a PKCS7 ContentInfo) containing | |
113 | * all certificates and CRLs. | |
114 | * | |
115 | * ContentInfo.type = CT_EncryptedData | |
116 | * Encryption algorithm is our "weak" encryption Alg, default | |
117 | * of CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4. | |
118 | * | |
119 | * -- One AuthenticatedSafe element containing all private keys in | |
120 | * the form of ShroudedKeyBags. | |
121 | * | |
122 | * ContentInfo.type = CT_Data | |
123 | * Encryption algorithm for shrouded key bags is our "strong" | |
124 | * encryption, default CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC | |
125 | * | |
126 | * -- Everything else goes in another AuthenticatedSafe element. | |
127 | * | |
128 | * ContentInfo.type = CT_EncryptedData | |
129 | * Encryption algorithm is our "strong" encryption Alg | |
130 | */ | |
131 | void P12Coder::authSafeBuild( | |
132 | NSS_P7_DecodedContentInfo &authSafe, | |
133 | SecNssCoder &localCdr) | |
134 | { | |
135 | p12EncodeLog("authSafeBuild top"); | |
136 | ||
137 | /* how many contentInfos are we going to build? */ | |
138 | unsigned numContents = 0; | |
139 | if(mCerts.size() || mCrls.size()) { | |
140 | numContents++; | |
141 | } | |
142 | if(mKeys.size()) { | |
143 | numContents++; | |
144 | } | |
145 | if(mOpaques.size()) { | |
146 | numContents++; | |
147 | } | |
148 | ||
149 | if(numContents == 0) { | |
150 | p12ErrorLog("authSafeBuild: no contents\n"); | |
151 | MacOSError::throwMe(paramErr); | |
152 | } | |
153 | ||
154 | NSS_P7_DecodedContentInfo **contents = | |
155 | (NSS_P7_DecodedContentInfo **)p12NssNullArray(numContents, | |
156 | localCdr); | |
157 | unsigned contentDex = 0; | |
158 | ||
159 | NSS_P12_SafeBag **safeBags; | |
160 | ||
161 | /* certs & crls */ | |
162 | unsigned numBags = mCerts.size() + mCrls.size(); | |
163 | p12EncodeLog("authSafeBuild : %u certs + CRLS", numBags); | |
164 | if(numBags) { | |
165 | safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr); | |
166 | unsigned bagDex = 0; | |
167 | for(unsigned dex=0; dex<mCerts.size(); dex++) { | |
168 | safeBags[bagDex++] = certBagBuild(mCerts[dex], localCdr); | |
169 | } | |
170 | for(unsigned dex=0; dex<mCrls.size(); dex++) { | |
171 | safeBags[bagDex++] = crlBagBuild(mCrls[dex], localCdr); | |
172 | } | |
173 | contents[contentDex++] = safeContentsBuild(safeBags, | |
174 | CT_EncryptedData, &mWeakEncrAlg, mWeakEncrIterCount, localCdr); | |
175 | } | |
176 | ||
177 | /* shrouded keys - encrypted at bag level */ | |
178 | numBags = mKeys.size(); | |
179 | if(numBags) { | |
180 | p12EncodeLog("authSafeBuild : %u keys", numBags); | |
181 | safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr); | |
182 | unsigned bagDex = 0; | |
183 | for(unsigned dex=0; dex<numBags; dex++) { | |
184 | safeBags[bagDex++] = keyBagBuild(mKeys[dex], localCdr); | |
185 | } | |
186 | contents[contentDex++] = safeContentsBuild(safeBags, | |
187 | CT_Data, NULL, 0, localCdr); | |
188 | } | |
189 | ||
190 | /* opaque */ | |
191 | numBags = mOpaques.size(); | |
192 | if(numBags) { | |
193 | p12EncodeLog("authSafeBuild : %u opaques", numBags); | |
194 | safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr); | |
195 | unsigned bagDex = 0; | |
196 | for(unsigned dex=0; dex<numBags; dex++) { | |
197 | safeBags[bagDex++] = opaqueBagBuild(mOpaques[dex], localCdr); | |
198 | } | |
199 | contents[contentDex++] = safeContentsBuild(safeBags, | |
200 | CT_EncryptedData, &mStrongEncrAlg, mStrongEncrIterCount, localCdr); | |
201 | } | |
202 | ||
203 | /* | |
204 | * Encode the whole elements array into authSafe.content.data | |
205 | */ | |
206 | NSS_P12_AuthenticatedSafe safe; | |
207 | safe.info = contents; | |
208 | CSSM_DATA *adata = localCdr.mallocn<CSSM_DATA>(); | |
209 | authSafe.content.data = adata; | |
210 | adata->Data = NULL; | |
211 | adata->Length = 0; | |
212 | if(localCdr.encodeItem(&safe, NSS_P12_AuthenticatedSafeTemplate, | |
213 | *adata)) { | |
214 | p12ErrorLog("authSafeBuild: error encoding auth safe\n"); | |
215 | P12_THROW_ENCODE; | |
216 | } | |
217 | authSafe.type = CT_Data; | |
218 | authSafe.contentType = CSSMOID_PKCS7_Data; | |
219 | } | |
220 | ||
221 | /* | |
222 | * Build a AuthSafe element of specified type out of the | |
223 | * specified array of bags. | |
224 | */ | |
225 | NSS_P7_DecodedContentInfo *P12Coder::safeContentsBuild( | |
226 | NSS_P12_SafeBag **bags, | |
227 | NSS_P7_CI_Type type, // CT_Data, CT_EncryptedData | |
228 | CSSM_OID *encrOid, // only for CT_EncryptedData | |
229 | unsigned iterCount, // ditto | |
230 | SecNssCoder &localCdr) | |
231 | { | |
232 | p12EncodeLog("safeContentsBuild type %u", (unsigned)type); | |
233 | ||
234 | /* | |
235 | * First, encode the bag array as a SafeContents | |
236 | */ | |
237 | CSSM_DATA encSafeContents = {0, NULL}; | |
238 | NSS_P12_SafeContents safeContents = {bags}; | |
239 | if(localCdr.encodeItem(&safeContents, | |
240 | NSS_P12_SafeContentsTemplate, encSafeContents)) { | |
241 | p12ErrorLog("error encoding SafeContents\n"); | |
242 | P12_THROW_ENCODE; | |
243 | } | |
244 | ||
245 | NSS_P7_DecodedContentInfo *dci = | |
246 | localCdr.mallocn<NSS_P7_DecodedContentInfo>(); | |
247 | dci->type = type; | |
248 | if(type == CT_Data) { | |
249 | /* plaintext gets encoded as an octet string */ | |
250 | localCdr.allocCopyItem(CSSMOID_PKCS7_Data, dci->contentType); | |
251 | dci->content.data = localCdr.mallocn<CSSM_DATA>(); | |
252 | localCdr.allocCopyItem(encSafeContents, *dci->content.data); | |
253 | } | |
254 | else if(type == CT_EncryptedData) { | |
255 | /* encrypt the encoded SafeContents */ | |
256 | localCdr.allocCopyItem(CSSMOID_PKCS7_EncryptedData, | |
257 | dci->contentType); | |
258 | dci->content.encryptData = localCdr.mallocn<NSS_P7_EncryptedData>(); | |
259 | NSS_P7_EncryptedData *ed = dci->content.encryptData; | |
260 | assert(encrOid != NULL); | |
261 | encryptData(encSafeContents, *encrOid, iterCount, *ed, localCdr); | |
262 | } | |
263 | else { | |
264 | p12ErrorLog("bad type in safeContentsBuild\n"); | |
265 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
266 | } | |
267 | return dci; | |
268 | } | |
269 | ||
270 | /* | |
271 | * Encrypt the specified plaintext with specified algorithm. | |
272 | * Drop result and other interesting info into an NSS_P7_EncryptedData. | |
273 | */ | |
274 | void P12Coder::encryptData( | |
275 | const CSSM_DATA &ptext, | |
276 | CSSM_OID &encrOid, | |
277 | unsigned iterCount, | |
278 | NSS_P7_EncryptedData &ed, | |
279 | SecNssCoder &localCdr) | |
280 | { | |
281 | p12EncodeLog("encryptData"); | |
282 | ||
283 | /* do the raw encrypt first to make sure we can do it... */ | |
284 | CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES | |
285 | CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE | |
286 | CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 | |
287 | uint32 keySizeInBits; | |
288 | uint32 blockSizeInBytes; // for IV, optional | |
289 | CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. | |
290 | CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. | |
291 | PKCS_Which pkcs; | |
292 | ||
293 | bool found = pkcsOidToParams(&encrOid, | |
294 | keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, | |
295 | padding, mode, pkcs); | |
296 | if(!found || (pkcs != PW_PKCS12)) { | |
297 | p12ErrorLog("encryptData encrAlg not understood\n"); | |
298 | CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); | |
299 | } | |
300 | ||
301 | /* Salt: we generate random bytes */ | |
302 | CSSM_DATA salt; | |
303 | p12GenSalt(salt, localCdr); | |
304 | ||
305 | const CSSM_DATA *pwd = getEncrPassPhrase(); | |
306 | const CSSM_KEY *passKey = getEncrPassKey(); | |
307 | if((pwd == NULL) && (passKey == NULL)) { | |
308 | p12ErrorLog("no passphrase set\n"); | |
309 | CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE); | |
310 | } | |
311 | CSSM_DATA ctext = {0, NULL}; | |
312 | ||
313 | CSSM_RETURN crtn = p12Encrypt(mCspHand, ptext, | |
314 | keyAlg, encrAlg, pbeHashAlg, | |
315 | keySizeInBits, blockSizeInBytes, | |
316 | padding, mode, | |
317 | iterCount, salt, | |
318 | pwd, passKey, localCdr, | |
319 | ctext); | |
320 | if(crtn) { | |
321 | CssmError::throwMe(crtn); | |
322 | } | |
323 | ||
324 | /* Now fill in the NSS_P7_EncryptedData */ | |
325 | p12IntToData(0, ed.version, localCdr); | |
326 | NSS_P7_EncrContentInfo &eci = ed.contentInfo; | |
327 | localCdr.allocCopyItem(CSSMOID_PKCS7_Data, eci.contentType); | |
328 | algIdBuild(eci.encrAlg, encrOid, salt, iterCount, localCdr); | |
329 | eci.encrContent = ctext; | |
330 | } | |
331 | ||
332 | /* | |
333 | * Fill in an CSSM_X509_ALGORITHM_IDENTIFIER with parameters in | |
334 | * the form of an encoded NSS_P12_PBE_Params | |
335 | */ | |
336 | void P12Coder::algIdBuild( | |
337 | CSSM_X509_ALGORITHM_IDENTIFIER &algId, | |
338 | const CSSM_OID &algOid, | |
339 | const CSSM_DATA &salt, | |
340 | unsigned iterCount, | |
341 | SecNssCoder &localCdr) | |
342 | { | |
343 | p12EncodeLog("algIdBuild"); | |
344 | localCdr.allocCopyItem(algOid, algId.algorithm); | |
345 | NSS_P12_PBE_Params pbeParams; | |
346 | pbeParams.salt = salt; | |
347 | p12IntToData(iterCount, pbeParams.iterations, localCdr); | |
348 | if(localCdr.encodeItem(&pbeParams, NSS_P12_PBE_ParamsTemplate, | |
349 | algId.parameters)) { | |
350 | p12ErrorLog("error encoding NSS_P12_PBE_Params\n"); | |
351 | P12_THROW_ENCODE; | |
352 | } | |
353 | } | |
354 | ||
355 | #pragma mark --- Individual Bag Builders --- | |
356 | ||
357 | NSS_P12_SafeBag *P12Coder::certBagBuild( | |
358 | P12CertBag *cert, | |
359 | SecNssCoder &localCdr) | |
360 | { | |
361 | p12EncodeLog("certBagBuild"); | |
362 | ||
363 | NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>(); | |
364 | safeBag->bagId = CSSMOID_PKCS12_certBag; | |
365 | safeBag->type = BT_CertBag; | |
366 | ||
367 | NSS_P12_CertBag *certBag = localCdr.mallocn<NSS_P12_CertBag>(); | |
368 | safeBag->bagValue.certBag = certBag; | |
369 | const CSSM_OID *certTypeOid = NULL; | |
370 | switch(cert->certType()) { | |
371 | case CT_X509: | |
372 | certTypeOid = &CSSMOID_PKCS9_X509Certificate; | |
373 | break; | |
374 | case CT_SDSI: | |
375 | certTypeOid = &CSSMOID_PKCS9_SdsiCertificate; | |
376 | break; | |
377 | default: | |
378 | p12ErrorLog("unknown certType on encode\n"); | |
379 | CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); | |
380 | ||
381 | } | |
382 | ||
383 | /* copies not needed, same scope as P12CertBag */ | |
384 | certBag->bagType = *certTypeOid; | |
385 | certBag->type = cert->certType(); | |
386 | certBag->certValue = cert->certData(); | |
387 | safeBag->bagAttrs = cert->getAllAttrs(); | |
388 | return safeBag; | |
389 | } | |
390 | ||
391 | NSS_P12_SafeBag *P12Coder::crlBagBuild( | |
392 | P12CrlBag *crl, | |
393 | SecNssCoder &localCdr) | |
394 | { | |
395 | p12EncodeLog("crlBagBuild"); | |
396 | ||
397 | NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>(); | |
398 | safeBag->bagId = CSSMOID_PKCS12_crlBag; | |
399 | safeBag->type = BT_CrlBag; | |
400 | ||
401 | NSS_P12_CrlBag *crlBag = localCdr.mallocn<NSS_P12_CrlBag>(); | |
402 | safeBag->bagValue.crlBag = crlBag; | |
403 | const CSSM_OID *crlTypeOid = NULL; | |
404 | switch(crl->crlType()) { | |
405 | case CRT_X509: | |
406 | crlTypeOid = &CSSMOID_PKCS9_X509Crl; | |
407 | break; | |
408 | default: | |
409 | p12ErrorLog("unknown crlType on encode\n"); | |
410 | CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); | |
411 | ||
412 | } | |
413 | ||
414 | /* copies not needed, same scope as P12CrlBag */ | |
415 | crlBag->bagType = *crlTypeOid; | |
416 | crlBag->type = crl->crlType(); | |
417 | crlBag->crlValue = crl->crlData(); | |
418 | safeBag->bagAttrs = crl->getAllAttrs(); | |
419 | return safeBag; | |
420 | } | |
421 | ||
422 | NSS_P12_SafeBag *P12Coder::keyBagBuild( | |
423 | P12KeyBag *key, | |
424 | SecNssCoder &localCdr) | |
425 | { | |
426 | p12EncodeLog("keyBagBuild"); | |
427 | ||
428 | NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>(); | |
429 | safeBag->bagId = CSSMOID_PKCS12_shroudedKeyBag; | |
430 | safeBag->type = BT_ShroudedKeyBag; | |
431 | ||
432 | NSS_EncryptedPrivateKeyInfo *keyInfo = localCdr. | |
433 | mallocn<NSS_EncryptedPrivateKeyInfo>(); | |
434 | safeBag->bagValue.shroudedKeyBag = keyInfo; | |
435 | safeBag->bagAttrs = key->getAllAttrs(); | |
436 | ||
437 | /* Prepare for key wrap */ | |
438 | CSSM_DATA salt; | |
439 | p12GenSalt(salt, localCdr); | |
440 | algIdBuild(keyInfo->algorithm, mStrongEncrAlg, salt, | |
441 | mStrongEncrIterCount, localCdr); | |
442 | ||
443 | CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES | |
444 | CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE | |
445 | CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 | |
446 | uint32 keySizeInBits; | |
447 | uint32 blockSizeInBytes; // for IV, optional | |
448 | CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. | |
449 | CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. | |
450 | PKCS_Which pkcs; | |
451 | ||
452 | bool found = pkcsOidToParams(&mStrongEncrAlg, | |
453 | keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, | |
454 | padding, mode, pkcs); | |
455 | if(!found || (pkcs != PW_PKCS12)) { | |
456 | /* app config error - they gave us bogus algorithm */ | |
457 | p12ErrorLog("keyBagBuild encrAlg not understood\n"); | |
458 | CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); | |
459 | } | |
460 | const CSSM_DATA *encrPhrase = getEncrPassPhrase(); | |
461 | const CSSM_KEY *passKey = getEncrPassKey(); | |
462 | if((encrPhrase == NULL) && (passKey == NULL)) { | |
463 | p12ErrorLog("no passphrase set\n"); | |
464 | CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE); | |
465 | } | |
466 | CSSM_DATA shroudedBits = {0, NULL}; | |
467 | ||
468 | CSSM_RETURN crtn = p12WrapKey(mCspHand, | |
469 | key->key(), key->privKeyCreds(), | |
470 | keyAlg, encrAlg, pbeHashAlg, | |
471 | keySizeInBits, blockSizeInBytes, | |
472 | padding, mode, | |
473 | mStrongEncrIterCount, salt, | |
474 | encrPhrase, | |
475 | passKey, | |
476 | localCdr, | |
477 | shroudedBits); | |
478 | if(crtn) { | |
479 | p12ErrorLog("Error wrapping private key\n"); | |
480 | CssmError::throwMe(crtn); | |
481 | } | |
482 | ||
483 | keyInfo->encryptedData = shroudedBits; | |
484 | return safeBag; | |
485 | } | |
486 | ||
487 | NSS_P12_SafeBag *P12Coder::opaqueBagBuild( | |
488 | P12OpaqueBag *opaque, | |
489 | SecNssCoder &localCdr) | |
490 | { | |
491 | p12EncodeLog("opaqueBagBuild"); | |
492 | NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>(); | |
493 | safeBag->bagId = opaque->oid(); | |
494 | safeBag->bagValue.secretBag = &opaque->blob(); | |
495 | safeBag->bagAttrs = opaque->getAllAttrs(); | |
496 | return safeBag; | |
497 | } |