📄 pgptls.c
字号:
case kPGPPublicKeyAlgorithm_RSA:
{
PGPByte signedData[kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize];
/* Do the additional MD5 hash for RSA */
err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
&skeHashMD5 ); CKERR;
(void)PGPContinueHash( skeHashMD5, session->cRandom,
kPGPtls_RandomSize);
(void)PGPContinueHash( skeHashMD5, session->sRandom,
kPGPtls_RandomSize);
(void)PGPContinueHash( skeHashMD5, buffer, pktLen);
(void)PGPFinalizeHash( skeHashMD5, signedData );
(void)PGPFinalizeHash( skeHashSHA, signedData +
kPGPtls_HA_MD5Size );
/* Create the Signature */
err = PGPPrivateKeySignRaw( privKeyCon, signedData,
kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize,
buffer + pktLen + 2, &actSigSize ); CKERR;
PGPUInt16ToEndian( (PGPUInt16) actSigSize, kPGPBigEndian,
&buffer[pktLen] );
break;
}
default:
break;
}
pgpAssert( actSigSize <= sigSize );
pktLen += sizeof(PGPUInt16) + actSigSize;
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerKeyExchange,
buffer, pktLen );
done:
if( IsntNull( secretX ) )
(void)PGPFreeData( secretX );
if( IsntNull( buffer ) )
(void)PGPFreeData( buffer );
if( PGPPrivateKeyContextRefIsValid( privKeyCon ) )
(void)PGPFreePrivateKeyContext( privKeyCon );
if( PGPHashContextRefIsValid( skeHashMD5 ) )
(void)PGPFreeHashContext( skeHashMD5 );
if( PGPHashContextRefIsValid( skeHashSHA ) )
(void)PGPFreeHashContext( skeHashSHA );
return err;
}
PGPError
pgpTLSSendClientKeyExchange(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[1024];
PGPUInt16 pktLen = 0,
preMasterSize = 0;
PGPByte * secretX = NULL;
PGPByte * preMaster = NULL;
PGPBigNumRef dhSecret = kPGPInvalidBigNumRef;
PGPPublicKeyContextRef pubKeyCon = kInvalidPGPPublicKeyContextRef;
if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
{
PGPUInt32 modBits,
modBytes,
expBytes = 0,
expBits;
/* Send ClientDiffieHellmanPublic */
modBits = PGPBigNumGetSignificantBits( session->dhP );
modBytes = ( modBits + 7 ) / 8;
(void)PGPDiscreteLogExponentBits(modBits, &expBytes);
expBytes = ( expBytes * 3 / 2 + 7 ) / 8;
expBits = 8 * expBytes;
secretX = PGPNewSecureData( session->memMgr, expBytes, 0 );
if( IsNull( secretX ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
err = PGPContextGetRandomBytes( session->pgpContext, secretX,
expBytes );
CKERR;
secretX[0] |= 0x80;
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhX ); CKERR;
err = PGPBigNumInsertBigEndianBytes(session->dhX, secretX, 0,
expBytes );
CKERR;
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYc ); CKERR;
err = PGPBigNumExpMod( session->dhG, session->dhX, session->dhP,
session->dhYc ); CKERR;
/* Setup outgoing packet, sending client Y with 2 byte length */
PGPUInt16ToEndian( (PGPUInt16) modBytes, kPGPBigEndian, buffer );
err = PGPBigNumExtractBigEndianBytes( session->dhYc,
buffer + sizeof(PGPUInt16),
0, modBytes ); CKERR;
pktLen = modBytes + sizeof(PGPUInt16);
/* Calculate the shared secret */
err = PGPNewBigNum( session->memMgr, TRUE, &dhSecret ); CKERR;
err = PGPBigNumExpMod( session->dhYs, session->dhX, session->dhP,
dhSecret ); CKERR;
/* Load premastersecret with the shared secret */
preMasterSize = modBytes;
preMaster = PGPNewSecureData( session->memMgr, preMasterSize, 0 );
if( IsNull( preMaster ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
(void)PGPBigNumExtractBigEndianBytes( dhSecret, preMaster,
0, modBytes );
}
else
{
PGPSize encSize;
/* Send EncryptedPreMasterSecret */
err = PGPNewPublicKeyContext( session->remoteKey,
kPGPPublicKeyMessageFormat_PKCS1,
&pubKeyCon ); CKERR;
err = PGPGetPublicKeyOperationSizes( pubKeyCon, NULL,
&encSize, NULL );CKERR;
preMasterSize = kPGPtls_MasterSecretSize;
preMaster = PGPNewSecureData( session->memMgr, preMasterSize, 0 );
if( IsNull( preMaster ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
preMaster[0] = kPGPtls_MajorVersion;
#ifdef PGPTLS_FORCESSL3
preMaster[1] = kPGPtls_SSL3MinorVersion;
#else
preMaster[1] = kPGPtls_MinorVersion; /* always latest version */
#endif
err = PGPContextGetRandomBytes( session->pgpContext,
&preMaster[2],
kPGPtls_MasterSecretSize - 2 ); CKERR;
if( session->minorVersion > kPGPtls_SSL3MinorVersion )
{
PGPUInt16ToEndian( (PGPUInt16) encSize, kPGPBigEndian, buffer );
pktLen += sizeof(PGPUInt16);
}
err = PGPPublicKeyEncrypt( pubKeyCon, preMaster, preMasterSize,
buffer + pktLen, &encSize ); CKERR;
pktLen += encSize;
}
pgpAssert( pktLen < sizeof(buffer) );
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ClientKeyExchange,
buffer, pktLen );
/* Calculate the Master Secret */
err = pgpTLSCalculateMasterSecret( session, preMaster, preMasterSize );
done:
if( IsntNull( secretX ) )
(void)PGPFreeData( secretX );
if( IsntNull( preMaster ) )
(void)PGPFreeData( preMaster );
if( dhSecret != kPGPInvalidBigNumRef )
(void)PGPFreeBigNum( dhSecret );
if( PGPPublicKeyContextRefIsValid( pubKeyCon ) )
(void)PGPFreePublicKeyContext( pubKeyCon );
return err;
}
PGPError
pgpTLSSendFinished(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[128];
PGPSize pktLen = 0;
err = pgpTLSCalculateFinished( session, session->isClientSide,
buffer, &pktLen ); CKERR;
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_Finished,
buffer, pktLen );
done:
return err;
}
PGPError
pgpTLSSendFinalHandshake(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
/* Change the cipher spec */
err = pgpTLSSendChangeCipherSpec( session ); CKERR;
/* Activate the pending client keys */
err = pgpTLSActivateWriteKeys( session ); CKERR;
/* Signal that our side of the handshake is complete */
err = pgpTLSSendFinished( session ); CKERR;
done:
return err;
}
PGPError
pgpTLSSendChangeCipherSpec(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[16];
PGPUInt16 pktLen = 0;
buffer[0] = 1;
pktLen = 1;
pgpAssert( pktLen < sizeof(buffer) );
err = pgpTLSSendRecordLayer( session, kPGPtls_RT_ChangeCipherSpec,
buffer, pktLen );
return err;
}
PGPError
pgpTLSReceiveServerHello(
PGPtlsSessionPriv * session,
PGPByte * inBuffer,
const PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPUInt16 pktInx = 0,
suiteIndex;
PGPtlsCipherSuiteID cipherID;
Boolean foundSuite = FALSE;
PGPValidatePtr( inBuffer );
pgpAssert( inLength >= 38 );
if( inLength < 38 )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_DecodeError );
FATALTLS( kPGPError_TLSProtocolViolation );
}
/* server_version */
if( ( inBuffer[pktInx++] != kPGPtls_MajorVersion ) ||
( inBuffer[pktInx] != kPGPtls_MinorVersion &&
inBuffer[pktInx] != kPGPtls_SSL3MinorVersion ) )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_ProtocolVersion );
FATALTLS( kPGPError_TLSVersionUnsupported );
}
session->minorVersion = inBuffer[pktInx++];
/* server_random */
pgpCopyMemory( &inBuffer[pktInx], session->sRandom,
kPGPtls_RandomSize );
pktInx += kPGPtls_RandomSize;
/* session_id */
pktInx += inBuffer[pktInx] + 1; /* skip for now ##### */
/* cipher_suite */
cipherID[0] = inBuffer[pktInx++];
cipherID[1] = inBuffer[pktInx++];
for( suiteIndex = 0; suiteIndex < session->numCipherSuites; suiteIndex++ )
{
if( ( cipherID[0] == session->cipherSuites[suiteIndex].id[0] ) &&
( cipherID[1] == session->cipherSuites[suiteIndex].id[1] ) )
{
session->cipherSuiteIndex = suiteIndex;
foundSuite = TRUE;
break;
}
}
if( !foundSuite )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_InsufficientSecurity );
FATALTLS( kPGPError_TLSProtocolViolation );
}
/* compression_method */
if( inBuffer[pktInx++] != kPGPtls_CT_None )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_DecodeError );
FATALTLS( kPGPError_TLSProtocolViolation );
}
/* do not verify that we have handled all data in this packet,
this packet is allowed to contain data we do not understand. */
done:
return err;
}
PGPError
pgpTLSReceiveClientHello(
PGPtlsSessionPriv * session,
PGPByte * inBuffer,
const PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPUInt16 pktInx = 0,
suiteIndex,
numSuites,
intSuiteIndex;
PGPtlsCipherSuiteID cipherID;
Boolean foundSuite = FALSE;
PGPValidatePtr( inBuffer );
pgpAssert( inLength >= 40 );
if( inLength < 40 )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_DecodeError );
FATALTLS( kPGPError_TLSProtocolViolation );
}
/* client_version */
if( inBuffer[pktInx++] != kPGPtls_MajorVersion )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_ProtocolVersion );
FATALTLS( kPGPError_TLSVersionUnsupported );
}
#ifdef PGPTLS_FORCESSL3
if( inBuffer[pktInx] > kPGPtls_SSL3MinorVersion )
session->minorVersion = kPGPtls_SSL3MinorVersion;
#else
if( inBuffer[pktInx] > kPGPtls_MinorVersion )
session->minorVersion = kPGPtls_MinorVersion;
#endif
else
session->minorVersion = inBuffer[pktInx];
session->originalClientVersion = inBuffer[pktInx];
pktInx++;
/* client_random */
pgpCopyMemory( &inBuffer[pktInx], session->cRandom,
kPGPtls_RandomSize );
pktInx += kPGPtls_RandomSize;
/* session_id */
pktInx += inBuffer[pktInx] + 1; /* skip for now ##### */
/* cipher_suites */
numSuites = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] ) / 2;
pktInx += sizeof(PGPUInt16);
if( pktInx + numSuites * sizeof(PGPUInt16) >= inLength )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_DecodeError );
FATALTLS( kPGPError_TLSProtocolViolation );
}
for( suiteIndex = 0; suiteIndex < numSuites; suiteIndex++ )
{
cipherID[0] = inBuffer[pktInx++];
cipherID[1] = inBuffer[pktInx++];
if( foundSuite )
continue;
for( intSuiteIndex = 0; intSuiteIndex < session->numCipherSuites;
intSuiteIndex++ )
{
if( ( cipherID[0] == session->cipherSuites[intSuiteIndex].id[0] ) &&
( cipherID[1] == session->cipherSuites[intSuiteIndex].id[1] ) )
{
if( session->localKeyAlg ==
session->cipherSuites[intSuiteIndex].sigAlg )
{
session->cipherSuiteIndex = intSuiteIndex;
foundSuite = TRUE;
}
}
}
}
if( !foundSuite )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_InsufficientSecurity );
FATALTLS( kPGPError_TLSNoCommonCipher );
}
/* compression_methods */
/* Nobody actually supports this, it's only in the spec for looks */
pktInx += inBuffer[pktInx];
/* do not verify that we have handled all data in this packet,
this packet is allowed to contain data we do not understand. */
err = pgpTLSSendServerHello( session ); CKERR;
err = pgpTLSSendCertificate( session ); CKERR;
if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
{
err = pgpTLSSendServerKeyExchange( session ); CKERR;
}
if( session->requestCert )
{
err = pgpTLSSendCertificateRequest( session ); CKERR;
}
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerHelloDone,
NULL, 0 ); CKERR;
done:
return err;
}
PGPError
pgpTLSReceiveClientKeyExchange(
PGPtlsSessionPriv * session,
PGPByte * inBuffer,
const PGPSize inLength )
{
PGPError err = kPGPError_NoErr;
PGPUInt16 pktInx = 0;
PGPSize preMasterSize = 0;
PGPBigNumRef dhSecret = kPGPInvalidBigNumRef;
PGPByte * preMaster = NULL;
PGPPrivateKeyContextRef privKeyCon = kInvalidPGPPrivateKeyContextRef;
PGPValidatePtr( inBuffer );
if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
{
PGPUInt32 modBytes,
varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
pktInx += sizeof(PGPUInt16);
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYc ); CKERR;
err = PGPBigNumInsertBigEndianBytes(session->dhYc, &inBuffer[pktInx],
0, varLen ); CKERR;
pktInx += varLen;
if( pktInx != inLength )
{
(void)pgpTLSSendAlert( session, kPGPtls_AL_FatalAlert,
kPGPtls_AT_UnexpectedMessage );
FATALTLS( kPGPError_TLSProtocolViolation );
}
/* Calculate the shared secret */
err = PGPNewBigNum( session->memMgr, TRUE, &dhSecret ); CKERR;
err = PGPBigNumExpMod( session->dhYc, session->dhX, session->dhP,
dhSecret ); CKERR;
/* Load premastersecret with the shared secret */
modBytes = ( PGPBigNumGetSignificantBits( session->dhYc )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -