/* * ShroudedKeyBag parser w/decrypt */ static int shroudedKeyBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag) { p12DecodeLog("Found shrouded key bag"); const NSS_P12_ShroudedKeyBag *keyBag = safeBag->bagValue.shroudedKeyBag; SecAsn1Item ptext = {0, NULL}; require_noerr_quiet(p12Decrypt(context, &keyBag->algorithm, &keyBag->encryptedData, &ptext), out); /* Decode PKCS#8 formatted private key */ NSS_PrivateKeyInfo pki; memset(&pki, 0, sizeof(pki)); require_noerr(decode_item(context, &ptext, kSecAsn1PrivateKeyInfoTemplate, &pki), out); DERItem algorithm = { pki.algorithm.algorithm.Data, pki.algorithm.algorithm.Length }; require(DEROidCompare(&oidRsa, &algorithm), out); CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, pki.privateKey.Data, pki.privateKey.Length); require_noerr(emit_item(context, safeBag->bagAttrs, CFSTR("key"), keyData), out); CFRelease(keyData); return 0; out: return -1; }
/* * Parse a ContentInfo in the context of (i.e., as an element of) * an AuthenticatedSafe. */ static int authSafeElementParse(pkcs12_context * context, const NSS_P7_DecodedContentInfo *info) { p12DecodeLog("authSafeElementParse"); switch(info->type) { case CT_Data: /* unencrypted SafeContents */ require_noerr(safeContentsParse(context, info->content.data), out); break; case CT_EncryptedData: { /* * Decrypt contents to get a SafeContents and * then parse that. */ SecAsn1Item ptext = {0, NULL}; NSS_P7_EncryptedData *edata = info->content.encryptData; require_noerr_quiet(p12Decrypt(context, &edata->contentInfo.encrAlg, &edata->contentInfo.encrContent, &ptext), out); require_noerr(safeContentsParse(context, &ptext), out); break; } default: break; } return 0; out: return -1; }
/* * 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); } }