2 * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * pkcs12Decode.h - P12Coder decoding engine.
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>
37 /* top-level PKCS12 PFX decoder */
38 void P12Coder::decode(
42 NSS_P12_DecodedPFX pfx
;
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
)};
49 if(localCdr
.decodeItem(rawBlob
, NSS_P12_DecodedPFXTemplate
, &pfx
)) {
50 p12ErrorLog("Error on top-level decode of NSS_P12_DecodedPFX\n");
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");
59 mIntegrityMode
= kSecPkcs12ModePassword
;
61 if(pfx
.macData
== NULL
) {
62 /* not present is an error in kSecPkcs12ModePassword */
63 p12ErrorLog("no MAC in PFX\n");
66 macParse(*pfx
.macData
, localCdr
);
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
);
74 CSSM_RETURN crtn
= p12VerifyMac(pfx
, mCspHand
, macPhrase
,
75 macPassKey
, localCdr
);
77 p12LogCssmError("p12VerifyMac", crtn
);
78 CssmError::throwMe(errSecPkcs12VerifyFailure
);
81 authSafeParse(*dci
.content
.data
, localCdr
);
84 * On success, if we have a keychain, store certs and CRLs there
86 if(mKeychain
!= NULL
) {
92 * Decrypt the contents of a NSS_P7_EncryptedData
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
100 p12DecodeLog("encryptedDataDecrypt");
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.
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
);
121 if(!p12DataToInt(pbep
->iterations
, iterCount
)) {
122 p12ErrorLog("encryptedDataDecrypt: badly formed iterCount\n");
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
);
133 CSSM_RETURN crtn
= p12Decrypt(mCspHand
,
134 edata
.contentInfo
.encrContent
,
135 keyAlg
, encrAlg
, pbeHashAlg
,
136 keySizeInBits
, blockSizeInBytes
,
138 iterCount
, pbep
->salt
,
144 CssmError::throwMe(crtn
);
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.
154 void P12Coder::algIdParse(
155 const CSSM_X509_ALGORITHM_IDENTIFIER
&algId
,
156 NSS_P12_PBE_Params
*pbeParams
, // optional
157 SecNssCoder
&localCdr
)
159 p12DecodeLog("algIdParse");
161 const CSSM_DATA
¶m
= algId
.parameters
;
162 if(pbeParams
== NULL
) {
163 /* alg params are uninterpreted */
167 if(param
.Length
== 0) {
168 p12ErrorLog("algIdParse: no alg parameters\n");
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");
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
186 void P12Coder::encryptedDataParse(
187 const NSS_P7_EncryptedData
&edata
,
188 SecNssCoder
&localCdr
,
189 NSS_P12_PBE_Params
*pbep
) // optional, RETURNED
191 p12DecodeLog("encryptedDataParse");
194 * Parse the alg ID, save PBE params for when we do the decrypt
197 const NSS_P7_EncrContentInfo
&ci
= edata
.contentInfo
;
198 const CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= ci
.encrAlg
;
199 algIdParse(algId
, pbep
, localCdr
);
203 * ShroudedKeyBag parser w/decrypt
205 void P12Coder::shroudedKeyBagParse(
206 const NSS_P12_SafeBag
&safeBag
,
207 SecNssCoder
&localCdr
)
209 p12DecodeLog("Found shrouded key bag");
210 if(mPrivKeyImportState
== PKIS_NoMore
) {
211 CssmError::throwMe(errSecMultiplePrivKeys
);
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
);
220 * Prepare for decryption
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.
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
);
240 if(!p12DataToInt(pbep
.iterations
, iterCount
)) {
241 p12ErrorLog("ShroudedKeyBag: badly formed iterCount\n");
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
);
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
));
256 p12GenLabel(labelData
, localCdr
);
258 CSSM_RETURN crtn
= p12UnwrapKey(mCspHand
,
259 mDlDbHand
.DLHandle
? &mDlDbHand
: NULL
,
260 mImportFlags
& kSecImportKeys
,
261 keyBag
->encryptedData
,
262 keyAlg
, encrAlg
, pbeHashAlg
,
263 keySizeInBits
, blockSizeInBytes
,
265 iterCount
, pbep
.salt
,
276 p12ErrorLog("Error unwrapping private key\n");
277 CssmError::throwMe(crtn
);
279 p12DecodeLog("unwrapped shrouded key bag");
281 P12KeyBag
*p12bag
= new P12KeyBag(privKey
, mCspHand
,
282 safeBag
.bagAttrs
, labelData
, mCoder
);
285 if(mPrivKeyImportState
== PKIS_AllowOne
) {
286 mPrivKeyImportState
= PKIS_NoMore
;
291 * (unshrouded) KeyBag parser
293 void P12Coder::keyBagParse(
294 const NSS_P12_SafeBag
&safeBag
,
295 SecNssCoder
&localCdr
)
297 if(mPrivKeyImportState
== PKIS_NoMore
) {
298 CssmError::throwMe(errSecMultiplePrivKeys
);
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 */
315 void P12Coder::certBagParse(
316 const NSS_P12_SafeBag
&safeBag
,
317 SecNssCoder
&localCdr
)
319 p12DecodeLog("found certBag");
320 NSS_P12_CertBag
*certBag
= safeBag
.bagValue
.certBag
;
321 switch(certBag
->type
) {
326 p12ErrorLog("certBagParse: unknown cert type\n");
329 P12CertBag
*p12Bag
= new P12CertBag(certBag
->type
,
339 void P12Coder::crlBagParse(
340 const NSS_P12_SafeBag
&safeBag
,
341 SecNssCoder
&localCdr
)
343 p12DecodeLog("found crlBag");
344 NSS_P12_CrlBag
*crlBag
= safeBag
.bagValue
.crlBag
;
345 switch(crlBag
->type
) {
349 p12ErrorLog("crlBagParse: unknown CRL type\n");
352 P12CrlBag
*p12Bag
= new P12CrlBag(crlBag
->type
,
362 void P12Coder::secretBagParse(
363 const NSS_P12_SafeBag
&safeBag
,
364 SecNssCoder
&localCdr
)
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 */
377 * SafeContentsBag parser
379 void P12Coder::safeContentsBagParse(
380 const NSS_P12_SafeBag
&safeBag
,
381 SecNssCoder
&localCdr
)
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 */
394 * Parse an encoded NSS_P12_SafeContents. This could be either
395 * present as plaintext in an AuthSafe or decrypted.
397 void P12Coder::safeContentsParse(
398 const CSSM_DATA
&contentsBlob
,
399 SecNssCoder
&localCdr
)
401 p12DecodeLog("safeContentsParse");
403 NSS_P12_SafeContents sc
;
404 memset(&sc
, 0, sizeof(sc
));
405 if(localCdr
.decodeItem(contentsBlob
, NSS_P12_SafeContentsTemplate
,
407 p12ErrorLog("Error decoding SafeContents\n");
410 unsigned numBags
= nssArraySize((const void **)sc
.bags
);
411 for(unsigned dex
=0; dex
<numBags
; dex
++) {
412 NSS_P12_SafeBag
*bag
= sc
.bags
[dex
];
415 /* ensure that *something* is there */
416 if(bag
->bagValue
.keyBag
== NULL
) {
417 p12ErrorLog("safeContentsParse: Empty SafeBag\n");
422 * Break out to individual bag type
426 keyBagParse(*bag
, localCdr
);
428 case BT_ShroudedKeyBag
:
429 shroudedKeyBagParse(*bag
, localCdr
);
432 certBagParse(*bag
, localCdr
);
435 crlBagParse(*bag
, localCdr
);
438 secretBagParse(*bag
,localCdr
);
440 case BT_SafeContentsBag
:
441 safeContentsBagParse(*bag
, localCdr
);
444 p12ErrorLog("unknown p12 BagType (%u)\n",
445 (unsigned)bag
->type
);
452 * Parse a ContentInfo in the context of (i.e., as an element of)
453 * an AuthenticatedSafe.
455 void P12Coder::authSafeElementParse(
456 const NSS_P7_DecodedContentInfo
*info
,
457 SecNssCoder
&localCdr
)
459 p12DecodeLog("authSafeElementParse");
462 /* unencrypted SafeContents */
463 safeContentsParse(*info
->content
.data
, localCdr
);
466 case CT_EncryptedData
:
468 NSS_P12_PBE_Params pbep
;
469 encryptedDataParse(*info
->content
.encryptData
, localCdr
, &pbep
);
472 * Decrypt contents to get a SafeContents and
475 CSSM_DATA ptext
= {0, NULL
};
476 encryptedDataDecrypt(*info
->content
.encryptData
,
477 localCdr
, &pbep
, ptext
);
478 safeContentsParse(ptext
, localCdr
);
482 p12ErrorLog("authSafeElementParse: unknown sage type (%u)\n",
483 (unsigned)info
->type
);
485 /* well, save it as an opaque bag for now */
486 P12OpaqueBag
*opaque
= new P12OpaqueBag(
487 info
->contentType
, *info
->content
.data
,
496 * Parse an encoded NSS_P12_AuthenticatedSafe
498 void P12Coder::authSafeParse(
499 const CSSM_DATA
&authSafeBlob
,
500 SecNssCoder
&localCdr
)
502 p12DecodeLog("authSafeParse");
504 NSS_P12_AuthenticatedSafe authSafe
;
506 memset(&authSafe
, 0, sizeof(authSafe
));
507 if(localCdr
.decodeItem(authSafeBlob
,
508 NSS_P12_AuthenticatedSafeTemplate
,
510 p12ErrorLog("Error decoding authSafe\n");
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
);
520 void P12Coder::macParse(
521 const NSS_P12_MacData
&macData
,
522 SecNssCoder
&localCdr
)
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
);