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

📄 pkcs15_wr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						cryptlib PKCS #15 Write Routines					*
*						Copyright Peter Gutmann 1996-2003					*
*																			*
****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "pkcs15.h"
  #include "asn1.h"
  #include "asn1_ext.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "keyset.h"
  #include "pkcs15.h"
  #include "../misc/asn1.h"
  #include "../misc/asn1_ext.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/pkcs15.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */

#ifdef USE_PKCS15

/* When writing attributes it's useful to have a fixed-size buffer rather
   than having to mess around with all sorts of variable-length structures,
   the following value defines the maximum size of the attribute data that 
   we can write (that is, the I/O stream is opened with this size and 
   generates a CRYPT_ERROR_OVERFLOW if we go beyond this).  The maximum-
   length buffer contents are two CRYPT_MAX_TEXTSIZE strings and a few odd 
   bits and pieces so this is plenty */

#define KEYATTR_BUFFER_SIZE		256

/* The minimum number of keying iterations to use when deriving a key wrap
   key from a password.  Any recent system will handle a significant 
   iteration count in no time but older systems may take awhile to handle
   this, however there's no easy way to determine CPU speed so we make the 
   mimimal assumption that a 16-bit system isn't going to be too fast */

#if INT_MAX > 32767
  #define MIN_KEYING_ITERATIONS	2000
#else
  #define MIN_KEYING_ITERATIONS	800
#endif /* 16-bit systems */

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Get the hash of various certificate name fields */

static int getCertID( const CRYPT_HANDLE iCryptHandle,
					  CRYPT_ATTRIBUTE_TYPE nameType, BYTE *nameID )
	{
	DYNBUF idDB;
	int status;

	assert( nameType == CRYPT_IATTRIBUTE_SPKI || \
			nameType == CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER || \
			nameType == CRYPT_IATTRIBUTE_SUBJECT || \
			nameType == CRYPT_IATTRIBUTE_ISSUER );

	status = dynCreate( &idDB, iCryptHandle, nameType );
	if( cryptStatusOK( status ) )
		{
		HASHFUNCTION hashFunction;

		/* Get the hash algorithm information and hash the name to get a name
		   ID */
		getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );
		hashFunction( NULL, nameID, dynData( idDB ), dynLength( idDB ), 
					  HASH_ALL );
		}
	dynDestroy( &idDB );
	return( status );
	}

/****************************************************************************
*																			*
*							Write PKCS #15 Attributes						*
*																			*
****************************************************************************/

/* Write PKCS #15 identifier values */

static int sizeofObjectIDs( const PKCS15_INFO *pkcs15info )
	{
	int identifierSize;
	
	identifierSize = ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) + \
				sizeofObject( pkcs15info->keyIDlength ) );
	if( pkcs15info->iAndSIDlength )
		identifierSize += ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) + \
				sizeofObject( pkcs15info->iAndSIDlength ) );
	if( pkcs15info->issuerNameIDlength )
		identifierSize += ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) + \
				sizeofObject( pkcs15info->issuerNameIDlength ) );
	if( pkcs15info->subjectNameIDlength )
		identifierSize += ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_SUBJECTNAMEHASH ) + \
				sizeofObject( pkcs15info->subjectNameIDlength ) );
	if( pkcs15info->pgp2KeyIDlength )
		identifierSize += ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_PGP2 ) + \
				sizeofObject( pkcs15info->pgp2KeyIDlength ) );
	if( pkcs15info->openPGPKeyIDlength )
		identifierSize += ( int ) \
			sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_OPENPGP ) + \
				sizeofObject( pkcs15info->openPGPKeyIDlength ) );

	return( identifierSize );
	}

static void writeObjectIDs( STREAM *stream, const PKCS15_INFO *pkcs15info,
							const int length, const int tag )
	{
	writeConstructed( stream, length, tag );
	writeSequence( stream,
				   sizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) + \
				   sizeofObject( pkcs15info->keyIDlength ) );
	writeShortInteger( stream, PKCS15_KEYID_SUBJECTKEYIDENTIFIER,
					   DEFAULT_TAG );
	writeOctetString( stream, pkcs15info->keyID,
					  pkcs15info->keyIDlength, DEFAULT_TAG );
	if( pkcs15info->iAndSIDlength )
		{
		writeSequence( stream,
					   sizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) + \
					   sizeofObject( pkcs15info->iAndSIDlength ) );
		writeShortInteger( stream, PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH,
						   DEFAULT_TAG );
		writeOctetString( stream, pkcs15info->iAndSID,
						  pkcs15info->iAndSIDlength, DEFAULT_TAG );
		}
	if( pkcs15info->issuerNameIDlength )
		{
		writeSequence( stream,
					   sizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) + \
					   sizeofObject( pkcs15info->issuerNameIDlength ) );
		writeShortInteger( stream, PKCS15_KEYID_ISSUERNAMEHASH, DEFAULT_TAG );
		writeOctetString( stream, pkcs15info->issuerNameID,
						  pkcs15info->issuerNameIDlength, DEFAULT_TAG );
		}
	if( pkcs15info->subjectNameIDlength )
		{
		writeSequence( stream,
					   sizeofShortInteger( PKCS15_KEYID_SUBJECTNAMEHASH ) + \
					   sizeofObject( pkcs15info->subjectNameIDlength ) );
		writeShortInteger( stream, PKCS15_KEYID_SUBJECTNAMEHASH, DEFAULT_TAG );
		writeOctetString( stream, pkcs15info->subjectNameID,
						  pkcs15info->subjectNameIDlength, DEFAULT_TAG );
		}
	if( pkcs15info->pgp2KeyIDlength )
		{
		writeSequence( stream, sizeofShortInteger( PKCS15_KEYID_PGP2 ) + \
							   sizeofObject( pkcs15info->pgp2KeyIDlength ) );
		writeShortInteger( stream, PKCS15_KEYID_PGP2, DEFAULT_TAG );
		writeOctetString( stream, pkcs15info->pgp2KeyID,
						  pkcs15info->pgp2KeyIDlength, DEFAULT_TAG );
		}
	if( pkcs15info->openPGPKeyIDlength )
		{
		writeSequence( stream, sizeofShortInteger( PKCS15_KEYID_OPENPGP ) + \
							   sizeofObject( pkcs15info->openPGPKeyIDlength ) );
		writeShortInteger( stream, PKCS15_KEYID_OPENPGP, DEFAULT_TAG );
		writeOctetString( stream, pkcs15info->openPGPKeyID,
						  pkcs15info->openPGPKeyIDlength, DEFAULT_TAG );
		}
	}

/* Write atributes to a buffer */

static int writeKeyAttributes( void *privKeyAttributes,
							   int *privKeyAttributeSize,
							   void *pubKeyAttributes,
							   int *pubKeyAttributeSize,
							   PKCS15_INFO *pkcs15info,
							   const CRYPT_HANDLE cryptHandle )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE sKIDbuffer[ CRYPT_MAX_HASHSIZE ];
	int keyUsage = 0, value, status;
	int commonAttributeSize, commonKeyAttributeSize;

	/* Get various pieces of information from the object.  The information
	   may already have been set up earlier on so we only set it if this is
	   a newly-added key.  We use a guard for the existence of both a label
	   and an ID, since there may be a pre-set user ID (which isn't the same
	   as the key ID) present for implicitly created keys in user keysets */
	if( !pkcs15info->labelLength )
		{
		setMessageData( &msgData, pkcs15info->label, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_LABEL );
		if( cryptStatusError( status ) )
			return( status );
		pkcs15info->labelLength = msgData.length;
		setMessageData( &msgData, pkcs15info->keyID, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEYID );
		if( cryptStatusError( status ) )
			return( status );
		pkcs15info->keyIDlength = msgData.length;
		}
	if( !pkcs15info->iDlength )
		{
		memcpy( pkcs15info->iD, pkcs15info->keyID, pkcs15info->keyIDlength );
		pkcs15info->iDlength = pkcs15info->keyIDlength;
		}

	/* The subjectKeyIdentifier, if present, may not be the same as the keyID
	   if the cert it's in has come from a CA that does strange things with
	   the sKID, so we try and read this value and if it's present override
	   the implicit sKID (== keyID) value with the actual sKID */
	setMessageData( &msgData, sKIDbuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
	if( cryptStatusOK( status ) )
		{
		memcpy( pkcs15info->keyID, sKIDbuffer, msgData.length );
		pkcs15info->keyIDlength = msgData.length;
		}

	/* Try and get the validity information.  This isn't used at this point,
	   but may be needed before it's set in the certificate write code, for
	   example when adding two certs that differ only in validity period to
	   a keyset.  Since we could be adding a raw key, we ignore any return
	   code */
	getValidityInfo( pkcs15info, cryptHandle );

	/* Figure out the PKCS #15 key usage flags.  This gets complicated
	   because they're a mixture of parts of X.509 and PKCS #11 flags (and
	   the X.509 -> PKCS #15 mapping isn't perfect, see for example key
	   agreement), so we have to build them up from bits and pieces pulled in
	   from all over the place.

	   One point to note is that the action flags for an object can change
	   over time under the influence of another object.  For example when a
	   raw private key is initially written and unless something else has
	   told it otherwise, it'll have all permissible actions enabled.  When a
	   certificate for the key is later added, the permissible actions for
	   the key may be constrained by the certificate, so the private key
	   flags will change when the object is re-written to the keyset */
	if( cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_ENCRYPT ) ) )
		keyUsage = PKCS15_USAGE_ENCRYPT;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_DECRYPT ) ) )
		keyUsage |= PKCS15_USAGE_DECRYPT;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_SIGN ) ) )
		keyUsage |= PKCS15_USAGE_SIGN;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_SIGCHECK ) ) )
		keyUsage |= PKCS15_USAGE_VERIFY;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_KA_EXPORT ) ) || \
		cryptStatusOK( krnlSendMessage( cryptHandle, IMESSAGE_CHECK,
										NULL, MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
		keyUsage |= PKCS15_USAGE_DERIVE;	/* I don't think so Tim */
	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
							  CRYPT_CERTINFO_KEYUSAGE );
	if( cryptStatusOK( status ) && \
		( value & CRYPT_KEYUSAGE_NONREPUDIATION ) )
		/* This may be a raw key or a cert with no keyUsage present so a
		   failure to read the usage attribute isn't a problem */
		keyUsage |= PKCS15_USAGE_NONREPUDIATION;
	if( !keyUsage )
		return( CRYPT_ERROR_PERMISSION );	/* No easy way to report this one */

	/* If this is a public-key object which is updating a private-key one, 
	   the only key usages we'll have found are public-key ones.  To ensure 
	   that we don't disable use of the private-key object, we copy across
	   private-key usages where corresponding public-key ones are enabled.
	   This is used, for example, when updating an unrestricted-usage raw
	   private key with a restricted-usage public key, e.g. from a
	   certificate */
	if( cryptStatusError( krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
										   MESSAGE_CHECK_PKC_PRIVATE ) ) )
		{
		if( keyUsage & PKCS15_USAGE_ENCRYPT )
			keyUsage |= pkcs15info->privKeyUsage & PKCS15_USAGE_DECRYPT;
		if( keyUsage & PKCS15_USAGE_VERIFY )
			keyUsage |= pkcs15info->privKeyUsage & PKCS15_USAGE_SIGN;
		}

	/* Determine how big the private key attribute collections will be */
	commonAttributeSize = ( int) sizeofObject( pkcs15info->labelLength );
	commonKeyAttributeSize = ( int ) sizeofObject( pkcs15info->iDlength ) + \
							 sizeofBitString( keyUsage ) + \
							 sizeofBitString( KEYATTR_ACCESS_PRIVATE );
	if( pkcs15info->validFrom )
		commonKeyAttributeSize += sizeofGeneralizedTime();
	if( pkcs15info->validTo )
		commonKeyAttributeSize += sizeofGeneralizedTime();

	/* Write the private key attributes */
	sMemOpen( &stream, privKeyAttributes, KEYATTR_BUFFER_SIZE );
	writeSequence( &stream, commonAttributeSize );
	writeCharacterString( &stream, ( BYTE * ) pkcs15info->label,
						  pkcs15info->labelLength, BER_STRING_UTF8 );
	writeSequence( &stream, commonKeyAttributeSize );
	writeOctetString( &stream, pkcs15info->iD, pkcs15info->iDlength,
					  DEFAULT_TAG );
	writeBitString( &stream, keyUsage, DEFAULT_TAG );
	writeBitString( &stream, KEYATTR_ACCESS_PRIVATE, DEFAULT_TAG );
	if( pkcs15info->validFrom )
		writeGeneralizedTime( &stream, pkcs15info->validFrom, DEFAULT_TAG );
	if( pkcs15info->validTo )
		writeGeneralizedTime( &stream, pkcs15info->validTo, CTAG_KA_VALIDTO );
	*privKeyAttributeSize = stell( &stream );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );
	pkcs15info->privKeyUsage = keyUsage;	/* Update stored usage info */

⌨️ 快捷键说明

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