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);
	}
}
Esempio n. 3
0
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;	
	}
}