#include "sslctx.h"
#include "cryptType.h"
#include "sslDebug.h"
#include "sslalloc.h"
#include "appleCdsa.h"
#include "symCipher.h"
#include <Security/cssm.h>
#include <string.h>
static void disposeCipherCtx(
CipherContext *cipherCtx)
{
CASSERT(cipherCtx != NULL);
if(cipherCtx->symKey != NULL) {
CASSERT(cipherCtx->cspHand != 0);
CSSM_FreeKey(cipherCtx->cspHand, NULL, cipherCtx->symKey, CSSM_FALSE);
sslFree(cipherCtx->symKey);
cipherCtx->symKey = NULL;
}
cipherCtx->cspHand = 0;
if(cipherCtx->ccHand != 0) {
CSSM_DeleteContext(cipherCtx->ccHand);
cipherCtx->ccHand = 0;
}
}
SSLErr CDSASymmInit(
uint8 *key,
uint8* iv,
CipherContext *cipherCtx,
SSLContext *ctx)
{
SSLErr serr = SSLInternalError;
CSSM_RETURN crtn;
const SSLSymmetricCipher *symCipher;
CSSM_DATA ivData;
CSSM_DATA_PTR ivDataPtr = NULL;
CSSM_KEY_PTR symKey = NULL;
CSSM_CC_HANDLE ccHand = 0;
char *op;
CASSERT(cipherCtx != NULL);
CASSERT(cipherCtx->symCipher != NULL);
CASSERT(ctx != NULL);
if(ctx->cspHand == 0) {
errorLog0("CDSASymmInit: NULL cspHand!\n");
return SSLInternalError;
}
disposeCipherCtx(cipherCtx);
symKey = sslMalloc(sizeof(CSSM_KEY));
if(symKey == NULL) {
return SSLMemoryErr;
}
serr = sslSetUpSymmKey(symKey, cipherCtx->symCipher->keyAlg,
CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_TRUE,
key, cipherCtx->symCipher->keySize);
if(serr) {
sslFree(symKey);
return serr;
}
cipherCtx->symKey = symKey;
symCipher = cipherCtx->symCipher;
if(symCipher->ivSize != 0) {
ivData.Data = iv;
ivData.Length = symCipher->ivSize;
ivDataPtr = &ivData;
}
crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand,
symCipher->encrAlg,
symCipher->encrMode,
NULL,
symKey,
ivDataPtr,
symCipher->encrPad,
0, &ccHand);
if(crtn) {
stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn);
serr = SSLCryptoError;
goto errOut;
}
cipherCtx->ccHand = ccHand;
if(cipherCtx->encrypting) {
crtn = CSSM_EncryptDataInit(ccHand);
op = "CSSM_EncryptDataInit";
}
else {
crtn = CSSM_DecryptDataInit(ccHand);
op = "CSSM_DecryptDataInit";
}
if(crtn) {
stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn);
serr = SSLCryptoError;
goto errOut;
}
cipherCtx->cspHand = ctx->cspHand;
serr = SSLNoErr;
errOut:
if(serr) {
disposeCipherCtx(cipherCtx);
}
return serr;
}
#define REDECRYPT_DATA 0
#define LOG_SYMM_DATA 0
#if LOG_SYMM_DATA
static void logSymmData(
char *field,
SSLBuffer *data,
int maxLen)
{
int i;
printf("%s: ", field);
for(i=0; i<data->length; i++) {
if(i == maxLen) {
break;
}
printf("%02X", data->data[i]);
if((i % 4) == 3) {
printf(" ");
}
}
printf("\n");
}
#else
#define logSymmData(f, d, l)
#endif
#define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0)
SSLErr CDSASymmEncrypt(
SSLBuffer src,
SSLBuffer dest,
CipherContext *cipherCtx,
SSLContext *ctx)
{
CSSM_RETURN crtn;
CSSM_DATA ptextData;
CSSM_DATA ctextData;
uint32 bytesEncrypted;
SSLErr serr = SSLInternalError;
uint32 origLen = dest.length;
CASSERT(ctx != NULL);
CASSERT(cipherCtx != NULL);
logSymmData("Symm encrypt ptext", &src, 48);
CASSERT(dest.length >= src.length);
#if SSL_DEBUG
{
unsigned blockSize = cipherCtx->symCipher->blockSize;
if(blockSize) {
if(!IS_ALIGNED(src.length, blockSize)) {
errorLog2("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n",
src.length, blockSize);
return SSLInternalError;
}
if(!IS_ALIGNED(dest.length, blockSize)) {
errorLog2("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n",
dest.length, blockSize);
return SSLInternalError;
}
}
}
#endif
if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
errorLog0("CDSASymmEncrypt: null args\n");
return SSLInternalError;
}
SSLBUF_TO_CSSM(&src, &ptextData);
SSLBUF_TO_CSSM(&dest, &ctextData);
crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand,
&ptextData,
1,
&ctextData,
1,
&bytesEncrypted);
if(crtn) {
stPrintCdsaError("CSSM_EncryptDataUpdate", crtn);
serr = SSLCryptoError;
goto errOut;
}
if(bytesEncrypted > origLen) {
errorLog2("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n",
bytesEncrypted, dest.length);
serr = SSLDataOverflow;
goto errOut;
}
dest.length = bytesEncrypted;
logSymmData("Symm encrypt ctext", &dest, 48);
serr = SSLNoErr;
errOut:
return serr;
}
SSLErr CDSASymmDecrypt(
SSLBuffer src,
SSLBuffer dest,
CipherContext *cipherCtx,
SSLContext *ctx)
{
CSSM_RETURN crtn;
CSSM_DATA ptextData = {0, NULL};
CSSM_DATA ctextData;
uint32 bytesDecrypted;
SSLErr serr = SSLInternalError;
uint32 origLen = dest.length;
CASSERT(ctx != NULL);
CASSERT(cipherCtx != NULL);
if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
errorLog0("CDSASymmDecrypt: null args\n");
return SSLInternalError;
}
CASSERT(dest.length >= src.length);
#if SSL_DEBUG
{
unsigned blockSize = cipherCtx->symCipher->blockSize;
if(blockSize) {
if(!IS_ALIGNED(src.length, blockSize)) {
errorLog2("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n",
src.length, blockSize);
return SSLInternalError;
}
if(!IS_ALIGNED(dest.length, blockSize)) {
errorLog2("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n",
dest.length, blockSize);
return SSLInternalError;
}
}
}
#endif
SSLBUF_TO_CSSM(&src, &ctextData);
SSLBUF_TO_CSSM(&dest, &ptextData);
crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand,
&ctextData,
1,
&ptextData,
1,
&bytesDecrypted);
if(crtn) {
stPrintCdsaError("CSSM_DecryptDataUpdate", crtn);
serr = SSLCryptoError;
goto errOut;
}
if(bytesDecrypted > origLen) {
errorLog2("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n",
bytesDecrypted, dest.length);
serr = SSLDataOverflow;
goto errOut;
}
dest.length = bytesDecrypted;
serr = SSLNoErr;
logSymmData("Symm decrypt ptext(1)", &dest, 48);
errOut:
return serr;
}
SSLErr CDSASymmFinish(
CipherContext *cipherCtx,
SSLContext *ctx)
{
disposeCipherCtx(cipherCtx);
return SSLNoErr;
}