📄 pgpipsecesp.c
字号:
pgpSetDestIPAddress(ipPacketOut, gatewayIP);
pgpSetPacketSize(packetSize, ipPacketOut);
}
if (IsntPGPError(err) && (hash != kPGPHashAlgorithm_Invalid))
{
switch (hash)
{
case kPGPHashAlgorithm_MD5:
hashSize = 16;
authKeySize = 16;
break;
case kPGPHashAlgorithm_SHA:
hashSize = 20;
authKeySize = 20;
break;
case kPGPHashAlgorithm_RIPEMD160:
hashSize = 20;
authKeySize = 20;
break;
};
if (hashSize > TRUNCATED_HASH_SIZE)
hashSize = TRUNCATED_HASH_SIZE;
err = PGPNewHMACContext(memoryMgr, hash, authKey, authKeySize,
&hmacRef);
outPtr = ipPacketOut;
outDataIndex = espIndex;
total = outPtr->dataSize - outDataIndex;
err = PGPContinueHMAC(hmacRef, &(outPtr->data[outDataIndex]), total);
while (IsntPGPError(err) && (total < (packetSize - espIndex)))
{
outPtr = outPtr->next;
total += outPtr->dataSize;
err = PGPContinueHMAC(hmacRef, outPtr->data, outPtr->dataSize);
}
if (IsntPGPError(err))
err = PGPFinalizeHMAC(hmacRef, authBuffer);
if (IsntPGPError(err))
{
tempBuffer.data = authBuffer;
tempBuffer.dataSize = hashSize;
tempBuffer.allocatedSize = hashSize;
tempBuffer.next = NULL;
PGPCopyIPsecBuffer(memoryMgr, &tempBuffer, 0, outPtr,
outPtr->dataSize, hashSize, maxBufferSize);
packetSize += hashSize;
pgpSetPacketSize(packetSize, ipPacketOut);
}
}
if (IsntPGPError(err))
pgpSetIPHeaderChecksum(ipPacketOut);
if (IsntNull(hmacRef))
PGPFreeHMACContext(hmacRef);
if (IsntNull(cbcRef))
PGPFreeCBCContext(cbcRef);
DBG_LEAVE(err);
return err;
}
PGPError pgpIPsecDecrypt(PGPIPsecContextRef ipsec, PGPUInt32 maxBufferSize,
PGPIPsecBuffer *ipPacketIn, PGPBoolean tunnelMode,
PGPCipherAlgorithm cipher, const PGPByte *cryptKey,
PGPHashAlgorithm hash, PGPByte *authKey,
PGPUInt32 *sequenceWindow, PGPUInt32 *upperSequence,
PGPUInt32 *lowerSequence, PGPIPsecBuffer *ipPacketOut)
{
PGPUInt32 espIndex;
PGPUInt32 sequenceNumber;
PGPUInt32 sequenceBit;
PGPUInt16 packetSize;
PGPUInt32 inDataIndex;
PGPUInt32 outDataIndex;
PGPUInt32 inSlopIndex;
PGPUInt32 outSlopIndex;
PGPUInt32 chunkSize;
PGPUInt32 inputStart;
PGPSize total;
PGPSize prevTotal;
PGPSize keySize;
PGPSize blockSize;
PGPSize inputSize;
PGPByte padLength;
PGPByte nextHeader;
PGPByte hashSize;
PGPByte authKeySize;
PGPByte *iv = NULL;
PGPByte hashData[MAXHASHSIZE];
PGPByte inSlopBlock[MAX_SLOP_BLOCK];
PGPByte outSlopBlock[MAX_SLOP_BLOCK];
PGPByte headerData[ESP_HEADERSIZE + MAXHASHSIZE];
PGPByte *inSlopPtr = NULL;
PGPByte *outSlopPtr = NULL;
PGPIPsecBuffer tempBuffer;
PGPIPsecBuffer *inPtr = NULL;
PGPIPsecBuffer *outPtr = NULL;
PGPIPsecBuffer *tempPtr = NULL;
PGPMemoryMgrRef memoryMgr = NULL;
PGPHMACContextRef hmacRef = NULL;
PGPSymmetricCipherContextRef cipherRef = NULL;
PGPCBCContextRef cbcRef = NULL;
PGPError err = kPGPError_NoErr;
DBG_FUNC("pgpIPsecDecrypt")
DBG_ENTER();
if (IsNull(ipsec)) {
DBG_LEAVE(kPGPError_BadParams);
return kPGPError_BadParams;
}
memoryMgr = ipsec->memory;
packetSize = pgpGetPacketSize(ipPacketIn);
if ((packetSize < maxBufferSize) || (maxBufferSize == 0))
{
if (ipPacketOut->allocatedSize < packetSize)
{
if (IsntNull(ipPacketOut->data))
PGPFreeData(ipPacketOut->data);
ipPacketOut->data = (PGPByte *) PGPNewData(memoryMgr,
packetSize,
kPGPMemoryMgrFlags_Clear);
ipPacketOut->allocatedSize = packetSize;
if (maxBufferSize == 0)
maxBufferSize = packetSize;
}
}
else
{
if (ipPacketOut->allocatedSize < maxBufferSize)
{
if (IsntNull(ipPacketOut->data))
PGPFreeData(ipPacketOut->data);
ipPacketOut->data = (PGPByte *) PGPNewData(memoryMgr,
maxBufferSize,
kPGPMemoryMgrFlags_Clear);
ipPacketOut->allocatedSize = maxBufferSize;
}
}
if (IsNull(ipPacketOut->data))
err = kPGPError_OutOfMemory;
switch (cipher)
{
case kPGPCipherAlgorithm_CAST5:
keySize = 16;
blockSize = 8;
err = PGPNewSymmetricCipherContext(memoryMgr,
kPGPCipherAlgorithm_CAST5, 16, &cipherRef);
if (IsntPGPError(err))
err = PGPNewCBCContext(cipherRef, &cbcRef);
break;
case kPGPCipherAlgorithm_3DES:
keySize = 24;
blockSize = 8;
err = PGPNewSymmetricCipherContext(memoryMgr,
kPGPCipherAlgorithm_3DES, 24, &cipherRef);
if (IsntPGPError(err))
err = PGPNewCBCContext(cipherRef, &cbcRef);
break;
case kPGPCipherAlgorithm_None:
keySize = 0;
blockSize = 0;
break;
default:
err = kPGPError_BadCipherNumber;
break;
};
if (IsntPGPError(err))
err = pgpFindProtocolHeader(ipPacketIn, ESP_PROTOCOL, &espIndex);
if (IsntPGPError(err))
{
tempBuffer.data = headerData;
tempBuffer.dataSize = ESP_HEADERSIZE + blockSize;
tempBuffer.allocatedSize = ESP_HEADERSIZE + blockSize;
tempBuffer.next = NULL;
PGPCopyIPsecBuffer(memoryMgr, ipPacketIn, espIndex, &tempBuffer, 0,
ESP_HEADERSIZE + blockSize, ESP_HEADERSIZE + blockSize);
if (hash != kPGPHashAlgorithm_Invalid)
{
if (*upperSequence < ((sizeof(*sequenceWindow) << 3) - 1))
*upperSequence = (sizeof(*sequenceWindow) << 3) - 1;
*lowerSequence = *upperSequence - (sizeof(sequenceWindow) << 3)
+ 1;
sequenceNumber = PGPEndianToUInt32(kPGPNetworkByteOrder,
&(headerData[ESPHDR_SEQNUMBER]));
if (sequenceNumber < *lowerSequence)
err = kPGPIPsecError_PacketReceivedTooLate;
else if (sequenceNumber <= *upperSequence)
{
sequenceBit = 0x00000001 << (sequenceNumber - *lowerSequence);
if (sequenceBit & *sequenceWindow)
err = kPGPIPsecError_PacketAlreadyReceived;
}
}
}
if (IsntPGPError(err))
{
if ((maxBufferSize > 0) &&
(maxBufferSize < (espIndex + ESP_HEADERSIZE + blockSize)))
err = kPGPError_BufferTooSmall;
}
if (IsntPGPError(err) && (hash != kPGPHashAlgorithm_Invalid))
{
switch (hash)
{
case kPGPHashAlgorithm_MD5:
hashSize = 16;
authKeySize = 16;
break;
case kPGPHashAlgorithm_SHA:
hashSize = 20;
authKeySize = 20;
break;
case kPGPHashAlgorithm_RIPEMD160:
hashSize = 20;
authKeySize = 20;
break;
};
if (hashSize > TRUNCATED_HASH_SIZE)
hashSize = TRUNCATED_HASH_SIZE;
err = PGPNewHMACContext(memoryMgr, hash, authKey, authKeySize,
&hmacRef);
inPtr = ipPacketIn;
inDataIndex = espIndex;
if (inPtr->dataSize > (PGPUInt32) (packetSize - hashSize))
total = packetSize - espIndex - hashSize;
else
total = inPtr->dataSize - inDataIndex;
err = PGPContinueHMAC(hmacRef, &(inPtr->data[inDataIndex]), total);
inDataIndex += total;
while (IsntPGPError(err) &&
(total < (packetSize - espIndex - hashSize)))
{
inPtr = inPtr->next;
prevTotal = total;
total += inPtr->dataSize;
if (total <= (packetSize - espIndex - hashSize))
inDataIndex = inPtr->dataSize;
else
inDataIndex = packetSize - espIndex - hashSize - prevTotal;
err = PGPContinueHMAC(hmacRef, inPtr->data, inDataIndex);
}
if (IsntPGPError(err))
err = PGPFinalizeHMAC(hmacRef, hashData);
if (IsntPGPError(err))
{
tempBuffer.data = hashData;
tempBuffer.dataSize = hashSize;
tempBuffer.allocatedSize = hashSize;
tempBuffer.next = NULL;
if (!PGPIPsecBufferDataIsEqual(&tempBuffer, 0, ipPacketIn,
packetSize - hashSize, hashSize))
{
err = kPGPIPsecError_PacketAuthenticationFailed;
}
else
{
packetSize -= hashSize;
if ((inDataIndex + hashSize) > inPtr->dataSize)
inPtr->next->dataSize = 0;
inPtr->dataSize = inDataIndex;
}
}
}
if (cipher != kPGPCipherAlgorithm_None)
{
if (IsntPGPError(err))
{
iv = (PGPByte *) PGPNewData(memoryMgr, blockSize,
kPGPMemoryMgrFlags_Clear);
if (IsNull(iv))
err = kPGPError_OutOfMemory;
}
if (IsntPGPError(err))
{
pgpCopyMemory(&(headerData[ESPHDR_DATA]), iv, blockSize);
err = PGPInitCBC(cbcRef, cryptKey, iv);
}
if (IsntPGPError(err))
{
inputStart = espIndex + ESPHDR_DATA + blockSize;
inputSize = packetSize - inputStart;
if (tunnelMode)
outDataIndex = 0;
else
outDataIndex = espIndex;
inPtr = ipPacketIn;
outPtr = ipPacketOut;
total = inPtr->dataSize;
prevTotal = 0;
inSlopIndex = 0;
outSlopIndex = 0;
while ((total < inputStart) && IsntNull(inPtr->next))
{
prevTotal = total;
inPtr = inPtr->next;
total += inPtr->dataSize;
}
inDataIndex = inputStart - prevTotal;
if (total < inputStart)
err = kPGPError_BufferTooSmall;
}
while (IsntPGPError(err) && (inputSize >= blockSize) &&
IsntNull(inPtr))
{
inSlopIndex = 0;
outSlopIndex = 0;
if (((inPtr->dataSize - inDataIndex) >= blockSize) &&
((outPtr->allocatedSize - outDataIndex) >= blockSize))
{
if ((inPtr->dataSize - inDataIndex) <=
(outPtr->allocatedSize - outDataIndex))
{
chunkSize = (inPtr->dataSize - inDataIndex) -
((inPtr->dataSize - inDataIndex) % blockSize);
}
else
{
chunkSize = (outPtr->allocatedSize - outDataIndex) -
((outPtr->allocatedSize - outDataIndex) %
blockSize);
}
err = PGPCBCDecrypt(cbcRef, &(inPtr->data[inDataIndex]),
chunkSize, &(outPtr->data[outDataIndex]));
outDataIndex += chunkSize;
inDataIndex += chunkSize;
inputSize -= chunkSize;
if (inDataIndex == inPtr->dataSize)
{
inPtr = inPtr->next;
inDataIndex = 0;
}
if (outDataIndex == outPtr->allocatedSize)
{
outPtr->dataSize = outPtr->allocatedSize;
tempPtr = outPtr;
outPtr = outPtr->next;
outDataIndex = 0;
}
}
else
{
if ((inPtr->dataSize - inDataIndex) < blockSize)
{
inSlopPtr = inSlopBlock;
while ((inSlopIndex < blockSize) && IsntNull(inPtr))
{
total = inPtr->dataSize - inDataIndex;
if (total > (blockSize - inSlopIndex))
total = blockSize - inSlopIndex;
pgpCopyMemory(&(inPtr->data[inDataIndex]),
&(inSlopBlock[inSlopIndex]), total);
inSlopIndex += total;
inDataIndex += total;
inputSize -= total;
if (inDataIndex == inPtr->dataSize)
{
inPtr = inPtr->next;
inDataIndex = 0;
}
}
}
else
{
inSlopPtr = &(inPtr->data[inDataIndex]);
inSlopIndex = blockSize;
inDataIndex += blockSize;
inputSize -= blockSize;
}
if ((outPtr->allocatedSize - outDataIndex) < blockSize)
{
err = PGPExpandIPsecBuffer(memoryMgr, outPtr,
maxBufferSize, blockSize + outDataIndex);
if ((outPtr->allocatedSize - outDataIndex) < blockSize)
outSlopPtr = outSlopBlock;
else
outSlopPtr = &(outPtr->data[outDataIndex]);
}
else
outSlopPtr = &(outPtr->data[outDataIndex]);
if (IsntPGPError(err) && (inSlopIndex == blockSize))
{
inSlopIndex = 0;
err = PGPCBCDecrypt(cbcRef, inSlopPtr, blockSize,
outSlopPtr);
if (IsntPGPError(err) && (outSlopPtr == outSlopBlock))
{
outSlopIndex = outPtr->allocatedSize - outDataIndex;
pgpCopyMemory(outSlopBlock,
&(outPtr->data[outDataIndex]), outSlopIndex);
outPtr->dataSize = outPtr->allocatedSize;
tempPtr = outPtr;
outPtr = outPtr->next;
pgpCopyMemory(&(outSlopBlock[outSlopIndex]),
outPtr->data, blockSize - outSlopIndex);
outDataIndex = blockSize - outSlopIndex;
}
else
outDataIndex += blockSize;
}
}
}
}
else
{
if (tunnelMode)
PGPCopyIPsecBuffer(memoryMgr,
ipPacketIn, espIndex + ESP_HEADERSIZE + blockSize,
ipPacketOut, 0, packetSize - espIndex - ESP_HEADERSIZE,
maxBufferSize);
else
PGPCopyIPsecBuffer(memoryMgr,
ipPacketIn, espIndex + ESP_HEADERSIZE + blockSize,
ipPacketOut, espIndex, packetSize - espIndex - ESP_HEADERSIZE,
maxBufferSize);
outPtr = ipPacketOut;
tempPtr = NULL;
while (IsntNull(outPtr->next))
{
if (outPtr->next->dataSize == 0)
break;
else
{
tempPtr = outPtr;
outPtr = outPtr->next;
}
}
outDataIndex = outPtr->dataSize;
}
if (IsntPGPError(err) && (hash != kPGPHashAlgorithm_Invalid))
{
if (sequenceNumber > *upperSequence)
{
PGPUInt32 sequenceMask = 0x7fffffff;
sequenceMask >>= sequenceNumber - *upperSequence - 1;
*sequenceWindow >>= sequenceNumber - *upperSequence;
*sequenceWindow &= sequenceMask;
*upperSequence = sequenceNumber;
*lowerSequence = *upperSequence - (sizeof(sequenceWindow) << 3)
+ 1;
}
sequenceBit = 0x00000001 << (sequenceNumber - *lowerSequence);
*sequenceWindow |= sequenceBit;
}
if (IsntPGPError(err))
{
if (outDataIndex > 1)
{
padLength = outPtr->data[outDataIndex - 2];
nextHeader = outPtr->data[outDataIndex - 1];
}
else if (outDataIndex == 1)
{
padLength = tempPtr->data[tempPtr->dataSize - 1];
nextHeader = outPtr->data[0];
}
else
{
padLength = tempPtr->data[tempPtr->dataSize - 2];
nextHeader = tempPtr->data[tempPtr->dataSize - 1];
}
if (outDataIndex > (PGPUInt32) (padLength + 2))
{
outDataIndex -= padLength + 2;
outPtr->dataSize = outDataIndex;
}
else
{
outPtr->dataSize = 0;
tempPtr->dataSize -= padLength + 2 - outDataIndex;
outDataIndex = tempPtr->dataSize;
outPtr = tempPtr;
}
if ((nextHeader == IP_IN_IP) && !tunnelMode)
{
tunnelMode = TRUE;
PGPCopyIPsecBuffer(memoryMgr, ipPacketOut, espIndex,
ipPacketOut, 0, inputSize - (padLength + 2), maxBufferSize);
}
packetSize -= blockSize;
if (tunnelMode)
packetSize -= padLength + 2 + ESP_HEADERSIZE + espIndex;
else
{
packetSize -= padLength + 2 + ESP_HEADERSIZE;
err = pgpRemoveProtocolFromIPHeader(ipPacketIn, ESP_PROTOCOL,
nextHeader, ipPacketOut);
}
}
if (IsntPGPError(err))
{
pgpSetPacketSize(packetSize, ipPacketOut);
pgpSetIPHeaderChecksum(ipPacketOut);
}
if (IsntNull(iv))
PGPFreeData(iv);
if (IsntNull(cbcRef))
PGPFreeCBCContext(cbcRef);
if (IsntNull(hmacRef))
PGPFreeHMACContext(hmacRef);
DBG_LEAVE(err);
return err;
}
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -