📄 pgptls.c
字号:
/*____________________________________________________________________________
Copyright (C) 1997-1999 Network Associates, Inc.
All rights reserved.
Platform independent state machine based implementation of
IETF Transport Layer Security 1.0 with support for OpenPGP/TLS.
TLS 1.0 is specified in IETF RFC 2246
$Id: pgpTLS.c,v 1.72.6.1 1999/06/04 00:28:50 heller Exp $
____________________________________________________________________________*/
#define PGPTLS_SSL_V2_CLIENT_HELLO
#define noPGPTLS_FORCESSL3 /* define this for all 6.0.X builds */
#define noPGPTLS_DEBUG
#include "pgpTLSPriv.h"
#include "pgpTLSPrimes.h"
#include "pgpErrors.h"
#include "pgpContext.h"
#include "pgpMem.h"
#include "pgpEndianConversion.h"
#include "pgpHash.h"
#include "pgpHMAC.h"
#include "pgpPublicKey.h"
#include "pgpSymmetricCipher.h"
#include "pgpCBC.h"
#include "pgpKeys.h"
#include "pgpFeatures.h"
#include "pgpOptionListPriv.h"
#include <string.h>
#define CKERR if( err ) goto done
#define FATALTLS( x ) { \
err = x; \
session->state = kPGPtls_FatalErrorState; \
goto done; }
#define TLSNUMCLIENTSTATES 10
#define TLSNUMSERVERSTATES 7
#define TLSNUMEVENTS 15
static PGPInt8 kPGPtls_ClientStateTable[TLSNUMCLIENTSTATES][TLSNUMEVENTS] =
{
/* HR CH SH CE EC SC SKE CR SHD CV CKE FIN FAT NC CC */
{ /* 0 */ -1, -2, 1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 1 */ -1, -2, -2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 2 */ -1, -2, -2, -2, 3, 4, -2, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 3 */ -1, -2, -2, -2, -2, -2, 5, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 4 */ -1, -2, -2, -2, -2, -2, -2, 6, 7, -2, -2, -2, -2, -2, -2 },
{ /* 5 */ -1, -2, -2, -2, -2, -2, -2, 6, 7, -2, -2, -2, -2, -2, -2 },
{ /* 6 */ -1, -2, -2, -2, -2, -2, -2, -2, 7, -2, -2, -2, -2, -2, -2 },
{ /* 7 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 8 },
{ /* 8 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 9, -2, -2, -2 },
{ /* 9 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 }
};
static PGPInt8 kPGPtls_ServerStateTable[TLSNUMSERVERSTATES][TLSNUMEVENTS] =
{
/* HR CH SH CE EC SC SKE CR SHD CV CKE FIN FAT NC CC */
{ /* 0 */ -1, 1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 1 */ -1, -2, -2, 2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2 },
{ /* 2 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2 },
{ /* 3 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, 4, -2, -2, -2, -2, 5 },
{ /* 4 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 5 },
{ /* 5 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 6, -2, -2, -2 },
{ /* 6 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 }
};
static PGPInt8 kPGPtls_SSL3ServerStateTable[TLSNUMSERVERSTATES][TLSNUMEVENTS] =
{
/* HR CH SH CE EC SC SKE CR SHD CV CKE FIN FAT NC CC */
{ /* 0 */ -1, 1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 },
{ /* 1 */ -1, -2, -2, 2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -1, -2 },
{ /* 2 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2 },
{ /* 3 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, 4, -2, -2, -2, -1, 5 },
{ /* 4 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 5 },
{ /* 5 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 6, -2, -2, -2 },
{ /* 6 */ -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 }
};
PGPInt8
pgpTLSNextState(
PGPtlsSessionPriv * session,
PGPByte event )
{
PGPInt8 newState;
if( session->isClientSide )
newState = kPGPtls_ClientStateTable[session->intState][event];
else if( session->minorVersion == kPGPtls_SSL3MinorVersion )
newState = kPGPtls_SSL3ServerStateTable[session->intState][event];
else
newState = kPGPtls_ServerStateTable[session->intState][event];
if( newState == -2 )
session->state = kPGPtls_FatalErrorState;
else if( newState >= 0 )
session->intState = newState;
return newState;
}
PGPError
PGPNewTLSContext(
PGPContextRef context,
PGPtlsContextRef * outRef )
{
PGPError err = kPGPError_NoErr;
PGPtlsContextPriv * pContext;
PGPValidatePtr( context );
*outRef = NULL;
pContext = (PGPtlsContextPriv *) pgpContextMemAlloc( context,
sizeof(PGPtlsContextPriv),
kPGPMemoryMgrFlags_Clear );
if( IsntNull( pContext ) )
{
pContext->pgpContext = context;
pContext->useCache = TRUE;
*outRef = ( PGPtlsContextRef ) pContext;
}
else
err = kPGPError_OutOfMemory;
pgpAssertErrWithPtr( err, *outRef );
return err;
}
PGPError
PGPFreeTLSContext(
PGPtlsContextRef ref )
{
PGPValidatePtr( ref );
return pgpContextMemFree( ((PGPtlsContextPriv *) ref)->pgpContext,
ref );
}
PGPError
PGPtlsSetCache(
PGPtlsContextRef ref,
PGPBoolean useCache )
{
PGPValidatePtr( ref );
((PGPtlsContextPriv *) ref)->useCache = useCache;
/* not implemented yet */
return kPGPError_NoErr;
}
PGPError
PGPtlsClearCache(
PGPtlsContextRef ref )
{
(void) ref;
/* not implemented yet */
return kPGPError_NoErr;
}
PGPBoolean
pubAlgSupported(
PGPPublicKeyAlgorithm pubAlg )
{
PGPUInt32 numPubAlgs,
algIndex;
PGPPublicKeyAlgorithmInfo info;
PGPCountPublicKeyAlgorithms( &numPubAlgs );
for( algIndex = 0; algIndex < numPubAlgs; algIndex++ )
{
PGPGetIndexedPublicKeyAlgorithmInfo( algIndex, &info);
if( info.algID == pubAlg )
return TRUE;
}
return FALSE;
}
PGPError
PGPNewTLSSession(
PGPtlsContextRef ref,
PGPtlsSessionRef * outRef )
{
PGPError err = kPGPError_NoErr;
PGPtlsContextPriv * pContext;
PGPtlsSessionPriv * session;
PGPValidatePtr( ref );
*outRef = NULL;
pContext = ( PGPtlsContextPriv * ) ref;
session = ( PGPtlsSessionPriv * ) pgpContextMemAlloc( pContext->pgpContext,
sizeof( PGPtlsSessionPriv ),
kPGPMemoryMgrFlags_Clear );
if( IsntNull( session ) )
{
session->pgpContext = pContext->pgpContext;
session->tlsContext = pContext;
session->memMgr =
PGPGetContextMemoryMgr( pContext->pgpContext );
session->state = kPGPtls_IdleState;
session->intState = 0;
session->isClientSide = TRUE;
session->blocking = TRUE;
session->minorVersion = kPGPtls_MinorVersion;
session->localKeyAlg = kPGPPublicKeyAlgorithm_Invalid;
session->requestedPrime = kPGPtls_DHPrime2048;
session->certRequested = FALSE;
session->certVerified = FALSE;
session->tlsReceiveProc = NULL;
session->tlsSendProc = NULL;
session->tlsReceiveUserData = NULL;
session->tlsSendUserData = NULL;
#ifdef PGPTLS_DEBUG
err = pgpTLSPRFTest( session );
if( IsPGPError( err ) )
{
pgpAssert( 0 );
}
#endif
err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
&session->handshakeSHA);
if( IsntPGPError( err ) )
{
err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
&session->handshakeMD5);
}
if( IsntPGPError( err ) )
{
session->cipherSuites = ( PGPtlsCipherSuite * )
pgpContextMemAlloc( pContext->pgpContext,
sizeof( kPGPtls_CipherSuites ),
kPGPMemoryMgrFlags_Clear );
if( IsntNull( session->cipherSuites ) )
{
/* Determine which available cipher suites we can
actually perform given the underlying SDK
algorithms. */
PGPUInt32 suiteIndex,
numSymAlgs,
algIndex,
totalSuites;
PGPSymmetricCipherInfo symInfo;
PGPBoolean foundPub,
foundSym;
totalSuites = sizeof( kPGPtls_CipherSuites ) /
sizeof( PGPtlsCipherSuite );
session->numCipherSuites = 0;
PGPCountSymmetricCiphers( &numSymAlgs );
for( suiteIndex = 0; suiteIndex < totalSuites;
suiteIndex++ )
{
foundPub = foundSym = FALSE;
if( pubAlgSupported(
kPGPtls_CipherSuites[ suiteIndex ].sigAlg ) )
foundPub = TRUE;
if( kPGPtls_CipherSuites[ suiteIndex ].cipherID ==
kPGPCipherAlgorithm_None )
foundSym = TRUE;
else for( algIndex = 0; algIndex < numSymAlgs;
algIndex++ )
{
PGPGetIndexedSymmetricCipherInfo( algIndex,
&symInfo );
if( symInfo.algID ==
kPGPtls_CipherSuites[ suiteIndex ].cipherID )
{
foundSym = TRUE;
break;
}
}
if( foundPub && foundSym )
session->cipherSuites[ session->numCipherSuites++ ] =
kPGPtls_CipherSuites[ suiteIndex ];
}
}
else
err = kPGPError_OutOfMemory;
}
session->fatalAlert = kPGPtls_AT_None;
*outRef = ( PGPtlsSessionRef ) session;
}
else
err = kPGPError_OutOfMemory;
if( IsPGPError( err ) && IsntNull( session ) )
{
if( PGPHashContextRefIsValid( session->handshakeSHA ) )
{
(void)PGPFreeHashContext( session->handshakeSHA );
session->handshakeSHA = kInvalidPGPHashContextRef;
}
if( PGPHashContextRefIsValid( session->handshakeMD5 ) )
{
(void)PGPFreeHashContext( session->handshakeMD5 );
session->handshakeMD5 = kInvalidPGPHashContextRef;
}
if( IsntNull( session->cipherSuites ) )
(void)PGPFreeData( session->cipherSuites );
pgpContextMemFree( pContext->pgpContext, session );
*outRef = NULL;
}
pgpAssertErrWithPtr( err, *outRef );
return err;
}
PGPError
PGPCopyTLSSession( PGPtlsSessionRef ref, PGPtlsSessionRef *outRef )
{
PGPError err = kPGPError_NoErr;
PGPtlsSessionPriv * session,
* newSession;
PGPValidatePtr( ref );
*outRef = NULL;
session = (PGPtlsSessionPriv *) ref;
newSession = ( PGPtlsSessionPriv * ) pgpContextMemAlloc(
session->pgpContext,
sizeof( PGPtlsSessionPriv ),
kPGPMemoryMgrFlags_Clear );
if( IsNull( newSession ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
newSession->state = kPGPtls_IdleState;
newSession->intState = 0;
newSession->minorVersion = kPGPtls_MinorVersion;
newSession->pgpContext = session->pgpContext;
newSession->tlsContext = session->tlsContext;
newSession->memMgr = session->memMgr;
newSession->requestedPrime = kPGPtls_DHPrime2048;
newSession->certRequested = FALSE;
newSession->certVerified = FALSE;
newSession->isClientSide = session->isClientSide;
newSession->tlsReceiveProc = session->tlsReceiveProc;
newSession->tlsSendProc = session->tlsSendProc;
newSession->tlsReceiveUserData = session->tlsReceiveUserData;
newSession->tlsSendUserData = session->tlsSendUserData;
newSession->isClientSide = session->isClientSide;
newSession->blocking = session->blocking;
newSession->requestCert = session->requestCert;
newSession->numCipherSuites = session->numCipherSuites;
newSession->localKey = session->localKey;
newSession->localCert = session->localCert;
newSession->localCertChain = session->localCertChain;
newSession->localKeyAlg = session->localKeyAlg;
newSession->localKeyPasskeySize = session->localKeyPasskeySize;
newSession->localKeyUsePasskey = session->localKeyUsePasskey;
newSession->remoteKey = session->remoteKey;
newSession->remoteKeySet = session->remoteKeySet;
newSession->remoteKeyAlg = session->remoteKeyAlg;
err = PGPNewHashContext( newSession->memMgr, kPGPHashAlgorithm_SHA,
&newSession->handshakeSHA);
if( IsPGPError( err ) )
goto done;
err = PGPNewHashContext( newSession->memMgr, kPGPHashAlgorithm_MD5,
&newSession->handshakeMD5);
if( IsPGPError( err ) )
goto done;
newSession->cipherSuites = ( PGPtlsCipherSuite * ) pgpContextMemAlloc(
newSession->pgpContext,
sizeof( kPGPtls_CipherSuites ),
kPGPMemoryMgrFlags_Clear );
if( IsNull( newSession ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( session->cipherSuites, newSession->cipherSuites,
sizeof( kPGPtls_CipherSuites ) );
if( IsntNull( session->localKeyPasskeyBuffer ) )
{
newSession->localKeyPasskeyBuffer = PGPNewSecureData(
newSession->memMgr,
newSession->localKeyPasskeySize,
kPGPMemoryMgrFlags_Clear );
if( IsNull( newSession->localKeyPasskeyBuffer ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( session->localKeyPasskeyBuffer,
newSession->localKeyPasskeyBuffer,
newSession->localKeyPasskeySize );
}
if( IsntNull( session->localKeyPassphrase ) )
{
PGPUInt16 passLen = strlen( session->localKeyPassphrase ) + 1;
newSession->localKeyPassphrase = PGPNewSecureData(
newSession->memMgr, passLen,
kPGPMemoryMgrFlags_Clear );
if( IsNull( newSession->localKeyPassphrase ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( session->localKeyPassphrase,
newSession->localKeyPassphrase, passLen );
}
*outRef = ( PGPtlsSessionRef ) newSession;
done:
if( IsPGPError( err ) && IsntNull( newSession ) )
{
if( PGPHashContextRefIsValid( newSession->handshakeSHA ) )
(void)PGPFreeHashContext( newSession->handshakeSHA );
if( PGPHashContextRefIsValid( newSession->handshakeMD5 ) )
(void)PGPFreeHashContext( newSession->handshakeMD5 );
if( IsntNull( newSession->cipherSuites ) )
(void)PGPFreeData( newSession->cipherSuites );
pgpContextMemFree( newSession->pgpContext, newSession );
*outRef = NULL;
}
return err;
}
PGPError
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -