#include "castContext.h"
CastContext::~CastContext()
{
deleteKey();
}
void CastContext::deleteKey()
{
memset(&mCastKey, 0, sizeof(mCastKey));
mInitFlag = false;
}
void CastContext::init(
const Context &context,
bool encrypting)
{
if(mInitFlag && !opStarted()) {
return;
}
UInt32 keyLen;
UInt8 *keyData = NULL;
bool sameKeySize = false;
symmetricKeyBits(context, CSSM_ALGID_CAST,
encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
keyData, keyLen);
if((keyLen < CAST_MIN_KEY_LENGTH) || (keyLen > CAST_KEY_LENGTH)) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
}
if(mRawKeySize == keyLen) {
sameKeySize = true;
}
else {
deleteKey();
}
if(!sameKeySize || memcmp(mRawKey, keyData, mRawKeySize)) {
CAST_set_key(&mCastKey, keyLen, keyData);
memmove(mRawKey, keyData, keyLen);
mRawKeySize = keyLen;
}
setup(CAST_BLOCK, context);
mInitFlag = true;
}
void CastContext::encryptBlock(
const void *plainText, size_t plainTextLen,
void *cipherText,
size_t &cipherTextLen, bool final) {
if(plainTextLen != CAST_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
}
if(cipherTextLen < CAST_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
CAST_ecb_encrypt((const unsigned char *)plainText, (unsigned char *)cipherText,
&mCastKey, CAST_ENCRYPT);
cipherTextLen = CAST_BLOCK;
}
void CastContext::decryptBlock(
const void *cipherText, void *plainText,
size_t &plainTextLen, bool final) {
if(plainTextLen < CAST_BLOCK) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
CAST_ecb_encrypt((const unsigned char *)cipherText, (unsigned char *)plainText,
&mCastKey, CAST_DECRYPT);
plainTextLen = CAST_BLOCK;
}