#include "bfContext.h"
BlowfishContext::~BlowfishContext()
{
deleteKey();
}
void BlowfishContext::deleteKey()
{
memset(&mBfKey, 0, sizeof(mBfKey));
mInitFlag = false;
}
void BlowfishContext::init(
const Context &context,
bool encrypting)
{
if(mInitFlag && !opStarted()) {
return;
}
CSSM_SIZE keyLen;
uint8 *keyData = NULL;
bool sameKeySize = false;
symmetricKeyBits(context, session(), CSSM_ALGID_BLOWFISH,
encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
keyData, keyLen);
if((keyLen < BF_MIN_KEY_SIZE_BYTES) || (keyLen > BF_MAX_KEY_SIZE_BYTES)) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
}
if(mRawKeySize == keyLen) {
sameKeySize = true;
}
else {
deleteKey();
}
if(!sameKeySize || memcmp(mRawKey, keyData, mRawKeySize)) {
BF_set_key(&mBfKey, (int)keyLen, keyData);
memmove(mRawKey, keyData, keyLen);
mRawKeySize = (unsigned int)keyLen;
}
setup(BF_BLOCK, context);
mInitFlag = true;
}
void BlowfishContext::encryptBlock(
const void *plainText, size_t plainTextLen,
void *cipherText,
size_t &cipherTextLen, bool final) {
if(plainTextLen != BF_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
}
if(cipherTextLen < BF_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
BF_ecb_encrypt((const unsigned char *)plainText, (unsigned char *)cipherText,
&mBfKey, BF_ENCRYPT);
cipherTextLen = BF_BLOCK;
}
void BlowfishContext::decryptBlock(
const void *cipherText, size_t cipherTextLen,
void *plainText,
size_t &plainTextLen, bool final) {
if(plainTextLen < BF_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
BF_ecb_encrypt((const unsigned char *)cipherText, (unsigned char *)plainText,
&mBfKey, BF_DECRYPT);
plainTextLen = BF_BLOCK;
}