📄 pgptls.c
字号:
PGPError
pgpTLSSendAlert(
PGPtlsSessionPriv * session,
PGPByte level,
PGPtlsAlert type )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[32];
PGPSize pktLen = 0;
buffer[0] = level;
buffer[1] = type;
pktLen = 2;
err = pgpTLSSendRecordLayer( session, kPGPtls_RT_Alert, buffer, pktLen );
if( level == kPGPtls_AL_FatalAlert )
{
session->state = kPGPtls_FatalErrorState;
session->fatalAlert = type;
}
return err;
}
PGPError
pgpTLSSendClientHello(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[384];
PGPUInt16 suiteIndex,
pktLen = 0;
/* client_version */
buffer[pktLen++] = kPGPtls_MajorVersion;
#ifdef PGPTLS_FORCESSL3
buffer[pktLen++] = kPGPtls_SSL3MinorVersion;
#else
buffer[pktLen++] = kPGPtls_MinorVersion; /* always latest version */
#endif
/* random */
*((PGPUInt32 *)&session->cRandom[0]) = PGPGetTime();
err = PGPContextGetRandomBytes( session->pgpContext,
&session->cRandom[4],
kPGPtls_RandomSeedSize ); CKERR;
pgpCopyMemory( session->cRandom, &buffer[pktLen], kPGPtls_RandomSize );
pktLen += kPGPtls_RandomSize;
/* session ID ##### */
buffer[pktLen++] = 0;
/* cipher_suites */
PGPUInt16ToEndian( (PGPUInt16)( session->numCipherSuites * 2 ),
kPGPBigEndian, &buffer[pktLen] );
pktLen += sizeof(PGPUInt16);
for( suiteIndex = 0; suiteIndex < session->numCipherSuites; suiteIndex++ )
{
buffer[pktLen++] = session->cipherSuites[suiteIndex].id[0];
buffer[pktLen++] = session->cipherSuites[suiteIndex].id[1];
}
/* compression_methods */
buffer[pktLen++] = 1;
buffer[pktLen++] = kPGPtls_CT_None;
pgpAssert( pktLen < sizeof(buffer) );
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ClientHello,
buffer, pktLen );
done:
return err;
}
PGPError
pgpTLSSendServerHello(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[128];
PGPUInt16 pktLen = 0;
/* server_version */
buffer[pktLen++] = kPGPtls_MajorVersion;
buffer[pktLen++] = session->minorVersion;
/* random */
*((PGPUInt32 *)&session->sRandom[0]) = PGPGetTime();
err = PGPContextGetRandomBytes( session->pgpContext,
&session->sRandom[4],
kPGPtls_RandomSeedSize ); CKERR;
pgpCopyMemory( session->sRandom, &buffer[pktLen], kPGPtls_RandomSize );
pktLen += kPGPtls_RandomSize;
/* session_id ##### */
buffer[pktLen++] = 0;
/* cipher_suite */
buffer[pktLen++] = session->cipherSuites[session->cipherSuiteIndex].id[0];
buffer[pktLen++] = session->cipherSuites[session->cipherSuiteIndex].id[1];
/* compression_method */
buffer[pktLen++] = kPGPtls_CT_None;
pgpAssert( pktLen < sizeof(buffer) );
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerHello,
buffer, pktLen );
done:
return err;
}
PGPError
pgpTLSSendCertificate(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte * buffer = NULL;
PGPUInt16 pktLen = 0;
PGPByte * keyBuffer = NULL;
PGPSize keyBufferLen;
if( session->isClientSide && !session->certMatched )
{
if( session->minorVersion == kPGPtls_SSL3MinorVersion )
{
err = pgpTLSSendAlert( session, kPGPtls_AL_WarningAlert,
kPGPtls_AT_NoCertificate ); CKERR;
goto done;
}
else if( !session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
{
buffer = PGPNewData( session->memMgr, 3, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
buffer[pktLen++] = 0;
buffer[pktLen++] = 0;
buffer[pktLen++] = 0;
}
}
else if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
{
pgpAssert( PGPKeyRefIsValid( session->localKey ) );
err = PGPExport( session->pgpContext,
PGPOExportKey( session->pgpContext, session->localKey ),
PGPOAllocatedOutputBuffer( session->pgpContext,
(void **) &keyBuffer, MAX_PGPUInt32, &keyBufferLen ),
PGPOArmorOutput( session->pgpContext, FALSE ),
PGPOLastOption( session->pgpContext ) ); CKERR;
buffer = PGPNewData( session->memMgr, keyBufferLen + 4, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
buffer[0] = ( keyBufferLen >> 16 ) & 0xFF;
buffer[1] = ( keyBufferLen >> 8 ) & 0xFF;
buffer[2] = keyBufferLen & 0xFF;
pgpCopyMemory( keyBuffer, &buffer[3], keyBufferLen );
pktLen = keyBufferLen + 3;
}
else
{
PGPSigRef curCert;
pgpAssert( PGPSigRefIsValid( session->localCert ) );
pktLen = 3;
buffer = PGPNewData( session->memMgr, pktLen, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
curCert = session->localCert;
do
{
err = PGPExport( session->pgpContext,
PGPOExportSig( session->pgpContext, curCert ),
PGPOAllocatedOutputBuffer( session->pgpContext,
(void **) &keyBuffer, MAX_PGPUInt32, &keyBufferLen ),
PGPOExportFormat( session->pgpContext, kPGPExportFormat_X509Cert ),
PGPOLastOption( session->pgpContext ) ); CKERR;
err = PGPReallocData( session->memMgr, (void **) &buffer,
pktLen + keyBufferLen + 3, 0 ); CKERR;
*( buffer + pktLen ) = ( keyBufferLen >> 16 ) & 0xFF;
*( buffer + pktLen + 1 ) = ( keyBufferLen >> 8 ) & 0xFF;
*( buffer + pktLen + 2 ) = keyBufferLen & 0xFF;
pgpCopyMemory( keyBuffer, buffer + pktLen + 3, keyBufferLen );
pktLen += keyBufferLen + 3;
(void)PGPFreeData( keyBuffer );
keyBuffer = NULL;
if( PGPKeySetRefIsValid( session->localCertChain ) )
{
PGPSigRef nextCert;
err = PGPGetSigX509CertifierSig( curCert, session->localCertChain,
&nextCert ); CKERR;
if( nextCert == curCert )
curCert = kInvalidPGPSigRef;
else
curCert = nextCert;
}
else
curCert = kInvalidPGPSigRef;
} while( PGPSigRefIsValid( curCert ) );
{
PGPSize chainLen = pktLen - 3;
buffer[0] = ( chainLen >> 16 ) & 0xFF;
buffer[1] = ( chainLen >> 8 ) & 0xFF;
buffer[2] = chainLen & 0xFF;
}
}
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_Certificate,
buffer, pktLen );
done:
if( IsntNull( buffer ) )
(void)PGPFreeData( buffer );
if( IsntNull( keyBuffer ) )
(void)PGPFreeData( keyBuffer );
return err;
}
PGPError
pgpTLSSendCertVerify(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[640],
sigData[640];
PGPSize pktLen = 0,
sigDataLen;
PGPPrivateKeyContextRef privKeyCon = kInvalidPGPPrivateKeyContextRef;
PGPSize actSigSize;
PGPPublicKeyMessageFormat format;
if( ( session->localKeyAlg == kPGPPublicKeyAlgorithm_DSA ) &&
( session->minorVersion > kPGPtls_SSL3MinorVersion ) )
format = kPGPPublicKeyMessageFormat_X509;
else
format = kPGPPublicKeyMessageFormat_PKCS1;
/* DSS uses ASN.1, RSA uses PKCS1 */
err = PGPNewPrivateKeyContext( session->localKey,
format, &privKeyCon, session->localKeyUsePasskey ?
PGPOPasskeyBuffer( session->pgpContext, session->localKeyPasskeyBuffer,
session->localKeyPasskeySize ) :
PGPOPassphrase( session->pgpContext, session->localKeyPassphrase ),
PGPOLastOption( session->pgpContext ) ); CKERR;
err = pgpTLSCalculateCertVerify( session, sigData, &sigDataLen ); CKERR;
pgpAssert( sigDataLen < sizeof( sigData ) );
/* Create the Signature */
err = PGPPrivateKeySignRaw( privKeyCon, sigData, sigDataLen,
buffer + pktLen + 2, &actSigSize ); CKERR;
PGPUInt16ToEndian( (PGPUInt16) actSigSize, kPGPBigEndian, &buffer[pktLen] );
pktLen += sizeof(PGPUInt16) + actSigSize;
pgpAssert( pktLen < sizeof(buffer) );
err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_CertificateVerify,
buffer, pktLen );
done:
if( PGPPrivateKeyContextRefIsValid( privKeyCon ) )
(void)PGPFreePrivateKeyContext( privKeyCon );
return err;
}
PGPError
pgpTLSSendCertificateRequest(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte buffer[512];
PGPUInt16 pktLen = 1,
numAlgs = 0;
/* allowed ClientCertificateTypes */
if( pubAlgSupported( kPGPPublicKeyAlgorithm_DSA ) )
{
buffer[pktLen++] = kPGPtls_CC_DSASign;
numAlgs ++;
}
if( pubAlgSupported( kPGPPublicKeyAlgorithm_RSA ) )
{
buffer[pktLen++] = kPGPtls_CC_RSASign;
numAlgs ++;
}
buffer[0] = (PGPByte) numAlgs;
/* Clear length field for distinguished name fields */
buffer[pktLen++] = 0;
buffer[pktLen++] = 0;
pgpAssert( pktLen < sizeof(buffer) );
if( IsntPGPError( err ) )
{
err = pgpTLSSendHandshakePacket( session,
kPGPtls_HT_CertificateRequest,
buffer, pktLen );
session->certRequested = TRUE;
}
return err;
}
PGPError
pgpTLSSendServerKeyExchange(
PGPtlsSessionPriv * session )
{
PGPError err = kPGPError_NoErr;
PGPByte * buffer = NULL;
PGPUInt16 pktLen = 0;
PGPByte * secretX = NULL;
PGPPrivateKeyContextRef privKeyCon = kInvalidPGPPrivateKeyContextRef;
PGPSize sigSize,
actSigSize;
PGPHashContextRef skeHashSHA = kInvalidPGPHashContextRef,
skeHashMD5 = kInvalidPGPHashContextRef;
DHPrime * prime;
PGPByte const dhGenerator[1] = { 2 };
PGPUInt32 modBits,
modBytes,
expBytes = 0,
expBits,
pSize,
gSize,
ySSize;
PGPPublicKeyMessageFormat format;
if( ( session->localKeyAlg == kPGPPublicKeyAlgorithm_DSA ) &&
( session->minorVersion > kPGPtls_SSL3MinorVersion ) )
format = kPGPPublicKeyMessageFormat_X509;
else
format = kPGPPublicKeyMessageFormat_PKCS1;
err = PGPNewPrivateKeyContext( 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, NULL, NULL, &sigSize );
CKERR;
switch( session->requestedPrime )
{
case kPGPtls_DHPrime1024:
prime = &DH_1024bitPrime;
break;
case kPGPtls_DHPrime1536:
prime = &DH_1536bitPrime;
break;
default:
case kPGPtls_DHPrime2048:
prime = &DH_2048bitPrime;
break;
case kPGPtls_DHPrime3072:
prime = &DH_3072bitPrime;
break;
case kPGPtls_DHPrime4096:
prime = &DH_4096bitPrime;
break;
}
/* Load up the prime modulus */
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhP ); CKERR;
err = PGPBigNumInsertBigEndianBytes( session->dhP,
prime->prime,
0, prime->length ); CKERR;
/* We always use a generator of 2 for speed */
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhG ); CKERR;
err = PGPBigNumInsertBigEndianBytes( session->dhG,
dhGenerator,
0, sizeof(dhGenerator) ); CKERR;
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;
}
/* Generate the secret random X value */
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;
/* Generate our server Y value */
err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYs ); CKERR;
err = PGPBigNumExpMod( session->dhG, session->dhX, session->dhP,
session->dhYs ); CKERR;
pSize = ( ( PGPBigNumGetSignificantBits( session->dhP ) + 7 ) / 8 );
gSize = ( ( PGPBigNumGetSignificantBits( session->dhG ) + 7 ) / 8 );
ySSize = ( ( PGPBigNumGetSignificantBits( session->dhYs ) + 7 ) / 8 );
buffer = PGPNewData( session->memMgr,
pSize + gSize + ySSize + 8 + sigSize, 0 );
if( IsNull( buffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
/* Write out p */
PGPUInt16ToEndian( (PGPUInt16) pSize, kPGPBigEndian, &buffer[pktLen] );
pktLen += sizeof(PGPUInt16);
err = PGPBigNumExtractBigEndianBytes( session->dhP,
&buffer[pktLen],
0, pSize ); CKERR;
pktLen += pSize;
/* Write out g */
PGPUInt16ToEndian( (PGPUInt16) gSize, kPGPBigEndian, &buffer[pktLen] );
pktLen += sizeof(PGPUInt16);
err = PGPBigNumExtractBigEndianBytes( session->dhG,
&buffer[pktLen],
0, gSize ); CKERR;
pktLen += gSize;
/* Write out yS */
PGPUInt16ToEndian( (PGPUInt16) ySSize, kPGPBigEndian, &buffer[pktLen] );
pktLen += sizeof(PGPUInt16);
err = PGPBigNumExtractBigEndianBytes( session->dhYs,
&buffer[pktLen],
0, ySSize ); CKERR;
pktLen += ySSize;
err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
&skeHashSHA ); CKERR;
(void)PGPContinueHash( skeHashSHA, session->cRandom, kPGPtls_RandomSize);
(void)PGPContinueHash( skeHashSHA, session->sRandom, kPGPtls_RandomSize);
(void)PGPContinueHash( skeHashSHA, buffer, pktLen);
switch( session->cipherSuites[session->cipherSuiteIndex].sigAlg )
{
case kPGPPublicKeyAlgorithm_DSA:
{
PGPByte signedData[ kPGPtls_HA_SHASize ];
/* Create the Signature */
(void)PGPFinalizeHash( skeHashSHA, signedData );
err = PGPPrivateKeySignRaw( privKeyCon, signedData,
kPGPtls_HA_SHASize, buffer + pktLen + 2,
&actSigSize ); CKERR;
PGPUInt16ToEndian( (PGPUInt16) actSigSize, kPGPBigEndian,
&buffer[pktLen] );
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -