dbxpk15.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,715 行 · 第 1/5 页

C
1,715
字号
				pkcs15info->privKeyOffset = ( int ) stell( stream );
				break;

			case PKCS15_OBJECT_CERT:
			case PKCS15_OBJECT_TRUSTEDCERT:
			case PKCS15_OBJECT_USEFULCERT:
				pkcs15info->certOffset = ( int ) stell( stream );
				break;

			case PKCS15_OBJECT_DATA:
				readOIDSelection( stream, cryptlibDataOIDselection, &value );
				if( value != CRYPT_IATTRIBUTE_USERINFO )
					/* UserInfo is a straight object, the others are 
					   SEQUENCEs of objects */
					readSequence( stream, NULL );
				pkcs15info->dataType = value;
				pkcs15info->dataOffset = ( int ) stell( stream );
				break;
			}
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}

	return( status );
	}

/* 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 )
		{
		setResourceData( &msgData, pkcs15info->label, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_LABEL );
		if( cryptStatusError( status ) )
			return( status );
		pkcs15info->labelLength = msgData.length;
		setResourceData( &msgData, pkcs15info->keyID, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( cryptHandle, 
								  RESOURCE_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 which 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 */
	setResourceData( &msgData, sKIDbuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( cryptHandle, RESOURCE_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 which 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, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT ) ) )
		keyUsage = PKCS15_USAGE_ENCRYPT;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_DECRYPT ) ) )
		keyUsage |= PKCS15_USAGE_DECRYPT;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGN ) ) )
		keyUsage |= PKCS15_USAGE_SIGN;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK ) ) )
		keyUsage |= PKCS15_USAGE_VERIFY;
	if( cryptStatusOK( krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT ) ) || \
		cryptStatusOK( krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CHECK, 
								NULL, RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
		keyUsage |= PKCS15_USAGE_DERIVE;	/* I don't think so Tim */
	status = krnlSendMessage( cryptHandle, RESOURCE_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 */

	/* We've now got the usage allowed by the object we've been passed, 
	   however if it's a non-private-key object it'll only allow the public-
	   key half of any operation so we have to adjust the usage further to 
	   match the existing private-key operations to allowed public-key ones */
	if( cryptStatusError( krnlSendMessage( cryptHandle, 
									RESOURCE_IMESSAGE_CHECK, NULL, 
									RESOURCE_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 ) + \
							 sizeofBoolean() + 
							 sizeofBitString( KEYATTR_ACCESS_PRIVATE );

	/* 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 );
	writeBoolean( &stream, FALSE, DEFAULT_TAG );
	writeBitString( &stream, KEYATTR_ACCESS_PRIVATE, DEFAULT_TAG );
	*privKeyAttributeSize = ( int ) stell( &stream );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );
	pkcs15info->privKeyUsage = keyUsage;	/* Update stored usage info */

	/* Determine how big the public key attribute collections will be */
	keyUsage &= PUBKEY_USAGE_MASK;
	commonKeyAttributeSize = ( int ) sizeofObject( pkcs15info->iDlength ) + \
							 sizeofBitString( keyUsage ) + \
							 sizeofBoolean() + 
							 sizeofBitString( KEYATTR_ACCESS_PUBLIC );

	/* Write the public key attributes */
	sMemOpen( &stream, pubKeyAttributes, 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 );
	writeBoolean( &stream, FALSE, DEFAULT_TAG );
	writeBitString( &stream, KEYATTR_ACCESS_PUBLIC, DEFAULT_TAG );
	*pubKeyAttributeSize = ( int ) stell( &stream );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );
	pkcs15info->pubKeyUsage = keyUsage;		/* Update stored usage info */

	return( CRYPT_OK );
	}

static int writeCertAttributes( void *certAttributes, 
								int *certAttributeSize,
							    PKCS15_INFO *pkcs15info,
								const CRYPT_HANDLE cryptHandle )
	{
	STREAM stream;
	BOOLEAN trustedImplicit = FALSE;
	int isCA, trustedUsage, status;
	int commonAttributeSize, commonCertAttributeSize;
	int keyIdentifierDataSize, trustedUsageSize;

	/* Get various pieces of information from the object.  If we're adding a
	   standalone cert then the iD and keyID won't have been set up yet, so 
	   we need to set these up as well.  Since the cert could be a data-only 
	   cert, we create the iD ourselves from the encoded public key 
	   components rather than trying to read an associated context's keyID 
	   attribute.  For similar reasons we specifically don't try and read the 
	   PGP ID information since for a cert chain it'll come from the context 
	   of the leaf cert rather than the current cert (in any case they're not
	   necessary since none of the certs in the chain will be PGP keys */
	status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &isCA, CRYPT_CERTINFO_CA );
	if( status == CRYPT_ERROR_NOTFOUND )
		{
		isCA = FALSE;
		status = CRYPT_OK;
		}
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( cryptHandle, 
							RESOURCE_IMESSAGE_GETATTRIBUTE, &trustedUsage, 
							CRYPT_CERTINFO_TRUSTED_USAGE );
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			/* If there's no trusted usage defined, don't store a trust
			   setting */
			trustedUsage = CRYPT_UNUSED;
			status = CRYPT_OK;
			}
		}
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( cryptHandle, 
							RESOURCE_IMESSAGE_GETATTRIBUTE, &trustedImplicit, 
							CRYPT_CERTINFO_TRUSTED_IMPLICIT );
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			/* If it's not implicitly trusted, don't store a trust setting */
			trustedImplicit = FALSE;
			status = CRYPT_OK;
			}
		}
	if( cryptStatusOK( status ) )
		status = getValidityInfo( pkcs15info, cryptHandle );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		/* The PGP IDs are certificate (rather than key) attributes since,
		   at least for the OpenPGP ID, they require the presence of 
		   information which is only present in a certificate.  Since PGP
		   stores extra, non-key-related data with its keys it'd be a key
		   attribute for PGP, but for anything else it's a certificate
		   attribute */
		setResourceData( &msgData, pkcs15info->pgp2KeyID, PGP_KEYID_SIZE );
		status = krnlSendMessage( cryptHandle, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_PGP_KEYID );
		if( cryptStatusOK( status ) )
			/* Not present for all key types, so an error isn't fatal */
			pkcs15info->pgp2KeyIDlength = msgData.length;
		setResourceData( &msgData, pkcs15info->openPGPKeyID, PGP_KEYID_SIZE );
		status = krnlSendMessage( cryptHandle, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_OPENPGP_KEYID );
		pkcs15info->openPGPKeyIDlength = msgData.length;
		}
	if( cryptStatusError( status ) )
		return( status );
	if( !pkcs15info->iDlength )
		{
		status = getCertID( cryptHandle, CRYPT_IATTRIBUTE_SPKI, 
							pkcs15info->iD );
		if( cryptStatusError( status ) )
			return( status );
		pkcs15info->iDlength = KEYID_SIZE;
		}
	if( !pkcs15info->keyIDlength )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, pkcs15info->keyID, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
		if( cryptStatusOK( status ) )
			pkcs15info->keyIDlength = msgData.length;
		else
			{
			memcpy( pkcs15info->keyID, pkcs15info->iD, pkcs15info->iDlength );
			pkcs15info->keyIDlength = pkcs15info->iDlength;
			}
		}

	/* Calculate the various name ID's for the cert */
	status = getCertID( cryptHandle, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER, 
						pkcs15info->iAndSID );
	if( cryptStatusOK( status ) )
		status = getCertID( cryptHandle, CRYPT_IATTRIBUTE_SUBJECT, 
							pkcs15info->subjectNameID );
	if( cryptStatusOK( status ) )
		status = getCertID( cryptHandle, CRYPT_IATTRIBUTE_ISSUER, 
							pkcs15info->issuerNameID );
	if( cryptStatusError( status ) )
		return( status );
	pkcs15info->iAndSIDlength = pkcs15info->subjectNameIDlength = \
		pkcs15info->issuerNameIDlength = KEYID_SIZE;
	trustedUsageSize = ( trustedUsage != CRYPT_UNUSED ) ? \
					   sizeofBitString( trustedUsage ) : 0;
	keyIdentifierDataSize = ( int ) sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) +
				sizeofObject( pkcs15info->keyIDlength ) ) + \
							( int ) sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) +
				sizeofObject( pkcs15info->iAndSIDlength ) ) + \
							( int ) sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) +
				sizeofObject( pkcs15info->issuerNameIDlength ) ) + \
							( int ) sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_SUBJECTNAMEHASH ) +
				sizeofObject( pkcs15info->subjectNameIDlength ) ) + \
							( int ) ( pkcs15info->pgp2KeyIDlength ? \
									sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_PGP2 ) +
				sizeofObject( pkcs15info->pgp2KeyIDlength ) ) : 0 ) + \
							( int ) sizeofObject( \
				sizeofShortInteger( PKCS15_KEYID_OPENPGP ) +
				sizeofObject( pkcs15info->openPGPKeyIDlength ) );

	/* Determine how big the attribute collection will be */
	commonAttributeSize = pkcs15info->labelLength ? \
						  ( int) sizeofObject( pkcs15info->labelLength ) : 0;
	commonCertAttributeSize = ( int ) sizeofObject( pkcs15info->iDlength ) + \
							  ( isCA ? sizeofBoolean() : 0 ) + \
							  ( int ) sizeofObject( keyIdentifierDataSize + \
							  ( ( trustedUsage != CRYPT_UNUSED ) ? \
								( int ) sizeofObject( trustedUsageSize ) : 0 ) ) + \
							  ( trustedImplicit ? sizeofBoolean() : 0 ) + \
							  sizeofGeneralizedTime() + sizeofGeneralizedTime();

	/* Write the cert attributes */
	sMemOpen( &stream, certAttributes, KEYATTR_BUFFER_SIZE );
	writeSequence( &stream, commonAttributeSize );

⌨️ 快捷键说明

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