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

📄 certcset.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*							Set Certificate Components						*
*						Copyright Peter Gutmann 1997-2003					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "cert.h"
  #include "certattr.h"
  #include "../misc/asn1_rw.h"
  #include "../misc/asn1s_rw.h"
#else
  #include "cert/cert.h"
  #include "cert/certattr.h"
  #include "misc/asn1_rw.h"
  #include "misc/asn1s_rw.h"
#endif /* Compiler-specific includes */

/* Prototypes for functions in certcget.c */

int moveCursorToField( CERT_INFO *certInfoPtr,
					   const CRYPT_ATTRIBUTE_TYPE certInfoType );
int selectGeneralName( CERT_INFO *certInfoPtr,
					   const CRYPT_ATTRIBUTE_TYPE certInfoType,
					   const SELECTION_OPTION option );
int selectDN( CERT_INFO *certInfoPtr, const CRYPT_ATTRIBUTE_TYPE certInfoType,
			  const SELECTION_OPTION option );
void syncSelection( CERT_INFO *certInfoPtr );

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Set the serial number for a certificate.  Ideally we would store this as 
   a static value in the configuration database, but this has three 
   disadvantages: Updating the serial number updates the entire 
   configuration database (including things the user might not want 
   updated), if the config database update fails the serial number never 
   changes, and the predictable serial number allows tracking of the number 
   of certificates which have been issued by the CA.  Because of this, we 
   just use a 64-bit nonce if the user doesn't supply a value */

int setSerialNumber( CERT_INFO *certInfoPtr, const void *serialNumber, 
					 const int serialNumberLength )
	{
	RESOURCE_DATA msgData;
	void *serialNumberPtr;
	BYTE buffer[ 128 ];
	int length = ( serialNumberLength > 0 ) ? serialNumberLength : 8;
	int bufPos, status;

	assert( ( serialNumber == NULL && serialNumberLength == 0 ) || \
			( serialNumber != NULL && serialNumberLength > 0 ) );

	/* If a serial number has already been set explicitly, don't override
	   it with an implicitly-set one */
	if( certInfoPtr->serialNumber != NULL )
		{
		assert( serialNumber == NULL && serialNumberLength == 0 );
		return( CRYPT_OK );
		}

	/* If we're using user-supplied serial number data, canonicalise it into 
	   a form suitable for use as an INTEGER-hole */
	if( serialNumber != NULL )
		{
		STREAM stream;

		sMemOpen( &stream, buffer, 128 );
		status = writeInteger( &stream, serialNumber, serialNumberLength, 
							   DEFAULT_TAG );
		length = stell( &stream ) - 2;
		sMemDisconnect( &stream );
		bufPos = 2;		/* Skip tag + length */
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		{
		/* Generate a random serial number and ensure that the first byte of 
		   the value we use is nonzero (to guarantee a DER encoding) and 
		   clear the high bit to provide a constant-length ASN.1 encoded 
		   value */
		setMessageData( &msgData, buffer, 16 );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusError( status ) )
			return( status );
		for( bufPos = 0; bufPos < length; bufPos++ )
			if( buffer[ bufPos ] )
				break;
		if( bufPos >= length )
			buffer[ bufPos ] = 1;
		buffer[ bufPos ] &= 0x7F;
		}

	/* Copy across the canonicalised serial number value */
	if( length < SERIALNO_BUFSIZE )
		certInfoPtr->serialNumber = certInfoPtr->serialNumberBuffer;
	else
		{
		if( ( serialNumberPtr = clDynAlloc( "setSerialNumber", \
											length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		certInfoPtr->serialNumber = serialNumberPtr;
		}
	memcpy( certInfoPtr->serialNumber, buffer + bufPos, length );
	certInfoPtr->serialNumberLength = length;

	return( CRYPT_OK );
	}

/* Copy the encoded issuer DN */

static int copyIssuerDnData( CERT_INFO *destCertInfoPtr,
						 const CERT_INFO *srcCertInfoPtr )
	{
	void *dnDataPtr;

	assert( srcCertInfoPtr->issuerDNptr != NULL );

	if( ( dnDataPtr = clAlloc( "copyIssuerDnData",
							   srcCertInfoPtr->issuerDNsize ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memcpy( dnDataPtr, srcCertInfoPtr->issuerDNptr,
			srcCertInfoPtr->issuerDNsize );
	destCertInfoPtr->issuerDNptr = destCertInfoPtr->issuerDNdata = dnDataPtr;
	destCertInfoPtr->issuerDNsize = srcCertInfoPtr->issuerDNsize;

	return( CRYPT_OK );
	}

/* Copy revocation information into a CRL or revocation request */

static int copyRevocationInfo( CERT_INFO *certInfoPtr,
							   const CERT_INFO *revInfoPtr )
	{
	int status = CRYPT_OK;

	assert( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
			certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION );

	/* If there's an issuer name recorded, make sure that it matches the one
	   in the cert that's being added */
	if( certInfoPtr->issuerDNptr != NULL )
		{
		if( certInfoPtr->issuerDNsize != revInfoPtr->issuerDNsize || \
			memcmp( certInfoPtr->issuerDNptr, revInfoPtr->issuerDNptr,
					certInfoPtr->issuerDNsize ) )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			status = CRYPT_ERROR_INVALID;
			}
		}
	else
		/* There's no issuer name present yet, set the CRL issuer name to
		   the cert's issuer to make sure that we can't add certs or sign
		   the CRL with a different issuer.  We do this here rather than
		   after setting the revocation list entry because of the
		   difficulty of undoing the revocation entry addition */
		status = copyIssuerDnData( certInfoPtr, revInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Add the cert information to the revocation list and make it the
	   currently selected entry.  The ID type isn't quite an 
	   issueAndSerialNumber, but the checking code eventually converts 
	   it into this form using the supplied issuer cert DN  */
	status = addRevocationEntry( &certInfoPtr->revocations,
								 &certInfoPtr->currentRevocation,
								 CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
								 revInfoPtr->serialNumber,
								 revInfoPtr->serialNumberLength, FALSE );
	if( status == CRYPT_ERROR_DUPLICATE )
		/* If this cert is already present in the list, set the extended
		   error code for it */
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
	return( status );
	}

/* Convert a DN in string form into a certificate DN */

static int getEncodedDn( CERT_INFO *certInfoPtr, const void *dnString, 
						 const int dnStringLength )
	{
	SELECTION_STATE savedState;
	int status;

	/* If there's already a DN set, we can't do anything else */
	saveSelectionState( savedState, certInfoPtr );
	status = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE, MUST_BE_PRESENT );
	if( cryptStatusOK( status ) && \
		*certInfoPtr->currentSelection.dnPtr == NULL )
		/* There's a DN selected but it's empty, we're OK */
		status = CRYPT_ERROR;
	restoreSelectionState( savedState, certInfoPtr );
	if( cryptStatusOK( status ) )
		return( CRYPT_ERROR_INITED );
	status = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE, CREATE_IF_ABSENT );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the entire DN from its string form into the selected DN */
	status = readDNstring( dnString, dnStringLength,
						   certInfoPtr->currentSelection.dnPtr );
	if( cryptStatusOK( status ) && \
		certInfoPtr->currentSelection.updateCursor )
		/* If we couldn't update the cursor earlier on because the attribute 
		   field in question hadn't been created yet, do it now */
		selectGeneralName( certInfoPtr,
						   certInfoPtr->currentSelection.generalName,
						   MAY_BE_ABSENT );
	return( status );
	}

/* The OCSPv1 ID doesn't contain any usable fields so we pre-encode it when
   the cert is added to the OCSP request and treat it as a blob thereafter */

static int writeOCSPv1ID( STREAM *stream, const CERT_INFO *certInfoPtr,
						  const void *issuerKeyHash )
	{
	HASHFUNCTION hashFunction;
	BYTE hashBuffer[ CRYPT_MAX_HASHSIZE ];
	int hashSize;

	assert( certInfoPtr->issuerDNptr != NULL );
	assert( certInfoPtr->serialNumber != NULL );

	/* Get the issuerName hash */
	getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
	hashFunction( NULL, hashBuffer, certInfoPtr->issuerDNptr,
				  certInfoPtr->issuerDNsize, HASH_ALL );

	/* Write the request data */
	writeSequence( stream, sizeofAlgoID( CRYPT_ALGO_SHA ) + \
						   sizeofObject( hashSize ) + \
						   sizeofObject( hashSize ) + \
						   sizeofInteger( certInfoPtr->serialNumber,
										  certInfoPtr->serialNumberLength ) );
	writeAlgoID( stream, CRYPT_ALGO_SHA );
	writeOctetString( stream, hashBuffer, hashSize, DEFAULT_TAG );
	writeOctetString( stream, issuerKeyHash, 20, DEFAULT_TAG );
	return( writeInteger( stream, certInfoPtr->serialNumber,
						  certInfoPtr->serialNumberLength, DEFAULT_TAG ) );
	}

/****************************************************************************
*																			*
*								Copy Cert Info								*
*																			*
****************************************************************************/

/* Copy public key data into a certificate object */

static int copyPublicKeyInfo( CERT_INFO *certInfoPtr,
							  const CRYPT_HANDLE cryptHandle,
							  const CERT_INFO *srcCertInfoPtr )
	{
	void *publicKeyInfoPtr;
	int length, status;

	assert( ( checkHandleRange( cryptHandle ) && srcCertInfoPtr == NULL ) || \
			( !checkHandleRange( cryptHandle ) && srcCertInfoPtr != NULL ) );

	/* Make sure that we haven't already got a public key present */
	if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
		certInfoPtr->publicKeyInfo != NULL )
		{
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( CRYPT_ERROR_INITED );
		}

	/* If we've been given a data-only cert, copy over the public key data */
	if( srcCertInfoPtr != NULL )
		{
		assert( srcCertInfoPtr->publicKeyAlgo > CRYPT_ALGO_NONE );
		assert( memcmp( srcCertInfoPtr->publicKeyID, 
						"\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) );
		assert( ( ( BYTE * ) srcCertInfoPtr->publicKeyInfo )[ 0 ] == 0x30 );

		length = srcCertInfoPtr->publicKeyInfoSize;
		if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo", length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		memcpy( publicKeyInfoPtr, srcCertInfoPtr->publicKeyInfo, length );
		certInfoPtr->publicKeyAlgo = srcCertInfoPtr->publicKeyAlgo;
		certInfoPtr->publicKeyFeatures = srcCertInfoPtr->publicKeyFeatures;
		memcpy( certInfoPtr->publicKeyID, srcCertInfoPtr->publicKeyID,
				KEYID_SIZE );
		}
	else
		{
		CRYPT_CONTEXT iCryptContext;
		RESOURCE_DATA msgData;

		/* Get the context handle.  All other checking has already been
		   performed by the kernel */
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT,
								  &iCryptContext, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			return( status );
			}
		assert( cryptStatusOK( \
					krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
									 MESSAGE_CHECK_PKC ) ) );

		/* Get the key information */
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
								  &certInfoPtr->publicKeyAlgo, 
								  CRYPT_CTXINFO_ALGO );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
									  &certInfoPtr->publicKeyFeatures, 
									  CRYPT_IATTRIBUTE_KEYFEATURES );
		if( cryptStatusOK( status ) )
			{
			setMessageData( &msgData, certInfoPtr->publicKeyID, KEYID_SIZE );
			status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, 
									  &msgData, CRYPT_IATTRIBUTE_KEYID );
			}
		if( cryptStatusError( status ) )
			return( status );

		/* Copy over the public-key data.  We copy the data rather than 
		   keeping a reference to the context for two reasons.  Firstly, 
		   when the cert is transitioned into the high state it will 
		   constrain the attached context, so a context shared between two 
		   certs could be constrained in unexpected ways.  Secondly, the 
		   context could be a private-key context, and attaching that to a 
		   cert would be rather inappropriate.  Furthermore, the constraint 
		   issue is even more problematic in that a context constrained by 
		   an encryption-only request could then no longer be used to sign 
		   the request or a PKI protocol message containing the request */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
		if( cryptStatusOK( status ) )
			{
			length = msgData.length;
			if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo",
											  length ) ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			}
		if( cryptStatusError( status ) )
			return( status );
		msgData.data = publicKeyInfoPtr;
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
		if( cryptStatusError( status ) )
			return( status );
		}
	certInfoPtr->publicKeyData = certInfoPtr->publicKeyInfo = \
		publicKeyInfoPtr;
	certInfoPtr->publicKeyInfoSize = length;
	certInfoPtr->flags |= CERT_FLAG_DATAONLY;

	return( CRYPT_OK );
	}

/* Copy cert request info into a certificate object.  This copies the public 
   key context, the DN, any valid attributes, and any other relevant bits and 
   pieces if it's a CRMF request */

static int copyCertReqInfo( CERT_INFO *certInfoPtr,
							CERT_INFO *certRequestInfoPtr )
	{
	int status;

	assert( certRequestInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
			certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );

	/* Copy the public key context, the DN, and the attributes.  Type 
	   checking has already been performed by the kernel.  We copy the 
	   attributes across after the DN because that copy is the hardest to 
	   undo: If there are already attributes present, the copied attributes 
	   will be mixed in among them so it's not really possible to undo the 
	   copy later without performing a complex selective delete */
	status = copyDN( &certInfoPtr->subjectName,
					 certRequestInfoPtr->subjectName );
	if( cryptStatusOK( status ) )
		{
		if( certRequestInfoPtr->flags & CERT_FLAG_DATAONLY )
			status = copyPublicKeyInfo( certInfoPtr, CRYPT_UNUSED,
										certRequestInfoPtr );
		else
			status = copyPublicKeyInfo( certInfoPtr, 
										certRequestInfoPtr->iPubkeyContext,	
										NULL );
		}
	if( cryptStatusOK( status ) && \
		certRequestInfoPtr->attributes != NULL )
		{
		status = copyAttributes( &certInfoPtr->attributes,
								 certRequestInfoPtr->attributes,
								 &certInfoPtr->errorLocus,
								 &certInfoPtr->errorType );
		if( cryptStatusError( status ) )

⌨️ 快捷键说明

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