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

📄 pkcs15_wr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Check the object and make sure the label of what we're adding 
	   doesn't duplicate the label of an existing object */
	status = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
							  MESSAGE_CHECK_CRYPT );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : status );
	setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_LABEL );
	if( cryptStatusError( status ) )
		return( status );
	if( findEntry( pkcs15info, CRYPT_KEYID_NAME, msgData.data, 
				   msgData.length, KEYMGMT_FLAG_NONE ) != NULL )
		return( CRYPT_ERROR_DUPLICATE );

	/* Find out where we can add the new key data */
	for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
		if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
			break;
	if( i == MAX_PKCS15_OBJECTS )
		return( CRYPT_ERROR_OVERFLOW );
	pkcs15info = &pkcs15info[ i ];

	pkcs15info->type = PKCS15_SUBTYPE_SECRETKEY;

	/* This functionality is currently unused */
	assert( NOTREACHED );
	return( CRYPT_ERROR );
	}

/* Add an item to the PKCS #15 keyset */

static int setItemFunction( KEYSET_INFO *keysetInfo,
							const CRYPT_HANDLE cryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const char *password, const int passwordLength,
							const int flags )
	{
	CRYPT_ALGO_TYPE pkcCryptAlgo;
	CRYPT_CERTIFICATE iCryptCert;
	PKCS15_INFO *pkcs15infoPtr;
	RESOURCE_DATA msgData;
	BYTE iD[ CRYPT_MAX_HASHSIZE ];
	BYTE pubKeyAttributes[ KEYATTR_BUFFER_SIZE ];
	BYTE privKeyAttributes[ KEYATTR_BUFFER_SIZE ];
	BOOLEAN certPresent = FALSE, privkeyContextPresent;
	BOOLEAN pkcs15certPresent = FALSE, pkcs15keyPresent = FALSE;
	BOOLEAN isCertChain = FALSE, isCertUpdate = FALSE;
	int pubKeyAttributeSize;
	int privKeyAttributeSize;
	int iDsize, modulusSize, value, status;

	/* If we're being sent pre-encoded data or a secret key, add it to the 
	   PKCS #15 data and exit */
	if( cryptHandle == CRYPT_UNUSED )
		return( addConfigData( keysetInfo->keyData, password, passwordLength, 
							   flags ) );
	if( itemType == KEYMGMT_ITEM_SECRETKEY )
		return( addSecretKey( keysetInfo->keyData, cryptHandle ) );

	/* Check the object, extract ID information from it, and determine
	   whether it's a standalone cert (which produces a PKCS #15 cert object)
	   or a private-key context (which produces PKCS #15 a private key object 
	   and either a PKCS #15 public-key object or a cert object) */
	status = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
							  MESSAGE_CHECK_PKC );
	if( cryptStatusOK( status ) )
		{
		krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &pkcCryptAlgo, 
						 CRYPT_CTXINFO_ALGO );
		krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &modulusSize, 
						 CRYPT_CTXINFO_KEYSIZE );
		setMessageData( &msgData, iD, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEYID );
		iDsize = msgData.length;
		}
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : status );
	privkeyContextPresent = cryptStatusOK( \
			krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
							 MESSAGE_CHECK_PKC_PRIVATE ) ) ? TRUE : FALSE;

	/* If there's a cert present, make sure that it's something that can be
	   stored.  We don't treat the wrong type as an error since we can still
	   store the public/private key components even if we don't store the
	   cert */
	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value, 
							  CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusOK( status ) && \
		( value == CRYPT_CERTTYPE_CERTIFICATE || \
		  value == CRYPT_CERTTYPE_CERTCHAIN ) )
		{
		/* If it's a cert chain, remember this for later since we may
		   need to store multiple certs */
		if( value == CRYPT_CERTTYPE_CERTCHAIN )
			isCertChain = TRUE;

		/* If the cert isn't signed, we can't store it in this state */
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,
								  &value, CRYPT_CERTINFO_IMMUTABLE );
		if( cryptStatusError( status ) || !value )
			return( CRYPT_ERROR_NOTINITED );
		krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert, 
						 OBJECT_TYPE_CERTIFICATE );
		certPresent = TRUE;
		}
	status = CRYPT_OK;	/* Reset status from the check above */

	/* Find out where we can add data and what needs to be added */
	pkcs15infoPtr = findEntry( keysetInfo->keyData, CRYPT_KEYIDEX_ID,
							   iD, iDsize, KEYMGMT_FLAG_NONE );
	if( pkcs15infoPtr != NULL )
		{
		BOOLEAN unneededCert, unneededKey;

		/* Determine what actually needs to be added */
		if( pkcs15infoPtr->privKeyData != NULL )
			pkcs15keyPresent = TRUE;
		if( pkcs15infoPtr->certData != NULL )
			pkcs15certPresent = TRUE;

		/* Make sure we can update at least one of the PKCS #15 objects in
		   the personality */
		unneededKey = privkeyContextPresent & pkcs15keyPresent;
		unneededCert = certPresent & pkcs15certPresent;
		if( ( ( unneededCert && !privkeyContextPresent ) || \
			  ( unneededKey && unneededCert ) ) && \
			pkcs15infoPtr->validTo != 0 )
			{
			time_t validTo;

			/* If the cert would be a duplicate, see if the new cert is more
			   recent than the existing one.  We only perform this check if 
			   there's a validTo time stored for the cert since without this 
			   restriction any cert without a stored time could be 
			   overwritten */
			setMessageData( &msgData, &validTo, sizeof( time_t ) );
			status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_CERTINFO_VALIDTO );
			if( cryptStatusOK( status ) && validTo > pkcs15infoPtr->validTo )
				{
				time_t validFrom;

				/* It's a newer cert, don't treat it as a duplicate.  This
				   check is effectively impossible to perform automatically
				   since there are an infinite number of variations that
				   have to be taken into account (e.g. cert for the same key
				   issued by a different CA, same CA but it's changed the
				   bits it sets in the keyUsage (digitalSignature vs
				   nonRepudiation), slightly different issuer DN (Thawte
				   certs with a date encoded in the DN), and so on an so on).
				   Because it requires manual processing by a human, we
				   don't even try and sort it all but just allow a cert for
				   a given key (checked by the ID match) to be replaced by a
				   newer cert for the same key.  This is restrictive enough
				   to prevent most obviously-wrong replacements, while being
				   permissive enough to allow most probably-OK replacements */
				unneededCert = FALSE;
				isCertUpdate = TRUE;

				/* There is one special-case situation in which odd things 
				   can happen when updating certs and that's when adding a 
				   future-dated cert, which would result in the cert being 
				   replaced with one that can't be used yet.  There's no 
				   clean way to handle this because in order to know what to 
				   do we'd have to be able to guess the intent of the user, 
				   however for anything but signature certs it's likely that 
				   the hit-and-miss cert checking performed by most software 
				   won't even notice a future-dated cert, and for signature
				   certs the semantics of signing data now using a cert that 
				   isn't valid yet are somewhat uncertain.  Since in most 
				   cases no-one will even notice the problem, we throw an 
				   exception in the debug build but don't do anything in 
				   release builds.  This is probably less annoying to users
				   than having the code reject a future-dated cert */
				setMessageData( &msgData, &validFrom, sizeof( time_t ) );
				status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
										  &msgData, CRYPT_CERTINFO_VALIDFROM );
				if( cryptStatusOK( status ) && \
					validFrom > getApproxTime() + 86400 )
					{
					assert( !"Attempt to replace cert with future-dated cert" );
					}
				}
			}
		if( ( unneededKey && !certPresent ) ||				/* Key only, duplicate */
			( unneededCert && !privkeyContextPresent ) ||	/* Cert only, duplicate */
			( unneededKey && unneededCert ) )				/* Key+cert, duplicate */
			{
			/* If it's anything other than a cert chain, we can't add
			   anything */
			if( !isCertChain )
				return( CRYPT_ERROR_DUPLICATE );

			/* It's a cert chain, there may be new certs present, try and add
			   them */
			status = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,
									  MESSAGE_VALUE_TRUE, 
									  CRYPT_IATTRIBUTE_LOCKED );
			if( cryptStatusError( status ) )
				return( status );
			status = addCertChain( pkcs15infoPtr, cryptHandle );
			krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, 
							 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
			return( status );
			}
		}
	else
		{
		char label[ CRYPT_MAX_TEXTSIZE + 1 ];
		int i;

		/* This key/cert isn't already present, make sure the label of what
		   we're adding doesn't duplicate the label of an existing object */
		if( privkeyContextPresent )
			{
			setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );
			status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_CTXINFO_LABEL );
			if( cryptStatusError( status ) )
				return( status );
			}
		if( findEntry( keysetInfo->keyData, CRYPT_KEYID_NAME,
					   msgData.data, msgData.length,
					   KEYMGMT_FLAG_NONE ) != NULL )
			return( CRYPT_ERROR_DUPLICATE );

		/* Find out where we can add the new key data */
		pkcs15infoPtr = keysetInfo->keyData;
		for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
			if( pkcs15infoPtr[ i ].type == PKCS15_SUBTYPE_NONE )
				break;
		if( i == MAX_PKCS15_OBJECTS )
			return( CRYPT_ERROR_OVERFLOW );
		pkcs15infoPtr = &pkcs15infoPtr[ i ];
		pkcs15infoPtr->index = i;
		}
	pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;

	/* If we're adding a private key, make sure there's a context and a 
	   password present.  Conversely, if there's a password present make 
	   sure that we're adding a private key.  This has already been checked 
	   by the kernel, but we perform a second check here just to be safe */
	if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
		{
		if( !privkeyContextPresent )
			return( CRYPT_ARGERROR_NUM1 );
		if( password == NULL )
			return( CRYPT_ARGERROR_STR1 );
		}
	else
		if( password != NULL )
			return( CRYPT_ARGERROR_NUM1 );

	/* We're ready to go, lock the object for our exclusive use */
	if( certPresent )
		{
		status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
								  MESSAGE_VALUE_TRUE, 
								  CRYPT_IATTRIBUTE_LOCKED );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the attribute information.  We have to rewrite the key
	   information when we add a non-standalone cert even if we don't change
	   the key because adding a cert can affect key attributes */
	if( ( certPresent && pkcs15keyPresent ) ||				/* Updating existing */
		( privkeyContextPresent && !pkcs15keyPresent ) )	/* Adding new */
		status = writeKeyAttributes( privKeyAttributes, &privKeyAttributeSize,
									 pubKeyAttributes, &pubKeyAttributeSize,
									 pkcs15infoPtr, cryptHandle );
	if( cryptStatusError( status ) )
		{
		if( certPresent )
			krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
							 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
		return( status );
		}

	/* Write the cert if necessary.  We do this one first because it's the
	   easiest to back out of */
	if( certPresent && ( isCertUpdate || !pkcs15certPresent ) )
		{
		/* Select the leaf cert in case it's a cert chain */
		krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,
						 MESSAGE_VALUE_CURSORFIRST,
						 CRYPT_CERTINFO_CURRENT_CERTIFICATE );

		/* Write the cert information.  There may be further certs in the
		   chain but we don't try and do anything with these until after the
		   rest of the key information has been added */
		status = addCert( pkcs15infoPtr, cryptHandle, pubKeyAttributes,
						  pubKeyAttributeSize, privKeyAttributes,
						  privKeyAttributeSize, pkcs15keyPresent ? \
							CERTADD_UPDATE_EXISTING : \
						  privkeyContextPresent ? \
							CERTADD_NORMAL : CERTADD_STANDALONE_CERT );
		if( cryptStatusError( status ) )
			{
			if( certPresent )
				krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
								 MESSAGE_VALUE_FALSE, 
								 CRYPT_IATTRIBUTE_LOCKED );
			return( status );
			}

		/* If there's no context to add we return now, however if we've been
		   given a cert chain with further certs in it we try and add these as
		   well before we exit.  Note that we may return an error at this 
		   point if the cert chain update fails even if the main cert add
		   succeeded.  This is better than returning CRYPT_OK but only adding
		   some certs since it lets the caller know the operation wasn't
		   completely successful and can be retried if necessary, at which
		   point it'll be handled via the cert-chain-only update code earlier
		   on */
		if( !privkeyContextPresent || pkcs15keyPresent )
			{
			if( isCertChain )
				status = addCertChain( pkcs15infoPtr, cryptHandle );
			if( certPresent )
				krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
								 MESSAGE_VALUE_FALSE, 
								 CRYPT_IATTRIBUTE_LOCKED );
			return( status );
			}
		}
	assert( itemType == KEYMGMT_ITEM_PRIVATEKEY );
	assert( !isCertUpdate );

	/* Add the public k

⌨️ 快捷键说明

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