RSA_asymmetric.cpp [plain text]
#include "RSA_asymmetric.h"
#include "RSA_DSA_utils.h"
#include <security_utilities/debugging.h>
#include <opensslUtils/opensslUtils.h>
#define rsaCryptDebug(args...) secdebug("rsaCrypt", ## args)
#define rbprintf(args...) secdebug("rsaBuf", ## args)
static ModuleNexus<Mutex> gMutex;
RSA_CryptContext::~RSA_CryptContext()
{
StLock<Mutex> _(gMutex());
if(mAllocdRsaKey) {
assert(mRsaKey != NULL);
RSA_free(mRsaKey);
mRsaKey = NULL;
mAllocdRsaKey = false;
}
}
void RSA_CryptContext::init(const Context &context, bool encoding )
{
StLock<Mutex> _(gMutex());
if(mInitFlag && !opStarted()) {
return;
}
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:
keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE);
}
if(mRsaKey == NULL) {
assert(!opStarted());
CSSM_DATA label = {0, NULL};
mRsaKey = contextToRsaKey(context,
session(),
keyClass,
encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
mAllocdRsaKey,
label);
if(label.Data) {
mLabel.copy(label);
mOaep = true;
free(label.Data);
}
}
else {
assert(opStarted());
}
unsigned cipherBlockSize = RSA_size(mRsaKey);
unsigned plainBlockSize;
uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING);
switch(padding) {
case CSSM_PADDING_NONE:
mPadding = RSA_NO_PADDING;
plainBlockSize = cipherBlockSize;
break;
case CSSM_PADDING_PKCS1:
mPadding = RSA_PKCS1_PADDING;
plainBlockSize = cipherBlockSize - 11;
break;
case CSSM_PADDING_APPLE_SSLv2:
rsaCryptDebug("RSA_CryptContext::init using CSSM_PADDING_APPLE_SSLv2");
mPadding = RSA_SSLV23_PADDING;
plainBlockSize = cipherBlockSize - 11;
break;
default:
rsaCryptDebug("RSA_CryptContext::init bad padding (0x%x)",
(unsigned)padding);
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
}
uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING);
if(blinding) {
if(RSA_blinding_on(mRsaKey, NULL) <= 0) {
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
}
else {
RSA_blinding_off(mRsaKey);
}
setup(encoding ? plainBlockSize : cipherBlockSize, encoding ? cipherBlockSize : plainBlockSize, false, false, BCM_ECB,
NULL); mInitFlag = true;
}
void RSA_CryptContext::encryptBlock(
const void *plainText, size_t plainTextLen,
void *cipherText,
size_t &cipherTextLen, bool final)
{
StLock<Mutex> _(gMutex());
int irtn;
if(mRsaKey->d == NULL) {
irtn = RSA_public_encrypt(plainTextLen,
(unsigned char *)plainText,
(unsigned char *)cipherText,
mRsaKey,
mPadding);
}
else {
irtn = RSA_private_encrypt(plainTextLen,
(unsigned char *)plainText,
(unsigned char *)cipherText,
mRsaKey,
mPadding);
}
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, size_t cipherTextLen,
void *plainText,
size_t &plainTextLen, bool final)
{
StLock<Mutex> _(gMutex());
int irtn;
rsaCryptDebug("decryptBlock padding %d", mPadding);
if(mRsaKey->d == NULL) {
irtn = RSA_public_decrypt(inBlockSize(),
(unsigned char *)cipherText,
(unsigned char *)plainText,
mRsaKey,
mPadding);
}
else {
irtn = RSA_private_decrypt(inBlockSize(),
(unsigned char *)cipherText,
(unsigned char *)plainText,
mRsaKey,
mPadding);
}
if(irtn < 0) {
rsaCryptDebug("decryptBlock err");
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, size_t inSize ) {
StLock<Mutex> _(gMutex());
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();
}