📄 pgptls.c
字号:
*outBuffer = NULL;
*outBufferLen = 0;
v2CipherSuiteLen = (inBuffer[0] << 8) | inBuffer[1];
v2SessionIDLen = (inBuffer[2] << 8) | inBuffer[3];
v2RandomLen = (inBuffer[4] << 8) | inBuffer[5];
if( v2CipherSuiteLen + v2SessionIDLen + v2RandomLen + 6ul != inBufferLen )
{
err = kPGPError_BufferTooSmall;
goto done;
}
/* 2 + 32 + 1 + (2 + # cipher suites * 2) + (1 + # compression methods) */
v3HelloPacketLen = 38 + (v2CipherSuiteLen / 3) * 2;
buffer = (PGPByte *) pgpContextMemAlloc(session->pgpContext,
v3HelloPacketLen + 4, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
offset = 0;
buffer[offset++] = kPGPtls_HT_ClientHello;
/* Skip the packet length */
packetLenOffset = offset;
offset += 3;
buffer[offset++] = session->sslv2MajorVersion;
buffer[offset++] = session->sslv2MinorVersion;
/* Copy over random data. Use low 32 bytes of v2, right justified, */
/* zero filled. */
pgpFillMemory(&buffer[offset], 32, 0);
if( v2RandomLen <= 32 )
pgpCopyMemory(&inBuffer[6 + v2CipherSuiteLen + v2SessionIDLen],
&buffer[offset + (32 - v2RandomLen)], v2RandomLen);
else
pgpCopyMemory(&inBuffer[6 + v2CipherSuiteLen + v2SessionIDLen],
&buffer[offset + 32], 32);
offset += 32;
/* Always use a zero session ID. */
buffer[offset++] = 0;
/* Hold a spot for the cipher suite length */
cipherSuiteLenOffset = offset;
offset += 2;
/* Translate the cipher suites. */
for( i = 0; i < v2CipherSuiteLen; i += 3 )
{
if( inBuffer[6 + i] == 0x00 )
{
buffer[offset++] = inBuffer[6 + i + 1];
buffer[offset++] = inBuffer[6 + i + 2];
}
else if( inBuffer[6 + i] == 0x01 && inBuffer[6 + i + 1] == 0x00 &&
inBuffer[6 + i + 2] == 0x80 )
{
/* SSL_RSA_WITH_RC4_128_MD5 */
buffer[offset++] = 0x00;
buffer[offset++] = 0x04;
}
else if( inBuffer[6 + i] == 0x02 && inBuffer[6 + i + 1] == 0x00 &&
inBuffer[6 + i + 2] == 0x80 )
{
/* SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
buffer[offset++] = 0x00;
buffer[offset++] = 0x03;
}
else if( inBuffer[6 + i] == 0x04 && inBuffer[6 + i + 1] == 0x00 &&
inBuffer[6 + i + 2] == 0x80 )
{
/* SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */
buffer[offset++] = 0x00;
buffer[offset++] = 0x06;
}
}
/* Now that we know the length, place it before the ciphers. */
cipherSuiteLen = offset - cipherSuiteLenOffset - 2;
buffer[cipherSuiteLenOffset] = cipherSuiteLen >> 8;
buffer[cipherSuiteLenOffset + 1] = cipherSuiteLen & 0xff;
/* Use zero compression methods. */
buffer[offset++] = 0;
/* Fill in the whole packet length */
buffer[packetLenOffset] = (offset >> 16) & 0xff;
buffer[packetLenOffset + 1] = (offset >> 8) & 0xff;
buffer[packetLenOffset + 2] = offset & 0xff;
*outBuffer = buffer;
*outBufferLen = offset;
done:
if( IsPGPError( err ) && IsntNull( buffer ) )
{
(void)pgpContextMemFree( session->pgpContext, buffer );
*outBuffer = NULL;
*outBufferLen = 0;
}
return err;
}
#endif
PGPError
pgpTLSReceiveHandshakePacket(
PGPtlsSessionPriv * session,
PGPByte * outType,
PGPByte ** outBuffer,
PGPSize * outLength )
{
PGPError err = kPGPError_NoErr;
PGPByte rcvdType;
PGPByte * buffer = NULL;
PGPSize rcvdLen = 0,
pktLen = 0;
#ifdef PGPTLS_SSL_V2_CLIENT_HELLO
PGPByte * v2Buffer = NULL;
PGPUInt32 v2BufferLen = 0;
#endif
*outType = 0;
*outBuffer = NULL;
*outLength = 0;
if( session->handDataSize > 0 )
{
err = pgpTLSExtractHandData( session, &buffer, &rcvdLen ); CKERR;
rcvdType = kPGPtls_RT_Handshake;
}
else
{
nextPkt:
err = pgpTLSReceiveRecordLayer( session, &rcvdType, &buffer, &rcvdLen );
}
if( IsPGPError( err ) || IsNull( buffer ) )
goto done;
if( rcvdType == kPGPtls_RT_Alert )
{
err = pgpTLSProcessAlert( session, buffer, rcvdLen ); CKERR;
(void)pgpContextMemFree( session->pgpContext, buffer );
buffer = NULL;
goto nextPkt;
}
else if( rcvdType == kPGPtls_RT_ChangeCipherSpec )
{
pgpTLSNextState( session, kPGPtls_EV_ReceiveChangeCipherSpec );
if( ( rcvdLen == 1 ) && ( buffer[0] == 1 ) &&
( session->readActive == NULL ) &&
( session->state != kPGPtls_FatalErrorState ) &&
( session->isClientSide ? IsntNull( session->serverPending ) :
IsntNull( session->clientPending ) ) )
{
err = pgpTLSActivateReadKeys( session ); CKERR;
(void)pgpContextMemFree( session->pgpContext, buffer );
buffer = NULL;
goto nextPkt;
}
else
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_UnexpectedMessage );
FATALTLS( kPGPError_TLSProtocolViolation );
}
}
else if( rcvdType != kPGPtls_RT_Handshake )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_UnexpectedMessage );
FATALTLS( kPGPError_TLSProtocolViolation );
}
err = pgpTLSExtractHandData( session, &buffer, &rcvdLen ); CKERR;
#ifdef PGPTLS_SSL_V2_CLIENT_HELLO
if( session->sslv2Hello )
{
PGPByte * v3Buffer;
v2BufferLen = rcvdLen + 3;
err = pgpConvertV2HelloToV3Hello(session, buffer, rcvdLen, &v3Buffer,
&rcvdLen); CKERR;
v2Buffer = (PGPByte *) pgpContextMemAlloc(session->pgpContext,
v2BufferLen, 0 );
if( IsNull( v2Buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
v2Buffer[0] = 0x01;
v2Buffer[1] = session->sslv2MajorVersion;
v2Buffer[2] = session->sslv2MinorVersion;
pgpCopyMemory( buffer, &v2Buffer[3], v2BufferLen );
(void)pgpContextMemFree( session->pgpContext, buffer );
buffer = v3Buffer;
/* Count the header info in the received size. */
rcvdLen += 4;
}
#endif
pktLen = ( buffer[1] << 16 ) | ( buffer[2] << 8 ) | buffer[3];
if( pktLen + 4 > rcvdLen )
{
/* handshake packet is fragmented */
err = pgpTLSBufferHandData( session, buffer, rcvdLen ); CKERR;
goto nextPkt;
}
if( pktLen + 4 < rcvdLen )
{
/* multiple handshake packets were in the record packet */
err = pgpTLSBufferHandData( session, buffer + pktLen + 4,
rcvdLen - pktLen - 4 ); CKERR;
}
if( buffer[0] != kPGPtls_HT_HelloRequest )
{
if( ( buffer[0] == kPGPtls_HT_Finished ) ||
( buffer[0] == kPGPtls_HT_CertificateVerify ) )
{
if( PGPHashContextRefIsValid( session->lastHandSHA ) ||
PGPHashContextRefIsValid( session->lastHandMD5 ) )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_UnexpectedMessage );
FATALTLS( kPGPError_TLSProtocolViolation );
}
err = PGPCopyHashContext( session->handshakeSHA,
&session->lastHandSHA); CKERR;
err = PGPCopyHashContext( session->handshakeMD5,
&session->lastHandMD5); CKERR;
}
#ifdef PGPTLS_SSL_V2_CLIENT_HELLO
if( session->sslv2Hello )
{
(void)PGPContinueHash( session->handshakeMD5, v2Buffer, v2BufferLen );
(void)PGPContinueHash( session->handshakeSHA, v2Buffer, v2BufferLen );
}
else
{
#endif
(void)PGPContinueHash( session->handshakeMD5, buffer, pktLen + 4 );
(void)PGPContinueHash( session->handshakeSHA, buffer, pktLen + 4 );
#ifdef PGPTLS_SSL_V2_CLIENT_HELLO
}
#endif
}
*outType = buffer[0];
*outBuffer = buffer;
*outLength = pktLen;
pgpCopyMemory( buffer + 4, buffer, pktLen );
done:
#ifdef PGPTLS_SSL_V2_CLIENT_HELLO
session->sslv2Hello = 0;
if( IsntNull( v2Buffer ) )
(void)pgpContextMemFree( session->pgpContext, v2Buffer );
#endif
if( IsPGPError( err ) && IsntNull( buffer ) )
(void)pgpContextMemFree( session->pgpContext, buffer );
return err;
}
PGPError
pgpTLSProcessAlert(
PGPtlsSessionPriv * session,
PGPByte * inBuffer,
PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPByte alertType;
PGPByte alertLevel;
if( inLength != 2 )
FATALTLS( kPGPError_TLSProtocolViolation );
alertLevel = inBuffer[0];
alertType = inBuffer[1];
/* Treat all alerts as fatal except close_notify and no_certificate */
if( alertType == kPGPtls_AT_CloseNotify )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_WarningAlert,
kPGPtls_AT_CloseNotify );
session->state = kPGPtls_ClosedState;
}
else if( alertType == kPGPtls_AT_NoCertificate )
{
pgpTLSNextState( session, kPGPtls_EV_ReceiveNoCertificate );
if( !session->isClientSide )
session->certRequested = FALSE;
}
else
{
session->fatalAlert = (PGPtlsAlert)alertType;
#ifdef PGPTLS_DEBUG
pgpAssert( 0 );
#endif
pgpTLSNextState( session, kPGPtls_EV_ReceiveFatalAlert );
}
if( session->state == kPGPtls_FatalErrorState )
err = kPGPError_TLSAlertReceived;
done:
return err;
}
PGPError
pgpTLSSendRecordLayer(
PGPtlsSessionPriv * session,
const PGPByte inType,
const PGPByte * inBuffer,
const PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPByte * buffer = NULL;
PGPSize bufLen = 0,
payloadLen = 0,
padLen = 0;
PGPInt32 serr = 0;
PGPValidatePtr( inBuffer );
if( inLength > kPGPtls_MaximumPacketSize )
{
err = kPGPError_BufferTooSmall;
goto done; /* non-fatal */
}
pgpAssert( ( inType == kPGPtls_RT_ChangeCipherSpec ) ||
( inType == kPGPtls_RT_Alert ) ||
( inType == kPGPtls_RT_Handshake ) ||
( inType == kPGPtls_RT_ApplicationData ) );
if( IsntNull( session->writeActive ) )
{
if( PGPCBCContextRefIsValid( session->writeCipher ) )
{
padLen = (kPGPtls_CipherBlockSize -
((inLength + session->hashSize + 1) %
kPGPtls_CipherBlockSize ) );
if( padLen == kPGPtls_CipherBlockSize )
padLen = 0;
bufLen += padLen + 1;
}
bufLen += session->hashSize;
}
bufLen += kPGPtls_RecordHeaderSize + inLength;
payloadLen = bufLen - kPGPtls_RecordHeaderSize;
buffer = PGPNewData( session->memMgr, bufLen, kPGPMemoryMgrFlags_Clear );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
buffer[0] = inType;
buffer[1] = kPGPtls_MajorVersion;
buffer[2] = session->minorVersion;
PGPUInt16ToEndian( (PGPUInt16) payloadLen, kPGPBigEndian, &buffer[3] );
pgpCopyMemory( inBuffer, &buffer[kPGPtls_RecordHeaderSize], inLength );
if( IsntNull( session->writeActive ) )
{
err = pgpTLSCalculateMAC( session, TRUE, inType, inBuffer, inLength,
buffer + inLength + kPGPtls_RecordHeaderSize ); CKERR;
if( PGPCBCContextRefIsValid( session->writeCipher ) )
{
if( padLen )
pgpFillMemory( buffer + inLength + session->hashSize +
kPGPtls_RecordHeaderSize, padLen + 1, padLen );
err = PGPCBCEncrypt( session->writeCipher,
buffer + kPGPtls_RecordHeaderSize, payloadLen,
buffer + kPGPtls_RecordHeaderSize );CKERR;
}
}
err = pgpTLSSendQueueIdleInternal( session );
if( err == kPGPError_TLSWouldBlock )
serr = err;
if( IsntPGPError( err ) && ( bufLen > 0 ) )
{
if( serr != kPGPError_TLSWouldBlock )
serr = (session->tlsSendProc)( session->tlsSendUserData,
buffer, (PGPInt32) bufLen );
if( serr == kPGPError_TLSWouldBlock )
{
err = pgpTLSBufferSendData( session, buffer, bufLen ); CKERR;
err = kPGPError_TLSWouldBlock;
}
else if( (PGPSize)serr != bufLen )
FATALTLS( kPGPError_TLSUnexpectedClose );
}
done:
if( IsntNull( buffer ) )
(void)PGPFreeData( buffer );
return err;
}
PGPError
pgpTLSSendHandshakePacket(
PGPtlsSessionPriv * session,
const PGPByte inType,
const PGPByte * inBuffer,
const PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPByte * buffer = NULL;
PGPByte prefix[4];
PGPUInt16 pktLen;
pktLen = inLength + sizeof(prefix);
prefix[0] = inType;
prefix[1] = 0; /* 24 bit length first byte */
PGPUInt16ToEndian( (PGPUInt16) inLength, kPGPBigEndian, &prefix[2] );
buffer = (PGPByte *) pgpContextMemAlloc( session->pgpContext, pktLen, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( prefix, buffer, sizeof(prefix) );
if( IsntNull( inBuffer ) )
pgpCopyMemory( inBuffer, buffer + sizeof(prefix), inLength );
if( inType != kPGPtls_HT_HelloRequest )
{
(void)PGPContinueHash(session->handshakeMD5, buffer, pktLen);
(void)PGPContinueHash(session->handshakeSHA, buffer, pktLen);
}
err = pgpTLSSendRecordLayer( session, kPGPtls_RT_Handshake,
buffer, pktLen ); CKERR;
done:
if( IsntNull( buffer ) )
(void)pgpContextMemFree( session->pgpContext, buffer );
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -