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

📄 pkcs15_wr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
									sizeofObject( \
									  sizeofObject( \
										sizeofObject( pubKeyDataSize ) + \
										extraDataSize ) ) );
		if( ( pkcs15info->pubKeyData = \
				clAlloc( "addCert", pkcs15info->pubKeyDataSize ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Write the public key data */
	sMemOpen( &stream, pkcs15info->pubKeyData,
			  pkcs15info->pubKeyDataSize );
	writeConstructed( &stream, pubKeyAttributeSize + \
					  ( int ) sizeofObject( \
								sizeofObject( \
								  sizeofObject( pubKeyDataSize ) + \
								  extraDataSize ) ),
					  keyTypeTag );
	swrite( &stream, pubKeyAttributes, pubKeyAttributeSize );
	writeConstructed( &stream,
					  ( int ) sizeofObject( \
								sizeofObject( pubKeyDataSize ) + \
								extraDataSize ),
					  CTAG_OB_TYPEATTR );
	writeSequence( &stream, ( int ) sizeofObject( pubKeyDataSize ) + \
									extraDataSize );
	writeConstructed( &stream, pubKeyDataSize, CTAG_OV_DIRECT );
	pkcs15info->pubKeyOffset = stell( &stream );
	status = exportAttributeToStream( &stream, cryptHandle, 
									  CRYPT_IATTRIBUTE_KEY_SPKI, 
									  CRYPT_USE_DEFAULT );
	if( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )
		{
		/* When using the SPKI option for storing key components, the RSA
		   components require a [1] tag since the basic (non-SPKI) option is
		   also a SEQUENCE, so if it's an RSA key we modify the tag.  This is
		   easier than passing the tag requirement down through the kernel
		   call to the context.  In addition RSA keys have an extra element
		   for PKCS #11 compatibility */
#if 0	/* Disabled until 3.1 is widespread, since 3.0 used readSequence() */
		sMemBufPtr( &stream )[ 0 ] = MAKE_CTAG( 1 );
#endif /* 0 */
		status = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );
		}
	sMemDisconnect( &stream );
	return( status );
	}

/* Add a private key to a PKCS #15 collection */

static int addPrivateKey( PKCS15_INFO *pkcs15info, 
						  const CRYPT_HANDLE cryptHandle,
						  const CRYPT_HANDLE ownerHandle,
						  const char *password, const int passwordLength,
						  const void *privKeyAttributes, 
						  const int privKeyAttributeSize,
						  const CRYPT_ALGO_TYPE pkcCryptAlgo,
						  const int modulusSize )
	{
	CRYPT_ALGO_TYPE wrapCryptAlgo;
	CRYPT_CONTEXT iSessionKeyContext;
	MECHANISM_WRAP_INFO mechanismInfo;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	STREAM stream;
	void *headerPtr, *dataPtr;
	const int keyTypeTag = getKeyTypeTag( cryptHandle );
	int privKeyInfoSize, privKeyDataSize;
	int value, status;

	/* Create a session key context and generate a key and IV into it.  The IV
	   would be generated automatically later on when we encrypt data for the
	   first time, but we do it explicitly here to catch any possible errors
	   at a point where recovery is easier.  In the interests of luser-
	   proofing we're really paranoid and force the use of non-weak algorithms
	   and modes of operation.  In addition since OIDs are only defined for a
	   limited subset of algorithms, we also default to a guaranteed available
	   algorithm if no OID is defined for the one requested */
	krnlSendMessage( ownerHandle, IMESSAGE_GETATTRIBUTE, &wrapCryptAlgo, 
					 CRYPT_OPTION_ENCR_ALGO );
	if( isWeakCryptAlgo( wrapCryptAlgo ) ||
		cryptStatusError( sizeofAlgoIDex( wrapCryptAlgo,
									( CRYPT_ALGO_TYPE ) CRYPT_MODE_CBC, 0 ) ) )
		wrapCryptAlgo = CRYPT_ALGO_3DES;
	setMessageCreateObjectInfo( &createInfo, wrapCryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_GENKEY,
								  NULL, FALSE );
	if( cryptStatusOK( status ) )
		status = krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_CTX_GENIV );
	if( cryptStatusError( status ) )
		{
		if( createInfo.cryptHandle != CRYPT_ERROR )
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	iSessionKeyContext = createInfo.cryptHandle;

	/* Calculate the eventual encrypted key size and allocate storage for it */
	setMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, cryptHandle,
						  iSessionKeyContext, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
	privKeyInfoSize = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusOK( status ) )
		{
		pkcs15info->privKeyDataSize = privKeyAttributeSize +
										 privKeyInfoSize + 512;
		if( ( pkcs15info->privKeyData = \
					clAlloc( "addPrivateKey", \
							 pkcs15info->privKeyDataSize ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Since we can't write the header and attributes until we write the
	   encrypted private key, we leave enough space at the start to contain
	   this information and write the private key after that */
	sMemOpen( &stream, pkcs15info->privKeyData, pkcs15info->privKeyDataSize );
	sseek( &stream, 200 + privKeyAttributeSize );
	dataPtr = sMemBufPtr( &stream );

	/* Write the encryption information with a gap at the start for the CMS
	   header.  Since we're using KEKRecipientInfo, we use a version of 2
	   rather than 0  */
	writeShortInteger( &stream, 2, DEFAULT_TAG );
	status = writeWrappedSessionKey( &stream, iSessionKeyContext,
									 ownerHandle, password, passwordLength );
	if( cryptStatusOK( status ) )
		status = writeCMSencrHeader( &stream, OID_CMS_DATA, privKeyInfoSize,
									 iSessionKeyContext );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Export the encrypted private key */
	setMechanismWrapInfo( &mechanismInfo, sMemBufPtr( &stream ),
						  privKeyInfoSize, NULL, 0, cryptHandle,
						  iSessionKeyContext, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
	if( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )
		{
		STREAM encDataStream;
		int length;

		/* Check that the wrapped key data no longer contains identifiable
		   structured data.  We can only do this for RSA keys since the
		   amount of information present for DLP keys is too small to 
		   reliably check.  For RSA keys the data would be:
			SEQUENCE {
				[0] INTEGER | [3] INTEGER,
				...
				}
		   This check is performed in addition to checks already performed by
		   the encryption code and the key wrap code */
		sMemConnect( &encDataStream, mechanismInfo.wrappedData, 
					 mechanismInfo.wrappedDataLength );
		status = readSequence( &encDataStream, &length );
		if( cryptStatusOK( status ) )
			{
			/* The data must contain at least p and q, or at most all key
			   components */
			if( length < ( bitsToBytes( MIN_PKCSIZE_BITS ) * 2 ) || \
				length > MAX_PRIVATE_KEYSIZE )
				status = CRYPT_ERROR;
			else
				{
				/* The first value is either n or p */
				value = peekTag( &encDataStream );
				if( value == MAKE_CTAG( 0 ) || value == MAKE_CTAG( 3 ) )
					{
					status = readIntegerTag( &encDataStream, NULL, 
											 &length, CRYPT_MAX_PKCSIZE, 
											 value );
					if( cryptStatusOK( status ) && \
						( length < bitsToBytes( MIN_PKCSIZE_BITS ) || \
						  length > CRYPT_MAX_PKCSIZE ) )
						status = CRYPT_ERROR;
					}
				}
			}
		sMemDisconnect( &encDataStream );
		status = ( cryptStatusError( status ) ) ? \
				 CRYPT_OK : CRYPT_ERROR_FAILED;
		}
	if( cryptStatusOK( status ) )
		status = sSkip( &stream, mechanismInfo.wrappedDataLength );
	clearMechanismInfo( &mechanismInfo );
	krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}
	privKeyDataSize = stell( &stream ) - ( 200 + privKeyAttributeSize );

	/* Kludge the CMS header onto the start of the data */
	sseek( &stream, 100 + privKeyAttributeSize );
	headerPtr = sMemBufPtr( &stream );
	writeConstructed( &stream, privKeyDataSize, CTAG_OV_DIRECTPROTECTED );
	memmove( sMemBufPtr( &stream ), dataPtr, privKeyDataSize );
	privKeyDataSize += stell( &stream ) - ( 100 + privKeyAttributeSize );

	/* Now that we've written the private key data and know how long it is,
	   move back to the start and write the attributes and outer header, then
	   move the private key information down to the end.  Finally, adjust the
	   private key size value to reflect its true size (rather than the
	   allocated buffer size) */
	sseek( &stream, 0 );
	if( pkcCryptAlgo == CRYPT_ALGO_RSA )
		/* RSA keys have an extra element for PKCS #11 compatibility */
		privKeyDataSize += sizeofShortInteger( modulusSize );
	writeConstructed( &stream, privKeyAttributeSize + \
					  ( int ) sizeofObject( sizeofObject( privKeyDataSize ) ),
					  keyTypeTag );
	swrite( &stream, privKeyAttributes, privKeyAttributeSize );
	writeConstructed( &stream, ( int ) sizeofObject( privKeyDataSize ),
					  CTAG_OB_TYPEATTR );
	writeSequence( &stream, privKeyDataSize );
	pkcs15info->privKeyOffset = stell( &stream );
	if( pkcCryptAlgo == CRYPT_ALGO_RSA )
		{
		/* RSA keys have an extra element for PKCS #11 compability that we
		   need to kludge onto the end of the private-key data */
		privKeyDataSize -= sizeofShortInteger( modulusSize );
		memmove( sMemBufPtr( &stream ), headerPtr, privKeyDataSize );
		sSkip( &stream, privKeyDataSize );
		status = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );
		}
	else
		{
		memmove( sMemBufPtr( &stream ), headerPtr, privKeyDataSize );
		status = sSkip( &stream, privKeyDataSize );
		}
	pkcs15info->privKeyDataSize = stell( &stream );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );

	return( status );
	}

/* Add configuration data to a PKCS #15 collection */

static int addConfigData( PKCS15_INFO *pkcs15info, const char *data, 
						  const int dataLength, const int flags )
	{
	int i;

	assert( flags == CRYPT_IATTRIBUTE_CONFIGDATA || \
			flags == CRYPT_IATTRIBUTE_USERINDEX || \
			flags == CRYPT_IATTRIBUTE_USERID || \
			flags == CRYPT_IATTRIBUTE_USERINFO );

	/* If it's a user ID, set all object IDs to this value.  This is needed 
	   for user keysets where there usually isn't any key ID present (there 
	   is one for SO keysets since they have public/private keys attached to 
	   them, but they're not identified by key ID so it's not much use).  In 
	   this case the caller has to explicitly set an ID, which is the user 
	   ID */
	if( flags == CRYPT_IATTRIBUTE_USERID )
		{
		for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
			{
			memcpy( pkcs15info[ i ].iD, data, dataLength );
			pkcs15info[ i ].iDlength = dataLength;
			}
		return( CRYPT_OK );
		}

	/* Find either the first free entry or an entry that contains data 
	   identical to what we're adding now, which we'll replace with the new 
	   data */
	for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
		if( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \
			  pkcs15info[ i ].dataType == flags ) || \
			pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
			break;
	if( i == MAX_PKCS15_OBJECTS )
		return( CRYPT_ERROR_OVERFLOW );
	pkcs15info = &pkcs15info[ i ];

	/* If there's existing data present which was read from a keyset that
	   was opened for update, clear and free it */
	if( pkcs15info->dataData != NULL )
		{
		assert( pkcs15info->dataType == flags );

		zeroise( pkcs15info->dataData, pkcs15info->dataDataSize );
		clFree( "addConfigData", pkcs15info->dataData );
		pkcs15info->type = PKCS15_SUBTYPE_NONE;

		/* If we're being sent empty data (corresponding to an empty 
		   SEQUENCE), it means the caller wants to clear this entry */
		if( dataLength < 8 )
			{
			zeroise( pkcs15info, sizeof( PKCS15_INFO ) );
			return( CRYPT_OK );
			}
		}

	/* Remember the pre-encoded config data */
	assert( pkcs15info->type == PKCS15_SUBTYPE_NONE );
	if( ( pkcs15info->dataData = \
						clAlloc( "addConfigData", dataLength ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memcpy( pkcs15info->dataData, data, dataLength );
	pkcs15info->dataDataSize = dataLength;

	/* Set the type information for the data */
	pkcs15info->type = PKCS15_SUBTYPE_DATA;
	pkcs15info->dataType = flags;

	return( CRYPT_OK );
	}

/* Add a secret key to a PKCS #15 collection */

static int addSecretKey( PKCS15_INFO *pkcs15info, 
						 const CRYPT_HANDLE cryptHandle )
	{
	RESOURCE_DATA msgData;
	char label[ CRYPT_MAX_TEXTSIZE + 1 ];
	int i, status;

⌨️ 快捷键说明

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