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

📄 certio.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						Certificate Import/Export Routines					*
*						Copyright Peter Gutmann 1997-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "asn1.h"
  #include "asn1objs.h"
  #include "asn1oid.h"
  #include "cert.h"
#else
  #include "keymgmt/asn1.h"
  #include "keymgmt/asn1objs.h"
  #include "keymgmt/asn1oid.h"
  #include "keymgmt/cert.h"
#endif /* Compiler-specific includes */

/* Context-specific tags for attribute certificates */

enum { CTAG_AC_BASECERTIFICATEID, CTAG_AC_ENTITYNAME,
	   CTAG_AC_OBJECTDIGESTINFO };

/* Oddball OID's which may be used to wrap certs */

#define OID_X509_USERCERTIFICATE	"\x06\x03\x55\x04\x24"

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Determine the object type and how long the total object is.  If fed an 
   unknown object we can (with some difficulty) determine its type at 
   runtime (although it's hardly LL(1)) and import it as appropriate.  
   
   If the data starts with a [0], it's CMS attributes.  If it starts with a 
   sequence followed by an OID it's a cert chain/sequence or (rarely) a cert 
   wrapped up in some weird packaging.  If it starts with a sequence followed
   by an integer (version = 3), it's a PKCS #12 mess.  Otherwise, it follows 
   the general pattern SEQUENCE { tbsSomething, signature }, it's at this 
   point that distinguishing the different types gets tricky.

	Cert:			SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
							INTEGER,
							AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:	SEQUENCE { SEQUENCE {
							INTEGER OPTIONAL,
						[1]	Name,
							Name,
							AlgorithmID,
							INTEGER

	CRL:			SEQUENCE { SEQUENCE {
							INTEGER OPTIONAL,
							AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:	SEQUENCE { SEQUENCE {
							INTEGER,
							Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:	SEQUENCE { SEQUENCE {
							INTEGER,
							SEQUENCE {
								{ [0] ... [9] }	-- cert request should have 
												-- [6] SubjectPublicKeyInfo

	CRMF rev.req:	SEQUENCE { SEQUENCE {
							{ [0] ... [9] }		-- Should have [1] INTEGER 
												-- (serialNo),

	OCSP request:	SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
						[1]	EXPLICIT ... OPTIONAL,
							SEQUENCE { SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:		SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
							{ [1] | [2] } ...,
							GeneralizedTime

	PKI user:		SEQUENCE { SEQUENCE {		-- Name
							{ SET ... | empty }	-- RDN or zero-length DN

   The first step is to strip out the SEQUENCE { SEQUENCE, which is shared 
   by all objects.  In addition we can remove the [0] ... OPTIONAL and
   [1] ... OPTIONAL, which isn't useful in distinguishing anything.  Since 
   the OCSP response can also have [2] in place of the [1] and leaving it in
   isn't notably useful, we strip this as well.  Note that attribute certs 
   can be left in one of two states depending on whether the initial INTEGER 
   is present or not and PKI user info is also left in one of two states 
   depending on whether there's a DN present.  Rather than parse down into
   the rest of the PKI user object (the next element is an AlgorithmID which
   clashes with a cert and CRL), we use the presence of a zero-length 
   sequence to identify a PKI user object with an absent DN.  This leaves 
   the following,

	Cert:					INTEGER,
							AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:			INTEGER OPTIONAL,
						[1]	Name,
							Name,					Name,
							AlgorithmID,			AlgorithmID,
							INTEGER					INTEGER

	CRL:					INTEGER OPTIONAL,
							AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:			INTEGER,
							Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			INTEGER,
							SEQUENCE {
								{ [0] ... [1] |	-- Implicitly tagged
								  [3] ... [9] }	-- [2] stripped

	CRMF rev.req:			{ [0] ... [1] |		-- Implicitly tagged
							  [3] ... [9] }		-- [2] stripped

	OCSP request:			SEQUENCE { SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:				GeneralizedTime

	PKI user:				SET ...				-- RDN

   Next we have the INTEGER, which also isn't notably useful.  Stripping this
   leaves:

	Cert:					AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:		[1]	Name,
							Name,					Name,
							AlgorithmID,			AlgorithmID,
							INTEGER					INTEGER

	CRL:					AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:			Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [0] | [1] |	-- Primitive tag
								  [3] ... [9] }	-- [2] stripped

	CRMF rev.req:			{ [0] | [1] |		-- Primitive tag
							  [3] ... [9] }		-- [2] stripped

	OCSP request:		SEQUENCE { SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:				GeneralizedTime

	PKI user:				SET ...				-- RDN

   We can now immediately identify the first attribute cert variant by the 
   [1] ..., a CRMF revocation request by the not-stripped [0] or [1] 
   primitive tags (implicitly tagged INTEGER) or [3]...[9] ..., an OCSP 
   response by the GeneralizedTime, and the alternative PKI user variant by 
   the SET ..., leaving:

	Cert:					AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:					AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:			Name,
							AlgorithmID,
							INTEGER

	Cert request:			Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [3] ... [9] }

	OCSP request:			SEQUENCE { SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }

   Expanding the complex types for cert, attribute cert, CRL, and cert 
   request, we get:

	Cert:					SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:					SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:			SEQUENCE {			-- Name
								SET {
									...
								...
							SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							INTEGER

	Cert request:			SEQUENCE {			-- Name
								SET {
									...
								...
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [3] ... [9] }

	OCSP request:		SEQUENCE { SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }

   Stripping the first SEQUENCE { we get:

	Cert:						OBJECT IDENTIFIER,
								...
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:						OBJECT IDENTIFIER,
								...
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:				SET {
									...
								...
							SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							INTEGER

	Cert request:				SET {
									...
								...
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:				{ [3] ... [9] }

	OCSP request:		SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }

   which allows us to distinguish certs and CRLs (the two are themselves
   distinguished by what follows the second Name) and cert requests and the 
   second attribute cert variant (the two are also distinguished by what
   follows the Name).  What's left now are the tricky ones, the other 
   request types:

	CRMF request:				{ [3] ... [9] }

	OCSP request:		SEQUENCE {
							{ SEQUENCE | [0] | [1] | [2] | [3] }

   which can themselves be distinguished by the remaining data */

static int decodeCertWrapper( STREAM *stream, int *offset )
	{
	BYTE oid[ MAX_OID_SIZE ];
	BOOLEAN isCertChain = FALSE;
	int oidLength, value, status;

	/* Read the contentType OID, determine the content type based on it,
	   and read the content encapsulation and header.  It can be either
	   a PKCS #7 cert chain, a Netscape cert sequence, or an X.509
	   userCertificate (which is just an oddball cert wrapper) */
	status = readRawObject( stream, oid, &oidLength, MAX_OID_SIZE, 
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );

⌨️ 快捷键说明

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