⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_cry.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:

	/* Generate the inner portion of the handshake message's MAC:

		hash( handshake_messages || cl/svr_label || master_secret || pad1 ).

	   Note that the SHA-1 pad size is 40 bytes and not 44 (to get a total
	   length of 64 bytes), this is due to an error in the spec */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) label, 
					 SSL_SENDERLABEL_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) label, 
					 SSL_SENDERLABEL_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 48 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 40 );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashValues, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Reset the hash contexts */
	krnlSendMessage( md5context, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( sha1context, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );

	/* Generate the outer portion of the handshake message's MAC:

		hash( master_secret || pad2 || inner_hash ) */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 48 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 40 );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, hashValues, 
					 MD5MAC_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, hashValues + MD5MAC_SIZE, 
					 SHA1MAC_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashValues, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	return( status );
	}

int completeTLSHashedMAC( const CRYPT_CONTEXT md5context,
						  const CRYPT_CONTEXT sha1context, BYTE *hashValues, 
						  const char *label, const BYTE *masterSecret )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	BYTE hashBuffer[ 64 + CRYPT_MAX_HASHSIZE * 2 ];
	const int labelLength = strlen( label );
	int status;

	memcpy( hashBuffer, label, labelLength );

	/* Complete the hashing and get the MD5 and SHA-1 hashes */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashBuffer + labelLength, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashBuffer + labelLength + MD5MAC_SIZE,
						SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Generate the TLS check value.  This isn't really a hash or a MAC, but
	   is generated by feeding the MD5 and SHA1 hashes of the handshake
	   messages into the TLS key derivation (PRF) function and truncating
	   the result to 12 bytes (96 bits) for no adequately explored reason, 
	   most probably it's IPsec cargo cult protocol design:

		TLS_PRF( label || MD5_hash || SHA1_hash ) */
	setMechanismDeriveInfo( &mechanismInfo, hashValues, TLS_HASHEDMAC_SIZE,
							( void * ) masterSecret, 48, CRYPT_USE_DEFAULT,
							hashBuffer, labelLength + MD5MAC_SIZE + SHA1MAC_SIZE, 1 );
	return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
							 &mechanismInfo, MECHANISM_DERIVE_TLS ) );
	}

/****************************************************************************
*																			*
*							Signature Functions								*
*																			*
****************************************************************************/

/* Create/check the signature on an SSL certificate verify message.  
   SSLv3/TLS use a weird signature format that dual-MACs (SSLv3) or hashes
   (TLS) all of the handshake messages exchanged to date (SSLv3 additionally 
   hashes in further data like the master secret), then signs them using 
   nonstandard PKCS #1 RSA without the ASN.1 wrapper (that is, it uses the 
   private key to encrypt the concatenated SHA-1 and MD5 MAC or hash of the 
   handshake messages with PKCS #1 padding prepended), unless we're using 
   DSA in which case it drops the MD5 MAC/hash and uses only the SHA-1 one.  
   This is an incredible pain to support because it requires running a 
   parallel hash of handshake messages that terminates before the main 
   hashing does, further hashing/MAC'ing of additional data, and the use of 
   weird nonstandard data formats and signature mechanisms that aren't 
   normally supported by anything.  For example if the signing is to be done 
   via a smart card then we can't use the standard PKCS #1 sig mechanism, we 
   can't even use raw RSA and kludge the format together ourselves because 
   some PKCS #11 implementations don't support the _X509 (raw) mechanism, 
   what we have to do is tunnel the nonstandard sig.format info down through 
   several cryptlib layers and then hope that the PKCS #11 implementation 
   that we're using (a) supports this format and (b) gets it right.  Another 
   problem (which only occurs for SSLv3) is that the MAC requires the use of 
   the master secret, which isn't available for several hundred more lines 
   of code, so we have to delay producing any more data packets until the 
   master secret is available, which severely screws up the handshake 
   processing flow.

   The chances of all of this working correctly are fairly low, and in any
   case there's no advantage to the weird mechanism and format used in
   SSL/TLS, all we actually need to do is sign the client and server nonces
   to ensure signature freshness.  Because of this what we actually do is
   just this, after which we create a standard PKCS #1 signature via the
   normal cryptlib mechanisms, which guarantees that it'll work with native
   cryptlib as well as any crypto hardware implementation.  Since client
   certs are hardly ever used and when they are it's in a closed environment,
   it's extremely unlikely that anyone will ever notice.  There'll be far
   more problems in trying to use the nonstandard SSL/TLS signature mechanism
   than there are with using a standard (but not-in-the-spec) one */

static CRYPT_CONTEXT createCertVerifyHash( const SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ];
	int status;

	/* Hash the client and server nonces */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	memcpy( nonceBuffer, "certificate verify", 18 );
	memcpy( nonceBuffer + 18, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
	memcpy( nonceBuffer + 18 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
			SSL_NONCE_SIZE );
	krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,
					 nonceBuffer, 18 + SSL_NONCE_SIZE + SSL_NONCE_SIZE );
	krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,
					 nonceBuffer, 0 );

	return( createInfo.cryptHandle );
	}

int createCertVerify( const SESSION_INFO *sessionInfoPtr,
					  const SSL_HANDSHAKE_INFO *handshakeInfo,
					  STREAM *stream )
	{
	CRYPT_CONTEXT iHashContext;
	int length, status;

	/* Create the hash of the data to sign */
	iHashContext = createCertVerifyHash( handshakeInfo );
	if( cryptStatusError( iHashContext ) )
		return( iHashContext );

	/* Create the signature.  The reason for the min() part of the 
	   expression is that iCryptCreateSignatureEx() gets suspicious of very 
	   large buffer sizes, for example when the user has specified the use 
	   of a 1MB send buffer */
	status = iCryptCreateSignatureEx( sMemBufPtr( stream ), &length, 
									  min( sMemDataLeft( stream ), 16384 ),
									  CRYPT_FORMAT_CRYPTLIB,
									  sessionInfoPtr->privateKey, 
									  iHashContext, CRYPT_UNUSED, 
									  CRYPT_UNUSED );
	if( cryptStatusOK( status ) )
		status = sSkip( stream, length );
	krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}

int checkCertVerify( const SESSION_INFO *sessionInfoPtr,
					 const SSL_HANDSHAKE_INFO *handshakeInfo,
					 STREAM *stream, const int sigLength )
	{
	CRYPT_CONTEXT iHashContext;
	int status;

	assert( sigLength > MIN_CRYPT_OBJECTSIZE );

	/* Create the hash of the data to sign */
	iHashContext = createCertVerifyHash( handshakeInfo );
	if( cryptStatusError( iHashContext ) )
		return( iHashContext );

	/* Verify the signature.  The reason for the min() part of the 
	   expression is that iCryptCheckSignatureEx() gets suspicious of very 
	   large buffer sizes, for example when the user has specified the use 
	   of a 1MB send buffer */
	status = iCryptCheckSignatureEx( sMemBufPtr( stream ), 
									 min( sigLength, 16384 ),
									 CRYPT_FORMAT_CRYPTLIB,
									 sessionInfoPtr->iKeyexAuthContext,
									 iHashContext, NULL );
	krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Create/check the signature on the server key data */

static int createKeyexHashes( const SSL_HANDSHAKE_INFO *handshakeInfo,
							  const void *keyData, const int keyDataLength,
							  CRYPT_CONTEXT *md5Context,
							  CRYPT_CONTEXT *shaContext )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE nonceBuffer[ SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
	int status;

	/* Create the dual hash contexts */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	*md5Context = createInfo.cryptHandle;
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( *md5Context, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	*shaContext = createInfo.cryptHandle;

	/* Hash the client and server nonces and key data */
	memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
	memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
			SSL_NONCE_SIZE );
	krnlSendMessage( *md5Context, IMESSAGE_CTX_HASH,
					 nonceBuffer, SSL_NONCE_SIZE + SSL_NONCE_SIZE );
	krnlSendMessage( *shaContext, IMESSAGE_CTX_HASH,
					 nonceBuffer, SSL_NONCE_SIZE + SSL_NONCE_SIZE );
	krnlSendMessage( *md5Context, IMESSAGE_CTX_HASH,
					 ( void * ) keyData, keyDataLength );
	krnlSendMessage( *shaContext, IMESSAGE_CTX_HASH,
					 ( void * ) keyData, keyDataLength );
	krnlSendMessage( *md5Context, IMESSAGE_CTX_HASH,
					 nonceBuffer, 0 );
	krnlSendMessage( *shaContext, IMESSAGE_CTX_HASH,
					 nonceBuffer, 0 );

	return( CRYPT_OK );
	}

int createKeyexSignature( SESSION_INFO *sessionInfoPtr, 
						  SSL_HANDSHAKE_INFO *handshakeInfo,
						  STREAM *stream, const void *keyData, 
						  const int keyDataLength )
	{
	CRYPT_CONTEXT md5Context, shaContext;
	int sigLength, status;

	/* Hash the data to be signed */
	status = createKeyexHashes( handshakeInfo, keyData, keyDataLength, 
								&md5Context, &shaContext );
	if( cryptStatusError( status ) )
		return( status );

	/* Sign the hashes.  The reason for the min() part of the expression is
	   that iCryptCreateSignatureEx() gets suspicious of very large buffer
	   sizes, for example when the user has specified the use of a 1MB send
	   buffer */
	status = iCryptCreateSignatureEx( sMemBufPtr( stream ), &sigLength,
							min( sMemDataLeft( stream ), 16384 ),
							CRYPT_IFORMAT_SSL, sessionInfoPtr->privateKey,
							md5Context, shaContext, CRYPT_UNUSED );
	if( cryptStatusOK( status ) )
		status = sSkip( stream, sigLength );

	/* Clean up */
	krnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );
	krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}

int checkKeyexSignature( SESSION_INFO *sessionInfoPtr, 
						 SSL_HANDSHAKE_INFO *handshakeInfo,
						 STREAM *stream, const void *keyData, 
						 const int keyDataLength )
	{
	CRYPT_CONTEXT md5Context, shaContext;
	int status;

	/* Make sure that there's enough data present for at least a minimal-
	   length signature */
	if( sMemDataLeft( stream ) < bitsToBytes( MIN_PKCSIZE_BITS ) )
		return( CRYPT_ERROR_BADDATA );

	/* Hash the data to be signed */
	status = createKeyexHashes( handshakeInfo, keyData, keyDataLength, 
								&md5Context, &shaContext );
	if( cryptStatusError( status ) )
		return( status );

	/* Check the signature on the hashes.  The reason for the min() part of 
	   the expression is that iCryptCreateSignatureEx() gets suspicious of 
	   very large buffer sizes, for example when the user has specified the 
	   use of a 1MB send buffer */
	status = iCryptCheckSignatureEx( sMemBufPtr( stream ), 
									 min( sMemDataLeft( stream ), 16384 ),
									 CRYPT_IFORMAT_SSL, 
									 sessionInfoPtr->iKeyexCryptContext,
									 md5Context, &shaContext );
	if( cryptStatusOK( status ) )
		status = readUniversal16( stream );

	/* Clean up */
	krnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );
	krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}
#endif /* USE_SSL */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -