#include "aescspi.h"
#include "rijndaelApi.h"
#include "rijndael-alg-ref.h"
#include "cspdebugging.h"
#define DEFAULT_BLOCK_SIZE (MIN_AES_BLOCK_BITS / 8)
void AESKeyGenContext::generate(
const Context &context,
CssmKey &symKey,
CssmKey &dummyKey)
{
uint32 reqKeySize = context.getInt(
CSSM_ATTRIBUTE_KEY_LENGTH,
CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
switch(reqKeySize) {
case MIN_AES_KEY_BITS:
case MID_AES_KEY_BITS:
case MAX_AES_KEY_BITS:
break;
default:
CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
}
AppleSymmKeyGenContext::generateSymKey(
context,
session(),
symKey);
}
AESContext::~AESContext()
{
deleteKey();
memset(mRawKey, 0, MAX_AES_KEY_BITS / 8);
mInitFlag = false;
}
void AESContext::aesError(
int artn,
const char *errStr)
{
CSSM_RETURN crtn;
errorLog2("AESContext: %s : %d\n", errStr, artn);
switch(artn) {
case BAD_KEY_INSTANCE:
default:
crtn = CSSMERR_CSP_INTERNAL_ERROR;
break;
case BAD_KEY_MAT:
crtn = CSSMERR_CSP_INVALID_KEY;
break;
}
CssmError::throwMe(crtn);
}
void AESContext::deleteKey()
{
if(mAesKey) {
memset(mAesKey, 0, sizeof(keyInstance));
session().free(mAesKey);
mAesKey = NULL;
}
}
void AESContext::init(
const Context &context,
bool encrypting)
{
if(mInitFlag && !opStarted()) {
return;
}
CSSM_SIZE keyLen;
uint8 *keyData = NULL;
unsigned lastBlockSize = mBlockSize; bool sameKeyAndBlockSizes = false;
symmetricKeyBits(context, session(), CSSM_ALGID_AES,
encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
keyData, keyLen);
switch(keyLen) {
case MIN_AES_KEY_BITS / 8:
case MID_AES_KEY_BITS / 8:
case MAX_AES_KEY_BITS / 8:
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
}
mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE);
if(mBlockSize == 0) {
mBlockSize = DEFAULT_BLOCK_SIZE;
}
if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) {
sameKeyAndBlockSizes = true;
}
if((mAesKey != NULL) && !sameKeyAndBlockSizes) {
deleteKey();
}
int opt128 = 0;
#if !GLADMAN_AES_128_ENABLE
if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) &&
(keyLen == (MIN_AES_KEY_BITS/8)) &&
doAES128) {
opt128 = 1;
}
#endif
if(mAesKey == NULL) {
mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance));
}
if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) {
int artn = makeKey((keyInstance *)mAesKey,
(int)keyLen * 8,
mBlockSize * 8,
(word8 *)keyData,
opt128);
if(artn < 0) {
aesError(artn, "makeKey");
}
memmove(mRawKey, keyData, mRawKeySize);
mRawKeySize = (uint32)keyLen;
}
#if !GLADMAN_AES_128_ENABLE
if(opt128) {
mEncryptFcn = rijndaelBlockEncrypt128;
mDecryptFcn = rijndaelBlockDecrypt128;
}
else {
mEncryptFcn = rijndaelBlockEncrypt;
mDecryptFcn = rijndaelBlockDecrypt;
}
#else
mEncryptFcn = rijndaelBlockEncrypt;
mDecryptFcn = rijndaelBlockDecrypt;
#endif
setup(mBlockSize, context);
mInitFlag = true;
}
void AESContext::encryptBlock(
const void *plainText, size_t plainTextLen,
void *cipherText,
size_t &cipherTextLen, bool final) {
if(plainTextLen != mBlockSize) {
CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
}
if(cipherTextLen < mBlockSize) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
int artn = mEncryptFcn(mAesKey,
(word8 *)plainText,
(word8 *)cipherText);
if(artn < 0) {
aesError(artn, "rijndaelBlockEncrypt");
}
cipherTextLen = mBlockSize;
}
void AESContext::decryptBlock(
const void *cipherText, size_t cipherTextLen,
void *plainText,
size_t &plainTextLen, bool final) {
if(plainTextLen < mBlockSize) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
int artn = mDecryptFcn(mAesKey,
(word8 *)cipherText,
(word8 *)plainText);
if(artn < 0) {
aesError(artn, "rijndaelBlockDecrypt");
}
plainTextLen = mBlockSize;
}