/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This 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. */ /* * RSA_asymmetric.cpp - CSPContext for RSA asymmetric encryption */ #include "RSA_asymmetric.h" #include "RSA_DSA_utils.h" #include #define rsaCryptDebug(args...) debug("rsaCrypt", ## args) #define rbprintf(args...) debug("rsaBuf", ## args) RSA_CryptContext::~RSA_CryptContext() { if(mAllocdRsaKey) { assert(mRsaKey != NULL); RSA_free(mRsaKey); mRsaKey = NULL; mAllocdRsaKey = false; } } /* called by CSPFullPluginSession */ void RSA_CryptContext::init(const Context &context, bool encoding = true) { if(mInitFlag && !opStarted()) { /* reusing - e.g. query followed by encrypt */ return; } /* optional mode to use alternate key class (e.g., decrypt with public key) */ CSSM_KEYCLASS keyClass; switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { case CSSM_ALGMODE_PUBLIC_KEY: keyClass = CSSM_KEYCLASS_PUBLIC_KEY; break; case CSSM_ALGMODE_PRIVATE_KEY: keyClass = CSSM_KEYCLASS_PRIVATE_KEY; break; case CSSM_ALGMODE_NONE: /* default, not present in context: infer from op type */ keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); } /* fetch key from context */ if(mRsaKey == NULL) { assert(!opStarted()); mRsaKey = contextToRsaKey(context, session(), keyClass, encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, mAllocdRsaKey); } else { assert(opStarted()); } /* validate context - TBD */ /* finally, have BlockCryptor set up its stuff. */ unsigned cipherBlockSize = RSA_size(mRsaKey); unsigned plainBlockSize = cipherBlockSize - 11; setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut false, // pkcs5Pad false, // needsFinal BCM_ECB, NULL); // IV mInitFlag = true; } /* called by BlockCryptor */ void RSA_CryptContext::encryptBlock( const void *plainText, // length implied (one block) size_t plainTextLen, void *cipherText, size_t &cipherTextLen, // in/out, throws on overflow bool final) { int irtn; if(mRsaKey->d == NULL) { irtn = RSA_public_encrypt(plainTextLen, (unsigned char *)plainText, (unsigned char *)cipherText, mRsaKey, RSA_PKCS1_PADDING); } else { irtn = RSA_private_encrypt(plainTextLen, (unsigned char *)plainText, (unsigned char *)cipherText, mRsaKey, RSA_PKCS1_PADDING); } if(irtn < 0) { throwRsaDsa("RSA_public_encrypt"); } else if((unsigned)irtn > cipherTextLen) { rsaCryptDebug("RSA_public_encrypt overflow"); CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); } cipherTextLen = (size_t)irtn; } void RSA_CryptContext::decryptBlock( const void *cipherText, // length implied (one cipher block) void *plainText, size_t &plainTextLen, // in/out, throws on overflow bool final) { int irtn; if(mRsaKey->d == NULL) { irtn = RSA_public_decrypt(inBlockSize(), (unsigned char *)cipherText, (unsigned char *)plainText, mRsaKey, RSA_PKCS1_PADDING); } else { irtn = RSA_private_decrypt(inBlockSize(), (unsigned char *)cipherText, (unsigned char *)plainText, mRsaKey, RSA_PKCS1_PADDING); } if(irtn < 0) { throwRsaDsa("RSA_private_decrypt"); } else if((unsigned)irtn > plainTextLen) { rsaCryptDebug("RSA_private_decrypt overflow"); CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); } plainTextLen = (size_t)irtn; } size_t RSA_CryptContext::outputSize( bool final, // ignored size_t inSize = 0) // output for given input size { UInt32 rawBytes = inSize + inBufSize(); UInt32 rawBlocks = (rawBytes + inBlockSize() - 1) / inBlockSize(); rbprintf("--- RSA_CryptContext::outputSize inSize 0x%lx outSize 0x%lx mInBufSize 0x%lx", inSize, rawBlocks * outBlockSize(), inBufSize()); return rawBlocks * outBlockSize(); }