static int
kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
		       RSA * rsa, int padding)
{
    struct kc_rsa *kc = RSA_get_app_data(rsa);

    CSSM_RETURN cret;
    OSStatus ret;
    const CSSM_ACCESS_CREDENTIALS *creds;
    SecKeyRef privKeyRef = kc->pkey;
    CSSM_CSP_HANDLE cspHandle;
    const CSSM_KEY *cssmKey;
    CSSM_CC_HANDLE handle = 0;
    CSSM_DATA out, in, rem;
    int fret = 0;
    CSSM_SIZE outlen = 0;
    char remdata[1024];

    if (padding != RSA_PKCS1_PADDING)
	return -1;

    cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
    if(cret) heim_abort("SecKeyGetCSSMKey failed: %d", (int)cret);

    cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);
    if(cret) heim_abort("SecKeyGetCSPHandle failed: %d", (int)cret);

    ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT,
			       kSecCredentialTypeNoUI, &creds);
    if(ret) heim_abort("SecKeyGetCredentials failed: %d", (int)ret);

    ret = CSSM_CSP_CreateAsymmetricContext (cspHandle,
					    CSSM_ALGID_RSA,
					    creds,
					    cssmKey,
					    CSSM_PADDING_PKCS1,
					    &handle);
    if(ret) heim_abort("CSSM_CSP_CreateAsymmetricContext failed: %d", (int)ret);

    in.Data = (uint8 *)from;
    in.Length = flen;

    out.Data = (uint8 *)to;
    out.Length = kc->keysize;

    rem.Data = (uint8 *)remdata;
    rem.Length = sizeof(remdata);

    cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem);
    if(cret) {
	/* cssmErrorString(cret); */
	fret = -1;
    } else
	fret = (int)out.Length;

    if(handle)
	CSSM_DeleteContext(handle);

    return fret;
}
예제 #2
0
파일: libCdsaCrypt.cpp 프로젝트: eross/misc
/*
 * Decrypt.
 * plainText->Data is allocated by the CSP and must be freed (via
 * free()) by caller.
 */
CSSM_RETURN cdsaDecrypt(
	CSSM_CSP_HANDLE		cspHandle,
	const CSSM_KEY		*key,
	const CSSM_DATA		*cipherText,
	CSSM_DATA_PTR		plainText)
{
	CSSM_RETURN 	crtn;
	CSSM_CC_HANDLE	ccHandle;
	CSSM_DATA		remData = {0, NULL};
	uint32			bytesDecrypted;
	
	crtn = genCryptHandle(cspHandle, key, &ivCommon, &ccHandle);
	if(crtn) {
		return crtn;
	}
	plainText->Length = 0;
	plainText->Data = NULL;
	crtn = CSSM_DecryptData(ccHandle,
		cipherText,
		1,
		plainText,
		1,
		&bytesDecrypted,
		&remData);
	CSSM_DeleteContext(ccHandle);
	if(crtn) {
		return crtn;
	}
	
	plainText->Length = bytesDecrypted;
	if(remData.Length != 0) {
		/* append remaining data to plainText */
		uint32 newLen = plainText->Length + remData.Length;
		plainText->Data = (uint8 *)appRealloc(plainText->Data,
			newLen,
			NULL);
		memmove(plainText->Data + plainText->Length, 
			remData.Data, remData.Length);
		plainText->Length = newLen;
		appFree(remData.Data, NULL);
	}
	return CSSM_OK;
}
static int badDecrypt(
	CSSM_CSP_HANDLE	cspHand,
	CSSM_KEY_PTR	key,
	const char		*keyAlgStr,
	CSSM_ALGORITHMS	opAlg,
	CSSM_RETURN		expectRtn,
	CSSM_BOOL		quiet,
	const char		*goodUseStr,
	const char		*badUseStr)
{
	CSSM_CC_HANDLE 	cryptHand;
	CSSM_DATA		ctext = {4, (uint8 *)"foo"};
	CSSM_DATA		ptext = {0, NULL};
	CSSM_DATA		remData = {0, NULL};
	CSSM_RETURN		crtn;
	CSSM_SIZE		bytesDecrypted;
	int				irtn;
	
	
	cryptHand = genCryptHandle(cspHand, opAlg, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
		key, NULL /* key2 */, NULL /* iv */, 0, 0);
	if(cryptHand == 0) {
		return testError(quiet);
	}
	crtn = CSSM_DecryptData(cryptHand, &ctext, 1, &ptext, 1, &bytesDecrypted, &remData);
	if(crtn != expectRtn) {
		printf("***Testing %s key w/%s during %s:\n", keyAlgStr, goodUseStr, badUseStr);
		printf("   CSSM_DecryptData: expect %s\n",	cssmErrToStr(expectRtn));
		printf("   CSSM_DecryptData: got    %s\n",  cssmErrToStr(crtn));
		irtn = testError(quiet);
	}
	else {
		irtn = 0;
	}
	/* assume no ptext or remdata - OK? */
	CSSM_DeleteContext(cryptHand);
	return irtn;
}
CFDataRef decodePrivateKeyHeader(SecKeychainRef keychain, const FVPrivateKeyHeader &inHeader)
{	
	// kSecKeyLabel is defined in libsecurity_keychain/lib/SecKey.h
	SecKeychainAttribute attrs[] =
	{
		{ 6 /* kSecKeyLabel */, inHeader.publicKeyHashSize, const_cast<uint8 *>(inHeader.publicKeyHash) }
	};
	SecKeychainAttributeList attrList =
	{
		sizeof(attrs) / sizeof(SecKeychainAttribute),
		attrs
	};
	CSSM_CSP_HANDLE cspHandle = 0;
	const CSSM_KEY *cssmKey = NULL;
    const CSSM_ACCESS_CREDENTIALS *accessCred = NULL;
    CSSM_CC_HANDLE cc = 0;
	
	SecKeychainSearchRef _searchRef;
	throwIfError(SecKeychainSearchCreateFromAttributes(keychain, (SecItemClass) CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList, &_searchRef));
	CFRef<SecKeychainSearchRef> searchRef(_searchRef);
	
	SecKeychainItemRef _item;
    if (SecKeychainSearchCopyNext(searchRef, &_item) != 0) {
		return NULL;  // XXX possibly should throw here?
    }
	
	CFRef<SecKeyRef> keyItem(reinterpret_cast<SecKeyRef>(_item));
	throwIfError(SecKeyGetCSPHandle(keyItem, &cspHandle));
	throwIfError(SecKeyGetCSSMKey(keyItem, &cssmKey));
    throwIfError(SecKeyGetCredentials(keyItem, CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault, &accessCred));
    throwIfError(CSSM_CSP_CreateAsymmetricContext(cspHandle, cssmKey->KeyHeader.AlgorithmId, accessCred, cssmKey, CSSM_PADDING_PKCS1, &cc));
	CFDataRef result;
	
	try
	{		
		CssmMemoryFunctions memFuncs;
		throwIfError(CSSM_GetAPIMemoryFunctions(cspHandle, &memFuncs));
		CssmMemoryFunctionsAllocator allocator(memFuncs);
		
		const CssmData cipherBuf(const_cast<uint8 *>(inHeader.encryptedBlob), inHeader.encryptedBlobSize);
		CssmAutoData clearBuf(allocator);
		CssmAutoData remData(allocator);
		size_t bytesDecrypted;
		CSSM_RETURN crx = CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get());
		secinfo("FDERecovery", "decodePrivateKeyHeader: CSSM_DecryptData result: %d", crx);
		throwIfError(crx);
//		throwIfError(CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get()));
		clearBuf.length(bytesDecrypted);
//		rawKey.copy(clearBuf.get());
		result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)clearBuf.get().data(), clearBuf.get().length());
//		result = parseKeyBlob(clearBuf.get());
	}
	catch(...)
	{
		CSSM_DeleteContext(cc);
		throw;
	}
	
	throwIfError(CSSM_DeleteContext(cc));
	
	return result;
}
예제 #5
0
/*
 * Decrypt (typically, an encrypted P7 ContentInfo contents)
 */
CSSM_RETURN p12Decrypt(
	CSSM_CSP_HANDLE		cspHand,
	const CSSM_DATA		&cipherText,
	CSSM_ALGORITHMS		keyAlg,				
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	/* exactly one of the following two must be valid */
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing plainText
	CSSM_DATA			&plainText)
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_DATA ourPtext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
	
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	
	/* go - CSP mallocs ptext and rem data */
	CSSM_SIZE bytesDecrypted;
	crtn = CSSM_DecryptData(ccHand,
		&cipherText,
		1,
		&ourPtext,
		1,
		&bytesDecrypted,
		&remData);
	if(crtn) {
		cuPrintError("CSSM_DecryptData", crtn);
	}
	else {
		coder.allocCopyItem(ourPtext, plainText);
		plainText.Length = bytesDecrypted;
		
		/* plaintext copied into coder space; free the memory allocated
		 * by the CSP */
		freeCssmMemory(cspHand, ourPtext.Data);
	}
	/* an artifact of CSPFullPLuginSession - this never contains
	 * valid data but sometimes gets mallocds */
	if(remData.Data) {
		freeCssmMemory(cspHand, remData.Data);
	}
errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
/*
 * CDSA private key decrypt with blinding option.
 */
static CSSM_RETURN _cspDecrypt(CSSM_CSP_HANDLE cspHand,
		uint32 algorithm,					// CSSM_ALGID_FEED, etc.
		uint32 mode,						// CSSM_ALGMODE_CBC, etc. - only for symmetric algs
		CSSM_PADDING padding,				// CSSM_PADDING_PKCS1, etc. 
		CSSM_BOOL blinding,
		const CSSM_KEY *key,				// public or session key
		const CSSM_DATA *ctext,
		CSSM_DATA_PTR ptext)				// RETURNED
{
	CSSM_CC_HANDLE 	cryptHand;
	CSSM_RETURN		crtn;
	CSSM_RETURN		ocrtn = CSSM_OK;
	CSSM_SIZE		bytesDecrypted;
	CSSM_DATA		remData = {0, NULL};

	cryptHand = genCryptHandle(cspHand, 
		algorithm, 
		mode, 
		padding,
		key, 
		NULL,		// pubKey, 
		NULL,		// iv,
		0,			// effectiveKeySizeInBits,
		0);			// rounds
	if(cryptHand == 0) {
		return CSSMERR_CSP_INTERNAL_ERROR;
	}
	if(blinding) {
		CSSM_CONTEXT_ATTRIBUTE	newAttr;	
		newAttr.AttributeType     = CSSM_ATTRIBUTE_RSA_BLINDING;
		newAttr.AttributeLength   = sizeof(uint32);
		newAttr.Attribute.Uint32  = 1;
		crtn = CSSM_UpdateContextAttributes(cryptHand, 1, &newAttr);
		if(crtn) {
			printError("CSSM_UpdateContextAttributes", crtn);
			return crtn;
		}
	}

	crtn = CSSM_DecryptData(cryptHand,
		ctext,
		1,
		ptext,
		1,
		&bytesDecrypted,
		&remData);
	if(crtn == CSSM_OK) {
		// NOTE: We return the proper length in ptext....
		ptext->Length = bytesDecrypted;
		
		// FIXME - sometimes get mallocd RemData here, but never any valid data
		// there...side effect of CSPFullPluginSession's buffer handling logic;
		// but will we ever actually see valid data in RemData? So far we never
		// have....
		if(remData.Data != NULL) {
			appFree(remData.Data, NULL);
		}
	}
	else {
		printError("CSSM_DecryptData", crtn);
		ocrtn = crtn;
	}
	crtn = CSSM_DeleteContext(cryptHand);
	if(crtn) {
		printError("CSSM_DeleteContext", crtn);
		ocrtn = crtn;
	}
	return ocrtn;
}
static int doDecrypt(
	CSSM_CSP_HANDLE	cspHand,
	const char *algStr,
	CSSM_KEY_PTR key,			// session, private
	CSSM_ALGORITHMS encrAlg,
	CSSM_ENCRYPT_MODE encrMode,
	CSSM_PADDING encrPad,
	DecrResult expResult,
	CSSM_BOOL quiet)
{
	uint8 ctextData[CTEXT_SIZE];
	CSSM_DATA ctext = {CTEXT_SIZE, ctextData};
	uint8 someIvData[IV_SIZE];
	CSSM_DATA someIv = {IV_SIZE, someIvData};
	 
	 /*
	  * I have not found a way to guarantee decrypt failure here, no matter
	  * what ctext and IV I specify. We can't just do an encrypt and 
	  * munge because we might be testing a bad (expired) key. 
	  * We might have to redesign, first generating a good key, then an
	  * expired key from it...? Until then this test is loose about
	  * handling "key is good" detection.
	  */
	memset(ctextData, 0, CTEXT_SIZE);	// guaranteed bad padding
	memset(someIvData, 0, IV_SIZE);
	
	CSSM_CC_HANDLE cryptHand = 0;
	CSSM_RETURN crtn;
	CSSM_ACCESS_CREDENTIALS	creds;
	
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	
	if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			encrAlg,
			encrMode,
			NULL,			// access cred
			key,
			&someIv,
			encrPad,	
			NULL,			// Params
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateSymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
			encrAlg,
			&creds,			// access
			key,
			encrPad,
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateAsymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else {
		printf("***BRRZAP! Only decrypt with session and private"
			" keys\n");
		exit(1);
	}

	CSSM_DATA ptext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	CSSM_SIZE bDecr;
	int irtn = 0;
	
	crtn = CSSM_DecryptData(cryptHand,
		&ctext,
		1,
		&ptext,
		1,
		&bDecr,
		&remData);
	switch(expResult) {
		case DR_BadStartDate:
			if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE) {
				printf("***Decrypt with %s: expected INVALID_KEY_START_DATE, "
					"got %s.\n", algStr, cssmErrToStr(crtn));
				irtn = testError(quiet);
			}
			break;
		case DR_BadEndDate:
			if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE) {
				printf("***Decrypt with %s: expected INVALID_KEY_END_DATE, "
					"got %s.\n", algStr, cssmErrToStr(crtn));
				irtn = testError(quiet);
			}
			break;
		case DR_BadData:
			switch(crtn) {
				case CSSM_OK:						// good data, seen sometimes
				case CSSMERR_CSP_INVALID_DATA:		// common case
				case CSSMERR_CSP_INTERNAL_ERROR:	// default case in CSP's
													//   throwRsaDsa() :-(
					break;
				default:
					printf("***Decrypt with %s: expected INVALID_DATA or OK, "
						"got %s.\n",
						algStr, cssmErrToStr(crtn));
					irtn = testError(quiet);
					break;
			}
			break;
	}
	appFreeCssmData(&ptext, CSSM_FALSE);
	appFreeCssmData(&remData, CSSM_FALSE);
	CSSM_DeleteContext(cryptHand);
	return irtn;
}