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