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

📄 pkcs15_rd.c

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

#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

/* The minimum size of an object in a keyset, used for sanity-checking when
   reading a keyset */

#define MIN_OBJECT_SIZE		16

/* OID information used to read a PKCS #15 file */

static const FAR_BSS OID_INFO dataOIDinfo[] = {
	{ OID_CMS_DATA, CRYPT_OK },
	{ NULL, 0 }
	};

static const FAR_BSS OID_INFO cryptlibDataOIDinfo[] = {
	{ OID_CRYPTLIB_CONFIGDATA, CRYPT_IATTRIBUTE_CONFIGDATA },
	{ OID_CRYPTLIB_USERINDEX, CRYPT_IATTRIBUTE_USERINDEX },
	{ OID_CRYPTLIB_USERINFO, CRYPT_IATTRIBUTE_USERINFO },
	{ NULL, 0 }
	};

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

/* Translate the PKCS #15 usage flags into cryptlib permitted actions.  The
   PKCS #11 use of the 'derive' flag to mean 'allow key agreement' is a bit
   of a kludge, we map it to allowing keyagreement export and import if it's
   a key-agreement algorithm, if there are further constraints they'll be 
   handled by the attached cert.  The PKCS #15 nonRepudiation flag doesn't 
   have any definition so we can't do anything with it, although we may need 
   to translate it to allowing signing and/or verification if implementations
   appear that expect it to be used this way */

static int getPermittedActions( const int usageFlags, 
								const CRYPT_ALGO_TYPE cryptAlgo )
	{
	int actionFlags = 0;

	if( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP ) )
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
	if( usageFlags & ( PKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) )
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
	if( usageFlags & PKCS15_USAGE_SIGN )
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
	if( usageFlags & PKCS15_USAGE_VERIFY )
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
	if( isKeyxAlgo( cryptAlgo ) && ( usageFlags & PKCS15_USAGE_DERIVE ) )
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \
					   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
	if( cryptAlgo == CRYPT_ALGO_RSA )
		{
		/* If there are any restrictions on the key usage, we have to make it
		   internal-only because of RSA's signature/encryption duality */
		if( !( ( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP | \
								PKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) ) && \
			   ( usageFlags & ( PKCS15_USAGE_SIGN | PKCS15_USAGE_VERIFY ) ) ) )
			actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
		}
	else
		/* Because of the special-case data formatting requirements for DLP 
		   algorithms, we make the usage internal-only */
		actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );

	return( !actionFlags ? CRYPT_ERROR_PERMISSION : actionFlags );
	}

/****************************************************************************
*																			*
*							Read PKCS #15 Attributes						*
*																			*
****************************************************************************/

/* Read a sequence of PKCS #15 key identifiers */

static int readKeyIdentifiers( STREAM *stream, PKCS15_INFO *pkcs15info,
							   const int length )
	{
	const int endPos = stell( stream ) + length;
	int status = CRYPT_OK;

	while( cryptStatusOK( status ) && stell( stream ) < endPos )
		{
		HASHFUNCTION hashFunction;
		void *iAndSPtr;
		long value;
		int hashSize, payloadLength, iAndSLength;

		/* Read each identifier type and copy the useful ones into the PKCS
		   #15 info */
		readSequence( stream, &payloadLength );
		status = readShortInteger( stream, &value );
		if( cryptStatusError( status ) )
			break;
		switch( value )
			{
			case PKCS15_KEYID_ISSUERANDSERIALNUMBER:
				/* Hash the full issuerAndSerialNumber to get an iAndSID */
				getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
				iAndSPtr = sMemBufPtr( stream );
				status = readSequence( stream, &iAndSLength );
				if( cryptStatusOK( status ) )
					status = sSkip( stream, iAndSLength );
				if( cryptStatusError( status ) )
					break;
				hashFunction( NULL, ( BYTE * ) pkcs15info->iAndSID, iAndSPtr,
							  ( int ) sizeofObject( iAndSLength ), HASH_ALL );
				pkcs15info->iAndSIDlength = hashSize;
				break;

			case PKCS15_KEYID_SUBJECTKEYIDENTIFIER:
				status = readOctetString( stream, pkcs15info->keyID,
								&pkcs15info->keyIDlength, CRYPT_MAX_HASHSIZE );
				break;

			case PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH:
				/* If we've already got the iAndSID by hashing the
				   issuerAndSerialNumber, use that version instead */
				if( pkcs15info->iAndSIDlength )
					{
					readUniversal( stream );
					continue;
					}
				status = readOctetString( stream, pkcs15info->iAndSID,
								&pkcs15info->iAndSIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_ISSUERNAMEHASH:
				status = readOctetString( stream, pkcs15info->issuerNameID,
								&pkcs15info->issuerNameIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_SUBJECTNAMEHASH:
				status = readOctetString( stream, pkcs15info->subjectNameID,
								&pkcs15info->subjectNameIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_PGP2:
				status = readOctetString( stream, pkcs15info->pgp2KeyID,
								&pkcs15info->pgp2KeyIDlength, PGP_KEYID_SIZE );
				break;

			case PKCS15_KEYID_OPENPGP:
				status = readOctetString( stream, pkcs15info->openPGPKeyID,
								&pkcs15info->openPGPKeyIDlength, PGP_KEYID_SIZE );
				break;

			default:
				status = readUniversal( stream );
			}
		}

	return( status );
	}

/* Read an object's attributes */

static int readObjectAttributes( STREAM *stream, PKCS15_INFO *pkcs15info,
								 const PKCS15_OBJECT_TYPE type )
	{
	int length, endPos, status;

	/* Clear the return value */
	memset( pkcs15info, 0, sizeof( PKCS15_INFO ) );

	/* Skip the outer header, which has already been checked when we read in
	   the object data */
	readGenericHole( stream, NULL, DEFAULT_TAG );

	/* Process the PKCS15CommonObjectAttributes */
	status = readSequence( stream, &length );
	if( cryptStatusOK( status ) && length > 0 )
		{
		endPos = stell( stream ) + length;

		/* Read the label if it's present and skip anything else */
		if( peekTag( stream ) == BER_STRING_UTF8 )
			status = readCharacterString( stream,
						( BYTE * ) pkcs15info->label, &pkcs15info->labelLength,
						CRYPT_MAX_TEXTSIZE, BER_STRING_UTF8 );
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Process the PKCS15CommonXXXAttributes */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	if( type == PKCS15_OBJECT_DATA )
		{
		/* It's a data object, make sure it's one of ours */
		status = readFixedOID( stream, OID_CRYPTLIB_CONTENTTYPE );
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	else
		{
		/* It's a key or cert object, read the ID and assorted flags */
		status = readOctetString( stream, pkcs15info->iD,
								  &pkcs15info->iDlength, CRYPT_MAX_HASHSIZE );
		if( cryptStatusError( status ) )
			return( status );
		if( type == PKCS15_OBJECT_PUBKEY || type == PKCS15_OBJECT_PRIVKEY )
			{
			int usageFlags;

			readBitString( stream, &usageFlags );		/* Usage flags */
			if( peekTag( stream ) == BER_BOOLEAN )		/* Native flag */
				status = readUniversal( stream );
			if( stell( stream ) < endPos &&				/* Access flags */
				peekTag( stream ) == BER_BITSTRING )
				status = readUniversal( stream );
			if( stell( stream ) < endPos &&				/* Key reference */
				peekTag( stream ) == BER_INTEGER )
				status = readUniversal( stream );
			if( stell( stream ) < endPos &&				/* Start date */
				peekTag( stream ) == BER_TIME_GENERALIZED )
				status = readGeneralizedTime( stream, 
									&pkcs15info->validFrom );
			if( stell( stream ) < endPos &&				/* End date */
				peekTag( stream ) == MAKE_CTAG( CTAG_KA_VALIDTO ) )
				status = readGeneralizedTimeTag( stream, 
									&pkcs15info->validTo, CTAG_KA_VALIDTO );
			if( type == PKCS15_OBJECT_PUBKEY )
				pkcs15info->pubKeyUsage = usageFlags;
			else
				pkcs15info->privKeyUsage = usageFlags;
			}
		else
			if( type == PKCS15_OBJECT_CERT )
				{
				if( peekTag( stream ) == BER_BOOLEAN )	/* Authority flag */
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&			/* Identifier */
					peekTag( stream ) == BER_SEQUENCE )
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&			/* Thumbprint */
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_DUMMY ) )
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&			/* Trusted usage */
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_TRUSTED_USAGE ) )
					{
					readConstructed( stream, NULL, CTAG_CA_TRUSTED_USAGE );
					status = readBitString( stream, &pkcs15info->trustedUsage );
					}
				if( stell( stream ) < endPos &&			/* Identifiers */
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_IDENTIFIERS ) )
					{
					status = readConstructed( stream, &length, 
											  CTAG_CA_IDENTIFIERS );
					if( cryptStatusOK( status ) )
						status = readKeyIdentifiers( stream, pkcs15info, 
													 length );
					}
				if( stell( stream ) < endPos &&			/* Implicitly trusted */
					peekTag( stream ) == \
							MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) )
					status = readBooleanTag( stream,
											 &pkcs15info->implicitTrust,
											 CTAG_CA_TRUSTED_IMPLICIT );
				if( peekTag( stream ) == MAKE_CTAG( CTAG_CA_VALIDTO ) )
					{
					/* Due to miscommunication between PKCS #15 and 7816-15,
					   there are two ways to encode the validity information
					   for certs, one based on the format used elsewhere in
					   PKCS #15 (for PKCS #15) and the other based on the 
					   format used in certs (for 7816-15).  Luckily they can
					   be distinguished by the tagging type */
					readConstructed( stream, NULL, CTAG_CA_VALIDTO );
					readUTCTime( stream, &pkcs15info->validFrom );
					status = readUTCTime( stream, &pkcs15info->validTo );
					}
				else
					{
					if( stell( stream ) < endPos &&		/* Start date */
						peekTag( stream ) == BER_TIME_GENERALIZED )
						status = readGeneralizedTime( stream, 
									&pkcs15info->validFrom );
					if( stell( stream ) < endPos &&		/* End date */
						peekTag( stream ) == MAKE_CTAG_PRIMITIVE( CTAG_CA_VALIDTO ) )
						status = readGeneralizedTimeTag( stream, 
														 &pkcs15info->validTo, 
													 CTAG_CA_VALIDTO );
					}
				}
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* For now we use the iD as the keyID, this may be overridden later if
	   there's a real keyID present */
	memcpy( pkcs15info->keyID, pkcs15info->iD, pkcs15info->iDlength );
	pkcs15info->keyIDlength = pkcs15info->iDlength;

	/* Skip the public/private key attributes if present */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_OB_SUBCLASSATTR ) )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Process the type attributes, which just consists of remembering where
	   the payload starts */
	readConstructed( stream, NULL, CTAG_OB_TYPEATTR );
	status = readSequence( stream, &length );
	endPos = stell( stream ) + length;
	if( cryptStatusOK( status ) )
		{
		int value;

		switch( type )
			{
			case PKCS15_OBJECT_PUBKEY:
				readConstructed( stream, NULL, CTAG_OV_DIRECT );
				pkcs15info->pubKeyOffset = stell( stream );
				break;

			case PKCS15_OBJECT_PRIVKEY:
				pkcs15info->privKeyOffset = stell( stream );
				break;

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

			case PKCS15_OBJECT_DATA:
				readOID( stream, cryptlibDataOIDinfo, &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 = stell( stream );
				break;
			}
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}

	return( status );
	}

/* Read an entire keyset */

⌨️ 快捷键说明

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