static int encryptedDataDecrypt( const NSS_P7_EncryptedData &edata, P12ParseInfo &pinfo, NSS_P12_PBE_Params *pbep, // preparsed CSSM_DATA &ptext) // result goes here in pinfo.coder space { /* 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. #if IMPORT_EXPORT_COMPLETE PKCS_Which pkcs; bool found = pkcsOidToParams(&edata.contentInfo.encrAlg.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, pkcs); #else bool found = pkcsOidToParams(&edata.contentInfo.encrAlg.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode); #endif /* IMPORT_EXPORT_COMPLETE */ if(!found) { printf("***EncryptedData encrAlg not understood\n"); return 1; } unsigned iterCount = dataToInt(pbep->iterations); /* go */ CSSM_RETURN crtn = p12Decrypt_app(pinfo.mCspHand, edata.contentInfo.encrContent, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, iterCount, pbep->salt, pinfo.mPwd, pinfo.mCoder, ptext); #if WRITE_DECRYPT_TEXT if(crtn == 0) { char fname[100]; sprintf(fname, "decrypt%d.der", ctr++); writeFile(fname, ptext.Data, ptext.Length); printf("...wrote %u bytes to %s\n", (unsigned)ptext.Length, fname); } #endif return crtn ? 1 : 0; }
/* * 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); } }
static int p12Decrypt(pkcs12_context * context, const SecAsn1AlgId *algId, const SecAsn1Item *cipherText, SecAsn1Item *plainText) { NSS_P12_PBE_Params pbep; // XXX/cs not requiring decoding, but if pbep is uninit this will fail later algIdParse(context, algId, &pbep); CCAlgorithm alg = 0; uint32_t keySizeInBits = 0; uint32_t blockSizeInBytes = 0; // for IV, optional CCOptions options = 0; require_noerr_quiet(pkcsOidToParams(&algId->algorithm, &alg, &keySizeInBits, &blockSizeInBytes, &options), out); uint32_t iterCount = 0; require_noerr(p12DataToInt(&pbep.iterations, &iterCount), out); /* P12 style key derivation */ SecAsn1Item key = {0, NULL}; if(keySizeInBits) alloc_item(context, &key, (keySizeInBits+7)/8); require_noerr(p12_pbe_gen(context->passphrase, pbep.salt.Data, pbep.salt.Length, iterCount, PBE_ID_Key, key.Data, key.Length), out); /* P12 style IV derivation, optional */ SecAsn1Item iv = {0, NULL}; if(blockSizeInBytes) { alloc_item(context, &iv, blockSizeInBytes); require_noerr(p12_pbe_gen(context->passphrase, pbep.salt.Data, pbep.salt.Length, iterCount, PBE_ID_IV, iv.Data, iv.Length), out); } SecAsn1Item ourPtext = {0, NULL}; alloc_item(context, &ourPtext, cipherText->Length); require_noerr(CCCrypt(kCCDecrypt, alg, options/*kCCOptionPKCS7Padding*/, key.Data, key.Length, iv.Data, cipherText->Data, cipherText->Length, ourPtext.Data, ourPtext.Length, &ourPtext.Length), out); *plainText = ourPtext; return 0; out: return -1; }
/* * ShroudedKeyBag parser w/decrypt */ static int shroudedKeyBagParse( const NSS_P12_ShroudedKeyBag *keyBag, P12ParseInfo &pinfo, unsigned depth) { const CSSM_X509_ALGORITHM_IDENTIFIER &algId = keyBag->algorithm; NSS_P12_PBE_Params pbep; if(p12AlgIdParse(algId, &pbep, pinfo, depth)) { return 1; } if(pinfo.mPwd.Data == NULL) { doIndent(depth); printf("=== Key not decrypted (no passphrase)===\n"); return 0; } /* * 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. #if IMPORT_EXPORT_COMPLETE PKCS_Which pkcs; bool found = pkcsOidToParams(&algId.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, pkcs); #else bool found = pkcsOidToParams(&algId.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode); #endif if(!found) { printf("***ShroudedKeyBag encrAlg not understood\n"); return 1; } unsigned iterCount = dataToInt(pbep.iterations); CSSM_DATA berPrivKey; /* decrypt, result is BER encoded private key */ CSSM_RETURN crtn = p12Decrypt_app(pinfo.mCspHand, keyBag->encryptedData, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, iterCount, pbep.salt, pinfo.mPwd, pinfo.mCoder, berPrivKey); if(crtn) { doIndent(depth); printf("***Error decrypting private key\n"); return 1; } /* decode */ NSS_PrivateKeyInfo privKey; memset(&privKey, 0, sizeof(privKey)); if(pinfo.mCoder.decodeItem(berPrivKey, kSecAsn1PrivateKeyInfoTemplate, &privKey)) { doIndent(depth); printf("***Error decoding decrypted private key\n"); return 1; } /* * in P12 library, we'd convert the result into a CSSM_KEY * or a SecItem... */ CSSM_X509_ALGORITHM_IDENTIFIER &privAlg = privKey.algorithm; doIndent(depth); printf("Priv Key Alg : %s\n", oidStr(privAlg.algorithm, pinfo.mParser)); doIndent(depth); printf("Priv Key Blob : "); printDataAsHex(&privKey.privateKey, 16); unsigned numAttrs = nssArraySize((const void**)privKey.attributes); if(numAttrs) { doIndent(depth+3); printf("numAttrs = %u\n", numAttrs); for(unsigned i=0; i<numAttrs; i++) { doIndent(depth+3); printf("attr[%u]:\n", i); attrParse(privKey.attributes[i], pinfo, depth+6); } } return 0; }
/* * 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; } }