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

📄 read.c

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

	/* Read the subject and issuer names */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_AC_BASECERTIFICATEID ) )
		{
		/* !!!!!!!!!!!! */
		return( CRYPT_ERROR );	/* Not handled yet */
		}
	if( peekTag( stream ) == MAKE_CTAG( CTAG_AC_ENTITYNAME ) )
		{
		readConstructed( stream, NULL, CTAG_AC_ENTITYNAME );
		status = readSubjectDN( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip the signature algorithm information.  This was included to avert
	   a somewhat obscure attack that isn't possible anyway because of the
	   way the signature data is encoded in PKCS #1 sigs (although it's still
	   possible for some of the ISO sig.types) so there's no need to record
	   it */
	readUniversal( stream );

	/* Read the serial number and validity information */
	status = readSerialNumber( stream, certInfoPtr, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = readValidity( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip the attributes for now since these aren't really defined yet */
	readUniversal( stream );

	/* Read the issuer unique ID if there's one present */
	if( peekTag( stream ) == BER_BITSTRING )
		{
		status = readUniqueID( stream, certInfoPtr, 
							   CRYPT_CERTINFO_ISSUERUNIQUEID );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Read the extensions if there are any present.  Because some certs will
	   have broken encoding of lengths, we allow for a bit of slop for
	   software that gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_ATTRIBUTE_CERT, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );

	return( status );
	}

/* Read the information in a CRL.  We read various lengths as long values 
   since CRLs can get quite large */

static int readCRLInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	long length, endPos;
	int status;

	/* If it's a standalone CRL entry, read the single entry and return */
	if( certInfoPtr->flags & CERT_FLAG_CRLENTRY )
		return( readCRLentry( stream, &certRevInfo->revocations, 
							  &certInfoPtr->errorLocus, 
							  &certInfoPtr->errorType ) );

	/* Read the outer SEQUENCE and version number if it's present */
	status = readLongSequence( stream, &length );
	if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
		/* If it's an (invalid) indefinite-length encoding we can't do 
		   anything with it */
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		return( status );
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == BER_INTEGER )
		{
		long version;

		readShortInteger( stream, &version );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else	
		certInfoPtr->version = 1;

	/* Skip the signature algorithm information.  This was included to avert
	   a somewhat obscure attack that isn't possible anyway because of the
	   way the signature data is encoded in PKCS #1 sigs (although it's still
	   possible for some of the ISO sig.types) so there's no need to record
	   it */
	readUniversal( stream );

	/* Read the issuer name, update time, and optional next update time */
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );
	status = readUTCTime( stream, &certInfoPtr->startTime );
	if( cryptStatusError( status ) )
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_THISUPDATE,
								 status ) );
	if( peekTag( stream ) == BER_TIME_UTC )
		{
		status = readUTCTime( stream, &certInfoPtr->endTime );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_NEXTUPDATE,
									 status ) );
		}

	/* Read the SEQUENCE OF revoked certs and make the currently selected one
	   the start of the list */
	if( stell( stream ) < endPos - MIN_ATTRIBUTE_SIZE && \
		peekTag( stream ) == BER_SEQUENCE )
		{
		status = readLongSequence( stream, &length );
		if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
			/* If it's an (invalid) indefinite-length encoding we can't do 
			   anything with it */
			status = CRYPT_ERROR_BADDATA;
		while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
			{
			const long innerStartPos = stell( stream );

			status = readCRLentry( stream, &certRevInfo->revocations, 
								   &certInfoPtr->errorLocus, 
								   &certInfoPtr->errorType );
			length -= stell( stream ) - innerStartPos;
			}
		if( cryptStatusError( status ) )
			/* The invalid attribute isn't quite a user certificate, but 
			   it's the data that arose from a user certificate so it's the 
			   most appropriate locus for the error */
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE, 
									 status ) );
		certRevInfo->currentRevocation = certRevInfo->revocations;
		}

	/* Read the extensions if there are any present.  Because some CRL's will
	   have broken encoding of lengths, we allow for a bit of slop for
	   software that gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_CRL, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

/* Read CMS attributes */

static int readCmsAttributes( STREAM *stream, CERT_INFO *attributeInfoPtr )
	{
	/* CMS attributes are straight attribute objects so we just pass the call
	   through */
	return( readAttributes( stream, &attributeInfoPtr->attributes,
							CRYPT_CERTTYPE_CMS_ATTRIBUTES, CRYPT_UNUSED,
							&attributeInfoPtr->errorLocus,
							&attributeInfoPtr->errorType ) );
	}

/* Read the information in a certification request */

static int readCertRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	long version;
	int status;

	/* Skip the outer SEQUENCE and read the version number */
	readSequence( stream, NULL );
	readShortInteger( stream, &version );
	certInfoPtr->version = version + 1;	/* Zero-based */

	/* Read the subject name and public key information */
	status = readSubjectDN( stream, certInfoPtr );
	if( cryptStatusOK( status ) )
		status = readPublicKeyInfo( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the attributes */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CR_ATTRIBUTES ) )
		{
		int length;
		
		status = readConstructed( stream, &length, CTAG_CR_ATTRIBUTES );
		if( cryptStatusOK( status ) && length >= MIN_ATTRIBUTE_SIZE )
			status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_CERTREQUEST, length, 
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	status = fixAttributes( certInfoPtr );

	/* Certification requests are always self-signed */
	certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
	return( status );
	}

/* Read the information in a CRMF certificate request.  We enforce the
   requirement that the request must contain at least a subject DN and a
   public key */

static int readCrmfRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	int tag, status;

	/* Skip the outer SEQUENCE, request ID, and inner SEQUENCE */
	readSequence( stream, NULL );
	readUniversal( stream );
	status = readSequence( stream, NULL );

	/* Skip any junk before the Validity, SubjectName, or 
	   SubjectPublicKeyInfo (the semantics of what we're stripping are at 
	   best undefined (version), at worst dangerous (serialNumber) */
	while( cryptStatusOK( status ) && \
		   ( peekTag( stream ) != MAKE_CTAG( CTAG_CF_VALIDITY ) && \
		     peekTag( stream ) != MAKE_CTAG( CTAG_CF_SUBJECT ) && \
			 peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) ) )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );

	/* If there's validity data present, read it */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_VALIDITY ) )
		{
		status = readCrmfValidity( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Read the subject name and public key information */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_SUBJECT ) )
		{
		readConstructed( stream, NULL, CTAG_CF_SUBJECT );
		status = readSubjectDN( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) )
		status = CRYPT_ERROR_BADDATA;
	else
		/* Read the public key information.  CRMF uses yet more nonstandard 
		   tagging for the public key, in theory we'd have to read it with 
		   the CTAG_CF_PUBLICKEY tag instead of the default SEQUENCE, 
		   however the public-key-read code reads the SPKI encapsulation as 
		   a generic hole to handle this so there's no need for any special 
		   handling */
		status = readPublicKeyInfo( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( certErrorReturn( certInfoPtr, 
							CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, status ) );

	/* Read the attributes */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )
		{
		int length;

		status = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );
		if( cryptStatusOK( status ) && length >= MIN_ATTRIBUTE_SIZE )
			status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_REQUEST_CERT, length, 
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	status = fixAttributes( certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* CRMF requests are usually self-signed, however if they've been 
	   generated with an encryption-only key then the place of the signature
	   is taken by one of a number of magic values which indicate that no 
	   signature is present and that something else needs to be done to 
	   verify that the sender has the private key */
	tag = peekTag( stream );
	status = readConstructed( stream, NULL, tag );
	if( tag == MAKE_CTAG( 1 ) )
		/* It's a signature, the request is self-signed */
		certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
	else
		/* If it's not an indication that private-key POP will be performed 
		   by returning the cert in encrypted form, we can't handle it */
		if( tag != MAKE_CTAG( 2 ) )
			return( CRYPT_ERROR_BADDATA );
	return( status );
	}

/* Read the information in a CRMF revocation request.  We enforce the
   requirement that the request must contain at least an issuer DN and a
   serial number */

static int readRevRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	int length, endPos, status;

	/* Find out how much cert template is present */
	status = readSequence( stream, &length );
	endPos = stell( stream ) + length;

	/* Skip any junk before the serial number and read the serial number */
	while( cryptStatusOK( status ) && \
		   peekTag( stream ) != MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ) )
		status = readUniversal( stream );
	if( cryptStatusOK( status ) )
		status = readSerialNumber( stream, certInfoPtr, 
								   CTAG_CF_SERIALNUMBER );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip any junk before the issuer name and read the issuer name.  We 
	   don't actually care about the contents but we have to decode them 
	   anyway in case the caller wants to view them */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_SIGNINGALG ) )
		status = readUniversal( stream );
	if( cryptStatusOK( status ) )
		{
		readConstructed( stream, NULL, CTAG_CF_ISSUER );
		status = readIssuerDN( stream, certInfoPtr );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Skip any further junk that may be present in the template and read 
	   the attributes */
	while( cryptStatusOK( status ) && \
		   stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		const int tag = peekTag( stream );
		
		if( tag == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )
			{
			status = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );
			if( cryptStatusOK( status ) && length >= MIN_ATTRIBUTE_SIZE )
				status = readAttributes( stream, &certInfoPtr->attributes,
										 CRYPT_CERTTYPE_REQUEST_REVOCATION, 
										 length, &certInfoPtr->errorLocus, 
										 &certInfoPtr->errorType );

⌨️ 快捷键说明

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