📄 pgpsecsh.c
字号:
{
if( PGPCFBContextRefIsValid( session->readCipherCFB ) )
{
PGPCFBDecrypt( session->readCipherCFB, buffer, bufLength, buffer );
} else if( PGPCBCContextRefIsValid( session->readCipherCBC ) ) {
PGPCBCDecrypt( session->readCipherCBC, buffer, bufLength, buffer );
}
}
/* Verify CRC */
sCalculateCRC( buffer, bufLength - kPGPsecsh_CRCSize, crcCheck );
if( !pgpMemoryEqual( crcCheck, buffer + bufLength - kPGPsecsh_CRCSize,
kPGPsecsh_CRCSize ) )
{
(void)pgpSECSHAlert( session, kPGPsecsh_AL_FatalAlert,
kPGPsecsh_AT_BadRecordCRC );
FATALSECSH( kPGPError_SECSHProtocolViolation );
}
*outBuffer = (PGPByte *) PGPNewData(session->memMgr,
length - 1 - kPGPsecsh_CRCSize, 0 );
CKNULL( *outBuffer );
pgpCopyMemory( buffer + padLength + 1, *outBuffer, length - kPGPsecsh_CRCSize );
*outType = buffer[padLength];
*outLength = length - 1 - kPGPsecsh_CRCSize;
done:
if( IsntNull( buffer ) )
{
(void)PGPFreeData( buffer );
}
return err;
}
PGPError
pgpSECSHReceiveServerVersion(
PGPsecshSessionPriv * session,
PGPByte * outMajor,
PGPByte * outMinor )
{
PGPError err = kPGPError_NoErr;
PGPError rerr = kPGPError_NoErr;
PGPByte buffer[kPGPsecsh_MaximumIDStringSize];
PGPByte * bp0;
PGPByte * bp1;
PGPByte * bp2;
PGPSize rcvd;
PGPByte major;
PGPByte minor;
PGPInt32 bytesRead;
*outMajor = 0;
*outMinor = 0;
rcvd = sizeof(buffer) - 1;
err = pgpSECSHExtractRawData( session, buffer, &rcvd ); CKERR;
buffer[rcvd] = '\0';
while( IsNull( bp0 = strchr( buffer, '\n' ) ) )
{
bytesRead = (session->secshReceiveProc)( session->secshReceiveUserData,
buffer + rcvd,
(PGPInt32)( sizeof(buffer) - 1 - rcvd ) );
if( bytesRead < 0 )
{
if( bytesRead != kPGPError_SECSHWouldBlock )
{
FATALSECSH( kPGPError_SECSHUnexpectedClose );
}
else
{
rerr = kPGPError_SECSHWouldBlock;
bytesRead = 0;
}
}
if( bytesRead == 0 )
{
if( session->blocking )
{
FATALSECSH( kPGPError_SECSHUnexpectedClose );
}
else
{
if( rcvd )
{
err = pgpSECSHBufferRawData( session, buffer, rcvd ); CKERR;
if(rerr == kPGPError_SECSHWouldBlock)
/* check to see if receive call returned a blocking error */
{
err = kPGPError_SECSHWouldBlock;
}
}
else if(rerr == kPGPError_SECSHWouldBlock)
/* check for blocking error */
{
err = kPGPError_SECSHWouldBlock;
}
goto done;
}
}
rcvd += bytesRead;
buffer[rcvd] = '\0';
}
if( !pgpMemoryEqual( buffer, SECSHIDPREFIX, strlen(SECSHIDPREFIX) )
|| IsNull( bp2 = strchr( buffer, '.' ) ) )
{
(void)pgpSECSHAlert( session, kPGPsecsh_AL_FatalAlert,
kPGPsecsh_AT_IDFailure );
FATALSECSH( kPGPError_SECSHProtocolViolation );
}
if( rcvd > (PGPSize)(bp0 - buffer + 1) )
{
err = pgpSECSHBufferRawData( session, bp0 + 1,
rcvd - (bp0 - buffer + 1) ); CKERR;
}
bp1 = buffer + strlen( SECSHIDPREFIX );
major = atoi( bp1 );
minor = atoi( bp2 + 1 );
*outMajor = major;
*outMinor = minor;
done:
return err;
}
PGPError
pgpSECSHSendQueueIdleInternal(
PGPsecshSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPInt32 serr;
if( IsntNull( session->queuedSendData ) && ( session->queuedSendSize > 0 ) )
{
serr = (session->secshSendProc)( session->secshSendUserData,
session->queuedSendData,
(PGPInt32) session->queuedSendSize );
if( serr == kPGPError_SECSHWouldBlock )
{
err = kPGPError_SECSHWouldBlock;
}
else if( serr == (PGPInt32) session->queuedSendSize )
{
session->queuedSendSize = 0;
err = PGPReallocData( session->memMgr,
(void **) &session->queuedSendData, 0, 0 ); CKERR;
}
else
FATALSECSH( kPGPError_SECSHUnexpectedClose );
}
done:
return err;
}
PGPError
pgpSECSHSendPacket(
PGPsecshSessionPriv * session,
PGPByte pktType,
const PGPByte * inBuffer,
PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPByte * buffer = NULL;
PGPSize bufLength = 0,
padLength = 0,
bufOff = 0;
PGPInt32 serr = 0;
PGPValidatePtr( inBuffer );
if( inLength+1 > kPGPsecsh_MaximumPacketSize )
{
err = kPGPError_BufferTooSmall;
goto done; /* non-fatal */
}
padLength = 8 - ((inLength+5) & 7);
bufLength = padLength + 1 + inLength + kPGPsecsh_CRCSize;
bufOff = sizeof(PGPUInt32); /* skip past length */
buffer = (PGPByte *) PGPNewData(session->memMgr, bufLength+bufOff, 0 );
CKNULL( buffer );
/* Store length */
PGPUInt32ToEndian( 1+inLength+kPGPsecsh_CRCSize, kPGPBigEndian, buffer );
/* Store padding and packet type */
PGPContextGetRandomBytes( session->pgpContext, buffer+bufOff, padLength );
buffer[bufOff+padLength] = pktType;
/* Store data */
pgpCopyMemory( inBuffer, buffer+bufOff+padLength+1, inLength );
sCalculateCRC( buffer+bufOff, bufLength - kPGPsecsh_CRCSize,
buffer + bufOff + bufLength - kPGPsecsh_CRCSize );
if( session->encrypting )
{
if( PGPCFBContextRefIsValid( session->writeCipherCFB ) )
{
PGPCFBEncrypt( session->writeCipherCFB, buffer+bufOff,
bufLength, buffer+bufOff );
} else if( PGPCBCContextRefIsValid( session->writeCipherCBC ) ) {
PGPCBCEncrypt( session->writeCipherCBC, buffer+bufOff,
bufLength, buffer+bufOff );
}
}
err = pgpSECSHSendQueueIdleInternal( session );
if( err == kPGPError_SECSHWouldBlock )
serr = err;
if( IsntPGPError( err ) && ( bufLength > 0 ) )
{
if( serr != kPGPError_SECSHWouldBlock )
serr = (session->secshSendProc)( session->secshSendUserData,
buffer, (PGPInt32)(bufLength+bufOff) );
if( serr == kPGPError_SECSHWouldBlock )
{
err = pgpSECSHBufferSendData( session, buffer, bufLength+bufOff ); CKERR;
err = kPGPError_SECSHWouldBlock;
}
else if( (PGPSize)serr != bufLength+bufOff )
FATALSECSH( kPGPError_SECSHUnexpectedClose );
}
done:
if( IsntNull( buffer ) )
(void)PGPFreeData( buffer );
return err;
}
PGPError
pgpSECSHSendRawData(
PGPsecshSessionPriv * session,
const PGPByte * inBuffer,
PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPInt32 serr = 0;
PGPValidatePtr( inBuffer );
if( inLength > kPGPsecsh_MaximumPacketSize )
{
err = kPGPError_BufferTooSmall;
goto done; /* non-fatal */
}
err = pgpSECSHSendQueueIdleInternal( session );
if( err == kPGPError_SECSHWouldBlock )
serr = err;
if( IsntPGPError( err ) && ( inLength > 0 ) )
{
if( serr != kPGPError_SECSHWouldBlock )
serr = (session->secshSendProc)( session->secshSendUserData,
inBuffer, (PGPInt32) inLength );
if( serr == kPGPError_SECSHWouldBlock )
{
err = pgpSECSHBufferSendData( session, inBuffer, inLength ); CKERR;
err = kPGPError_SECSHWouldBlock;
}
else if( (PGPSize)serr != inLength )
FATALSECSH( kPGPError_SECSHUnexpectedClose );
}
done:
return err;
}
PGPError
pgpSECSHSendSessionKey(
PGPsecshSessionPriv * session)
{
PGPByte * sessionKey = NULL;
PGPCipherAlgorithm cipher;
PGPSize sbufSize;
PGPSize lbufSize;
PGPPublicKeyContextRef smallContext;
PGPPublicKeyContextRef largeContext;
PGPByte * sBuffer = NULL;
PGPByte * lBuffer = NULL;
PGPUInt32 lbufOff;
PGPUInt16 lbufBits;
PGPByte * payload = NULL;
PGPSize payloadLen;
PGPUInt32 payOff;
PGPByte iv[16];
PGPInt32 i;
PGPSymmetricCipherContextRef
symContext;
PGPError err = kPGPError_NoErr;
err = pgpSECSHClientChooseAlgorithm( session, &cipher ); CKERR;
sessionKey = (PGPByte *)PGPNewSecureData( session->memMgr, kPGPsecsh_SessionKeySize, 0 );
CKNULL( sessionKey );
PGPContextGetRandomBytes( session->pgpContext, sessionKey, kPGPsecsh_SessionKeySize );
PGPGetPublicKeyOperationSizes( session->remoteServerKeyContext, NULL,
&sbufSize, NULL );
PGPGetPublicKeyOperationSizes( session->remoteHostKeyContext, NULL,
&lbufSize, NULL );
if( sbufSize < lbufSize )
{
smallContext = session->remoteServerKeyContext;
largeContext = session->remoteHostKeyContext;
} else {
PGPUInt32 t = sbufSize; sbufSize = lbufSize; lbufSize = t;
smallContext = session->remoteHostKeyContext;
largeContext = session->remoteServerKeyContext;
}
sBuffer = (PGPByte *)PGPNewData( session->memMgr, sbufSize, 0 ); CKNULL( sBuffer );
lBuffer = (PGPByte *)PGPNewData( session->memMgr, lbufSize, 0 ); CKNULL( lBuffer );
err = PGPPublicKeyEncrypt( smallContext, sessionKey, kPGPsecsh_SessionKeySize,
sBuffer, &sbufSize ); CKERR;
err = PGPPublicKeyEncrypt( largeContext, sBuffer, sbufSize, lBuffer,
&lbufSize ); CKERR;
lbufBits = sCountBits( lBuffer, lbufSize, &lbufOff );
payloadLen = 1 + kPGPsecsh_CookieSize + sizeof(PGPUInt16)
+ lbufSize-lbufOff + sizeof(PGPUInt32);
payload = (PGPByte *)PGPNewData( session->memMgr, payloadLen, 0 ); CKNULL( payload );
payOff = 0;
payload[payOff++] = (cipher==kPGPCipherAlgorithm_IDEA) ? kPGPsecsh_CT_IDEA
: kPGPsecsh_CT_3DES;
pgpCopyMemory( session->cookie, payload+payOff, kPGPsecsh_CookieSize );
payOff += kPGPsecsh_CookieSize;
PGPUInt16ToEndian( lbufBits, kPGPBigEndian, payload+payOff );
payOff += sizeof( PGPUInt16 );
pgpCopyMemory( lBuffer+lbufOff, payload+payOff, lbufSize-lbufOff );
payOff += lbufSize - lbufOff;
PGPUInt32ToEndian( session->localProtocolFlags, kPGPBigEndian, payload+payOff );
payOff += sizeof( PGPUInt32 );
pgpAssert( payOff == payloadLen );
err = pgpSECSHSendPacket( session, kPGPsecsh_CMsg_SessionKey, payload, payloadLen ); CKERR;
/* Done with host key encryption */
(void) PGPFreePublicKeyContext( session->remoteHostKeyContext );
(void) PGPFreePublicKeyContext( session->remoteServerKeyContext );
session->remoteHostKeyContext = kInvalidPGPPublicKeyContextRef;
session->remoteServerKeyContext = kInvalidPGPPublicKeyContextRef;
/* Set up IV and keys for symmetric encryption */
pgpClearMemory( iv, sizeof( iv ) );
for( i=0; i<kPGPsecsh_SessionIDSize; ++i )
{
sessionKey[i] ^= session->sessionID[i];
}
if( cipher == kPGPCipherAlgorithm_IDEA )
{
err = PGPNewSymmetricCipherContext( session->pgpContext,
kPGPCipherAlgorithm_IDEA,
&symContext ); CKERR;
err = PGPNewCFBContext( symContext, 1, &session->writeCipherCFB ); CKERR;
symContext = kInvalidPGPSymmetricCipherContextRef;
err = PGPInitCFB( session->writeCipherCFB, sessionKey, iv ); CKERR;
err = PGPNewSymmetricCipherContext( session->pgpContext,
kPGPCipherAlgorithm_IDEA,
&symContext ); CKERR;
err = PGPNewCFBContext( symContext, 1, &session->readCipherCFB ); CKERR;
symContext = kInvalidPGPSymmetricCipherContextRef;
err = PGPInitCFB( session->readCipherCFB, sessionKey, iv ); CKERR;
} else {
pgpAssert( 0 );
}
session->encrypting = TRUE;
done:
if( PGPSymmetricCipherContextRefIsValid( symContext ) )
PGPFreeSymmetricCipherContext( symContext );
if( IsntNull( sessionKey ) )
PGPFreeData( sessionKey );
if( IsntNull( payload ) )
PGPFreeData( payload );
if( IsntNull( sBuffer ) )
PGPFreeData( sBuffer );
if( IsntNull( lBuffer ) )
PGPFreeData( lBuffer );
return err;
}
PGPError
pgpSECSHSendUserName(
PGPsecshSessionPriv * session)
{
PGPByte * payload = NULL;
PGPUInt32 payOff = 0;
PGPSize payloadSize;
PGPUInt32 nameLen;
PGPError err = kPGPError_NoErr;
nameLen = strlen( session->userName );
payloadSize = sizeof(PGPUInt32) + nameLen;
payload = (PGPByte *)PGPNewData( session->memMgr, payloadSize, 0 );
CKNULL( payload );
PGPUInt32ToEndian( nameLen, kPGPBigEndian, payload+payOff );
payOff += sizeof( PGPUInt32 );
pgpCopyMemory( session->userName, payload+payOff, nameLen );
payOff += nameLen;
pgpAssert( payOff == payloadSize );
err = pgpSECSHSendPacket( session, kPGPsecsh_CMsg_User, payload, payloadSize ); CKERR;
done:
if( IsntNull( payload ) )
PGPFreeData( payload );
return err;
}
PGPError
pgpSECSHSendRSAChallengeRequest(
PGPsecshSessionPriv * session)
{
void * vbuf;
PGPByte * mbuf = NULL;
PGPSize mbufSize;
PGPUInt16 mbufBits;
PGPError err = kPGPError_NoErr;
/* Send modulus of local authentication key */
err = PGPGetKeyDBObjAllocatedDataProperty( session->localKey,
kPGPKeyProperty_KeyData,
&vbuf, &mbufSize ); CKERR;
mbuf = vbuf;
mbufBits = (mbuf[0] << 8) | mbuf[1];
mbufSize = 2 + ((mbufBits + 7) / 8);
err = pgpSECSHSendPacket( session, kPGPsecsh_CMsg_AuthRSA, mbuf, mbufSize ); CKERR;
done:
if( IsntNull( mbuf ) )
PGPFreeData( mbuf );
return err;
}
PGPError
pgpSECSHSendRSAResponse(
PGPsecshSessionPriv * session,
const PGPByte * inChallenge,
PGPSize inLength )
{
PGPPrivateKeyContextRef privKeyCon = kInvalidPGPPrivateKeyContextRef;
PGPPublicKeyMessageFormat format;
PGPSize bufSize;
PGPByte * decryptBuf = NULL;
PGPByte * payload = NULL;
PGPHashContextRef handshakeMD5 = kInvalidPGPHashContextRef;
PGPError err;
format = kPGPPublicKeyMessageFormat_PKCS1;
err = PGPNewPrivateKeyContext( PGPPeekKeyDBObjKey( session->localKey ),
format, &privKeyCon, session->localKeyUsePasskey ?
PGPOPasskeyBuffer( session->pgpContext, session->localKeyPasskeyBuffer,
session->localKeyPasskeySize ) :
PGPOPassphrase( session->pgpContext, session->localKeyPassphrase ),
PGPOLastOption( session->pgpContext ) ); CKERR;
err = PGPGetPrivateKeyOperationSizes( privKeyCon, &bufSize, NULL, NULL ); CKERR;
decryptBuf = (PGPByte *)PGPNewData( session->memMgr, bufSize, 0 );
CKNULL( decryptBuf );
err = PGPPrivateKeyDecrypt( privKeyCon, inChallenge, inLength, decryptBuf,
&bufSize ); CKERR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -