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

📄 read.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:

	/* Skip the outer SEQUENCE and read the version number */
	readSequence( stream, NULL );
	status = readShortInteger( stream, &version );
	if( cryptStatusError( status ) )
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
								 status ) );
	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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCrmfRequestInfo( INOUT STREAM *stream, 
								INOUT CERT_INFO *certInfoPtr )
	{
	int tag, fieldsProcessed = 0, length, endPos, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Skip the outer SEQUENCE, request ID, and inner SEQUENCE */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	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 ) && \
		   fieldsProcessed++ < 8 )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );
	if( fieldsProcessed >= 8 )
		{
		/* We should have hit something useful by this point */
		return( CRYPT_ERROR_BADDATA );
		}

	/* 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 ) )
		{
		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 );

	/* The request may contain additional data that doesn't apply to the
	   request itself but to the management of the request (which means that 
	   it should actually be part of the management protocol and not the 
	   request data).  Because we can't do anything with this information, 
	   we just skip it if it's present */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		readUniversal( stream );	/* Skip request management info */

	/* 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 );
	if( cryptStatusError( tag ) )
		return( tag );
	tag = EXTRACT_CTAG( tag );
	if( tag == CTAG_CF_POP_SIGNATURE )
		{
		/* It's a signature, the request is self-signed */
		certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
		}
	else
		{
		/* If it's neither a signature nor an indication that private-key 
		   POP will be performed by returning the certificate in encrypted 
		   form we can't do anything with it */
		if( tag != CTAG_CF_POP_ENCRKEY )
			return( CRYPT_ERROR_BADDATA );
		}
	return( readConstructed( stream, NULL, EXTRACT_CTAG( tag ) ) );
	}

/* 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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readRevRequestInfo( INOUT STREAM *stream, 
							   INOUT CERT_INFO *certInfoPtr )
	{
	int length, endPos, fieldsProcessed = 0, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Find out how much certificate 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 ) && \
		   fieldsProcessed++ < 8 )
		status = readUniversal( stream );
	if( cryptStatusOK( status ) )
		status = readSerialNumber( stream, certInfoPtr,
								   CTAG_CF_SERIALNUMBER );
	if( cryptStatusError( status ) )
		return( status );
	if( fieldsProcessed >= 8 )
		{
		/* We should have hit something useful by this point */
		return( CRYPT_ERROR_BADDATA );
		}

	/* 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 */
	for( fieldsProcessed = 0;
		 cryptStatusOK( status ) && \
			stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE && \
			fieldsProcessed < 8; fieldsProcessed++ )
		{
		const int tag = peekTag( stream );

		if( cryptStatusError( tag ) )
			return( tag );
		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 );
				}
			}
		else
			status = readUniversal( stream );
		}
	if( cryptStatusError( status ) )
		return( status );
	if( fieldsProcessed >= 8 )
		{
		/* We shouldn't encounter this many bits of junk */
		return( CRYPT_ERROR_BADDATA );
		}

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

/* Read an RTCS request/response */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readRtcsRequestInfo( INOUT STREAM *stream, 
								INOUT CERT_INFO *certInfoPtr )
	{
	CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
	int length, endPos, fieldsProcessed, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Read the outer wrapper and SEQUENCE OF request info and make the
	   currently selected one the start of the list */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	status = readSequence( stream, &length );
	for( fieldsProcessed = 0;
		 cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE && \
			fieldsProcessed < FAILSAFE_ITERATIONS_LARGE; 
		 fieldsProcessed++ )
		{
		const int innerStartPos = stell( stream );

		status = readRtcsRequestEntry( stream, &certValInfo->validityInfo,
									   certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusOK( status ) && \
		fieldsProcessed >= FAILSAFE_ITERATIONS_LARGE )
		status = CRYPT_ERROR_OVERFLOW;
	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 ) );
		}
	certValInfo->currentValidity = certValInfo->validityInfo;

	/* Read the extensions if there are any present.  Because some requests
	   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_RTCS_REQUEST, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readRtcsResponseInfo( INOUT STREAM *stream, 
								 INOUT CERT_INFO *certInfoPtr )
	{
	CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
	int length, endPos, fieldsProcessed, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Read the SEQUENCE OF validity info and make the currently selected
	   one the start of the list */
	status = readSequence( stream, &length );
	endPos = stell( stream ) + length;
	for( fieldsProcessed = 0;
		 cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE && \
			fieldsProcessed < FAILSAFE_ITERATIONS_LARGE;
		 fieldsProcessed++ )
		{
		const int innerStartPos = stell( stream );

		status = readRtcsResponseEntry( stream, &certValInfo->validityInfo,
										certInfoPtr, FALSE );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusOK( status ) && \
		fieldsProcessed >= FAILSAFE_ITERATIONS_LARGE )
		status = CRYPT_ERROR_OVERFLOW;
	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,

⌨️ 快捷键说明

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