X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp diff --git a/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp deleted file mode 100644 index 9e426c1a..00000000 --- a/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * pkcs12Decode.h - P12Coder decoding engine. - */ - -#include "pkcs12Coder.h" -#include "pkcs12Templates.h" -#include "pkcs12Utils.h" -#include "pkcs12Debug.h" -#include "pkcs12Crypto.h" -#include -#include - -/* 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 = {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(); - } -} - -/* - * Decrypt the contents of a NSS_P7_EncryptedData - */ -void P12Coder::encryptedDataDecrypt( - const NSS_P7_EncryptedData &edata, - SecNssCoder &localCdr, - NSS_P12_PBE_Params *pbep, // preparsed - CSSM_DATA &ptext) // result goes here in localCdr space -{ - p12DecodeLog("encryptedDataDecrypt"); - - /* see if we can grok the encr alg */ - CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES - CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE - CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 - uint32 keySizeInBits; - uint32 blockSizeInBytes; // for IV, optional - CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. - CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. - PKCS_Which pkcs; - - bool found = pkcsOidToParams(&edata.contentInfo.encrAlg.algorithm, - keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, - padding, mode, pkcs); - if(!found || (pkcs != PW_PKCS12)) { - p12ErrorLog("EncryptedData encrAlg not understood\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); - } - - uint32 iterCount; - if(!p12DataToInt(pbep->iterations, iterCount)) { - p12ErrorLog("encryptedDataDecrypt: badly formed iterCount\n"); - P12_THROW_DECODE; - } - const CSSM_DATA *pwd = getEncrPassPhrase(); - const CSSM_KEY *passKey = getEncrPassKey(); - if((pwd == NULL) && (passKey == NULL)) { - p12ErrorLog("no passphrase set\n"); - CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE); - } - - /* go */ - CSSM_RETURN crtn = p12Decrypt(mCspHand, - edata.contentInfo.encrContent, - keyAlg, encrAlg, pbeHashAlg, - keySizeInBits, blockSizeInBytes, - padding, mode, - iterCount, pbep->salt, - pwd, - passKey, - localCdr, - ptext); - if(crtn) { - CssmError::throwMe(crtn); - } -} - - -/* - * Parse an CSSM_X509_ALGORITHM_IDENTIFIER specific to P12. - * Decode the alg params as a NSS_P12_PBE_Params and parse and - * return the result if the pbeParams is non-NULL. - */ -void P12Coder::algIdParse( - const CSSM_X509_ALGORITHM_IDENTIFIER &algId, - NSS_P12_PBE_Params *pbeParams, // optional - SecNssCoder &localCdr) -{ - p12DecodeLog("algIdParse"); - - const CSSM_DATA ¶m = algId.parameters; - if(pbeParams == NULL) { - /* alg params are uninterpreted */ - return; - } - - if(param.Length == 0) { - p12ErrorLog("algIdParse: no alg parameters\n"); - P12_THROW_DECODE; - } - - memset(pbeParams, 0, sizeof(*pbeParams)); - if(localCdr.decodeItem(param, - NSS_P12_PBE_ParamsTemplate, pbeParams)) { - p12ErrorLog("Error decoding NSS_P12_PBE_Params\n"); - P12_THROW_DECODE; - } -} - -/* - * Parse a NSS_P7_EncryptedData - specifically in the context - * of a P12 in password privacy mode. (The latter assumption is - * to enable us to infer CSSM_X509_ALGORITHM_IDENTIFIER.parameters - * format). - */ -void P12Coder::encryptedDataParse( - const NSS_P7_EncryptedData &edata, - SecNssCoder &localCdr, - NSS_P12_PBE_Params *pbep) // optional, RETURNED -{ - p12DecodeLog("encryptedDataParse"); - - /* - * Parse the alg ID, save PBE params for when we do the decrypt - * key unwrap - */ - const NSS_P7_EncrContentInfo &ci = edata.contentInfo; - const CSSM_X509_ALGORITHM_IDENTIFIER &algId = ci.encrAlg; - algIdParse(algId, pbep, localCdr); -} - -/* - * ShroudedKeyBag parser w/decrypt - */ -void P12Coder::shroudedKeyBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - p12DecodeLog("Found shrouded key bag"); - if(mPrivKeyImportState == PKIS_NoMore) { - CssmError::throwMe(errSecMultiplePrivKeys); - } - - const NSS_P12_ShroudedKeyBag *keyBag = safeBag.bagValue.shroudedKeyBag; - const CSSM_X509_ALGORITHM_IDENTIFIER &algId = keyBag->algorithm; - NSS_P12_PBE_Params pbep; - algIdParse(algId, &pbep, localCdr); - - /* - * Prepare for decryption - */ - CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES - CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE - CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 - uint32 keySizeInBits; - uint32 blockSizeInBytes; // for IV, optional - CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. - CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. - PKCS_Which pkcs; - - bool found = pkcsOidToParams(&algId.algorithm, - keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, - padding, mode, pkcs); - if(!found || (pkcs != PW_PKCS12)) { - p12ErrorLog("ShroudedKeyBag encrAlg not understood\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); - } - - uint32 iterCount; - if(!p12DataToInt(pbep.iterations, iterCount)) { - p12ErrorLog("ShroudedKeyBag: badly formed iterCount\n"); - P12_THROW_DECODE; - } - const CSSM_DATA *encrPhrase = getEncrPassPhrase(); - const CSSM_KEY *passKey = getEncrPassKey(); - if((encrPhrase == NULL) && (passKey == NULL)) { - p12ErrorLog("no passphrase set\n"); - CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE); - } - - /* We'll own the actual CSSM_KEY memory */ - CSSM_KEY_PTR privKey = (CSSM_KEY_PTR)mCoder.malloc(sizeof(CSSM_KEY)); - memset(privKey, 0, sizeof(CSSM_KEY)); - - CSSM_DATA labelData; - p12GenLabel(labelData, localCdr); - - CSSM_RETURN crtn = p12UnwrapKey(mCspHand, - mDlDbHand.DLHandle ? &mDlDbHand : NULL, - mImportFlags & kSecImportKeys, - keyBag->encryptedData, - keyAlg, encrAlg, pbeHashAlg, - keySizeInBits, blockSizeInBytes, - padding, mode, - iterCount, pbep.salt, - encrPhrase, - passKey, - localCdr, - labelData, - mAccess, - mNoAcl, - mKeyUsage, - mKeyAttrs, - privKey); - if(crtn) { - p12ErrorLog("Error unwrapping private key\n"); - CssmError::throwMe(crtn); - } - p12DecodeLog("unwrapped shrouded key bag"); - - P12KeyBag *p12bag = new P12KeyBag(privKey, mCspHand, - safeBag.bagAttrs, labelData, mCoder); - addKey(p12bag); - - if(mPrivKeyImportState == PKIS_AllowOne) { - mPrivKeyImportState = PKIS_NoMore; - } -} - -/* - * (unshrouded) KeyBag parser - */ -void P12Coder::keyBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - if(mPrivKeyImportState == PKIS_NoMore) { - CssmError::throwMe(errSecMultiplePrivKeys); - } - - /* FIXME - should be able to parse and handle this.... */ - p12DecodeLog("found keyBag"); - NSS_P12_KeyBag *keyBag = safeBag.bagValue.keyBag; - P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId, - /* this breaks when NSS_P12_KeyBag is not a CSSM_DATA */ - *keyBag, - safeBag.bagAttrs, - mCoder); - addOpaque(p12Bag); -} - -/* - * CertBag parser - */ -void P12Coder::certBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - p12DecodeLog("found certBag"); - NSS_P12_CertBag *certBag = safeBag.bagValue.certBag; - switch(certBag->type) { - case CT_X509: - case CT_SDSI: - break; - default: - p12ErrorLog("certBagParse: unknown cert type\n"); - P12_THROW_DECODE; - } - P12CertBag *p12Bag = new P12CertBag(certBag->type, - certBag->certValue, - safeBag.bagAttrs, - mCoder); - addCert(p12Bag); -} - -/* - * CrlBag parser - */ -void P12Coder::crlBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - p12DecodeLog("found crlBag"); - NSS_P12_CrlBag *crlBag = safeBag.bagValue.crlBag; - switch(crlBag->type) { - case CRT_X509: - break; - default: - p12ErrorLog("crlBagParse: unknown CRL type\n"); - P12_THROW_DECODE; - } - P12CrlBag *p12Bag = new P12CrlBag(crlBag->type, - crlBag->crlValue, - safeBag.bagAttrs, - mCoder); - addCrl(p12Bag); -} - -/* - * SecretBag parser - */ -void P12Coder::secretBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - p12DecodeLog("found secretBag"); - NSS_P12_SecretBag *secretBag = safeBag.bagValue.secretBag; - P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId, - /* this breaks when NSS_P12_SecretBag is not a CSSM_DATA */ - *secretBag, - safeBag.bagAttrs, - mCoder); - addOpaque(p12Bag); -} - -/* - * SafeContentsBag parser - */ -void P12Coder::safeContentsBagParse( - const NSS_P12_SafeBag &safeBag, - SecNssCoder &localCdr) -{ - p12DecodeLog("found SafeContents safe bag"); - NSS_P12_SafeContentsBag *scBag = safeBag.bagValue.safeContentsBag; - P12OpaqueBag *p12Bag = new P12OpaqueBag(safeBag.bagId, - /* this breaks when NSS_P12_SafeContentsBag is not a CSSM_DATA */ - *scBag, - safeBag.bagAttrs, - mCoder); - addOpaque(p12Bag); -} - -/* - * Parse an encoded NSS_P12_SafeContents. This could be either - * present as plaintext in an AuthSafe or decrypted. - */ -void P12Coder::safeContentsParse( - const CSSM_DATA &contentsBlob, - SecNssCoder &localCdr) -{ - p12DecodeLog("safeContentsParse"); - - NSS_P12_SafeContents sc; - memset(&sc, 0, sizeof(sc)); - if(localCdr.decodeItem(contentsBlob, NSS_P12_SafeContentsTemplate, - &sc)) { - p12ErrorLog("Error decoding SafeContents\n"); - P12_THROW_DECODE; - } - unsigned numBags = nssArraySize((const void **)sc.bags); - for(unsigned dex=0; dexbagValue.keyBag == NULL) { - p12ErrorLog("safeContentsParse: Empty SafeBag\n"); - P12_THROW_DECODE; - } - - /* - * Break out to individual bag type - */ - switch(bag->type) { - case BT_KeyBag: - keyBagParse(*bag, localCdr); - break; - case BT_ShroudedKeyBag: - shroudedKeyBagParse(*bag, localCdr); - break; - case BT_CertBag: - certBagParse(*bag, localCdr); - break; - case BT_CrlBag: - crlBagParse(*bag, localCdr); - break; - case BT_SecretBag: - secretBagParse(*bag ,localCdr); - break; - case BT_SafeContentsBag: - safeContentsBagParse(*bag, localCdr); - break; - default: - p12ErrorLog("unknown p12 BagType (%u)\n", - (unsigned)bag->type); - P12_THROW_DECODE; - } - } -} - -/* - * Parse a ContentInfo in the context of (i.e., as an element of) - * an AuthenticatedSafe. - */ -void P12Coder::authSafeElementParse( - const NSS_P7_DecodedContentInfo *info, - SecNssCoder &localCdr) -{ - p12DecodeLog("authSafeElementParse"); - switch(info->type) { - case CT_Data: - /* unencrypted SafeContents */ - safeContentsParse(*info->content.data, localCdr); - break; - - case CT_EncryptedData: - { - NSS_P12_PBE_Params pbep; - encryptedDataParse(*info->content.encryptData, localCdr, &pbep); - - /* - * Decrypt contents to get a SafeContents and - * then parse that. - */ - CSSM_DATA ptext = {0, NULL}; - encryptedDataDecrypt(*info->content.encryptData, - localCdr, &pbep, ptext); - safeContentsParse(ptext, localCdr); - break; - } - default: - p12ErrorLog("authSafeElementParse: unknown sage type (%u)\n", - (unsigned)info->type); - - /* well, save it as an opaque bag for now */ - P12OpaqueBag *opaque = new P12OpaqueBag( - info->contentType, *info->content.data, - NULL, // no attrs - localCdr); - addOpaque(opaque); - break; - } -} - -/* - * Parse an encoded NSS_P12_AuthenticatedSafe - */ -void P12Coder::authSafeParse( - const CSSM_DATA &authSafeBlob, - SecNssCoder &localCdr) -{ - p12DecodeLog("authSafeParse"); - - NSS_P12_AuthenticatedSafe authSafe; - - memset(&authSafe, 0, sizeof(authSafe)); - if(localCdr.decodeItem(authSafeBlob, - NSS_P12_AuthenticatedSafeTemplate, - &authSafe)) { - p12ErrorLog("Error decoding authSafe\n"); - P12_THROW_DECODE; - } - unsigned numInfos = nssArraySize((const void **)authSafe.info); - for(unsigned dex=0; dex 4) { - p12ErrorLog("malformed iteration length (%u)\n", - (unsigned)iter.Length); - P12_THROW_DECODE; - } -} -