/* top-level PKCS12 PFX decoder */
void P12Coder::decode(
	CFDataRef				cdpfx)
{
	SecNssCoder localCdr;
	NSS_P12_DecodedPFX pfx;

	p12DecodeLog("decode");
	memset(&pfx, 0, sizeof(pfx));
	const CSSM_DATA rawBlob = {int_cast<CFIndex, CSSM_SIZE>(CFDataGetLength(cdpfx)),
		(uint8 *)CFDataGetBytePtr(cdpfx)};
		
	if(localCdr.decodeItem(rawBlob, NSS_P12_DecodedPFXTemplate, &pfx)) {
		p12ErrorLog("Error on top-level decode of NSS_P12_DecodedPFX\n");
		P12_THROW_DECODE;
	}
	NSS_P7_DecodedContentInfo &dci = pfx.authSafe;
	if(dci.type != CT_Data) {
		/* no other types supported yet */
		p12ErrorLog("bad top-level contentType\n");
		P12_THROW_DECODE;
	}
	mIntegrityMode = kSecPkcs12ModePassword;

	if(pfx.macData == NULL) {
		/* not present is an error in kSecPkcs12ModePassword */
		p12ErrorLog("no MAC in PFX\n");
		P12_THROW_DECODE;
	}
	macParse(*pfx.macData, localCdr);

	const CSSM_DATA *macPhrase = getMacPassPhrase();
	const CSSM_KEY *macPassKey = getMacPassKey();
	if((macPhrase == NULL) && (macPassKey == NULL)) {
		p12ErrorLog("no passphrase set\n");
		CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
	}
	CSSM_RETURN crtn = p12VerifyMac(pfx, mCspHand, macPhrase, 
		macPassKey, localCdr);
	if(crtn) {
		p12LogCssmError("p12VerifyMac", crtn);
		CssmError::throwMe(errSecPkcs12VerifyFailure);
	}
	
	authSafeParse(*dci.content.data, localCdr);

	/*
	 * On success, if we have a keychain, store certs and CRLs there
	 */
	if(mKeychain != NULL) {
		storeDecodeResults();
	}
}
p12_error p12decode(pkcs12_context * context, CFDataRef cdpfx)
{
    int err = p12_decodeErr;
	NSS_P12_DecodedPFX pfx;
	memset(&pfx, 0, sizeof(pfx));
    SecAsn1Item raw_blob = { CFDataGetLength(cdpfx), (void*)CFDataGetBytePtr(cdpfx) };

    require_noerr_quiet(decode_item(context, &raw_blob, NSS_P12_DecodedPFXTemplate, &pfx), out);
	NSS_P7_DecodedContentInfo *dci = &pfx.authSafe;
    
    /* only support CT_Data at top level (password based integrity mode) */
	require(dci->type == CT_Data, out);
	require(pfx.macData, out);
    
	require_noerr_action_quiet(p12VerifyMac(context, &pfx), out, err = p12_passwordErr);
    require_noerr_quiet(authSafeParse(context, dci->content.data), out);
    
	return errSecSuccess;
out:
    return err;
}