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_asn1/nssUtils.h>
36 /* top-level PKCS12 PFX decoder */
37 void P12Coder::decode(
41 NSS_P12_DecodedPFX pfx
;
43 p12DecodeLog("decode");
44 memset(&pfx
, 0, sizeof(pfx
));
45 const CSSM_DATA rawBlob
= {CFDataGetLength(cdpfx
),
46 (uint8
*)CFDataGetBytePtr(cdpfx
)};
48 if(localCdr
.decodeItem(rawBlob
, NSS_P12_DecodedPFXTemplate
, &pfx
)) {
49 p12ErrorLog("Error on top-level decode of NSS_P12_DecodedPFX\n");
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");
58 mIntegrityMode
= kSecPkcs12ModePassword
;
60 if(pfx
.macData
== NULL
) {
61 /* not present is an error in kSecPkcs12ModePassword */
62 p12ErrorLog("no MAC in PFX\n");
65 macParse(*pfx
.macData
, localCdr
);
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
);
73 CSSM_RETURN crtn
= p12VerifyMac(pfx
, mCspHand
, macPhrase
,
74 macPassKey
, localCdr
);
76 p12LogCssmError("p12VerifyMac", crtn
);
77 CssmError::throwMe(errSecPkcs12VerifyFailure
);
80 authSafeParse(*dci
.content
.data
, localCdr
);
83 * On success, if we have a keychain, store certs and CRLs there
85 if(mKeychain
!= NULL
) {
91 * Decrypt the contents of a NSS_P7_EncryptedData
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
99 p12DecodeLog("encryptedDataDecrypt");
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.
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
);
120 if(!p12DataToInt(pbep
->iterations
, iterCount
)) {
121 p12ErrorLog("encryptedDataDecrypt: badly formed iterCount\n");
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
);
132 CSSM_RETURN crtn
= p12Decrypt(mCspHand
,
133 edata
.contentInfo
.encrContent
,
134 keyAlg
, encrAlg
, pbeHashAlg
,
135 keySizeInBits
, blockSizeInBytes
,
137 iterCount
, pbep
->salt
,
143 CssmError::throwMe(crtn
);
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.
153 void P12Coder::algIdParse(
154 const CSSM_X509_ALGORITHM_IDENTIFIER
&algId
,
155 NSS_P12_PBE_Params
*pbeParams
, // optional
156 SecNssCoder
&localCdr
)
158 p12DecodeLog("algIdParse");
160 const CSSM_DATA
¶m
= algId
.parameters
;
161 if(pbeParams
== NULL
) {
162 /* alg params are uninterpreted */
166 if(param
.Length
== 0) {
167 p12ErrorLog("algIdParse: no alg parameters\n");
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");
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
185 void P12Coder::encryptedDataParse(
186 const NSS_P7_EncryptedData
&edata
,
187 SecNssCoder
&localCdr
,
188 NSS_P12_PBE_Params
*pbep
) // optional, RETURNED
190 p12DecodeLog("encryptedDataParse");
193 * Parse the alg ID, save PBE params for when we do the decrypt
196 const NSS_P7_EncrContentInfo
&ci
= edata
.contentInfo
;
197 const CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= ci
.encrAlg
;
198 algIdParse(algId
, pbep
, localCdr
);
202 * ShroudedKeyBag parser w/decrypt
204 void P12Coder::shroudedKeyBagParse(
205 const NSS_P12_SafeBag
&safeBag
,
206 SecNssCoder
&localCdr
)
208 p12DecodeLog("Found shrouded key bag");
209 if(mPrivKeyImportState
== PKIS_NoMore
) {
210 CssmError::throwMe(errSecMultiplePrivKeys
);
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
);
219 * Prepare for decryption
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.
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
);
239 if(!p12DataToInt(pbep
.iterations
, iterCount
)) {
240 p12ErrorLog("ShroudedKeyBag: badly formed iterCount\n");
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
);
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
));
255 p12GenLabel(labelData
, localCdr
);
257 CSSM_RETURN crtn
= p12UnwrapKey(mCspHand
,
258 mDlDbHand
.DLHandle
? &mDlDbHand
: NULL
,
259 mImportFlags
& kSecImportKeys
,
260 keyBag
->encryptedData
,
261 keyAlg
, encrAlg
, pbeHashAlg
,
262 keySizeInBits
, blockSizeInBytes
,
264 iterCount
, pbep
.salt
,
275 p12ErrorLog("Error unwrapping private key\n");
276 CssmError::throwMe(crtn
);
278 p12DecodeLog("unwrapped shrouded key bag");
280 P12KeyBag
*p12bag
= new P12KeyBag(privKey
, mCspHand
,
281 safeBag
.bagAttrs
, labelData
, mCoder
);
284 if(mPrivKeyImportState
== PKIS_AllowOne
) {
285 mPrivKeyImportState
= PKIS_NoMore
;
290 * (unshrouded) KeyBag parser
292 void P12Coder::keyBagParse(
293 const NSS_P12_SafeBag
&safeBag
,
294 SecNssCoder
&localCdr
)
296 if(mPrivKeyImportState
== PKIS_NoMore
) {
297 CssmError::throwMe(errSecMultiplePrivKeys
);
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 */
314 void P12Coder::certBagParse(
315 const NSS_P12_SafeBag
&safeBag
,
316 SecNssCoder
&localCdr
)
318 p12DecodeLog("found certBag");
319 NSS_P12_CertBag
*certBag
= safeBag
.bagValue
.certBag
;
320 switch(certBag
->type
) {
325 p12ErrorLog("certBagParse: unknown cert type\n");
328 P12CertBag
*p12Bag
= new P12CertBag(certBag
->type
,
338 void P12Coder::crlBagParse(
339 const NSS_P12_SafeBag
&safeBag
,
340 SecNssCoder
&localCdr
)
342 p12DecodeLog("found crlBag");
343 NSS_P12_CrlBag
*crlBag
= safeBag
.bagValue
.crlBag
;
344 switch(crlBag
->type
) {
348 p12ErrorLog("crlBagParse: unknown CRL type\n");
351 P12CrlBag
*p12Bag
= new P12CrlBag(crlBag
->type
,
361 void P12Coder::secretBagParse(
362 const NSS_P12_SafeBag
&safeBag
,
363 SecNssCoder
&localCdr
)
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 */
376 * SafeContentsBag parser
378 void P12Coder::safeContentsBagParse(
379 const NSS_P12_SafeBag
&safeBag
,
380 SecNssCoder
&localCdr
)
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 */
393 * Parse an encoded NSS_P12_SafeContents. This could be either
394 * present as plaintext in an AuthSafe or decrypted.
396 void P12Coder::safeContentsParse(
397 const CSSM_DATA
&contentsBlob
,
398 SecNssCoder
&localCdr
)
400 p12DecodeLog("safeContentsParse");
402 NSS_P12_SafeContents sc
;
403 memset(&sc
, 0, sizeof(sc
));
404 if(localCdr
.decodeItem(contentsBlob
, NSS_P12_SafeContentsTemplate
,
406 p12ErrorLog("Error decoding SafeContents\n");
409 unsigned numBags
= nssArraySize((const void **)sc
.bags
);
410 for(unsigned dex
=0; dex
<numBags
; dex
++) {
411 NSS_P12_SafeBag
*bag
= sc
.bags
[dex
];
414 /* ensure that *something* is there */
415 if(bag
->bagValue
.keyBag
== NULL
) {
416 p12ErrorLog("safeContentsParse: Empty SafeBag\n");
421 * Break out to individual bag type
425 keyBagParse(*bag
, localCdr
);
427 case BT_ShroudedKeyBag
:
428 shroudedKeyBagParse(*bag
, localCdr
);
431 certBagParse(*bag
, localCdr
);
434 crlBagParse(*bag
, localCdr
);
437 secretBagParse(*bag
,localCdr
);
439 case BT_SafeContentsBag
:
440 safeContentsBagParse(*bag
, localCdr
);
443 p12ErrorLog("unknown p12 BagType (%u)\n",
444 (unsigned)bag
->type
);
451 * Parse a ContentInfo in the context of (i.e., as an element of)
452 * an AuthenticatedSafe.
454 void P12Coder::authSafeElementParse(
455 const NSS_P7_DecodedContentInfo
*info
,
456 SecNssCoder
&localCdr
)
458 p12DecodeLog("authSafeElementParse");
461 /* unencrypted SafeContents */
462 safeContentsParse(*info
->content
.data
, localCdr
);
465 case CT_EncryptedData
:
467 NSS_P12_PBE_Params pbep
;
468 encryptedDataParse(*info
->content
.encryptData
, localCdr
, &pbep
);
471 * Decrypt contents to get a SafeContents and
474 CSSM_DATA ptext
= {0, NULL
};
475 encryptedDataDecrypt(*info
->content
.encryptData
,
476 localCdr
, &pbep
, ptext
);
477 safeContentsParse(ptext
, localCdr
);
481 p12ErrorLog("authSafeElementParse: unknown sage type (%u)\n",
482 (unsigned)info
->type
);
484 /* well, save it as an opaque bag for now */
485 P12OpaqueBag
*opaque
= new P12OpaqueBag(
486 info
->contentType
, *info
->content
.data
,
495 * Parse an encoded NSS_P12_AuthenticatedSafe
497 void P12Coder::authSafeParse(
498 const CSSM_DATA
&authSafeBlob
,
499 SecNssCoder
&localCdr
)
501 p12DecodeLog("authSafeParse");
503 NSS_P12_AuthenticatedSafe authSafe
;
505 memset(&authSafe
, 0, sizeof(authSafe
));
506 if(localCdr
.decodeItem(authSafeBlob
,
507 NSS_P12_AuthenticatedSafeTemplate
,
509 p12ErrorLog("Error decoding authSafe\n");
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
);
519 void P12Coder::macParse(
520 const NSS_P12_MacData
&macData
,
521 SecNssCoder
&localCdr
)
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
);