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

📄 write.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
			int complianceLevel;

			/* PKIX allows empty subject DNs if a subject altName is present,
			   however creating certs like this breaks every cert-using 
			   protocol supported by cryptlib so we only allow it at the
			   highest compliance level.  In addition we have to be very
			   careful to ensure that the empty subject DN can't end up 
			   becoming an empty issuer DN, for example if it's a self-signed
			   or CA cert */
			if( status != CRYPT_ERROR_NOTINITED || \
				( type == CRYPT_CERTTYPE_CERTIFICATE && \
				  subjectCertInfoPtr->cCertCert->subjectUniqueID != NULL ) || \
				( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
				return( status );
			if( cryptStatusError( \
					krnlSendMessage( subjectCertInfoPtr->ownerHandle, 
									 IMESSAGE_GETATTRIBUTE, &complianceLevel, 
									 CRYPT_OPTION_CERT_COMPLIANCELEVEL ) ) || \
				complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL )
				/* We only allow this behaviour at the highest compliance 
				   level */
				return( status );
			attributeListPtr = \
				findAttributeField( subjectCertInfoPtr->attributes,
									CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE );
			if( attributeListPtr != NULL && attributeListPtr->intValue )
				/* It's a CA cert, the subject DN can't be empty */
				return( status );
			attributeListPtr = \
				findAttributeField( subjectCertInfoPtr->attributes,
									CRYPT_CERTINFO_SUBJECTALTNAME, 
									CRYPT_ATTRIBUTE_NONE );
			if( attributeListPtr == NULL )
				/* Either a subject DN or subject altName must be present */
				return( status );

			/* There's a subject altName present but no subject DN, mark the
			   altName as critical */
			attributeListPtr->flags |= ATTR_FLAG_CRITICAL;
			}

		/* If we're creating a non-self-signed cert, check whether the
		   subject's DN is the same as the issuer's DN.  If this is the case,
		   the resulting object would appear to be self-signed so we disallow
		   it */
		if( ( type == CRYPT_CERTTYPE_CERTIFICATE || \
			  type == CRYPT_CERTTYPE_ATTRIBUTE_CERT ) && \
			!( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
			compareDN( issuerCertInfoPtr->subjectName,
					   subjectCertInfoPtr->subjectName, FALSE ) )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_NOTINITED );
			}
		}

	/* Handle various default certificate extensions if necessary */
	if( type == CRYPT_CERTTYPE_CERTIFICATE || \
		type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		{
		/* Constrain the subject validity period to be within the issuer
		   validity period */
		if( subjectCertInfoPtr->startTime < issuerCertInfoPtr->startTime )
			subjectCertInfoPtr->startTime = issuerCertInfoPtr->startTime;
		if( subjectCertInfoPtr->endTime > issuerCertInfoPtr->endTime )
			subjectCertInfoPtr->endTime = issuerCertInfoPtr->endTime;

		/* If it's a >= v3 cert, add the standard X.509v3 extensions if these
		   aren't already present */
		if( ( type == CRYPT_CERTTYPE_CERTIFICATE ) && \
			( subjectCertInfoPtr->version >= 3 ) )
			{
			status = addStandardExtensions( subjectCertInfoPtr );
			if( cryptStatusError( status ) )
				return( status );
			}
		}
	if( type == CRYPT_CERTTYPE_CERTIFICATE || \
		type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
		( type == CRYPT_CERTTYPE_CRL && issuerCertInfoPtr != NULL ) )
		{
		/* Copy the issuer DN if this isn't already present */
		if( subjectCertInfoPtr->issuerName == NULL )
			{
			status = copyDN( &subjectCertInfoPtr->issuerName,
							 issuerCertInfoPtr->subjectName );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* Copy any required extensions from the issuer to the subject cert
		   if necessary */
		if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
			{
			status = copyIssuerAttributes( &subjectCertInfoPtr->attributes,
										   issuerCertInfoPtr->attributes,
										   subjectCertInfoPtr->type,
										   &subjectCertInfoPtr->errorLocus,
										   &subjectCertInfoPtr->errorType );
			if( cryptStatusError( status ) )
				return( status );
			}
		}
	if( type == CRYPT_CERTTYPE_CRL && issuerCertInfoPtr != NULL )
		{
		/* If it's a CRL, compare the revoked cert issuer DN and signer DN
		   to make sure we're not trying to revoke someone else's certs, and
		   prepare the revocation entries */
		if( !compareDN( subjectCertInfoPtr->issuerName,
						issuerCertInfoPtr->subjectName, FALSE ) )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			return( CRYPT_ERROR_INVALID );
			}
		}
	if( type == CRYPT_CERTTYPE_RTCS_RESPONSE )
		{
		/* If it's an RTCS response, prepare the cert status list entries
		   prior to encoding them */
		status = prepareCertStatusEntries( subjectCertInfoPtr->cCertVal->validityInfo,
										   &subjectCertInfoPtr->cCertVal->currentValidity,
										   &subjectCertInfoPtr->errorLocus,
										   &subjectCertInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( type == CRYPT_CERTTYPE_CRL || type == CRYPT_CERTTYPE_OCSP_RESPONSE )
		{
		/* If it's a CRL or OCSP response, prepare the revocation list
		   entries prior to encoding them */
		status = prepareRevocationEntries( subjectCertInfoPtr->cCertRev->revocations,
										   subjectCertInfoPtr->cCertRev->revocationTime,
										   &subjectCertInfoPtr->cCertRev->currentRevocation,
										   &subjectCertInfoPtr->errorLocus,
										   &subjectCertInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Now that we've set up the attributes, perform the remainder of the
	   checks.  Because RTCS is a CMS standard rather than PKIX, the RTCS 
	   attributes are CMS rather than certificate attributes */
	status = checkAttributes( ( type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
							  ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,
							  subjectCertInfoPtr->attributes,
							  &subjectCertInfoPtr->errorLocus,
							  &subjectCertInfoPtr->errorType );
	if( cryptStatusOK( status ) )
		status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr, FALSE,
							&subjectCertInfoPtr->errorLocus,
							&subjectCertInfoPtr->errorType );
	if( cryptStatusOK( status ) && \
		( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
		  subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) )
		subjectCertInfoPtr->cCertCert->maxCheckLevel = \
									CRYPT_COMPLIANCELEVEL_PKIX_FULL;

	return( status );
	}

/****************************************************************************
*																			*
*							Write a Certificate Object						*
*																			*
****************************************************************************/

/* Write certificate information:

	CertificateInfo ::= SEQUENCE {
		version			  [ 0 ]	EXPLICIT INTEGER DEFAULT(0),
		serialNumber			INTEGER,
		signature				AlgorithmIdentifier,
		issuer					Name
		validity				Validity,
		subject					Name,
		subjectPublicKeyInfo	SubjectPublicKeyInfo,
		extensions		  [ 3 ]	Extensions OPTIONAL
		} */

static int writeCertInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
						  const CERT_INFO *issuerCertInfoPtr,
						  const CRYPT_CONTEXT iIssuerCryptContext )
	{
	const CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;
	int length, extensionSize, status;

	/* Perform any necessary pre-encoding steps */
	if( sIsNullStream( stream ) )
		{
		status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
									   CRYPT_CERTTYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Determine how the issuer name will be encoded */
	subjectCertInfoPtr->issuerDNsize = \
							( issuerCertInfoPtr->subjectDNptr != NULL ) ? \
							issuerCertInfoPtr->subjectDNsize : \
							sizeofDN( subjectCertInfoPtr->issuerName );
	subjectCertInfoPtr->subjectDNsize = \
							sizeofDN( subjectCertInfoPtr->subjectName );

	/* Determine the size of the certificate information */
	extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
	length = sizeofInteger( certCertInfo->serialNumber,
							certCertInfo->serialNumberLength ) + \
			 sizeofContextAlgoID( iIssuerCryptContext, certCertInfo->hashAlgo,
								  ALGOID_FLAG_ALGOID_ONLY ) + \
			 subjectCertInfoPtr->issuerDNsize + \
			 sizeofObject( sizeofUTCTime() * 2 ) + \
			 subjectCertInfoPtr->subjectDNsize + \
			 subjectCertInfoPtr->publicKeyInfoSize;
	if( extensionSize > 0 )
		length += ( int ) \
				  sizeofObject( sizeofShortInteger( X509VERSION_3 ) ) + \
				  sizeofObject( sizeofObject( extensionSize ) );

	/* Write the outer SEQUENCE wrapper */
	writeSequence( stream, length );

	/* If there are extensions present, mark this as a v3 certificate */
	if( extensionSize )
		{
		writeConstructed( stream, sizeofShortInteger( X509VERSION_3 ),
						  CTAG_CE_VERSION );
		writeShortInteger( stream, X509VERSION_3, DEFAULT_TAG );
		}

	/* Write the serial number and signature algorithm identifier */
	writeInteger( stream, certCertInfo->serialNumber,
				  certCertInfo->serialNumberLength, DEFAULT_TAG );
	status = writeContextAlgoID( stream, iIssuerCryptContext, 
								 certCertInfo->hashAlgo,
								 ALGOID_FLAG_ALGOID_ONLY );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the issuer name, validity period, subject name, and public key
	   information */
	if( issuerCertInfoPtr->subjectDNptr != NULL )
		swrite( stream, issuerCertInfoPtr->subjectDNptr,
				issuerCertInfoPtr->subjectDNsize );
	else
		{
		status = writeDN( stream, subjectCertInfoPtr->issuerName, DEFAULT_TAG );
		if( cryptStatusError( status ) )
			return( status );
		}
	writeSequence( stream, sizeofUTCTime() * 2 );
	writeUTCTime( stream, subjectCertInfoPtr->startTime, DEFAULT_TAG );
	writeUTCTime( stream, subjectCertInfoPtr->endTime, DEFAULT_TAG );
	status = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = swrite( stream, subjectCertInfoPtr->publicKeyInfo,
						 subjectCertInfoPtr->publicKeyInfoSize );
	if( cryptStatusError( status ) || extensionSize <= 0 )
		return( status );

	/* Write the extensions */
	return( writeAttributes( stream, subjectCertInfoPtr->attributes,
							 CRYPT_CERTTYPE_CERTIFICATE, extensionSize ) );
	}

/* Write attribute certificate information:

	AttributeCertificateInfo ::= SEQUENCE {
		version					INTEGER DEFAULT(1),
		owner			  [ 1 ]	Name,
		issuer					Name,
		signature				AlgorithmIdentifier,
		serialNumber			INTEGER,
		validity				Validity,
		attributes				SEQUENCE OF Attribute,
		extensions				Extensions OPTIONAL
		} */

static int writeAttributeCertInfo( STREAM *stream,
								   CERT_INFO *subjectCertInfoPtr,
								   const CERT_INFO *issuerCertInfoPtr,
								   const CRYPT_CONTEXT iIssuerCryptContext )
	{
	const CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;
	int length, extensionSize, issuerNameSize, status;

	/* Perform any necessary pre-encoding steps */
	if( sIsNullStream( stream ) )
		{
		status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
									   CRYPT_CERTTYPE_ATTRIBUTE_CERT );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Determine how the issuer name will be encoded */
	issuerNameSize = ( issuerCertInfoPtr->subjectDNptr != NULL ) ? \
					 issuerCertInfoPtr->subjectDNsize : \
					 sizeofDN( subjectCertInfoPtr->issuerName );

	/* Determine the size of the certificate information */
	extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
	length = ( int ) sizeofObject( sizeofDN( subjectCertInfoPtr->subjectName ) ) + \
			 issuerNameSize + \
			 sizeofContextAlgoID( iIssuerCryptContext, certCertInfo->hashAlgo,
								  ALGOID_FLAG_ALGOID_ONLY ) + \
			 sizeofInteger( certCertInfo->serialNumber,
							certCertInfo->serialNumberLength ) + \
			 sizeofObject( sizeofUTCTime() * 2 ) + \
			 sizeofObject( 0 ) + \
			 ( extensionSize ? ( int ) sizeofObject( extensionSize ) : 0 );

	/* Write the outer SEQUENCE wrapper */
	writeSequence( stream, length );

	/* Write the owner and issuer name */
	writeConstructed( stream, sizeofDN( subjectCertInfoPtr->subjectName ),
					  CTAG_AC_ENTITYNAME );
	status = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		{
		if( issuerCertInfoPtr->subjectDNptr != NULL )
			swrite( stream, issuerCertInfoPtr->subjectDNptr,
					issuerCertInfoPtr->subjectDNsize );
		else
			status = writeDN( stream, subjectCertInfoPtr->issuerName, DEFAULT_TAG );
		}
	if( cryptStatusError( status ) )
		return( status );

⌨️ 快捷键说明

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