📄 pgpipsecesp.c
字号:
/*____________________________________________________________________________
Copyright (C) 1998 Network Associates, Inc.
All rights reserved.
$Id: pgpIPsecESP.c,v 1.47.4.1 1999/06/17 15:28:47 dgal Exp $
____________________________________________________________________________*/
#ifndef USERLAND_TEST
#define USERLAND_TEST 0
#endif
#if USERLAND_TEST
#define DBG_FUNC(x)
#define DBG_ENTER()
#define DBG_PRINT(x)
#define DBG_LEAVE(x)
#else
#if PGP_WIN32
#include "vpn.h"
#include "vpndbg.h"
#include "ipdef.h"
#elif PGP_MACINTOSH
#define DBG_FUNC(x)
#define DBG_ENTER()
#define DBG_PRINT(x)
#define DBG_LEAVE(x)
#endif
#endif
#include "pgpIPsecESP.h"
#include "pgpIPheader.h"
#include "pgpIPsecErrors.h"
#include "pgpIPsecContextPriv.h"
#include "pgpHMAC.h"
#include "pgpEndianConversion.h"
#include "pgpMem.h"
#define ESP_PROTOCOL 50
#define ESP_HEADERSIZE 8
#define ESPHDR_SPI 0
#define ESPHDR_SEQNUMBER 4
#define ESPHDR_DATA 8
#define MAXHASHSIZE 32
#define TRUNCATED_HASH_SIZE 12
#define MAX_SLOP_BLOCK 16
#define MAX_PADDING 24
static PGPByte nullIV[] = {0,0,0,0,0,0,0,0};
PGPError pgpIPsecESPGetSPI(PGPIPsecBuffer *inPacket, PGPUInt32 *spi)
{
PGPUInt32 espIndex;
PGPIPsecBuffer tempPacket;
PGPByte data[ESP_HEADERSIZE];
PGPError err = kPGPError_NoErr;
*spi = 0;
tempPacket.data = data;
tempPacket.dataSize = 0;
tempPacket.allocatedSize = ESP_HEADERSIZE;
tempPacket.next = NULL;
err = pgpFindProtocolHeader(inPacket, ESP_PROTOCOL, &espIndex);
if (IsntPGPError(err))
{
PGPCopyIPsecBuffer(NULL, inPacket, espIndex, &tempPacket, 0,
ESP_HEADERSIZE, ESP_HEADERSIZE);
*spi = PGPEndianToUInt32(kPGPNetworkByteOrder, &(data[ESPHDR_SPI]));
}
return err;
}
PGPError pgpIPsecEncrypt(PGPIPsecContextRef ipsec, PGPUInt32 maxBufferSize,
PGPIPsecBuffer *ipPacketIn, PGPBoolean tunnelMode,
PGPUInt32 gatewayIP, PGPCipherAlgorithm cipher,
const PGPByte *cryptKey, PGPByte *iv, PGPHashAlgorithm hash,
PGPByte *authKey, PGPUInt32 spi, PGPUInt32 sequenceNumber,
PGPIPsecBuffer *ipPacketOut)
{
PGPUInt32 espIndex;
PGPUInt32 index;
PGPUInt32 padStart;
PGPUInt16 packetSize;
PGPUInt32 inputStart;
PGPUInt32 inDataIndex;
PGPUInt32 outDataIndex;
PGPUInt32 inSlopIndex;
PGPUInt32 outSlopIndex;
PGPUInt32 chunkSize;
PGPSize total;
PGPSize prevTotal;
PGPByte nextHeader;
PGPByte padLength;
PGPSize keySize;
PGPSize encryptSize;
PGPSize blockSize;
PGPSize inputSize;
PGPByte hashSize;
PGPByte authKeySize;
PGPByte inSlopBlock[MAX_SLOP_BLOCK];
PGPByte outSlopBlock[MAX_SLOP_BLOCK];
PGPByte padding[MAX_PADDING];
PGPByte authBuffer[MAXHASHSIZE];
PGPByte headerData[ESP_HEADERSIZE + MAXHASHSIZE];
PGPByte *inSlopPtr = NULL;
PGPByte *outSlopPtr = NULL;
PGPIPsecBuffer tempBuffer;
PGPIPsecBuffer *inPtr = NULL;
PGPIPsecBuffer *outPtr = NULL;
PGPMemoryMgrRef memoryMgr = NULL;
PGPHMACContextRef hmacRef = NULL;
PGPSymmetricCipherContextRef cipherRef = NULL;
PGPCBCContextRef cbcRef = NULL;
PGPError err = kPGPError_NoErr;
DBG_FUNC("pgpIPsecEncrypt")
DBG_ENTER();
if (IsNull(ipsec)) {
DBG_PRINT(("!!!!! pgpIPsecEncrypt error: %d !!!!!!!!!!!\n", kPGPError_BadParams););
DBG_LEAVE(kPGPError_BadParams);
return kPGPError_BadParams;
}
memoryMgr = ipsec->memory;
packetSize = pgpGetPacketSize(ipPacketIn);
if (((PGPUInt32)(packetSize + 32) < maxBufferSize) ||
(maxBufferSize == 0))
{
if (ipPacketOut->allocatedSize < (PGPUInt32) (packetSize + 32))
{
if (IsntNull(ipPacketOut->data))
PGPFreeData(ipPacketOut->data);
ipPacketOut->data = (PGPByte *) PGPNewData(memoryMgr,
packetSize + 32,
kPGPMemoryMgrFlags_Clear);
ipPacketOut->allocatedSize = packetSize + 32;
if (maxBufferSize == 0)
maxBufferSize = packetSize + 32;
}
}
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))
{
pgpGetIPHeaderNextProtocol(ipPacketIn, tunnelMode, &nextHeader);
espIndex = pgpGetIPHeaderLength(ipPacketIn);
err = pgpAddProtocolToIPHeader(ipPacketIn, ESP_PROTOCOL, ipPacketOut);
if (tunnelMode)
packetSize += espIndex;
}
if (IsntPGPError(err))
{
if ((maxBufferSize > 0) &&
(maxBufferSize <= (espIndex + ESP_HEADERSIZE + blockSize)))
err = kPGPError_BufferTooSmall;
encryptSize = packetSize - espIndex;
if (tunnelMode)
inputStart = 0;
else
inputStart = espIndex;
inputSize = encryptSize;
outDataIndex = espIndex + ESPHDR_DATA + blockSize;
}
if (cipher != kPGPCipherAlgorithm_None)
{
if (IsntPGPError(err))
{
if (IsntNull(iv))
err = PGPInitCBC(cbcRef, cryptKey, iv);
else
err = PGPInitCBC(cbcRef, cryptKey, nullIV);
}
if (IsntPGPError(err))
{
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 = PGPCBCEncrypt(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;
outPtr = outPtr->next;
outDataIndex = 0;
}
}
else
{
if ((inPtr->dataSize - inDataIndex) < blockSize)
{
inSlopPtr = inSlopBlock;
while ((inputSize >= (blockSize - inSlopIndex) ) &&
(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 = PGPCBCEncrypt(cbcRef, inSlopPtr, blockSize,
outSlopPtr);
if (IsntPGPError(err) && (outSlopPtr == outSlopBlock))
{
outSlopIndex = outPtr->allocatedSize - outDataIndex;
pgpCopyMemory(outSlopBlock,
&(outPtr->data[outDataIndex]), outSlopIndex);
outPtr->dataSize = outPtr->allocatedSize;
outPtr = outPtr->next;
pgpCopyMemory(&(outSlopBlock[outSlopIndex]),
outPtr->data, blockSize - outSlopIndex);
outDataIndex = blockSize - outSlopIndex;
}
else
outDataIndex += blockSize;
}
}
}
if (IsntPGPError(err))
{
if (inputSize)
{
if ((inPtr->dataSize - inDataIndex) < inputSize)
{
pgpCopyMemory(&(inPtr->data[inDataIndex]),
&(inSlopBlock[inSlopIndex]),
inPtr->dataSize - inDataIndex);
inSlopIndex += inPtr->dataSize - inDataIndex;
inputSize -= inPtr->dataSize - inDataIndex;
inPtr = inPtr->next;
pgpCopyMemory(inPtr->data, &(inSlopBlock[inSlopIndex]),
inputSize);
}
else
pgpCopyMemory(&(inPtr->data[inDataIndex]),
&(inSlopBlock[inSlopIndex]), inputSize);
inSlopIndex += inputSize;
}
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 (inSlopIndex < 7)
{
padLength = blockSize - inSlopIndex - 2;
if (padLength)
for (index=0; index<padLength; index++)
inSlopBlock[index+inSlopIndex] = index + 1;
inSlopBlock[inSlopIndex + padLength] = padLength;
inSlopBlock[inSlopIndex + padLength + 1] = nextHeader;
err = PGPCBCEncrypt(cbcRef, inSlopBlock, blockSize,
outSlopPtr);
if (IsntPGPError(err) && (outSlopPtr == outSlopBlock))
{
outSlopIndex = outPtr->allocatedSize - outDataIndex;
pgpCopyMemory(outSlopBlock,
&(outPtr->data[outDataIndex]), outSlopIndex);
outPtr->dataSize = outPtr->allocatedSize;
outPtr = outPtr->next;
pgpCopyMemory(&(outSlopBlock[outSlopIndex]),
outPtr->data, blockSize - outSlopIndex);
outDataIndex = blockSize - outSlopIndex;
}
else
outDataIndex += blockSize;
}
else
{
inSlopBlock[7] = 1;
err = PGPCBCEncrypt(cbcRef, inSlopBlock, blockSize,
outSlopPtr);
if (IsntPGPError(err) && (outSlopPtr == outSlopBlock))
{
outSlopIndex = outPtr->allocatedSize - outDataIndex;
pgpCopyMemory(outSlopBlock,
&(outPtr->data[outDataIndex]), outSlopIndex);
outPtr->dataSize = outPtr->allocatedSize;
outPtr = outPtr->next;
pgpCopyMemory(&(outSlopBlock[outSlopIndex]),
outPtr->data, blockSize - outSlopIndex);
outDataIndex = blockSize - outSlopIndex;
}
else
outDataIndex += 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))
{
for (index=0; index<6; index++)
inSlopBlock[index] = index + 2;
padLength = 7;
inSlopBlock[6] = padLength;
inSlopBlock[7] = nextHeader;
err = PGPCBCEncrypt(cbcRef, inSlopBlock, blockSize,
outSlopPtr);
}
if (IsntPGPError(err) && (outSlopPtr == outSlopBlock))
{
outSlopIndex = outPtr->allocatedSize - outDataIndex;
pgpCopyMemory(outSlopBlock,
&(outPtr->data[outDataIndex]), outSlopIndex);
outPtr->dataSize = outPtr->allocatedSize;
outPtr = outPtr->next;
pgpCopyMemory(&(outSlopBlock[outSlopIndex]),
outPtr->data, blockSize - outSlopIndex);
outDataIndex = blockSize - outSlopIndex;
}
else
outDataIndex += blockSize;
}
}
if (IsntPGPError(err))
{
packetSize += padLength + 2 + ESP_HEADERSIZE + blockSize;
outPtr->dataSize = outDataIndex;
}
}
else
{
if (tunnelMode)
PGPCopyIPsecBuffer(memoryMgr, ipPacketIn, 0, ipPacketOut,
espIndex + ESP_HEADERSIZE + blockSize, packetSize - espIndex,
maxBufferSize);
else
PGPCopyIPsecBuffer(memoryMgr, ipPacketIn, espIndex, ipPacketOut,
espIndex + ESP_HEADERSIZE + blockSize, packetSize - espIndex,
maxBufferSize);
padStart = espIndex + ESPHDR_DATA + blockSize + encryptSize;
if (blockSize > 0)
{
padLength = blockSize - ((encryptSize + 2) % blockSize);
if (padLength == 8)
padLength = 0;
}
else
{
padLength = 4 - ((encryptSize + 2) % 4);
if (padLength == 4)
padLength = 0;
}
if (padLength)
{
for (index=0; index<padLength; index++)
padding[index] = index + 1;
}
padding[padLength] = padLength;
padding[padLength + 1] = nextHeader;
tempBuffer.data = padding;
tempBuffer.dataSize = padLength + 2;
tempBuffer.allocatedSize = padLength + 2;
tempBuffer.next = NULL;
PGPCopyIPsecBuffer(memoryMgr, &tempBuffer, 0, ipPacketOut, padStart,
padLength + 2, maxBufferSize);
packetSize += padLength + 2 + ESP_HEADERSIZE + blockSize;
}
if (IsntPGPError(err))
{
tempBuffer.data = headerData;
tempBuffer.dataSize = ESP_HEADERSIZE + blockSize;
tempBuffer.allocatedSize = ESP_HEADERSIZE + blockSize;
tempBuffer.next = NULL;
PGPUInt32ToEndian(spi, kPGPNetworkByteOrder,
&(headerData[ESPHDR_SPI]));
PGPUInt32ToEndian(sequenceNumber, kPGPNetworkByteOrder,
&(headerData[ESPHDR_SEQNUMBER]));
if (IsntNull(iv))
{
pgpCopyMemory(iv, &(headerData[ESPHDR_DATA]), blockSize);
if (IsntNull(outSlopPtr))
pgpCopyMemory(outSlopPtr, iv, blockSize);
}
else
pgpCopyMemory(nullIV, &(headerData[ESPHDR_DATA]), blockSize);
PGPCopyIPsecBuffer(memoryMgr, &tempBuffer, 0, ipPacketOut, espIndex,
ESP_HEADERSIZE + blockSize, ESP_HEADERSIZE + blockSize);
err = pgpAddProtocolToIPHeader(ipPacketIn, ESP_PROTOCOL,
ipPacketOut);
if (tunnelMode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -