DSEncryptedEndpoint.cpp [plain text]
#include <string.h> // for memset(), memcpy() and strcpy()
#include <new> // for bad_alloc exceptions
#include <stdexcept> // for standard exceptions
#include <machine/byte_order.h>
#ifdef DSSERVERTCP
#include "CLog.h"
#endif
#include "DSEncryptedEndpoint.h"
uint8 paramBlob[] = { \
0x30, 0x52, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03, 0x30, 0x46, 0x02, 0x41,\
0x00, 0xa0, 0xd4, 0x42, 0xd5, 0x68, 0x08, 0x94, 0xc9, 0xef, 0xb7, 0x18, 0x9c, 0x0b, 0x72, 0x53,\
0xac, 0x8a, 0x7b, 0xc2, 0x40, 0x17, 0x96, 0x29, 0xd1, 0xf2, 0x96, 0xe8, 0x2b, 0x4e, 0x48, 0xaf,\
0x59, 0xbe, 0x29, 0xc4, 0x9b, 0x52, 0xda, 0x05, 0x18, 0x29, 0x73, 0xff, 0xd5, 0x26, 0x47, 0x53,\
0x54, 0x79, 0xf4, 0x39, 0x96, 0x6f, 0x61, 0x5e, 0xe6, 0xfc, 0x92, 0x7d, 0xf4, 0x20, 0x6e, 0xa9,\
0xa3, 0x02, 0x01, 0x02 };
#pragma mark **** Instance Methods ****
DSEncryptedEndpoint::DSEncryptedEndpoint (
int inConnectFD,
UInt32 inOpenTimeout,
UInt32 inRWTimeout)
: inherited (inConnectFD, inOpenTimeout, inRWTimeout)
{
CSSM_RETURN crtn;
crtn = cdsaCspAttach(&fcspHandle);
if (crtn)
{
}
else
{
fOurDerivedKey.KeyData.Data = nil;
fOurDerivedKey.KeyData.Length = 0;
fOurParamBlock.Data = (uint8 *)paramBlob;
fOurParamBlock.Length = 84;
}
}
DSEncryptedEndpoint::DSEncryptedEndpoint (
const DSTCPEndpoint *inEndpoint,
const UInt32 inSessionID)
: inherited (inEndpoint, inSessionID)
{
CSSM_RETURN crtn;
mListenFD = -1 ;
crtn = cdsaCspAttach(&fcspHandle);
if (crtn)
{
}
else
{
fOurDerivedKey.KeyData.Data = nil;
fOurDerivedKey.KeyData.Length = 0;
fOurParamBlock.Data = (uint8 *)paramBlob;
fOurParamBlock.Length = 84;
}
}
DSEncryptedEndpoint::~DSEncryptedEndpoint (void)
{
cdsaFreeKey(fcspHandle, &fOurDerivedKey);
cdsaCspDetach(fcspHandle);
}
SInt32 DSEncryptedEndpoint::ClientNegotiateKey ( void )
{
bool bFirstPass = true;
SInt32 result = eDSContinue;
CSSM_RETURN crtn;
UInt8 *outBuff = nil;
UInt32 outLen = 0;
UInt8 *inBuff = nil;
UInt32 inLen = 0;
UInt32 readBytes = 0;
CSSM_KEY myPriv;
CSSM_KEY myPub;
CSSM_KEY localDerived;
UInt32 theTestBlob = 0;
UInt32 theTestBlobBE = 0;
CSSM_DATA plainText = {0, NULL};
CSSM_DATA cipherText = {0, NULL};
SInt32 syncRet = eDSNoErr;
bzero(&myPriv,sizeof(CSSM_KEY));
bzero(&myPub,sizeof(CSSM_KEY));
bzero(&localDerived,sizeof(CSSM_KEY));
do {
if (bFirstPass)
{
crtn = cdsaDhGenerateKeyPair(
fcspHandle,
&myPub,
&myPriv,
DH_KEY_SIZE,
&fOurParamBlock,
NULL);
if (crtn)
{
return eDSCorruptBuffer; }
outBuff = (UInt8*)calloc(1,4 + myPub.KeyData.Length);
*((FourCharCode *) outBuff) = NXSwapHostIntToBig(DSTCPAuthTag);
outLen = myPub.KeyData.Length;
memcpy(outBuff+4, (UInt8 *)myPub.KeyData.Data, outLen);
outLen += 4; bFirstPass = false;
}
else {
crtn = cdsaDhKeyExchange(
fcspHandle,
&myPriv,
(void *)inBuff,
inLen,
&localDerived,
DERIVE_KEY_SIZE,
DERIVE_KEY_ALG);
if (crtn)
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
::srandom(getpid() + time(NULL));
theTestBlob = random();
theTestBlobBE = NXSwapHostIntToBig(theTestBlob);
plainText.Data = (UInt8 *)&theTestBlobBE;
plainText.Length = 4;
crtn = cdsaEncrypt(
fcspHandle,
&localDerived,
&plainText,
&cipherText);
if (crtn)
{
return eDSCorruptBuffer; }
outBuff = cipherText.Data;
outLen = cipherText.Length;
result = eDSNoErr;
}
if (outLen != 0)
{
SendBuffer(outBuff,outLen) ;
if (outBuff != nil)
{
free(outBuff);
outBuff = nil;
}
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
syncRet = SyncToMessageBody(true, &inLen);
if (syncRet != eDSNoErr) return syncRet;
inBuff = (UInt8*)calloc(1, inLen);
readBytes = DoTCPRecvFrom(inBuff, inLen);
if (readBytes != inLen)
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
}
} while ( result == eDSContinue );
if (inLen != 0)
{
cipherText.Data = inBuff;
cipherText.Length = inLen;
plainText.Data = nil;
plainText.Length = 0;
crtn = cdsaDecrypt(
fcspHandle,
&localDerived,
&cipherText,
&plainText);
if (crtn)
{
result = eDSCorruptBuffer; }
else
{
if ( (plainText.Data == nil) ||
(plainText.Length != 4) ||
(theTestBlob+1 != NXSwapBigIntToHost(*((UInt32*)plainText.Data))) )
{
result = eDSCorruptBuffer; }
if (plainText.Data != nil)
{
free(plainText.Data);
}
}
}
else
{
return eDSCorruptBuffer; }
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
if (result == eDSNoErr)
{
fOurDerivedKey = localDerived;
}
return result;
}
SInt32 DSEncryptedEndpoint::ServerNegotiateKey ( void )
{
bool bFirstPass = true;
SInt32 result = eDSContinue;
CSSM_RETURN crtn;
UInt8 *outBuff = nil;
UInt32 outLen = 0;
UInt8 *inBuff = nil;
UInt32 inLen = 0;
UInt32 readBytes = 0;
CSSM_KEY myPriv;
CSSM_KEY myPub;
CSSM_KEY localDerived;
CSSM_DATA plainText = {0, NULL};
CSSM_DATA cipherText = {0, NULL};
FourCharCode rxCode = 0;
SInt32 syncRet = eDSNoErr;
bzero(&myPriv,sizeof(CSSM_KEY));
bzero(&myPub,sizeof(CSSM_KEY));
bzero(&localDerived,sizeof(CSSM_KEY));
do {
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
syncRet = SyncToMessageBody(true, &inLen);
if (syncRet != eDSNoErr) return syncRet;
inBuff = (UInt8*)calloc(1, inLen);
readBytes = DoTCPRecvFrom(inBuff, inLen);
if (readBytes != inLen)
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
if (bFirstPass)
{
rxCode = NXSwapBigIntToHost(*((FourCharCode *) inBuff));
if ( (inLen <= 4) || (rxCode != DSTCPAuthTag) )
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
crtn = cdsaDhGenerateKeyPair(
fcspHandle,
&myPub,
&myPriv,
DH_KEY_SIZE,
&fOurParamBlock,
NULL);
if (crtn)
{
return eDSCorruptBuffer; }
crtn = cdsaDhKeyExchange(
fcspHandle,
&myPriv,
(void *)(inBuff+4),
(inLen-4),
&localDerived,
DERIVE_KEY_SIZE,
DERIVE_KEY_ALG);
if (crtn)
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
outBuff = myPub.KeyData.Data;
outLen = myPub.KeyData.Length;
bFirstPass = false;
}
else {
if (inLen != 0)
{
cipherText.Data = inBuff;
cipherText.Length = inLen;
crtn = cdsaDecrypt(
fcspHandle,
&localDerived,
&cipherText,
&plainText);
if (crtn)
{
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
return eDSCorruptBuffer; }
if (inBuff != nil)
{
free(inBuff);
inBuff = nil;
}
}
if ( (plainText.Data == nil) || (plainText.Length != 4) )
{
return eDSCorruptBuffer; }
UInt32 temp = NXSwapBigIntToHost(*(UInt32*)plainText.Data);
temp++;
*(UInt32*)plainText.Data = NXSwapHostIntToBig(temp);
cipherText.Data = nil;
cipherText.Length = 0;
crtn = cdsaEncrypt(
fcspHandle,
&localDerived,
&plainText,
&cipherText);
if (crtn)
{
return eDSCorruptBuffer; }
outBuff = cipherText.Data;
outLen = cipherText.Length;
result = eDSNoErr;
}
if (outLen != 0)
{
SendBuffer(outBuff,outLen) ;
if (outBuff != nil)
{
free(outBuff);
outBuff = nil;
}
}
} while ( result == eDSContinue );
if (result == eDSNoErr)
{
fOurDerivedKey = localDerived;
}
return result;
}
void DSEncryptedEndpoint::EncryptData ( void *inData, const UInt32 inBuffSize, void *&outData, UInt32 &outBuffSize )
{
CSSM_RETURN crtn;
CSSM_DATA plainText = {0, NULL};
CSSM_DATA cipherText = {0, NULL};
if (fOurDerivedKey.KeyData.Data == nil)
{
outBuffSize = 0;
return;
}
plainText.Data = (UInt8 *)inData;
plainText.Length = inBuffSize;
crtn = cdsaEncrypt(
fcspHandle,
&fOurDerivedKey,
&plainText,
&cipherText);
if (crtn)
{
return;
}
else
{
outData = cipherText.Data;
outBuffSize = cipherText.Length;
}
return;
}
void DSEncryptedEndpoint::DecryptData ( void *inData, const UInt32 inBuffSize, void *&outData, UInt32 &outBuffSize )
{
CSSM_RETURN crtn;
CSSM_DATA plainText = {0, NULL};
CSSM_DATA cipherText = {0, NULL};
if (fOurDerivedKey.KeyData.Data == nil)
{
outBuffSize = 0;
return;
}
cipherText.Data = (UInt8 *)inData;
cipherText.Length = inBuffSize;
crtn = cdsaDecrypt(
fcspHandle,
&fOurDerivedKey,
&cipherText,
&plainText);
if (crtn)
{
return;
}
else
{
outData = plainText.Data;
outBuffSize = plainText.Length;
}
return;
}