]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp
Security-57031.40.6.tar.gz
[apple/security.git] / Security / libsecurity_pkcs12 / lib / pkcs12Decode.cpp
1 /*
2 * Copyright (c) 2003-2004,2011,2014 Apple 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 * pkcs12Decode.h - P12Coder decoding engine.
26 */
27
28 #include "pkcs12Coder.h"
29 #include "pkcs12Templates.h"
30 #include "pkcs12Utils.h"
31 #include "pkcs12Debug.h"
32 #include "pkcs12Crypto.h"
33 #include <security_cdsa_utilities/cssmerrors.h>
34 #include <security_asn1/nssUtils.h>
35
36 /* top-level PKCS12 PFX decoder */
37 void P12Coder::decode(
38 CFDataRef cdpfx)
39 {
40 SecNssCoder localCdr;
41 NSS_P12_DecodedPFX pfx;
42
43 p12DecodeLog("decode");
44 memset(&pfx, 0, sizeof(pfx));
45 const CSSM_DATA rawBlob = {CFDataGetLength(cdpfx),
46 (uint8 *)CFDataGetBytePtr(cdpfx)};
47
48 if(localCdr.decodeItem(rawBlob, NSS_P12_DecodedPFXTemplate, &pfx)) {
49 p12ErrorLog("Error on top-level decode of NSS_P12_DecodedPFX\n");
50 P12_THROW_DECODE;
51 }
52 NSS_P7_DecodedContentInfo &dci = pfx.authSafe;
53 if(dci.type != CT_Data) {
54 /* no other types supported yet */
55 p12ErrorLog("bad top-level contentType\n");
56 P12_THROW_DECODE;
57 }
58 mIntegrityMode = kSecPkcs12ModePassword;
59
60 if(pfx.macData == NULL) {
61 /* not present is an error in kSecPkcs12ModePassword */
62 p12ErrorLog("no MAC in PFX\n");
63 P12_THROW_DECODE;
64 }
65 macParse(*pfx.macData, localCdr);
66
67 const CSSM_DATA *macPhrase = getMacPassPhrase();
68 const CSSM_KEY *macPassKey = getMacPassKey();
69 if((macPhrase == NULL) && (macPassKey == NULL)) {
70 p12ErrorLog("no passphrase set\n");
71 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
72 }
73 CSSM_RETURN crtn = p12VerifyMac(pfx, mCspHand, macPhrase,
74 macPassKey, localCdr);
75 if(crtn) {
76 p12LogCssmError("p12VerifyMac", crtn);
77 CssmError::throwMe(errSecPkcs12VerifyFailure);
78 }
79
80 authSafeParse(*dci.content.data, localCdr);
81
82 /*
83 * On success, if we have a keychain, store certs and CRLs there
84 */
85 if(mKeychain != NULL) {
86 storeDecodeResults();
87 }
88 }
89
90 /*
91 * Decrypt the contents of a NSS_P7_EncryptedData
92 */
93 void P12Coder::encryptedDataDecrypt(
94 const NSS_P7_EncryptedData &edata,
95 SecNssCoder &localCdr,
96 NSS_P12_PBE_Params *pbep, // preparsed
97 CSSM_DATA &ptext) // result goes here in localCdr space
98 {
99 p12DecodeLog("encryptedDataDecrypt");
100
101 /* see if we can grok the encr alg */
102 CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES
103 CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE
104 CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5
105 uint32 keySizeInBits;
106 uint32 blockSizeInBytes; // for IV, optional
107 CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc.
108 CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc.
109 PKCS_Which pkcs;
110
111 bool found = pkcsOidToParams(&edata.contentInfo.encrAlg.algorithm,
112 keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
113 padding, mode, pkcs);
114 if(!found || (pkcs != PW_PKCS12)) {
115 p12ErrorLog("EncryptedData encrAlg not understood\n");
116 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
117 }
118
119 uint32 iterCount;
120 if(!p12DataToInt(pbep->iterations, iterCount)) {
121 p12ErrorLog("encryptedDataDecrypt: badly formed iterCount\n");
122 P12_THROW_DECODE;
123 }
124 const CSSM_DATA *pwd = getEncrPassPhrase();
125 const CSSM_KEY *passKey = getEncrPassKey();
126 if((pwd == NULL) && (passKey == NULL)) {
127 p12ErrorLog("no passphrase set\n");
128 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
129 }
130
131 /* go */
132 CSSM_RETURN crtn = p12Decrypt(mCspHand,
133 edata.contentInfo.encrContent,
134 keyAlg, encrAlg, pbeHashAlg,
135 keySizeInBits, blockSizeInBytes,
136 padding, mode,
137 iterCount, pbep->salt,
138 pwd,
139 passKey,
140 localCdr,
141 ptext);
142 if(crtn) {
143 CssmError::throwMe(crtn);
144 }
145 }
146
147
148 /*
149 * Parse an CSSM_X509_ALGORITHM_IDENTIFIER specific to P12.
150 * Decode the alg params as a NSS_P12_PBE_Params and parse and
151 * return the result if the pbeParams is non-NULL.
152 */
153 void P12Coder::algIdParse(
154 const CSSM_X509_ALGORITHM_IDENTIFIER &algId,
155 NSS_P12_PBE_Params *pbeParams, // optional
156 SecNssCoder &localCdr)
157 {
158 p12DecodeLog("algIdParse");
159
160 const CSSM_DATA &param = algId.parameters;
161 if(pbeParams == NULL) {
162 /* alg params are uninterpreted */
163 return;
164 }
165
166 if(param.Length == 0) {
167 p12ErrorLog("algIdParse: no alg parameters\n");
168 P12_THROW_DECODE;
169 }
170
171 memset(pbeParams, 0, sizeof(*pbeParams));
172 if(localCdr.decodeItem(param,
173 NSS_P12_PBE_ParamsTemplate, pbeParams)) {
174 p12ErrorLog("Error decoding NSS_P12_PBE_Params\n");
175 P12_THROW_DECODE;
176 }
177 }
178
179 /*
180 * Parse a NSS_P7_EncryptedData - specifically in the context
181 * of a P12 in password privacy mode. (The latter assumption is
182 * to enable us to infer CSSM_X509_ALGORITHM_IDENTIFIER.parameters
183 * format).
184 */
185 void P12Coder::encryptedDataParse(
186 const NSS_P7_EncryptedData &edata,
187 SecNssCoder &localCdr,
188 NSS_P12_PBE_Params *pbep) // optional, RETURNED
189 {
190 p12DecodeLog("encryptedDataParse");
191
192 /*
193 * Parse the alg ID, save PBE params for when we do the decrypt
194 * key unwrap
195 */
196 const NSS_P7_EncrContentInfo &ci = edata.contentInfo;
197 const CSSM_X509_ALGORITHM_IDENTIFIER &algId = ci.encrAlg;
198 algIdParse(algId, pbep, localCdr);
199 }
200
201 /*
202 * ShroudedKeyBag parser w/decrypt
203 */
204 void P12Coder::shroudedKeyBagParse(
205 const NSS_P12_SafeBag &safeBag,
206 SecNssCoder &localCdr)
207 {
208 p12DecodeLog("Found shrouded key bag");
209 if(mPrivKeyImportState == PKIS_NoMore) {
210 CssmError::throwMe(errSecMultiplePrivKeys);
211 }
212
213 const NSS_P12_ShroudedKeyBag *keyBag = safeBag.bagValue.shroudedKeyBag;
214 const CSSM_X509_ALGORITHM_IDENTIFIER &algId = keyBag->algorithm;
215 NSS_P12_PBE_Params pbep;
216 algIdParse(algId, &pbep, localCdr);
217
218 /*
219 * Prepare for decryption
220 */
221 CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES
222 CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE
223 CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5
224 uint32 keySizeInBits;
225 uint32 blockSizeInBytes; // for IV, optional
226 CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc.
227 CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc.
228 PKCS_Which pkcs;
229
230 bool found = pkcsOidToParams(&algId.algorithm,
231 keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
232 padding, mode, pkcs);
233 if(!found || (pkcs != PW_PKCS12)) {
234 p12ErrorLog("ShroudedKeyBag encrAlg not understood\n");
235 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
236 }
237
238 uint32 iterCount;
239 if(!p12DataToInt(pbep.iterations, iterCount)) {
240 p12ErrorLog("ShroudedKeyBag: badly formed iterCount\n");
241 P12_THROW_DECODE;
242 }
243 const CSSM_DATA *encrPhrase = getEncrPassPhrase();
244 const CSSM_KEY *passKey = getEncrPassKey();
245 if((encrPhrase == NULL) && (passKey == NULL)) {
246 p12ErrorLog("no passphrase set\n");
247 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
248 }
249
250 /* We'll own the actual CSSM_KEY memory */
251 CSSM_KEY_PTR privKey = (CSSM_KEY_PTR)mCoder.malloc(sizeof(CSSM_KEY));
252 memset(privKey, 0, sizeof(CSSM_KEY));
253
254 CSSM_DATA labelData;
255 p12GenLabel(labelData, localCdr);
256
257 CSSM_RETURN crtn = p12UnwrapKey(mCspHand,
258 mDlDbHand.DLHandle ? &mDlDbHand : NULL,
259 mImportFlags & kSecImportKeys,
260 keyBag->encryptedData,
261 keyAlg, encrAlg, pbeHashAlg,
262 keySizeInBits, blockSizeInBytes,
263 padding, mode,
264 iterCount, pbep.salt,
265 encrPhrase,
266 passKey,
267 localCdr,
268 labelData,
269 mAccess,
270 mNoAcl,
271 mKeyUsage,
272 mKeyAttrs,
273 privKey);
274 if(crtn) {
275 p12ErrorLog("Error unwrapping private key\n");
276 CssmError::throwMe(crtn);
277 }
278 p12DecodeLog("unwrapped shrouded key bag");
279
280 P12KeyBag *p12bag = new P12KeyBag(privKey, mCspHand,
281 safeBag.bagAttrs, labelData, mCoder);
282 addKey(p12bag);
283
284 if(mPrivKeyImportState == PKIS_AllowOne) {
285 mPrivKeyImportState = PKIS_NoMore;
286 }
287 }
288
289 /*
290 * (unshrouded) KeyBag parser
291 */
292 void P12Coder::keyBagParse(
293 const NSS_P12_SafeBag &safeBag,
294 SecNssCoder &localCdr)
295 {
296 if(mPrivKeyImportState == PKIS_NoMore) {
297 CssmError::throwMe(errSecMultiplePrivKeys);
298 }
299
300 /* FIXME - should be able to parse and handle this.... */
301 p12DecodeLog("found keyBag");
302 NSS_P12_KeyBag *keyBag = safeBag.bagValue.keyBag;
303 P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId,
304 /* this breaks when NSS_P12_KeyBag is not a CSSM_DATA */
305 *keyBag,
306 safeBag.bagAttrs,
307 mCoder);
308 addOpaque(p12Bag);
309 }
310
311 /*
312 * CertBag parser
313 */
314 void P12Coder::certBagParse(
315 const NSS_P12_SafeBag &safeBag,
316 SecNssCoder &localCdr)
317 {
318 p12DecodeLog("found certBag");
319 NSS_P12_CertBag *certBag = safeBag.bagValue.certBag;
320 switch(certBag->type) {
321 case CT_X509:
322 case CT_SDSI:
323 break;
324 default:
325 p12ErrorLog("certBagParse: unknown cert type\n");
326 P12_THROW_DECODE;
327 }
328 P12CertBag *p12Bag = new P12CertBag(certBag->type,
329 certBag->certValue,
330 safeBag.bagAttrs,
331 mCoder);
332 addCert(p12Bag);
333 }
334
335 /*
336 * CrlBag parser
337 */
338 void P12Coder::crlBagParse(
339 const NSS_P12_SafeBag &safeBag,
340 SecNssCoder &localCdr)
341 {
342 p12DecodeLog("found crlBag");
343 NSS_P12_CrlBag *crlBag = safeBag.bagValue.crlBag;
344 switch(crlBag->type) {
345 case CRT_X509:
346 break;
347 default:
348 p12ErrorLog("crlBagParse: unknown CRL type\n");
349 P12_THROW_DECODE;
350 }
351 P12CrlBag *p12Bag = new P12CrlBag(crlBag->type,
352 crlBag->crlValue,
353 safeBag.bagAttrs,
354 mCoder);
355 addCrl(p12Bag);
356 }
357
358 /*
359 * SecretBag parser
360 */
361 void P12Coder::secretBagParse(
362 const NSS_P12_SafeBag &safeBag,
363 SecNssCoder &localCdr)
364 {
365 p12DecodeLog("found secretBag");
366 NSS_P12_SecretBag *secretBag = safeBag.bagValue.secretBag;
367 P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId,
368 /* this breaks when NSS_P12_SecretBag is not a CSSM_DATA */
369 *secretBag,
370 safeBag.bagAttrs,
371 mCoder);
372 addOpaque(p12Bag);
373 }
374
375 /*
376 * SafeContentsBag parser
377 */
378 void P12Coder::safeContentsBagParse(
379 const NSS_P12_SafeBag &safeBag,
380 SecNssCoder &localCdr)
381 {
382 p12DecodeLog("found SafeContents safe bag");
383 NSS_P12_SafeContentsBag *scBag = safeBag.bagValue.safeContentsBag;
384 P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId,
385 /* this breaks when NSS_P12_SafeContentsBag is not a CSSM_DATA */
386 *scBag,
387 safeBag.bagAttrs,
388 mCoder);
389 addOpaque(p12Bag);
390 }
391
392 /*
393 * Parse an encoded NSS_P12_SafeContents. This could be either
394 * present as plaintext in an AuthSafe or decrypted.
395 */
396 void P12Coder::safeContentsParse(
397 const CSSM_DATA &contentsBlob,
398 SecNssCoder &localCdr)
399 {
400 p12DecodeLog("safeContentsParse");
401
402 NSS_P12_SafeContents sc;
403 memset(&sc, 0, sizeof(sc));
404 if(localCdr.decodeItem(contentsBlob, NSS_P12_SafeContentsTemplate,
405 &sc)) {
406 p12ErrorLog("Error decoding SafeContents\n");
407 P12_THROW_DECODE;
408 }
409 unsigned numBags = nssArraySize((const void **)sc.bags);
410 for(unsigned dex=0; dex<numBags; dex++) {
411 NSS_P12_SafeBag *bag = sc.bags[dex];
412 assert(bag != NULL);
413
414 /* ensure that *something* is there */
415 if(bag->bagValue.keyBag == NULL) {
416 p12ErrorLog("safeContentsParse: Empty SafeBag\n");
417 P12_THROW_DECODE;
418 }
419
420 /*
421 * Break out to individual bag type
422 */
423 switch(bag->type) {
424 case BT_KeyBag:
425 keyBagParse(*bag, localCdr);
426 break;
427 case BT_ShroudedKeyBag:
428 shroudedKeyBagParse(*bag, localCdr);
429 break;
430 case BT_CertBag:
431 certBagParse(*bag, localCdr);
432 break;
433 case BT_CrlBag:
434 crlBagParse(*bag, localCdr);
435 break;
436 case BT_SecretBag:
437 secretBagParse(*bag ,localCdr);
438 break;
439 case BT_SafeContentsBag:
440 safeContentsBagParse(*bag, localCdr);
441 break;
442 default:
443 p12ErrorLog("unknown p12 BagType (%u)\n",
444 (unsigned)bag->type);
445 P12_THROW_DECODE;
446 }
447 }
448 }
449
450 /*
451 * Parse a ContentInfo in the context of (i.e., as an element of)
452 * an AuthenticatedSafe.
453 */
454 void P12Coder::authSafeElementParse(
455 const NSS_P7_DecodedContentInfo *info,
456 SecNssCoder &localCdr)
457 {
458 p12DecodeLog("authSafeElementParse");
459 switch(info->type) {
460 case CT_Data:
461 /* unencrypted SafeContents */
462 safeContentsParse(*info->content.data, localCdr);
463 break;
464
465 case CT_EncryptedData:
466 {
467 NSS_P12_PBE_Params pbep;
468 encryptedDataParse(*info->content.encryptData, localCdr, &pbep);
469
470 /*
471 * Decrypt contents to get a SafeContents and
472 * then parse that.
473 */
474 CSSM_DATA ptext = {0, NULL};
475 encryptedDataDecrypt(*info->content.encryptData,
476 localCdr, &pbep, ptext);
477 safeContentsParse(ptext, localCdr);
478 break;
479 }
480 default:
481 p12ErrorLog("authSafeElementParse: unknown sage type (%u)\n",
482 (unsigned)info->type);
483
484 /* well, save it as an opaque bag for now */
485 P12OpaqueBag *opaque = new P12OpaqueBag(
486 info->contentType, *info->content.data,
487 NULL, // no attrs
488 localCdr);
489 addOpaque(opaque);
490 break;
491 }
492 }
493
494 /*
495 * Parse an encoded NSS_P12_AuthenticatedSafe
496 */
497 void P12Coder::authSafeParse(
498 const CSSM_DATA &authSafeBlob,
499 SecNssCoder &localCdr)
500 {
501 p12DecodeLog("authSafeParse");
502
503 NSS_P12_AuthenticatedSafe authSafe;
504
505 memset(&authSafe, 0, sizeof(authSafe));
506 if(localCdr.decodeItem(authSafeBlob,
507 NSS_P12_AuthenticatedSafeTemplate,
508 &authSafe)) {
509 p12ErrorLog("Error decoding authSafe\n");
510 P12_THROW_DECODE;
511 }
512 unsigned numInfos = nssArraySize((const void **)authSafe.info);
513 for(unsigned dex=0; dex<numInfos; dex++) {
514 NSS_P7_DecodedContentInfo *info = authSafe.info[dex];
515 authSafeElementParse(info, localCdr);
516 }
517 }
518
519 void P12Coder::macParse(
520 const NSS_P12_MacData &macData,
521 SecNssCoder &localCdr)
522 {
523 p12DecodeLog("macParse");
524 algIdParse(macData.mac.digestAlgorithm, NULL, localCdr);
525 const CSSM_DATA &iter = macData.iterations;
526 if(iter.Length > 4) {
527 p12ErrorLog("malformed iteration length (%u)\n",
528 (unsigned)iter.Length);
529 P12_THROW_DECODE;
530 }
531 }
532