certrd.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,383 行 · 第 1/4 页

C
1,383
字号
		int fixEmailAddress;

		krnlSendMessage( certInfoPtr->ownerHandle, 
						 RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress, 
						 CRYPT_OPTION_CERT_FIXEMAILADDRESS );
		if( fixEmailAddress )
			status = convertEmailAddress( certInfoPtr );
		}

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

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

int readCRMFRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	int status;

	/* Skip the outer SEQUENCE, request ID, and inner SEQUENCE (these have 
	   already been checked earlier on) */
	readSequence( stream, NULL );
	readUniversal( stream );
	status = readSequence( stream, NULL );

	/* Skip any junk before the Validity, SubjectName, or 
	   SubjectPublicKeyInfo */
	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->startTime,
								   &certInfoPtr->endTime, 
								   &certInfoPtr->errorLocus );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, certInfoPtr->errorLocus, 
									 status ) );

		/* Skip any subsequent junk until we find the subject name or public 
		   key */
		while( cryptStatusOK( status ) && \
			   ( peekTag( stream ) != MAKE_CTAG( CTAG_CF_SUBJECT ) && \
				 peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) ) )
			status = readUniversal( stream );
		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 );
		}
	certInfoPtr->publicKeyInfo = sMemBufPtr( stream );
	if( certInfoPtr->flags & CERT_FLAG_DATAONLY )
		/* We're doing deferred handling of the public key, skip it for now */
		status = readUniversal( stream );
	else
		/* CRMF uses yet more nonstandard tagging for the public key, so we 
		   have to read it with an oddball tag instead of the default 
		   SEQUENCE */
		status = readPublicKey( stream, &certInfoPtr->iCryptContext, 
								READKEY_OPTION_NONE, 
								MAKE_CTAG( CTAG_CF_PUBLICKEY ) );
	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 );
		}

	/* Convert an email address in a DN into an altName if required */
	if( cryptStatusOK( status ) )
		{
		int fixEmailAddress;

		krnlSendMessage( certInfoPtr->ownerHandle, 
						 RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress, 
						 CRYPT_OPTION_CERT_FIXEMAILADDRESS );
		if( fixEmailAddress )
			status = convertEmailAddress( certInfoPtr );
		}

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

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

int readRevRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	long startPos;
	int length, status;

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

	/* Skip any junk before the SerialNumber */
	while( cryptStatusOK( status ) && \
		   peekTag( stream ) != MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ) )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the serial number */
	status = readSerialNumber( stream, &certInfoPtr->serialNumber,
							   &certInfoPtr->serialNumberLength, 
							   MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ) );
	if( cryptStatusError( status ) )
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,
								 status ) );

	/* Skip any junk before the IssuerName */
	while( cryptStatusOK( status ) && \
		   peekTag( stream ) != MAKE_CTAG( CTAG_CF_ISSUER ) )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );

	/* 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 */
	readConstructed( stream, NULL, CTAG_CF_ISSUER );
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip any further junk which may be present in the template */
	if( startPos - length > 0 )
		sSkip( stream, startPos - length );

	/* 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_REVOCATION, length, 
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		}

	/* Convert an email address in a DN into an altName if required */
	if( cryptStatusOK( status ) )
		{
		int fixEmailAddress;

		krnlSendMessage( certInfoPtr->ownerHandle, 
						 RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress, 
						 CRYPT_OPTION_CERT_FIXEMAILADDRESS );
		if( fixEmailAddress )
			status = convertEmailAddress( certInfoPtr );
		}

	return( status );
	}

/* Read an OCSP request:

	OCSPRequest ::= SEQUENCE {				-- Read
						SEQUENCE {			-- tbsRequest
		version		[0]	EXPLICIT INTEGER DEFAULT 0,
											-- Must be 1 if !certID used
		reqName		[1]	EXPLICIT ... OPTIONAL
											-- Ignored
		reqList			SEQUENCE OF Response
			}
						...					-- Ignored
		}
	} */

int readOCSPRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	BYTE idBuffer[ 1024 ], *idBufPtr = idBuffer;
	int length, endPos, status;

	/* Read the wrapper, version information, and requestor name */
	readSequence( stream, &length );
	endPos = ( int ) stell( stream ) + length;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_RQ_VERSION ) )
		{
		long version;

		readConstructed( stream, NULL, CTAG_RQ_VERSION );
		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( status );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_RQ_DUMMY ) )
		readUniversal( stream );

	/* Read the SEQUENCE OF revocation info and make the currently selected 
	   one the start of the list */
	status = readSequence( stream, &length );
	while( !cryptStatusError( status ) && length > 16 )
		{
		const int innerStartPos = ( int ) stell( stream );

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

	/* 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 which gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_OCSP_REQUEST, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );

	/* Convert an email address in a DN into an altName if required */
	if( cryptStatusOK( status ) )
		{
		int fixEmailAddress;

		krnlSendMessage( certInfoPtr->ownerHandle, 
						 RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress, 
						 CRYPT_OPTION_CERT_FIXEMAILADDRESS );
		if( fixEmailAddress )
			status = convertEmailAddress( certInfoPtr );
		}

	return( sGetStatus( stream ) );
	}

/* Read OCSP response information:

	OCSPResponse ::= SEQUENCE {				-- tbsRespData
			version [0] EXPLICIT ... OPTIONAL,-- Ignored
			respID		CHOICE {
					[1]	EXPLICIT Name,		-- Read in case caller needs it
					[2] EXPLICIT KeyHash	-- Ignored
					},
			producedAt	...,				-- Ignored
			responses	SEQUENCE OF Response
			exts	[1]	EXPLICIT Extensions OPTIONAL,
				} */

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

	/* Read the wrapper, version information, and responder ID */
	readSequence( stream, &length );			/* tbsResponseData */
	endPos = ( int ) stell( stream ) + length;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_RP_VERSION ) )
		{
		long version;

		readConstructed( stream, NULL, CTAG_RP_VERSION );
		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( status );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;
	if( peekTag( stream ) == MAKE_CTAG( 1 ) )
		{
		/* It's a DN, read it as the issuer name in case the caller is 
		   interested in it */
		readConstructed( stream, NULL, 1 );
		status = readIssuerDN( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		/* We can't to much with a key hash, in any case all current 
		   responders use the issuer DN to identify the responder so
		   this shouldn't be much of a problem */
		readUniversal( stream );
	readGeneralizedTime( stream, NULL );		/* producedAt */

	/* Read the SEQUENCE OF revocation info and make the currently selected 
	   one the start of the list */
	status = readSequence( stream, &length );
	while( !cryptStatusError( status ) && length > 16 )
		{
		const int innerStartPos = ( int ) stell( stream );

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

	/* Read the extensions if there are any present */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_OCSP_RESPONSE, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );

	/* In theory some OCSP responses can be sort of self-signed via attached
	   certs, but there are so many weird ways to delegate trust and signing 
	   authority mentioned in the RFC without any indication of which one 
	   implementors will follow that we require the user to supply the sig 
	   check certificate rather than assuming that some particular trust
	   delegation mechanism will happen to be in place */
/*	certInfoPtr->flags |= CERT_FLAG_SELFSIGNED; */
	return( status );
	}

⌨️ 快捷键说明

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