bsafeSymmetric.cpp [plain text]
#ifdef BSAFE_CSP_ENABLE
#include "bsafecspi.h"
#include <Security/debugging.h>
#define bbprintf(args...) debug("BSafeBuf", ## args)
#define VERBOSE_DEBUG 0
#if VERBOSE_DEBUG
static void dumpBuf(
char *title,
const CSSM_DATA *d,
uint32 maxLen)
{
unsigned i;
uint32 len;
if(title) {
printf("%s: ", title);
}
if(d == NULL) {
printf("NO DATA\n");
return;
}
printf("Total Length: %d\n ", d->Length);
len = maxLen;
if(d->Length < len) {
len = d->Length;
}
for(i=0; i<len; i++) {
printf("%02X ", d->Data[i]);
if((i % 16) == 15) {
printf("\n ");
}
}
printf("\n");
}
#else
#define dumpBuf(t, d, m)
#endif
void BSafe::SymmetricKeyGenContext::generate(
const Context &context,
CssmKey &symKey,
CssmKey &dummyKey)
{
AppleSymmKeyGenContext::generateSymKey(
context,
session(),
symKey);
}
void BSafe::BlockCipherContext::init(
const Context &context,
bool encrypting)
{
bool hasIV = false;
bool requirePad = false;
if (reusing(encrypting))
return;
cssmAlg = context.algorithm();
switch(cssmAlg) {
case CSSM_ALGID_RC4:
RC4init(context);
return;
case CSSM_ALGID_DES:
case CSSM_ALGID_DESX:
case CSSM_ALGID_3DES_3KEY_EDE:
case CSSM_ALGID_RC5:
case CSSM_ALGID_RC2:
break;
default:
assert(0);
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
BSafeItem iv;
B_BLK_CIPHER_W_FEEDBACK_PARAMS spec;
A_RC5_PARAMS rc5Params;
A_RC2_PARAMS rc2Params;
spec.encryptionParams = NULL_PTR; switch (cssmAlg) {
case CSSM_ALGID_DES:
spec.encryptionMethodName = POINTER("des");
break;
case CSSM_ALGID_DESX:
spec.encryptionMethodName = POINTER("desx");
break;
case CSSM_ALGID_3DES_3KEY_EDE:
spec.encryptionMethodName = POINTER("des_ede");
break;
case CSSM_ALGID_RC5:
spec.encryptionMethodName = POINTER("rc5");
spec.encryptionParams = POINTER(&rc5Params);
rc5Params.version = 0x10;
rc5Params.rounds = 1;
rc5Params.wordSizeInBits = 32;
break;
case CSSM_ALGID_RC2:
{
spec.encryptionMethodName = POINTER("rc2");
spec.encryptionParams = POINTER(&rc2Params);
uint32 bits = context.getInt(CSSM_ATTRIBUTE_EFFECTIVE_BITS);
if(bits == 0) {
CssmKey &key = context.get<CssmKey>(CSSM_ATTRIBUTE_KEY,
CSSMERR_CSP_MISSING_ATTR_KEY);
bits = key.KeyHeader.LogicalKeySizeInBits;
}
rc2Params.effectiveKeyBits = bits;
break;
}
}
cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE);
switch (cssmMode) {
case CSSM_ALGMODE_CBCPadIV8:
requirePad = true;
case CSSM_ALGMODE_CBC_IV8:
{
iv = context.get<CssmData>(CSSM_ATTRIBUTE_INIT_VECTOR,
CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR);
spec.feedbackMethodName = POINTER("cbc");
spec.feedbackParams = POINTER(&iv);
hasIV = true;
break;
}
case CSSM_ALGMODE_OFB_IV8: {
iv = context.get<CssmData>(CSSM_ATTRIBUTE_INIT_VECTOR,
CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR);
spec.feedbackMethodName = POINTER("ofb");
spec.feedbackParams = POINTER(&iv);
hasIV = true;
break;
}
case CSSM_ALGMODE_ECB: {
spec.feedbackMethodName = POINTER("ecb");
spec.feedbackParams = POINTER(&blockSize);
break;
}
default:
errorLog1("BSafe symmetric init: illegal mode (%d)\n", (int)cssmMode);
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE);
}
spec.paddingParams = NULL_PTR;
padEnable = false;
uint32 cssmPadding = context.getInt(CSSM_ATTRIBUTE_PADDING);
if(requirePad) {
switch(cssmPadding) {
case CSSM_PADDING_PKCS1: case CSSM_PADDING_PKCS5:
case CSSM_PADDING_PKCS7:
spec.paddingMethodName = POINTER("pad");
padEnable = true;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
}
}
else {
if(cssmPadding != CSSM_PADDING_NONE) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
}
else {
spec.paddingMethodName = POINTER("nopad");
}
}
setAlgorithm(AI_FeedbackCipher, &spec); setKeyFromContext(context); cipherInit(); }
void BSafe::BlockCipherContext::RC4init(
const Context &context)
{
setAlgorithm(AI_RC4, NULL); setKeyFromContext(context); padEnable = false;
cipherInit(); }
void BSafe::BlockCipherContext::trackUpdate(size_t inSize, size_t outSize)
{
size_t newPending = pending + inSize;
pending = newPending % blockSize;
if(!mDirection && padEnable && (pending == 0) && (newPending > 0)) {
pending = blockSize;
}
bbprintf("===trackUpdte: %s; inSize=%d newPending=%d pending=%d",
(mDirection ? "encrypt" : "decrypt"),
inSize, newPending, pending);
}
size_t BSafe::BlockCipherContext::inputSize(size_t outSize)
{
size_t wholeBlocks = outSize / blockSize;
return wholeBlocks * blockSize - pending + (blockSize - 1);
}
size_t BSafe::BlockCipherContext::outputSize(bool final, size_t inSize)
{
size_t totalToGo = inSize + pending;
size_t numBlocks = (totalToGo + blockSize - 1) / blockSize;
size_t outSize;
if(mDirection && final && padEnable && ((totalToGo % blockSize) == 0)) { numBlocks++; }
outSize = numBlocks * blockSize;
bbprintf("===outputSize: %s; final=%d inSize=%d pending=%d outSize=%d",
(mDirection ? "encrypt" : "decrypt"),
final, inSize, pending, outSize);
return outSize;
}
void BSafe::BlockCipherContext::minimumProgress(size_t &inSize, size_t &outSize)
{
inSize = blockSize - pending;
outSize = blockSize;
}
#endif